(py-indent-right, py-outdent-left): new commands, bound to C-c C-r and
[python/dscho.git] / Mac / Unsupported / mactcp / socket.py
blobe1ef0acca51bf7729d05c5d05de3259ee6650d55
1 """socket.py for mac - Emulate socket module with mactcp and macdnr
3 Currently only implements TCP sockets (AF_INET, SOCK_STREAM).
4 Esoteric things like socket options don't work,
5 but getpeername() and makefile() do work; everything used by ftplib works!
6 """
8 # Jack Jansen, CWI, November 1994 (initial version)
9 # Guido van Rossum, CWI, March 1995 (bug fixes and lay-out)
12 import mactcp
13 import MACTCP
14 import macdnr
17 # Exported constants
19 _myerror = 'socket_wrapper.error'
20 error = (mactcp.error, macdnr.error, _myerror)
22 SOCK_DGRAM = 1
23 SOCK_STREAM = 2
25 AF_INET = 1
28 # Internal constants
30 _BUFSIZE = 15*1024 # Size of TCP/UDP input buffer
32 _myaddress = None
33 _myname = None
34 _myaddrstr = None
37 def _myipaddress():
38 global _myaddress
39 if _myaddress == None:
40 _myaddress = mactcp.IPAddr()
41 return _myaddress
44 def _ipaddress(str):
45 if type(str) == type(1):
46 return str # Already numeric
47 ptr = macdnr.StrToAddr(str)
48 ptr.wait()
49 return ptr.ip0
52 def gethostbyname(str):
53 id = _ipaddress(str)
54 return macdnr.AddrToStr(id)
57 def gethostname():
58 global _myname
59 if _myname == None:
60 id = _myipaddress()
61 ptr = macdnr.AddrToName(id)
62 ptr.wait()
63 _myname = ptr.cname
64 return _myname
67 def _gethostaddress():
68 global _myaddrstr
69 if _myaddrstr == None:
70 id = _myipaddress()
71 _myaddrstr = macdnr.AddrToStr(id)
72 return _myaddrstr
75 def socket(family, type, *which):
76 if family <> AF_INET:
77 raise _myerror, 'Protocol family %d not supported' % type
78 if type == SOCK_DGRAM:
79 return _udpsocket()
80 elif type == SOCK_STREAM:
81 return _tcpsocket()
82 raise _myerror, 'Protocol type %d not supported' % type
85 def fromfd(*args):
86 raise _myerror, 'Operation not supported on a mac'
89 class _socket:
90 def unsupported(self, *args):
91 raise _myerror, 'Operation not supported on this socket'
93 accept = unsupported
94 bind = unsupported
95 close = unsupported
96 connect = unsupported
97 fileno = unsupported
98 getpeername = unsupported
99 getsockname = unsupported
100 getsockopt = unsupported
101 listen = unsupported
102 recv = unsupported
103 recvfrom = unsupported
104 send = unsupported
105 sendto = unsupported
106 setblocking = unsupported
107 setsockopt = unsupported
108 shutdown = unsupported
111 class _tcpsocket(_socket):
113 def __init__(self):
114 self.stream = mactcp.TCPCreate(_BUFSIZE)
115 ##self.stream.asr = self.asr
116 self.databuf = ''
117 self.udatabuf = ''
118 self.port = 0
119 self.accepted = 0
120 self.listening = 0
122 def accept(self):
123 if not self.listening:
124 raise _myerror, 'Not listening'
125 self.listening = 0
126 self.stream.wait()
127 self.accepted = 1
128 return self, self.getsockname()
130 # bind has two ways of calling: s.bind(host, port) or s.bind((host, port));
131 # the latter is more proper but the former more common
132 def bind(self, a1, a2=None):
133 if a2 is None:
134 host, port = a1
135 else:
136 host, port = a1, a2
137 self.port = port
139 def close(self):
140 if self.accepted:
141 self.accepted = 0
142 return
143 self.stream.Abort()
145 # connect has the same problem as bind (see above)
146 def connect(self, a1, a2=None):
147 if a2 is None:
148 host, port = a1
149 else:
150 host, port = a1, a2
151 self.stream.ActiveOpen(self.port, _ipaddress(host), port)
153 def getsockname(self):
154 host, port = self.stream.GetSockName()
155 host = macdnr.AddrToStr(host)
156 return host, port
158 def getpeername(self):
159 st = self.stream.Status()
160 host = macdnr.AddrToStr(st.remoteHost)
161 return host, st.remotePort
163 def listen(self, backlog):
164 self.stream.PassiveOpen(self.port)
165 self.listening = 1
167 def makefile(self, rw = 'r'):
168 return _socketfile(self, rw)
170 def recv(self, bufsize, flags=0):
171 if flags:
172 raise _myerror, 'recv flags not yet supported on mac'
173 if not self.databuf:
174 try:
175 self.databuf, urg, mark = self.stream.Rcv(0)
176 except mactcp.error, arg:
177 if arg[0] != MACTCP.connectionClosing:
178 raise mactcp.error, arg
179 rv = self.databuf[:bufsize]
180 self.databuf = self.databuf[bufsize:]
181 return rv
183 def send(self, buf):
184 self.stream.Send(buf)
185 return len(buf)
187 def shutdown(self, how):
188 if how == 0:
189 return
190 self.stream.Close()
192 def bytes_readable(self):
193 st = self.stream.Status()
194 return st.amtUnreadData
196 def bytes_writeable(self):
197 st = self.stream.Status()
198 return st.sendWindow - st.sendUnacked;
201 class _udpsocket(_socket):
203 def __init__(self):
204 pass
207 class _socketfile:
209 def __init__(self, sock, rw):
210 if rw not in ('r', 'w'): raise _myerror, "mode must be 'r' or 'w'"
211 self.sock = sock
212 self.rw = rw
213 self.buf = ''
215 def read(self, length = 0):
216 if length <= 0:
217 length = 0x7fffffff
218 while len(self.buf) < length:
219 new = self.sock.recv(0x7fffffff)
220 if not new:
221 break
222 self.buf = self.buf + new
223 rv = self.buf[:length]
224 self.buf = self.buf[length:]
225 return rv
227 def readline(self):
228 import string
229 while not '\n' in self.buf:
230 new = self.sock.recv(0x7fffffff)
231 if not new:
232 break
233 self.buf = self.buf + new
234 if not '\n' in self.buf:
235 rv = self.buf
236 self.buf = ''
237 else:
238 i = string.index(self.buf, '\n')
239 rv = self.buf[:i+1]
240 self.buf = self.buf[i+1:]
241 return rv
243 def write(self, buf):
244 BS = 512
245 if len(buf) >= BS:
246 self.flush()
247 self.sock.send(buf)
248 elif len(buf) + len(self.buf) >= BS:
249 self.flush()
250 self.buf = buf
251 else:
252 self.buf = self.buf + buf
254 def flush(self):
255 if self.buf and self.rw == 'w':
256 self.sock.send(self.buf)
257 self.buf = ''
259 def close(self):
260 self.flush()
261 ##self.sock.close()
262 del self.sock
265 def __test_tcp():
266 s = socket(AF_INET, SOCK_STREAM)
267 s.connect('poseidon.cwi.nl', 13)
268 rv = s.recv(1000)
269 print 'Time/date:', rv
270 rv = s.recv(1000)
271 if rv:
272 print 'Unexpected extra data:', rv
273 s.close()
276 def __test_udp():
277 s = socket(AF_INET, SOCK_DGRAM)
278 print 'Sending data... (hello world)'
279 s.sendto(('poseidon.cwi.nl', 7), 'hello world')
280 rv, host = s.recvfrom(1000)
281 print 'Got from ', host, ':', rv