blob: dc3e7489fe9b62160e814a83d3f350cb20ee5934 [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
28type TServerSocket struct {
29 /**
30 * Underlying socket conection object
31 */
32 conn net.Conn
33 /**
34 * Underlying socket conection object
35 */
36 listener net.Listener
37
38 /**
39 * Address to listen on
40 */
41 addr net.Addr
42
43 /**
44 * Client timeout in nanoseconds
45 */
46 nsecClientTimeout int64
47}
48
49type TServerSocketTransportFactory struct {
50 addr net.Addr
51 nsecClientTimeout int64
52}
53
54func (p *TServerSocketTransportFactory) GetTransport(trans TTransport) TTransport {
55 if trans != nil {
56 t, ok := trans.(*TServerSocket)
57 if ok && t.addr != nil {
58 s, _ := NewTServerSocketAddrTimeout(t.addr, t.nsecClientTimeout)
59 return s
60 }
61 }
62 s, _ := NewTServerSocketAddrTimeout(p.addr, p.nsecClientTimeout)
63 return s
64}
65
66func NewTServerSocketTransportFactory(addr net.Addr, nsecClientTimeout int64) *TServerSocketTransportFactory {
67 return &TServerSocketTransportFactory{addr: addr, nsecClientTimeout: nsecClientTimeout}
68}
69
70func NewTServerSocketConn(conn net.Conn) *TServerSocket {
71 return NewTServerSocketConnTimeout(conn, 0)
72}
73
74func NewTServerSocketConnTimeout(conn net.Conn, nsecClientTimeout int64) *TServerSocket {
75 v := &TServerSocket{conn: conn, addr: conn.LocalAddr(), nsecClientTimeout: nsecClientTimeout}
76 conn.SetTimeout(nsecClientTimeout)
77 return v
78}
79
80func NewTServerSocketAddr(addr net.Addr) (*TServerSocket, TTransportException) {
81 return NewTServerSocketAddrTimeout(addr, 0)
82}
83
84func NewTServerSocketAddrTimeout(addr net.Addr, nsecClientTimeout int64) (*TServerSocket, TTransportException) {
85 s := &TServerSocket{addr: addr, nsecClientTimeout: nsecClientTimeout}
86 return s, nil
87}
88
89func (p *TServerSocket) Listen() (err os.Error) {
90 if p.listener == nil {
91 if p.listener, err = net.Listen("tcp", p.addr.String()); err != nil {
92 return err
93 }
94 }
95 return nil
96}
97
98func (p *TServerSocket) Accept() (TTransport, os.Error) {
99 if p.listener == nil {
100 if err := p.Listen(); err != nil {
101 return nil, NewTTransportExceptionFromOsError(err)
102 }
103 if p.listener == nil {
104 return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
105 }
106 }
107 conn, err := p.listener.Accept()
108 if err != nil {
109 return nil, NewTTransportExceptionFromOsError(err)
110 }
111 conn.SetTimeout(p.nsecClientTimeout)
112 return NewTSocketConn(conn)
113}
114
115/**
116 * Checks whether the socket is connected.
117 */
118func (p *TServerSocket) IsOpen() bool {
119 return p.listener != nil
120}
121
122/**
123 * Connects the socket, creating a new socket object if necessary.
124 */
125func (p *TServerSocket) Open() os.Error {
126 if !p.IsOpen() {
127 l, err := net.Listen(p.addr.Network(), p.addr.String())
128 if err != nil {
129 return err
130 }
131 p.listener = l
132 return nil
133 }
134 return NewTTransportException(ALREADY_OPEN, "Server socket already open")
135}
136
137/**
138 * Perform a nonblocking read into buffer.
139 */
140func (p *TServerSocket) Read(buf []byte) (int, os.Error) {
141 return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Read([]byte) is not implemented")
142}
143
144func (p *TServerSocket) ReadAll(buf []byte) (int, os.Error) {
145 return ReadAllTransport(p, buf)
146}
147
148/**
149 * Perform a nonblocking write of the data in buffer;
150 */
151func (p *TServerSocket) Write(buf []byte) (int, os.Error) {
152 return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Write([]byte) is not implemented")
153}
154
155/**
156 * Flushes the underlying output stream if not null.
157 */
158func (p *TServerSocket) Flush() os.Error {
159 return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Flush() is not implemented")
160}
161
162func (p *TServerSocket) Addr() net.Addr {
163 return p.addr
164}
165
166func (p *TServerSocket) Peek() bool {
167 return p.IsOpen()
168}
169
170/**
171 * Closes the socket.
172 */
173func (p *TServerSocket) Close() (err os.Error) {
174 if p.IsOpen() {
175 err := p.listener.Close()
176 if err != nil {
177 return NewTTransportExceptionFromOsError(err)
178 }
179 p.listener = nil
180 }
181 if p.conn != nil {
182 err := p.conn.Close()
183 if err != nil {
184 return NewTTransportExceptionFromOsError(err)
185 }
186 p.conn = nil
187 }
188 return nil
189}
190
191func (p *TServerSocket) Interrupt() os.Error {
192 // TODO(pomack) fix Interrupt as it is probably not right
193 return NewTTransportExceptionFromOsError(p.Close())
194}