blob: 9b175b872a5863c829438ea4e94f3ccc07059eb0 [file] [log] [blame]
Christian Lavoieafc6d8f2011-02-20 02:39:19 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package thrift
21
22import (
23 "net"
24 "os"
25)
26
27/**
28 * Socket implementation of the TTransport interface. To be commented soon!
29 */
30type TNonblockingSocket struct {
31 conn net.Conn
32 addr net.Addr
33 /**
34 * Socket timeout
35 */
36 nsecTimeout int64
37}
38
39type TNonblockingSocketTransportFactory struct {
40 addr net.Addr
41}
42
43func (p *TNonblockingSocketTransportFactory) GetTransport(trans TTransport) TTransport {
44 if trans != nil {
45 t, ok := trans.(*TNonblockingSocket)
46 if ok {
47 s, _ := NewTNonblockingSocketAddr(t.addr)
48 s.SetTimeout(t.nsecTimeout)
49 return s
50 }
51 }
52 s, _ := NewTNonblockingSocketAddr(p.addr)
53 return s
54}
55
56func NewTNonblockingSocketTransportFactory(addr net.Addr) *TNonblockingSocketTransportFactory {
57 return &TNonblockingSocketTransportFactory{addr: addr}
58}
59
60func NewTNonblockingSocketConn(conn net.Conn) (*TNonblockingSocket, TTransportException) {
61 s := &TNonblockingSocket{conn: conn, addr: conn.RemoteAddr()}
62 return s, nil
63}
64
65func NewTNonblockingSocketAddr(addr net.Addr) (*TNonblockingSocket, TTransportException) {
66 s := &TNonblockingSocket{addr: addr}
67 return s, nil
68}
69
70/**
71 * Sets the socket timeout
72 *
73 * @param nsecTimeout Nanoseconds timeout
74 */
75func (p *TNonblockingSocket) SetTimeout(nsecTimeout int64) os.Error {
76 p.nsecTimeout = nsecTimeout
77 if p.IsOpen() {
78 if err := p.conn.SetTimeout(nsecTimeout); err != nil {
79 LOGGER.Print("Could not set socket timeout.", err)
80 return err
81 }
82 }
83 return nil
84}
85
86/**
87 * Checks whether the socket is connected.
88 */
89func (p *TNonblockingSocket) IsOpen() bool {
90 return p.conn != nil
91}
92
93/**
94 * Connects the socket, creating a new socket object if necessary.
95 */
96func (p *TNonblockingSocket) Open() os.Error {
97 if p.IsOpen() {
98 return NewTTransportException(ALREADY_OPEN, "Socket already connected.")
99 }
100 if p.addr == nil {
101 return NewTTransportException(NOT_OPEN, "Cannot open nil address.")
102 }
103 if len(p.addr.Network()) == 0 {
104 return NewTTransportException(NOT_OPEN, "Cannot open bad network name.")
105 }
106 if len(p.addr.String()) == 0 {
107 return NewTTransportException(NOT_OPEN, "Cannot open bad address.")
108 }
109
110 var err os.Error
Bryan Duxburyb7bd5622011-07-13 17:58:05 +0000111 if p.conn, err = net.Dial(p.addr.Network(), p.addr.String()); err != nil {
Christian Lavoieafc6d8f2011-02-20 02:39:19 +0000112 LOGGER.Print("Could not open socket", err.String())
113 return NewTTransportException(NOT_OPEN, err.String())
114 }
115 if p.conn != nil {
116 p.conn.SetTimeout(p.nsecTimeout)
117 }
118 return nil
119}
120
121/**
122 * Perform a nonblocking read into buffer.
123 */
124func (p *TNonblockingSocket) Read(buf []byte) (int, os.Error) {
125 if !p.IsOpen() {
126 return 0, NewTTransportException(NOT_OPEN, "Connection not open")
127 }
128 n, err := p.conn.Read(buf)
129 return n, NewTTransportExceptionFromOsError(err)
130}
131
132
133func (p *TNonblockingSocket) ReadAll(buf []byte) (int, os.Error) {
134 return ReadAllTransport(p, buf)
135}
136
137/**
138 * Perform a nonblocking write of the data in buffer;
139 */
140func (p *TNonblockingSocket) Write(buf []byte) (int, os.Error) {
141 if !p.IsOpen() {
142 return 0, NewTTransportException(NOT_OPEN, "Connection not open")
143 }
144 return p.conn.Write(buf)
145}
146
147/**
148 * Flushes the underlying output stream if not null.
149 */
150func (p *TNonblockingSocket) Flush() os.Error {
151 if !p.IsOpen() {
152 return NewTTransportException(NOT_OPEN, "Connection not open")
153 }
154 f, ok := p.conn.(Flusher)
155 if ok {
156 err := f.Flush()
157 if err != nil {
158 return NewTTransportExceptionFromOsError(err)
159 }
160 }
161 return nil
162}
163
164func (p *TNonblockingSocket) Addr() net.Addr {
165 return p.addr
166}
167
168func (p *TNonblockingSocket) Peek() bool {
169 return p.IsOpen()
170}
171
172/**
173 * Closes the socket.
174 */
175func (p *TNonblockingSocket) Close() os.Error {
176 if p.conn != nil {
177 if err := p.conn.Close(); err != nil {
178 LOGGER.Print("Could not close socket.", err.String())
179 return err
180 }
181 p.conn = nil
182 }
183 return nil
184}
185
186func (p *TNonblockingSocket) Interrupt() os.Error {
187 if !p.IsOpen() {
188 return nil
189 }
190 // TODO(pomack) fix Interrupt as it is probably not right
191 return p.Close()
192}