TcpSocket.py
2.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""
@author Georg Hopp
"""
import errno
import socket
import Transport
from Socket import Socket, CONTINUE
ACC_CONTINUE = CONTINUE + (
errno.ENETDOWN,
errno.EPROTO,
errno.ENOPROTOOPT,
errno.EHOSTDOWN,
errno.ENONET,
errno.EHOSTUNREACH,
errno.EOPNOTSUPP
)
class TcpSocket(Socket):
def __init__(self, host, port, con_ttl=30):
super(TcpSocket, self).__init__(host, port, socket.SOCK_STREAM, con_ttl)
self.remote = None
def bind(self):
super(TcpSocket, self).bind()
self.socket.listen(128)
self._listen = True
def connect(self):
with self._addrinfo():
self.socket.settimeout(self._con_ttl)
self.socket.connect(self._sa)
self.socket.settimeout(None)
self.socket.setblocking(0)
def accept(self):
try:
con, remote = self.socket.accept()
except socket.error as error:
if error.errno not in ACC_CONTINUE:
raise Transport.Error(Transport.Error.ERR_FAILED)
return None
try:
host, port = con.getpeername()
except Exception as error:
# Here we should destinguish the addr_family...
# Port is only available for INET and INET6 but not for UNIX.
# Currently I don't support UNIX so i don't change it now.
host = addr[0]
port = addr[1]
con.setblocking(0)
newsock = type(self)(host, port, self._con_ttl)
newsock.socket = con
newsock.remote = remote
return newsock
def recv(self, size):
data = ''
try:
data = self.socket.recv(size)
except socket.error as error:
if error.errno not in CONTINUE:
raise Transport.Error(Transport.Error.ERR_FAILED)
return None
if not data:
raise Transport.Error(Transport.Error.ERR_REMOTE_CLOSE)
return (data, self.remote)
def send(self, data, remote=None):
send = 0
try:
if self.socket:
send = self.socket.send(data)
except socket.error as error:
if error.errno not in CONTINUE:
if error.errno == errno.ECONNRESET:
raise Transport.Error(Transport.Error.ERR_REMOTE_CLOSE)
else:
raise Transport.Error(Transport.Error.ERR_FAILED)
return send
# vim: set ft=python et ts=4 sw=4 sts=4: