Socket.py
3.33 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
@author Georg Hopp
"""
import socket
import errno
import sys
import Transport
from contextlib import contextmanager
CONTINUE = (errno.EAGAIN, errno.EWOULDBLOCK)
if 'win32' == sys.platform:
CONTINUE = CONTINUE + (errno.WSAEWOULDBLOCK)
class Socket(object):
def __init__(self, host, port, socket_type, con_ttl=30):
self.socket = None
self._host = host
self._port = port
self._con_ttl = con_ttl
self._socket_type = socket_type
self._listen = False
self._fin_state = 0
def isListen(self):
return self._listen
def isFin(self):
# TODO important, create something sane here.
return 0 != self._fin_state
def readReady(self):
return 0 == self._fin_state & 1
def writeReady(self):
return 0 == self._fin_state & 2
def getHandle(self):
return self.socket
def getHost(self):
return self._host
def getPort(self):
return self._port
def getAddr(self):
return (self._host, self._port)
@contextmanager
def _addrinfo(self, flags=0):
for res in socket.getaddrinfo(
self._host, self._port,
socket.AF_UNSPEC, self._socket_type,
0, flags):
af, socktype, proto, canonname, self._sa = res
try:
if not self.socket:
self.socket = socket.socket(af, socktype, proto)
except socket.error as error:
current_exception = error
self.socket = None
continue
try:
yield socktype
except socket.error as error:
current_exception = error
self.socket.close()
self.socket = None
continue
break
if not self.socket:
raise Transport.Error(Transport.Error.ERR_FAILED)
def bind(self):
with self._addrinfo(socket.AI_PASSIVE):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self._sa)
self.socket.setblocking(0)
def open(self):
with self._addrinfo(socket.AI_PASSIVE):
self.socket.setblocking(0)
def shutdownRead(self):
try:
if 0 == self._fin_state & 1:
self.socket.shutdown(socket.SHUT_RD)
self._fin_state |= 1
except socket.error as error:
self._fin_state |= 3
return self._fin_state
def shutdownWrite(self):
try:
if 0 == self._fin_state & 2:
self.socket.shutdown(socket.SHUT_WR)
self._fin_state |= 2
except socket.error as error:
self._fin_state |= 3
return self._fin_state
def shutdown(self):
try:
if 0 == self._fin_state:
self.socket.shutdown(socket.SHUT_RDWR)
else:
self.shutdownRead()
self.shutdownWrite()
except socket.error as error:
pass
self._fin_state |= 3
return self._fin_state
def close(self):
try:
self.shutdown()
self.socket.close()
except socket.error as error:
pass
self.socket = None
# vim: set ft=python et ts=4 sw=4 sts=4: