mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			304 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """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
 | 
