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!
8 # Jack Jansen, CWI, November 1994 (initial version)
9 # Guido van Rossum, CWI, March 1995 (bug fixes and lay-out)
19 _myerror
= 'socket_wrapper.error'
20 error
= (mactcp
.error
, macdnr
.error
, _myerror
)
30 _BUFSIZE
= 15*1024 # Size of TCP/UDP input buffer
39 if _myaddress
== None:
40 _myaddress
= mactcp
.IPAddr()
45 if type(str) == type(1):
46 return str # Already numeric
47 ptr
= macdnr
.StrToAddr(str)
52 def gethostbyname(str):
54 return macdnr
.AddrToStr(id)
61 ptr
= macdnr
.AddrToName(id)
67 def _gethostaddress():
69 if _myaddrstr
== None:
71 _myaddrstr
= macdnr
.AddrToStr(id)
75 def socket(family
, type, *which
):
77 raise _myerror
, 'Protocol family %d not supported' % type
78 if type == SOCK_DGRAM
:
80 elif type == SOCK_STREAM
:
82 raise _myerror
, 'Protocol type %d not supported' % type
86 raise _myerror
, 'Operation not supported on a mac'
90 def unsupported(self
, *args
):
91 raise _myerror
, 'Operation not supported on this socket'
98 getpeername
= unsupported
99 getsockname
= unsupported
100 getsockopt
= unsupported
103 recvfrom
= unsupported
106 setblocking
= unsupported
107 setsockopt
= unsupported
108 shutdown
= unsupported
111 class _tcpsocket(_socket
):
114 self
.stream
= mactcp
.TCPCreate(_BUFSIZE
)
115 ##self.stream.asr = self.asr
123 if not self
.listening
:
124 raise _myerror
, 'Not listening'
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):
145 # connect has the same problem as bind (see above)
146 def connect(self
, a1
, a2
=None):
151 self
.stream
.ActiveOpen(self
.port
, _ipaddress(host
), port
)
153 def getsockname(self
):
154 host
, port
= self
.stream
.GetSockName()
155 host
= macdnr
.AddrToStr(host
)
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
)
167 def makefile(self
, rw
= 'r'):
168 return _socketfile(self
, rw
)
170 def recv(self
, bufsize
, flags
=0):
172 raise _myerror
, 'recv flags not yet supported on mac'
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
:]
184 self
.stream
.Send(buf
)
187 def shutdown(self
, how
):
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
):
209 def __init__(self
, sock
, rw
):
210 if rw
not in ('r', 'w'): raise _myerror
, "mode must be 'r' or 'w'"
215 def read(self
, length
= 0):
218 while len(self
.buf
) < length
:
219 new
= self
.sock
.recv(0x7fffffff)
222 self
.buf
= self
.buf
+ new
223 rv
= self
.buf
[:length
]
224 self
.buf
= self
.buf
[length
:]
229 while not '\n' in self
.buf
:
230 new
= self
.sock
.recv(0x7fffffff)
233 self
.buf
= self
.buf
+ new
234 if not '\n' in self
.buf
:
238 i
= string
.index(self
.buf
, '\n')
240 self
.buf
= self
.buf
[i
+1:]
243 def write(self
, buf
):
248 elif len(buf
) + len(self
.buf
) >= BS
:
252 self
.buf
= self
.buf
+ buf
255 if self
.buf
and self
.rw
== 'w':
256 self
.sock
.send(self
.buf
)
266 s
= socket(AF_INET
, SOCK_STREAM
)
267 s
.connect('poseidon.cwi.nl', 13)
269 print 'Time/date:', rv
272 print 'Unexpected extra data:', rv
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