blob: d6e9495d203131d6fa577c62b88e29bee8ae042a [file] [log] [blame]
Jens Geyer0e87c462013-06-18 22:25:07 +02001/*
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"
Jens Geyerc975bbc2014-03-06 21:11:46 +010024 "sync"
Jens Geyer0e87c462013-06-18 22:25:07 +020025 "time"
26)
27
28type TServerSocket struct {
29 listener net.Listener
30 addr net.Addr
31 clientTimeout time.Duration
Jens Geyerc975bbc2014-03-06 21:11:46 +010032
33 // Protects the interrupted value to make it thread safe.
34 mu sync.RWMutex
35 interrupted bool
Jens Geyer0e87c462013-06-18 22:25:07 +020036}
37
38func NewTServerSocket(listenAddr string) (*TServerSocket, error) {
39 return NewTServerSocketTimeout(listenAddr, 0)
40}
41
42func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) {
43 addr, err := net.ResolveTCPAddr("tcp", listenAddr)
44 if err != nil {
45 return nil, err
46 }
Jens Geyer6794c622014-11-11 00:11:16 +010047 return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil
Jens Geyer0e87c462013-06-18 22:25:07 +020048}
49
50func (p *TServerSocket) Listen() error {
51 if p.IsListening() {
52 return nil
53 }
54 l, err := net.Listen(p.addr.Network(), p.addr.String())
55 if err != nil {
56 return err
57 }
58 p.listener = l
59 return nil
60}
61
62func (p *TServerSocket) Accept() (TTransport, error) {
Jens Geyerc975bbc2014-03-06 21:11:46 +010063 p.mu.RLock()
64 interrupted := p.interrupted
65 p.mu.RUnlock()
66
67 if interrupted {
Jens Geyer0e87c462013-06-18 22:25:07 +020068 return nil, errTransportInterrupted
69 }
70 if p.listener == nil {
71 return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
72 }
73 conn, err := p.listener.Accept()
74 if err != nil {
75 return nil, NewTTransportExceptionFromError(err)
76 }
Jens Geyer6794c622014-11-11 00:11:16 +010077 return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil
Jens Geyer0e87c462013-06-18 22:25:07 +020078}
79
80// Checks whether the socket is listening.
81func (p *TServerSocket) IsListening() bool {
82 return p.listener != nil
83}
84
85// Connects the socket, creating a new socket object if necessary.
86func (p *TServerSocket) Open() error {
87 if p.IsListening() {
88 return NewTTransportException(ALREADY_OPEN, "Server socket already open")
89 }
90 if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil {
91 return err
92 } else {
93 p.listener = l
94 }
95 return nil
96}
97
98func (p *TServerSocket) Addr() net.Addr {
Jens Geyer6af074e2014-12-18 22:11:46 +010099 if p.listener != nil {
100 return p.listener.Addr()
101 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200102 return p.addr
103}
104
105func (p *TServerSocket) Close() error {
106 defer func() {
107 p.listener = nil
108 }()
109 if p.IsListening() {
110 return p.listener.Close()
111 }
112 return nil
113}
114
115func (p *TServerSocket) Interrupt() error {
Jens Geyerc975bbc2014-03-06 21:11:46 +0100116 p.mu.Lock()
Jens Geyer0e87c462013-06-18 22:25:07 +0200117 p.interrupted = true
Mark Sonnabauma6b12032015-11-13 10:48:25 -0600118 p.Close()
Jens Geyerc975bbc2014-03-06 21:11:46 +0100119 p.mu.Unlock()
120
Jens Geyer0e87c462013-06-18 22:25:07 +0200121 return nil
122}