Ditched '_find_SET()', since it was a no-value-added wrapper around
[python/dscho.git] / Mac / Unsupported / mactcp / socket.py
blobe6600b137071b07f5bf2a5ed5be93b53d6698f82
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 MACTCPconst
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 gethostbyaddr(str):
58 id = _ipaddress(str)
59 ptr = macdnr.AddrToName(id)
60 ptr.wait()
61 name = ptr.cname
62 if name[-1:] == '.': name = name[:-1]
63 names, addresses = [], [str]
64 return name, names, addresses
66 def gethostname():
67 global _myname
68 if _myname == None:
69 id = _myipaddress()
70 ptr = macdnr.AddrToName(id)
71 ptr.wait()
72 _myname = ptr.cname
73 return _myname
76 def _gethostaddress():
77 global _myaddrstr
78 if _myaddrstr == None:
79 id = _myipaddress()
80 _myaddrstr = macdnr.AddrToStr(id)
81 return _myaddrstr
84 def socket(family, type, *which):
85 if family <> AF_INET:
86 raise _myerror, 'Protocol family %d not supported' % type
87 if type == SOCK_DGRAM:
88 return _udpsocket()
89 elif type == SOCK_STREAM:
90 return _tcpsocket()
91 raise _myerror, 'Protocol type %d not supported' % type
94 def fromfd(*args):
95 raise _myerror, 'Operation not supported on a mac'
98 class _socket:
99 def unsupported(self, *args):
100 raise _myerror, 'Operation not supported on this socket'
102 accept = unsupported
103 bind = unsupported
104 close = unsupported
105 connect = unsupported
106 fileno = unsupported
107 getpeername = unsupported
108 getsockname = unsupported
109 getsockopt = unsupported
110 listen = unsupported
111 recv = unsupported
112 recvfrom = unsupported
113 send = unsupported
114 sendto = unsupported
115 setblocking = unsupported
116 setsockopt = unsupported
117 shutdown = unsupported
120 class _tcpsocket(_socket):
122 def __init__(self):
123 self.stream = mactcp.TCPCreate(_BUFSIZE)
124 ##self.stream.asr = self.asr
125 self.databuf = ''
126 self.udatabuf = ''
127 self.port = 0
128 self.accepted = 0
129 self.listening = 0
131 def accept(self):
132 if not self.listening:
133 raise _myerror, 'Not listening'
134 self.listening = 0
135 self.stream.wait()
136 self.accepted = 1
137 return self, self.getsockname()
139 # bind has two ways of calling: s.bind(host, port) or s.bind((host, port));
140 # the latter is more proper but the former more common
141 def bind(self, a1, a2=None):
142 if a2 is None:
143 host, port = a1
144 else:
145 host, port = a1, a2
146 self.port = port
148 def close(self):
149 if self.accepted:
150 self.accepted = 0
151 return
152 self.stream.Abort()
154 # connect has the same problem as bind (see above)
155 def connect(self, a1, a2=None):
156 if a2 is None:
157 host, port = a1
158 else:
159 host, port = a1, a2
160 self.stream.ActiveOpen(self.port, _ipaddress(host), port)
162 def getsockname(self):
163 host, port = self.stream.GetSockName()
164 host = macdnr.AddrToStr(host)
165 return host, port
167 def getpeername(self):
168 st = self.stream.Status()
169 host = macdnr.AddrToStr(st.remoteHost)
170 return host, st.remotePort
172 def listen(self, backlog):
173 self.stream.PassiveOpen(self.port)
174 self.listening = 1
176 def makefile(self, rw = 'r', bs = 512):
177 return _socketfile(self, rw, bs)
179 def recv(self, bufsize, flags=0):
180 if flags:
181 raise _myerror, 'recv flags not yet supported on mac'
182 if not self.databuf:
183 try:
184 self.databuf, urg, mark = self.stream.Rcv(0)
185 except mactcp.error, arg:
186 if arg[0] != MACTCPconst.connectionClosing:
187 raise mactcp.error, arg
188 rv = self.databuf[:bufsize]
189 self.databuf = self.databuf[bufsize:]
190 return rv
192 def send(self, buf):
193 self.stream.Send(buf)
194 return len(buf)
196 def shutdown(self, how):
197 if how == 0:
198 return
199 self.stream.Close()
201 def bytes_readable(self):
202 st = self.stream.Status()
203 return st.amtUnreadData
205 def bytes_writeable(self):
206 st = self.stream.Status()
207 return st.sendWindow - st.sendUnacked;
210 class _udpsocket(_socket):
212 def __init__(self):
213 pass
216 class _socketfile:
218 def __init__(self, sock, rw, bs):
219 if rw[1:] == 'b': rw = rw[:1]
220 if rw not in ('r', 'w'): raise _myerror, "mode must be 'r' or 'w'"
221 self.sock = sock
222 self.rw = rw
223 self.bs = bs
224 self.buf = ''
226 def read(self, length = -1):
227 if length < 0:
228 length = 0x7fffffff
229 while len(self.buf) < length:
230 new = self.sock.recv(0x7fffffff)
231 if not new:
232 break
233 self.buf = self.buf + new
234 rv = self.buf[:length]
235 self.buf = self.buf[length:]
236 return rv
238 def readline(self):
239 import string
240 while not '\n' in self.buf:
241 new = self.sock.recv(0x7fffffff)
242 if not new:
243 break
244 self.buf = self.buf + new
245 if not '\n' in self.buf:
246 rv = self.buf
247 self.buf = ''
248 else:
249 i = string.index(self.buf, '\n')
250 rv = self.buf[:i+1]
251 self.buf = self.buf[i+1:]
252 return rv
254 def readlines(self):
255 list = []
256 line = self.readline()
257 while line:
258 list.append(line)
259 line = self.readline()
260 return list
262 def write(self, buf):
263 BS = self.bs
264 if len(buf) >= BS:
265 self.flush()
266 self.sock.send(buf)
267 elif len(buf) + len(self.buf) >= BS:
268 self.flush()
269 self.buf = buf
270 else:
271 self.buf = self.buf + buf
273 def writelines(self, list):
274 for line in list:
275 self.write(line)
277 def flush(self):
278 if self.buf and self.rw == 'w':
279 self.sock.send(self.buf)
280 self.buf = ''
282 def close(self):
283 self.flush()
284 ##self.sock.close()
285 del self.sock
288 def __test_tcp():
289 s = socket(AF_INET, SOCK_STREAM)
290 s.connect('poseidon.cwi.nl', 13)
291 rv = s.recv(1000)
292 print 'Time/date:', rv
293 rv = s.recv(1000)
294 if rv:
295 print 'Unexpected extra data:', rv
296 s.close()
299 def __test_udp():
300 s = socket(AF_INET, SOCK_DGRAM)
301 print 'Sending data... (hello world)'
302 s.sendto(('poseidon.cwi.nl', 7), 'hello world')
303 rv, host = s.recvfrom(1000)
304 print 'Got from ', host, ':', rv