35 raise ValueError(buf) |
35 raise ValueError(buf) |
36 |
36 |
37 # XXX: do some GIL-releasin' |
37 # XXX: do some GIL-releasin' |
38 cdef class socket : |
38 cdef class socket : |
39 |
39 |
40 def __init__ (self, int fd = -1) : |
40 def __cinit__ (self) : |
41 """ |
41 """ |
42 Construct this socket with the given fd, or -1 to mark it as fd-less |
42 Initialize the socket to set fd to -1, so that we dont't try and close stdin too often :) |
43 """ |
43 """ |
44 |
44 |
45 self.fd = fd |
45 self.fd = -1 |
46 |
46 |
47 def socket (self, int family = platform.AF_INET, int socktype = platform.SOCK_STREAM, int protocol = 0) : |
47 def __init__ (self, int family = platform.AF_INET, int socktype = platform.SOCK_STREAM, int protocol = 0, int fd = -1) : |
48 """ |
48 """ |
49 Create a new socket endpoint with the given family/domain, socktype and optionally, specific protocol. |
49 Create a new socket endpoint with the given family/domain, socktype and optionally, specific protocol, |
|
50 unless the fd argument is given as >= 0, in which case it used directly. |
50 |
51 |
51 family - one of AF_* |
52 family - one of AF_* |
52 socktype - one of SOCK_* |
53 socktype - one of SOCK_* |
53 protocol - one of IPPROTO_* or zero to select default |
54 protocol - one of IPPROTO_* or zero to select default |
54 """ |
55 """ |
55 |
56 |
56 if self.fd >= 0 : |
57 if fd >= 0 : |
57 raise Exception("Socket fd already exists") |
58 # given fd |
58 |
59 self.fd = fd |
59 # socket() |
60 |
60 self.fd = platform.socket(family, socktype, protocol) |
61 else : |
|
62 # socket() |
|
63 self.fd = platform.socket(family, socktype, protocol) |
61 |
64 |
62 # trap |
65 # trap |
63 if self.fd < 0 : |
66 if self.fd < 0 : |
64 raise_errno('socket') |
67 raise_errno('socket') |
65 |
68 |
139 # accept() |
142 # accept() |
140 sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len) |
143 sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len) |
141 |
144 |
142 if sock_fd < 0 : |
145 if sock_fd < 0 : |
143 raise_errno('accept') |
146 raise_errno('accept') |
144 |
147 |
145 # prep the new socket |
148 try : |
146 sock_obj = socket(sock_fd) |
149 # prep the new socket |
|
150 sock_obj = socket(sock_fd) |
|
151 |
|
152 except : |
|
153 # XXX: don't leak the socket fd? How does socket.__init__ handle this? |
|
154 platform.close(sock_fd) |
|
155 |
|
156 raise |
147 |
157 |
148 # prep the new addr |
158 # prep the new addr |
149 sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len) |
159 sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len) |
150 |
160 |
151 return sock_obj, sock_addr |
161 return sock_obj, sock_addr |
301 |
311 |
302 # fill in the iovecs |
312 # fill in the iovecs |
303 for i, buf in enumerate(iov) : |
313 for i, buf in enumerate(iov) : |
304 iovec = &iov_list[i] |
314 iovec = &iov_list[i] |
305 |
315 |
306 |
|
307 parse_buf(&iovec.iov_base, &iovec.iov_len, buf, 1) |
316 parse_buf(&iovec.iov_base, &iovec.iov_len, buf, 1) |
308 |
317 |
309 # sendmsg() |
318 # sendmsg() |
310 ret = libc.writev(self.fd, iov_list, iov_count) |
319 ret = libc.writev(self.fd, iov_list, iov_count) |
311 |
320 |
312 if ret < 0 : |
321 if ret < 0 : |
313 raise_errno('writev') |
322 raise_errno('writev') |
314 |
323 |
315 else : |
324 else : |
316 return ret |
325 return ret |
317 |
326 |
|
327 |
|
328 def shutdown (self, how) : |
|
329 """ |
|
330 Shutdown part of a full-duplex connection. |
|
331 |
|
332 how - one of SHUT_* |
|
333 |
|
334 This does not affect this socket's fd. |
|
335 """ |
|
336 |
|
337 # shutdown() |
|
338 if platform.shutdown(self.fd, how) : |
|
339 raise_errno('shutdown') |
|
340 |
|
341 def close (self) : |
|
342 """ |
|
343 Close the socket fd if we have one, invalidating it if succesful. |
|
344 |
|
345 Note that this will raise an error and keep the fd if the system close() returns an error. |
|
346 |
|
347 Calling this again after a succesfull close() does nothing. |
|
348 |
|
349 XXX: SO_LINGER/blocking? |
|
350 |
|
351 >>> s = socket() |
|
352 >>> s.fd >= 0 |
|
353 True |
|
354 >>> s.close() |
|
355 >>> s.fd >= 0 |
|
356 False |
|
357 >>> s.close() |
|
358 """ |
|
359 |
|
360 # ignore if already closed |
|
361 if self.fd < 0 : |
|
362 return |
|
363 |
|
364 # close() |
|
365 if libc.close(self.fd) : |
|
366 raise_errno('close') |
|
367 |
|
368 # invalidate |
|
369 self.fd = -1 |
|
370 |
|
371 def __dealloc__ (self) : |
|
372 """ |
|
373 Close the socket fd if one is set, ignoring any errors from close |
|
374 """ |
|
375 |
|
376 if self.fd >= 0 : |
|
377 if libc.close(self.fd) : |
|
378 # XXX: at least warn... ? |
|
379 pass |
|
380 |