### py_interface -- A Python-implementation of an Erlang node
###
### $Id: erl_async_conn.py,v 1.9 2002/05/28 22:08:41 tab Exp $
###
### Copyright (C) 2002 Tomas Abrahamsson
###
### Author: Tomas Abrahamsson <tab@lysator.liu.se>
###
### This file is part of the Py-Interface library
###
### This library is free software; you can redistribute it and/or
### modify it under the terms of the GNU Library General Public
### License as published by the Free Software Foundation; either
### version 2 of the License, or (at your option) any later version.
###
### This library is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
### Library General Public License for more details.
###
### You should have received a copy of the GNU Library General Public
### License along with this library; if not, write to the Free
### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
### erl_async_conn.py -- general async communication over tcp/ip
import socket
try:
import SOCKET
except ImportError:
SOCKET = socket
import erl_common
import erl_eventhandler
class ErlAsyncPeerConnection:
def __init__(self, openSocket=None):
self.evhandler = erl_eventhandler.GetEventHandler()
if openSocket == None:
self._Init()
else:
self._Init()
self._SetConnectionOpen(openSocket)
def Close(self):
if not self._isConnected:
return
self._SetConnectionClosed()
def Send(self, data):
self._SendOrQueue(data)
def GetConnection(self):
if not self._isConnected:
return None
else:
return self._connection
##
## Internal routines
##
def _Init(self):
self._isConnected = 0
self._pendingOutput = ""
def _SetConnectionClosed(self):
if self._isConnected:
self.evhandler.PopReadEvent(self._connection)
self._connection.close()
self._connection = None
self._isConnected = 0
self._Init()
def _SetConnectionOpen(self, sock):
if not self._isConnected:
self._connection = sock
self._isConnected = 1
self.evhandler.PushReadEvent(self._connection, self._In)
def _SendOrQueue(self, data):
numBytesToSend = len(data)
try:
numBytesSent = self._connection.send(data)
if numBytesSent < numBytesToSend:
remaining = data[numBytesSent:]
self._Queue(remaining)
except socket.error, (errNum, errText):
if errNum == 11:
self._Queue(data)
else:
raise
def _Queue(self, strToQueue):
if self._pendingOutput == "":
self.evhandler.PushWriteEvent(self._connection, self._QueuedWrite)
self._pendingOutput = self._pendingOutput + strToQueue
def _QueuedWrite(self):
numBytesToSend = len(self._pendingOutput)
try:
numBytesSent = self._connection.send(erlStr)
if numBytesSent == numBytesToSend:
self._pendingOutput = ""
self.evhandler.PopWriteEvent(self._connection)
else:
self._pendingOutput = self._pendingOutput[numBytesSent:]
except socket.error, (errNum, errText):
if errNum == 11:
# still not possible to send...
# wait a bit more
pass
def _In(self):
print "erl_sync_conn: please override me!"
newData = self._connection.recv(10000)
def ReadInt1(self, s):
return erl_common.ReadInt1(s)
def ReadInt2(self, s):
return erl_common.ReadInt2(s)
def ReadInt4(self, s):
return erl_common.ReadInt4(s)
def PackInt1(self, i):
return erl_common.PackInt1(i)
def PackInt2(self, i):
return erl_common.PackInt2(i)
def PackInt4(self, i):
return erl_common.PackInt4(i)
class ErlAsyncClientConnection(ErlAsyncPeerConnection):
def __init__(self):
ErlAsyncPeerConnection.__init__(self)
def Connect(self, hostname, portNum):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((hostname, portNum))
s.setblocking(0)
self.hostname = hostname
self.portNum = portNum
self._SetConnectionOpen(s)
return 1
except socket.error, errInfo:
print "socket error:", errInfo
self._SetConnectionClosed()
return 0
class ErlAsyncServer(ErlAsyncPeerConnection):
def __init__(self):
ErlAsyncPeerConnection.__init__(self)
def Start(self, portNum=0, iface=""):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.setsockopt(SOCKET.SOL_SOCKET, SOCKET.SO_REUSEADDR, 1)
s.bind((iface, portNum))
(ipNum, resultPortNum) = s.getsockname()
s.listen(5)
s.setblocking(0)
self.hostname = iface
self.portNum = resultPortNum
self._SetConnectionOpen(s)
return resultPortNum
except socket.error, errInfo:
print "socket error:", errInfo
return None
def _In(self):
s = self.GetConnection()
(s2, (remoteHost, remotePort)) = s.accept()
self._NewConnection(s2, (remoteHost, remotePort))
def _NewConnection(self, sockConn, remoteAddr):
asyncConnection = ErlAsyncPeerConnection(s2)
pass
syntax highlighted by Code2HTML, v. 0.9.1