1 | """ |
---|
2 | SocketIO imported from socket module in Python 3. |
---|
3 | |
---|
4 | Copyright (c) 2001-2013 Python Software Foundation; All Rights Reserved. |
---|
5 | """ |
---|
6 | |
---|
7 | from socket import * |
---|
8 | import io |
---|
9 | import errno |
---|
10 | |
---|
11 | __all__ = ['SocketIO'] |
---|
12 | |
---|
13 | EINTR = errno.EINTR |
---|
14 | _blocking_errnos = (errno.EAGAIN, errno.EWOULDBLOCK) |
---|
15 | |
---|
16 | class SocketIO(io.RawIOBase): |
---|
17 | |
---|
18 | """Raw I/O implementation for stream sockets. |
---|
19 | |
---|
20 | This class supports the makefile() method on sockets. It provides |
---|
21 | the raw I/O interface on top of a socket object. |
---|
22 | """ |
---|
23 | |
---|
24 | # One might wonder why not let FileIO do the job instead. There are two |
---|
25 | # main reasons why FileIO is not adapted: |
---|
26 | # - it wouldn't work under Windows (where you can't used read() and |
---|
27 | # write() on a socket handle) |
---|
28 | # - it wouldn't work with socket timeouts (FileIO would ignore the |
---|
29 | # timeout and consider the socket non-blocking) |
---|
30 | |
---|
31 | # XXX More docs |
---|
32 | |
---|
33 | def __init__(self, sock, mode): |
---|
34 | if mode not in ("r", "w", "rw", "rb", "wb", "rwb"): |
---|
35 | raise ValueError("invalid mode: %r" % mode) |
---|
36 | io.RawIOBase.__init__(self) |
---|
37 | self._sock = sock |
---|
38 | if "b" not in mode: |
---|
39 | mode += "b" |
---|
40 | self._mode = mode |
---|
41 | self._reading = "r" in mode |
---|
42 | self._writing = "w" in mode |
---|
43 | self._timeout_occurred = False |
---|
44 | |
---|
45 | def readinto(self, b): |
---|
46 | """Read up to len(b) bytes into the writable buffer *b* and return |
---|
47 | the number of bytes read. If the socket is non-blocking and no bytes |
---|
48 | are available, None is returned. |
---|
49 | |
---|
50 | If *b* is non-empty, a 0 return value indicates that the connection |
---|
51 | was shutdown at the other end. |
---|
52 | """ |
---|
53 | self._checkClosed() |
---|
54 | self._checkReadable() |
---|
55 | if self._timeout_occurred: |
---|
56 | raise IOError("cannot read from timed out object") |
---|
57 | while True: |
---|
58 | try: |
---|
59 | return self._sock.recv_into(b) |
---|
60 | except timeout: |
---|
61 | self._timeout_occurred = True |
---|
62 | raise |
---|
63 | except error as e: |
---|
64 | n = e.args[0] |
---|
65 | if n == EINTR: |
---|
66 | continue |
---|
67 | if n in _blocking_errnos: |
---|
68 | return None |
---|
69 | raise |
---|
70 | |
---|
71 | def write(self, b): |
---|
72 | """Write the given bytes or bytearray object *b* to the socket |
---|
73 | and return the number of bytes written. This can be less than |
---|
74 | len(b) if not all data could be written. If the socket is |
---|
75 | non-blocking and no bytes could be written None is returned. |
---|
76 | """ |
---|
77 | self._checkClosed() |
---|
78 | self._checkWritable() |
---|
79 | try: |
---|
80 | return self._sock.send(b) |
---|
81 | except error as e: |
---|
82 | # XXX what about EINTR? |
---|
83 | if e.args[0] in _blocking_errnos: |
---|
84 | return None |
---|
85 | raise |
---|
86 | |
---|
87 | def readable(self): |
---|
88 | """True if the SocketIO is open for reading. |
---|
89 | """ |
---|
90 | if self.closed: |
---|
91 | raise ValueError("I/O operation on closed socket.") |
---|
92 | return self._reading |
---|
93 | |
---|
94 | def writable(self): |
---|
95 | """True if the SocketIO is open for writing. |
---|
96 | """ |
---|
97 | if self.closed: |
---|
98 | raise ValueError("I/O operation on closed socket.") |
---|
99 | return self._writing |
---|
100 | |
---|
101 | def seekable(self): |
---|
102 | """True if the SocketIO is open for seeking. |
---|
103 | """ |
---|
104 | if self.closed: |
---|
105 | raise ValueError("I/O operation on closed socket.") |
---|
106 | return super().seekable() |
---|
107 | |
---|
108 | def fileno(self): |
---|
109 | """Return the file descriptor of the underlying socket. |
---|
110 | """ |
---|
111 | self._checkClosed() |
---|
112 | return self._sock.fileno() |
---|
113 | |
---|
114 | @property |
---|
115 | def name(self): |
---|
116 | if not self.closed: |
---|
117 | return self.fileno() |
---|
118 | else: |
---|
119 | return -1 |
---|
120 | |
---|
121 | @property |
---|
122 | def mode(self): |
---|
123 | return self._mode |
---|
124 | |
---|
125 | def close(self): |
---|
126 | """Close the SocketIO object. This doesn't close the underlying |
---|
127 | socket, except if all references to it have disappeared. |
---|
128 | """ |
---|
129 | if self.closed: |
---|
130 | return |
---|
131 | io.RawIOBase.close(self) |
---|
132 | self._sock._decref_socketios() |
---|
133 | self._sock = None |
---|
134 | |
---|