Пример #1
0
    def close(self):
        if getattr(self, 'socket', None) is not None:
            asocket.close(self)

        if self.callback is not None:
            self.callback, cb = None, self.callback
            cb.error()
Пример #2
0
    def __init__(self, proxy, conn, post):
        asocket.__init__(self, conn)

        self.callback = None
        self.post_negotiate = post
        self._negotiating = False
        if proxy is None:
            proxy = {}
        self._proxyinfo = proxy.copy()
        self.mid = (self._proxyinfo.get('addr', ''), self._proxyinfo.get('port',0))
        self.end = ('',0)
Пример #3
0
 def __init__(self, *a, **k):
     asocket.__init__(self, *a, **k)
     self.set_terminator('\r\n\r\n')
     self.push('HEAD / HTTP/1.0\r\n\r\n')
     self.push_handler(lambda d: log.info(repr(d)))
Пример #4
0
    def __repr__(self):
        parentrepr = asocket.__repr__(self).strip('<>')

        return '<%s, fileno=%r>' % (parentrepr, self._fileno)
Пример #5
0
 def handle_close(self):
     log.info('ProxySocket.handle_close - calling callback.error')
     self.close()
     asocket.handle_close(self)
Пример #6
0
 def _pconnect(self):
     asocket.connect(self, self.mid)
Пример #7
0
 def _connectRealSocket(self):
     self.sock = AsyncSocket(self.asyncSocketManager)
     self.sock.connect((self.ip, self.port))
     self.sockNum = self.sock.fileno()
     self.realSockStatus.addConn(self.sockNum, self.destId)
     self.realSockStatus.setWantsToSend(True, self.sockNum)
Пример #8
0
class SamBaseDestination:
    def __init__(self, destId, asyncSocketManager, realSockStatus, log, ip, port,
                 sessionName, sessionType, sessionDirection, sessionOptions):
        self.destId = destId
        self.asyncSocketManager = asyncSocketManager
        self.realSockStatus = realSockStatus
        self.log = log
        
        #session - stats
        self.sessionName = sessionName
        self.sessionType = sessionType
        self.sessionDirection = sessionDirection
        self.sessionOptions = sessionOptions
        
        #session - state
        self.sessionEstablished = False
        self.sessionKey = None
        
        #socket
        self.sock = None
        self.sockNum = None
        self.ip = ip
        self.port = port
        self.connected = False
        self.inMessage = None
        self.inQueue = deque()
        self.outQueue = deque()
        
        self._connectRealSocket()
        
    
    ##internal functions - socket
    
    def _connectRealSocket(self):
        self.sock = AsyncSocket(self.asyncSocketManager)
        self.sock.connect((self.ip, self.port))
        self.sockNum = self.sock.fileno()
        self.realSockStatus.addConn(self.sockNum, self.destId)
        self.realSockStatus.setWantsToSend(True, self.sockNum)
        
        
    def _closeRealSocket(self):
        self.inMessage = None
        self.outQueue.clear()
        self.realSockStatus.removeConn(self.sockNum)
        self.connected = False
        self.sock.close()
        self.sock = None
        
        
    def _reconnectRealSocket(self):
        self._closeRealSocket()
        self._connectRealSocket()
        
    
    def _sendOverRealSocket(self, data):
        self.outQueue.append(data)
        if len(self.outQueue) == 1:
            #first message in buffer, add to sockets with send interest
            self.realSockStatus.setWantsToSend(True, self.sockNum)

        if self.log is not None:
            self.log.debug("Send Message: \"%s\"", data.split('\n')[0])
            
            
    ##internal functions - destinations
    
    def _establishedDestination(self):
        pass
    
    
    def _failDestination(self, reason):
        self.sessionKey = None
        self.sessionEstablished = False
        self._reconnectRealSocket()
        
        
    def _removeDestination(self):
        self._closeRealSocket()
        
    
    ##internal functions - messages
    
    def _handleCustomMessage(self, message):
        if self.log is not None:
            self.log.warn("Received unknown message from Sam bridge: \"%s\"", str(message))
            
            
    def _handleNameLookup(self, message):
        pass
    
    
    def _handleMessages(self, messages):
        for message in messages:
            messageType = message['msgType']
            messageParas = message['msgParas']
            
            if messageType=='HELLO REPLY':
                #handshake reply
                if messageParas['RESULT'].upper()=='OK' and messageParas['VERSION']=='2.0':
                    #send session create message
                    assert len(self.outQueue)==0, "just handshaked and stuff to send?!"
                    self._sendOverRealSocket(SamMessages.sessionCreateMessage(self.sessionType, self.sessionName, self.sessionDirection, self.sessionOptions))
                else:
                    #something borked
                    self._failDestination('Invalid HELLO REPLY: Result<%s> Version<%s>' % (messageParas['RESULT'], messageParas['VERSION']))
                
            elif messageType=='SESSION STATUS':
                #session established
                if not messageParas['RESULT'].upper()=='OK':
                    #urgh
                    self._failDestination('Failed to setup session: "%s"' % (messageParas['RESULT'],))
                else:
                    #ok, session is established
                    self.sessionEstablished = True
                    self._sendOverRealSocket('NAMING LOOKUP NAME=ME\n')
                    self._establishedDestination()
                    
            elif messageType=='NAMING REPLY':
                #reply to destination request
                if not messageParas['NAME'].upper() == 'ME': 
                    self._handleNameLookup(message)
                elif messageParas['RESULT'].upper() == 'OK':
                        self.sessionKey = messageParas['VALUE']
                    
            else:
                self._handleCustomMessage(message)
                    
            
    ##external functions - socket events
    
    def errorEvent(self):
        self._failDestination('Connection to SAM failed')
        
        
    def sendEvent(self):
        if not self.connected:
            #connected, send handshake as soon as possible
            self.connected = True
            self.realSockStatus.setWantsToRecv(True, self.sockNum)
            self.realSockStatus.setWantsToSend(False, self.sockNum)
            self._sendOverRealSocket("HELLO VERSION MIN=2.0 MAX=2.0\n")
            
            
        else:
            #already connected, send data
            assert len(self.outQueue) > 0, 'Empty outbuffer, but trying to send?!'
            
            while len(self.outQueue) > 0:
                #still something in the queue, try to send the next message
                data = self.outQueue.popleft()
                bytesSend = self.sock.send(data)
                if bytesSend < len(data):
                    #not all data send, push remaining data back into queue and abort loop
                    self.outQueue.appendleft(data[bytesSend:])
                    break
                    
            if len(self.outQueue) == 0:
                #managed to empty the queue, nothing to send anymore
                self.realSockStatus.setWantsToSend(False, self.sockNum)
                
                
    def recvEvent(self):
        data = self.sock.recv()
        dataLen = len(data)
        messages = []
        offset = 0
        
        #process data
        while not offset >= dataLen:
            #loop until all received data was processed
            if self.inMessage is None:
                ##there is no finished message that needs bulk data
                endOfMessage = data.find('\n', offset)
                if endOfMessage == -1:
                    #only the beginning of a message, store it in the inbound queue
                    self.inQueue.append(data[offset:])
                    offset = dataLen
                    
                else:
                    #the whole message or the ending
                    message = data[offset:endOfMessage]
                    offset = endOfMessage + 1
                    if len(self.inQueue) > 0:
                        #get the beginning of the message out of the queue
                        self.inQueue.append(message)
                        message = ''.join(self.inQueue)
                        self.inQueue.clear()
                    
                    #parse message
                    if self.log is not None:
                        self.log.debug("Got Message: \"%s\"", message)
                    message = SamMessages.parseMessage(message)
                        
                    #check if we need to wait for more data
                    if 'SIZE' in message['msgParas']:
                        message['Data'] = []
                        message['DataCurrentLen'] = 0
                        message['DataTargetLen'] = int(message['msgParas']['SIZE'])
                        self.inMessage = message
                    else:
                        messages.append(message)
            else:
                ##only missing a few bytes here ...
                assert len(self.inQueue) == 0, 'receiving data but stuff in the inqueue?!'
                missingBytes = self.inMessage['DataTargetLen'] - self.inMessage['DataCurrentLen']
                remainingBytes = dataLen - offset
                if remainingBytes >= missingBytes:
                    #got all
                    if self.log is not None:
                        self.log.debug("Got missing %i bytes for message", missingBytes)
                    self.inMessage['Data'].append(data[offset:offset+missingBytes])
                    self.inMessage['DataCurrentLen'] += missingBytes
                    assert self.inMessage['DataCurrentLen'] == self.inMessage['DataTargetLen'], 'message finished but too short?!'
                    offset += missingBytes
                    messages.append(self.inMessage)
                    self.inMessage = None
                
                else:
                    #still missing a bit
                    if self.log is not None:
                        self.log.debug("Got %i bytes for message but still missing %i bytes", remainingBytes, (missingBytes - remainingBytes))
                    self.inMessage['Data'].append(data[offset:])
                    self.inMessage['DataCurrentLen'] += remainingBytes
                    offset += remainingBytes        
        
        #handle messages
        self._handleMessages(messages)
        
        
    ##external functions - destination
    
    def getOwnDestination(self):
        return self.sessionKey
    
    
    def shutdown(self):
        self._removeDestination()
        
        
    ##external functions - changing settings
    
    def changeSessionAddress(self, ip=None, port=None, reconnect=False):
        if ip is not None:
            self.ip = ip
            
        if port is not None:
            self.port = port
            
        if reconnect:
            self._failDestination('SESSION_ADDR_CHANGE')
        
        
    def changeSessionName(self, sessionName, reconnect=False):
        self.sessionName = sessionName
        if reconnect:
            self._failDestination('SESSION_NAME_CHANGE')
        
       
    def changeSessionOption(self, option, value, reconnect=False):
        self.sessionOptions[option] = value
        if reconnect:
            self._failDestination('SESSION_OPTION_CHANGE')
        
        
    def removeSessionOption(self, option, reconnect=False):
        del self.sessionOptions[option]
        if reconnect:
            self._failDestination('SESSION_OPTION_CHANGE')
        
        
    def replaceSessionOptions(self, sessionOptions, reconnect=False):
        self.sessionOptions = sessionOptions
        if reconnect:
            self._failDestination('SESSION_OPTION_CHANGE')