home *** CD-ROM | disk | FTP | other *** search
- """socket.py for mac - Emulate socket module with mactcp and macdnr
-
- Currently only implements TCP sockets (AF_INET, SOCK_STREAM).
- Esoteric things like socket options don't work,
- but getpeername() and makefile() do work; everything used by ftplib works!
- """
-
- # Jack Jansen, CWI, November 1994 (initial version)
- # Guido van Rossum, CWI, March 1995 (bug fixes and lay-out)
-
-
- import mactcp
- import MACTCPconst
- import macdnr
-
-
- # Exported constants
-
- _myerror = 'socket_wrapper.error'
- error = (mactcp.error, macdnr.error, _myerror)
-
- SOCK_DGRAM = 1
- SOCK_STREAM = 2
-
- AF_INET = 1
-
-
- # Internal constants
-
- _BUFSIZE = 15*1024 # Size of TCP/UDP input buffer
-
- _myaddress = None
- _myname = None
- _myaddrstr = None
-
-
- def _myipaddress():
- global _myaddress
- if _myaddress == None:
- _myaddress = mactcp.IPAddr()
- return _myaddress
-
-
- def _ipaddress(str):
- if type(str) == type(1):
- return str # Already numeric
- ptr = macdnr.StrToAddr(str)
- ptr.wait()
- return ptr.ip0
-
-
- def gethostbyname(str):
- id = _ipaddress(str)
- return macdnr.AddrToStr(id)
-
-
- def gethostbyaddr(str):
- id = _ipaddress(str)
- ptr = macdnr.AddrToName(id)
- ptr.wait()
- name = ptr.cname
- if name[-1:] == '.': name = name[:-1]
- names, addresses = [], [str]
- return name, names, addresses
-
- def gethostname():
- global _myname
- if _myname == None:
- id = _myipaddress()
- ptr = macdnr.AddrToName(id)
- ptr.wait()
- _myname = ptr.cname
- return _myname
-
-
- def _gethostaddress():
- global _myaddrstr
- if _myaddrstr == None:
- id = _myipaddress()
- _myaddrstr = macdnr.AddrToStr(id)
- return _myaddrstr
-
-
- def socket(family, type, *which):
- if family <> AF_INET:
- raise _myerror, 'Protocol family %d not supported' % type
- if type == SOCK_DGRAM:
- return _udpsocket()
- elif type == SOCK_STREAM:
- return _tcpsocket()
- raise _myerror, 'Protocol type %d not supported' % type
-
-
- def fromfd(*args):
- raise _myerror, 'Operation not supported on a mac'
-
-
- class _socket:
- def unsupported(self, *args):
- raise _myerror, 'Operation not supported on this socket'
-
- accept = unsupported
- bind = unsupported
- close = unsupported
- connect = unsupported
- fileno = unsupported
- getpeername = unsupported
- getsockname = unsupported
- getsockopt = unsupported
- listen = unsupported
- recv = unsupported
- recvfrom = unsupported
- send = unsupported
- sendto = unsupported
- setblocking = unsupported
- setsockopt = unsupported
- shutdown = unsupported
-
-
- class _tcpsocket(_socket):
-
- def __init__(self):
- self.stream = mactcp.TCPCreate(_BUFSIZE)
- ##self.stream.asr = self.asr
- self.databuf = ''
- self.udatabuf = ''
- self.port = 0
- self.accepted = 0
- self.listening = 0
-
- def accept(self):
- if not self.listening:
- raise _myerror, 'Not listening'
- self.listening = 0
- self.stream.wait()
- self.accepted = 1
- return self, self.getsockname()
-
- # bind has two ways of calling: s.bind(host, port) or s.bind((host, port));
- # the latter is more proper but the former more common
- def bind(self, a1, a2=None):
- if a2 is None:
- host, port = a1
- else:
- host, port = a1, a2
- self.port = port
-
- def close(self):
- if self.accepted:
- self.accepted = 0
- return
- self.stream.Abort()
-
- # connect has the same problem as bind (see above)
- def connect(self, a1, a2=None):
- if a2 is None:
- host, port = a1
- else:
- host, port = a1, a2
- self.stream.ActiveOpen(self.port, _ipaddress(host), port)
-
- def getsockname(self):
- host, port = self.stream.GetSockName()
- host = macdnr.AddrToStr(host)
- return host, port
-
- def getpeername(self):
- st = self.stream.Status()
- host = macdnr.AddrToStr(st.remoteHost)
- return host, st.remotePort
-
- def listen(self, backlog):
- self.stream.PassiveOpen(self.port)
- self.listening = 1
-
- def makefile(self, rw = 'r', bs = 512):
- return _socketfile(self, rw, bs)
-
- def recv(self, bufsize, flags=0):
- if flags:
- raise _myerror, 'recv flags not yet supported on mac'
- if not self.databuf:
- try:
- self.databuf, urg, mark = self.stream.Rcv(0)
- except mactcp.error, arg:
- if arg[0] != MACTCPconst.connectionClosing:
- raise mactcp.error, arg
- rv = self.databuf[:bufsize]
- self.databuf = self.databuf[bufsize:]
- return rv
-
- def send(self, buf):
- self.stream.Send(buf)
- return len(buf)
-
- def shutdown(self, how):
- if how == 0:
- return
- self.stream.Close()
-
- def bytes_readable(self):
- st = self.stream.Status()
- return st.amtUnreadData
-
- def bytes_writeable(self):
- st = self.stream.Status()
- return st.sendWindow - st.sendUnacked;
-
-
- class _udpsocket(_socket):
-
- def __init__(self):
- pass
-
-
- class _socketfile:
-
- def __init__(self, sock, rw, bs):
- if rw[1:] == 'b': rw = rw[:1]
- if rw not in ('r', 'w'): raise _myerror, "mode must be 'r' or 'w'"
- self.sock = sock
- self.rw = rw
- self.bs = bs
- self.buf = ''
-
- def read(self, length = -1):
- if length < 0:
- length = 0x7fffffff
- while len(self.buf) < length:
- new = self.sock.recv(0x7fffffff)
- if not new:
- break
- self.buf = self.buf + new
- rv = self.buf[:length]
- self.buf = self.buf[length:]
- return rv
-
- def readline(self):
- import string
- while not '\n' in self.buf:
- new = self.sock.recv(0x7fffffff)
- if not new:
- break
- self.buf = self.buf + new
- if not '\n' in self.buf:
- rv = self.buf
- self.buf = ''
- else:
- i = string.index(self.buf, '\n')
- rv = self.buf[:i+1]
- self.buf = self.buf[i+1:]
- return rv
-
- def readlines(self):
- list = []
- line = self.readline()
- while line:
- list.append(line)
- line = self.readline()
- return list
-
- def write(self, buf):
- BS = self.bs
- if len(buf) >= BS:
- self.flush()
- self.sock.send(buf)
- elif len(buf) + len(self.buf) >= BS:
- self.flush()
- self.buf = buf
- else:
- self.buf = self.buf + buf
-
- def writelines(self, list):
- for line in list:
- self.write(line)
-
- def flush(self):
- if self.buf and self.rw == 'w':
- self.sock.send(self.buf)
- self.buf = ''
-
- def close(self):
- self.flush()
- ##self.sock.close()
- del self.sock
-
-
- def __test_tcp():
- s = socket(AF_INET, SOCK_STREAM)
- s.connect('poseidon.cwi.nl', 13)
- rv = s.recv(1000)
- print 'Time/date:', rv
- rv = s.recv(1000)
- if rv:
- print 'Unexpected extra data:', rv
- s.close()
-
-
- def __test_udp():
- s = socket(AF_INET, SOCK_DGRAM)
- print 'Sending data... (hello world)'
- s.sendto(('poseidon.cwi.nl', 7), 'hello world')
- rv, host = s.recvfrom(1000)
- print 'Got from ', host, ':', rv
-