67 class Common (Base) : |
67 class Common (Base) : |
68 """ |
68 """ |
69 Common operations for Client/Service |
69 Common operations for Client/Service |
70 """ |
70 """ |
71 |
71 |
72 @classmethod |
72 # default socktype |
73 def _socket (self, family, socktype, protocol = 0) : |
73 _SOCKTYPE = 0 |
|
74 |
|
75 @classmethod |
|
76 def _socket (cls, family, socktype = None, protocol = 0) : |
74 """ |
77 """ |
75 Construct and return a new socket object using the given parameters. |
78 Construct and return a new socket object using the given parameters. |
76 """ |
79 """ |
|
80 |
|
81 if socktype is None : |
|
82 socktype = cls._SOCKTYPE |
77 |
83 |
78 return socket.socket(family, socktype, protocol) |
84 return socket.socket(family, socktype, protocol) |
79 |
85 |
80 @classmethod |
86 @classmethod |
81 def _bind_addrinfo (cls, ai) : |
87 def _bind_addrinfo (cls, ai) : |
98 |
104 |
99 else : |
105 else : |
100 return sock |
106 return sock |
101 |
107 |
102 @classmethod |
108 @classmethod |
103 def _bind_endpoint (cls, endpoint, family, socktype, protocol=0) : |
109 def _bind_endpoint (cls, endpoint, socktype = None, protocol=0) : |
104 """ |
110 """ |
105 This will resolve the given endpoint, and attempt to create and bind a suitable socket and return it. |
111 This will resolve the given endpoint, and attempt to create and bind a suitable socket and return it. |
106 |
112 |
107 endpoint - local Endpoint to bind() to. |
113 endpoint - local Endpoint to bind() to. |
108 family - socket address family to use. |
114 socktype - (optiona) socket type to use, defaults to _SOCKTYPE |
109 socktype - socket type to use |
|
110 protocol - (optional) specific protocol |
115 protocol - (optional) specific protocol |
111 |
116 |
112 Raises a ServiceBindError if this is unable to create a bound socket. |
117 Raises a ServiceBindError if this is unable to create a bound socket. |
113 |
118 |
114 XXX: bind to all of the given endpoint's addresses instead of just one...? |
119 XXX: bind to all of the given endpoint's addresses instead of just one...? |
115 """ |
120 """ |
116 |
121 |
117 errors = [] |
122 errors = [] |
118 |
123 |
|
124 if socktype is None : |
|
125 socktype = cls._SOCKTYPE |
|
126 |
119 # resolve the endpoint and try socket+bind |
127 # resolve the endpoint and try socket+bind |
120 for ai in endpoint.resolve(family, socktype, protocol, AI_PASSIVE) : |
128 for ai in endpoint.resolve(socktype, protocol, AI_PASSIVE) : |
121 try : |
129 try : |
122 # try to socket+bind this addrinfo |
130 # try to socket+bind this addrinfo |
123 sock = cls._bind_addrinfo(ai) |
131 sock = cls._bind_addrinfo(ai) |
124 |
132 |
125 except SocketBindAddrinfoError, error : |
133 except SocketBindAddrinfoError, error : |
135 |
143 |
136 else : |
144 else : |
137 # no suitable address found :( |
145 # no suitable address found :( |
138 raise SocketBindEndpointError(endpoint, errors) |
146 raise SocketBindEndpointError(endpoint, errors) |
139 |
147 |
140 def _init_endpoint (self, endpoint, family, socktype, protocol = 0) : |
148 def _init_endpoint (self, endpoint, socktype = None, protocol = 0, family = None) : |
141 """ |
149 """ |
142 Initialize this socket by constructing a new socket with the given parameters, bound to the given endpoint, |
150 Initialize this socket by constructing a new socket with the given parameters, bound to the given endpoint, |
143 if given. If no endpoint is given, this simply creates a socket with the given settings and does not bind |
151 if given. If no endpoint is given, this simply creates a socket with the given settings and does not bind |
144 it anywhere. |
152 it anywhere. |
145 """ |
153 """ |
146 |
154 |
147 # create local socket |
155 if endpoint is not None : |
148 if endpoint : |
|
149 # create a suitable socket bound to a the given endpoint |
156 # create a suitable socket bound to a the given endpoint |
150 self.sock = self._bind_endpoint(endpoint, family, socktype, protocol) |
157 self.sock = self._bind_endpoint(endpoint, socktype, protocol) |
151 |
158 |
152 else : |
159 else : |
153 # create a suitable socket not bound to anything |
160 assert family |
|
161 |
|
162 # simply create a socket |
154 self.sock = self._socket(family, socktype, protocol) |
163 self.sock = self._socket(family, socktype, protocol) |
155 |
|
156 |
164 |
157 class Service (Common) : |
165 class Service (Common) : |
158 """ |
166 """ |
159 Listener socket |
167 Listener socket |
160 """ |
168 """ |
250 |
258 |
251 # return once succesfully |
259 # return once succesfully |
252 return sock |
260 return sock |
253 |
261 |
254 @classmethod |
262 @classmethod |
255 def _connect_sock_endpoint (cls, sock, endpoint, family, socktype, protocol = 0) : |
263 def _connect_sock_endpoint (cls, sock, endpoint, socktype = None, protocol = 0) : |
256 """ |
264 """ |
257 Connect this socket to the given remote endpoint, using the given parameters to resolve the endpoint. |
265 Connect this socket to the given remote endpoint, using the given parameters to resolve the endpoint. |
258 """ |
266 """ |
259 |
267 |
260 errors = [] |
268 errors = [] |
261 |
269 |
|
270 if socktype is None : |
|
271 socktype = cls._SOCKTYPE |
|
272 |
262 # resolve the endpoint and try socket+bind |
273 # resolve the endpoint and try socket+bind |
263 for ai in endpoint.resolve(family, socktype, protocol) : |
274 for ai in endpoint.resolve(socktype, protocol) : |
264 try : |
275 try : |
265 # try to connect the socket to this addrinfo |
276 # try to connect the socket to this addrinfo |
266 cls._connect_sock_addrinfo(sock, ai) |
277 cls._connect_sock_addrinfo(sock, ai) |
267 |
278 |
268 except SocketConnectAddrinfoError, error : |
279 except SocketConnectAddrinfoError, error : |
279 else : |
290 else : |
280 # no suitable address found :( |
291 # no suitable address found :( |
281 raise SocketConnectEndpointError(endpoint, errors) |
292 raise SocketConnectEndpointError(endpoint, errors) |
282 |
293 |
283 @classmethod |
294 @classmethod |
284 def _connect_endpoint (cls, endpoint, family, socktype, protocol = 0) : |
295 def _connect_endpoint (cls, endpoint, socktype = None, protocol = 0) : |
285 """ |
296 """ |
286 Create a new socket and connect it to the given remote endpoint, using the given parameters to resolve the |
297 Create a new socket and connect it to the given remote endpoint, using the given parameters to resolve the |
287 endpoint. |
298 endpoint. |
288 """ |
299 """ |
289 |
300 |
290 errors = [] |
301 errors = [] |
291 |
302 |
|
303 if socktype is None : |
|
304 socktype = cls._SOCKTYPE |
|
305 |
292 # resolve the endpoint and try socket+bind |
306 # resolve the endpoint and try socket+bind |
293 for ai in endpoint.resolve(family, socktype, protocol) : |
307 for ai in endpoint.resolve(socktype, protocol) : |
294 try : |
308 try : |
295 # try to socket+connect this addrinfo |
309 # try to socket+connect this addrinfo |
296 sock = cls._connect_addrinfo(ai) |
310 sock = cls._connect_addrinfo(ai) |
297 |
311 |
298 except SocketConnectAddrinfoError, error : |
312 except SocketConnectAddrinfoError, error : |
308 |
322 |
309 else : |
323 else : |
310 # no suitable address found :( |
324 # no suitable address found :( |
311 raise SocketConnectEndpointError(endpoint, errors) |
325 raise SocketConnectEndpointError(endpoint, errors) |
312 |
326 |
313 def _init_connect_endpoint (self, endpoint, family, socktype, protocol = 0): |
327 def _init_connect_endpoint (self, endpoint, socktype = None, protocol = 0): |
314 """ |
328 """ |
315 If we already have an existing socket, connect it to the given endpoint, otherwise try and connect to the |
329 If we already have an existing socket, connect it to the given endpoint, otherwise try and connect to the |
316 given endpoint with a new socket. |
330 given endpoint with a new socket. |
317 |
331 |
318 There is a subtle difference here, because if we have e.g. an IPv4 socket and try and connect it to an |
332 There is a subtle difference here, because if we have e.g. an IPv4 socket and try and connect it to an |
323 and to the IPv4 address using an IPv4 socket. |
337 and to the IPv4 address using an IPv4 socket. |
324 """ |
338 """ |
325 |
339 |
326 if self.socket : |
340 if self.socket : |
327 # connect with existing socket |
341 # connect with existing socket |
328 self._connect_sock_endpoint(self.socket, endpoint, family, socktype, protocol) |
342 self._connect_sock_endpoint(self.socket, endpoint, socktype, protocol) |
329 |
343 |
330 else : |
344 else : |
331 # connect with new socket |
345 # connect with new socket |
332 self._connect_endpoint(endpoint, family, socktype, protocol) |
346 self._connect_endpoint(endpoint, socktype, protocol) |
333 |
347 |
334 class Stream (Base) : |
348 class Stream (Base) : |
335 """ |
349 """ |
336 Unbuffered byte-stream interface. |
350 Unbuffered byte-stream interface. |
337 """ |
351 """ |