def process_chunk(self, data):
     """
     Generic message dispatcher for IPA (sub)protocols based on protocol name, lambda default should never happen
     """
     (_, proto, extension, content) = IPA().del_header(data)
     if content is not None:
         self.dbg('IPA received %s::%s [%d/%d] %s' % (IPA().proto(proto), IPA().ext_name(proto, extension), len(data), len(content), content))
         method = getattr(self, 'handle_' + IPA().proto(proto), lambda: "protocol dispatch failure")
         method(content, proto, extension)
Exemplo n.º 2
0
    def recv_msgs(self):
        responses = {}
        data = self.sock.recv(4096)
        while (len(data) > 0):
            (head, data) = IPA().split_combined(data)
            answer = Ctrl().rem_header(head)
            if verbose:
                print "Got message:", answer
            (mtype, id, msg) = answer.split(None, 2)
            id = int(id)
            rsp = {'mtype': mtype, 'id': id}
            if mtype == "ERROR":
                rsp['error'] = msg
            else:
                split = msg.split(None, 1)
                rsp['var'] = split[0]
                if len(split) > 1:
                    rsp['value'] = split[1]
                else:
                    rsp['value'] = None
            responses[id] = rsp

        if verbose:
            print "Decoded replies: ", responses

        return responses
class IPAFactory(ReconnectingClientFactory):
    """
    Generic IPA Client Factory which can be used to store state for various subprotocols and manage connections
    Note: so far we do not really need separate Factory for acting as a server due to protocol simplicity
    """
    protocol = IPACommon
    log = None
    ccm_id = IPA().identity(unit=b'1515/0/1', mac=b'b0:0b:fa:ce:de:ad:be:ef', utype=b'sysmoBTS', name=b'StingRay', location=b'hell', sw=IPA.version.encode('utf-8'))

    def __init__(self, proto=None, log=None, ccm_id=None):
        if proto:
            self.protocol = proto
        if ccm_id:
            self.ccm_id = ccm_id
        if log:
            self.log = log
        else:
            self.log = logging.getLogger('IPAFactory')
            self.log.setLevel(logging.CRITICAL)
            self.log.addHandler(logging.NullHandler)

    def clientConnectionFailed(self, connector, reason):
        """
        Only necessary for as debugging aid - if we can somehow set parent's class noisy attribute then we can omit this method
        """
        self.log.warning('IPAFactory connection failed: %s' % reason.getErrorMessage())
        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

    def clientConnectionLost(self, connector, reason):
        """
        Only necessary for as debugging aid - if we can somehow set parent's class noisy attribute then we can omit this method
        """
        self.log.warning('IPAFactory connection lost: %s' % reason.getErrorMessage())
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
Exemplo n.º 4
0
 def receive(self):
     responses = []
     data = self.socket.recv(4096)
     while (len(data)>0):
         (response_with_header, data) = IPA().split_combined(data)
         response = Ctrl().rem_header(response_with_header)
         responses.append(response.decode('utf-8'))
     return responses
 def connectionMade(self):
     """
     Keep reconnection logic working by calling routine from CCM
     Initiate CCM upon connection
     """
     addr = self.transport.getPeer()
     self.factory.log.info('IPA server: connection from %s:%d client' % (addr.host, addr.port))
     super(IPAServer, self).connectionMade()
     self.transport.write(IPA().id_get())
 def dataReceived(self, data):
     """
     Override for dataReceived from Int16StringReceiver because of inherently incompatible interpretation of length
     If default handler is used than we would always get off-by-1 error (Int16StringReceiver use equivalent of l + 2)
     """
     if len(data):
         (head, tail) = IPA().split_combined(data)
         self.process_chunk(head)
         self.dataReceived(tail)
def ipa_handle_small(x, verbose=False):
    s = data2str(x.recv(4))
    if len(s) != 4 * 2:
        raise Exception("expected to receive 4 bytes, but got %d (%r)" %
                        (len(s) / 2, s))
    if "0001fe00" == s:
        if (verbose):
            print "\tBSC <- NAT: PING?"
        x.send(IPA().pong())
    elif "0001fe06" == s:
        if (verbose):
            print "\tBSC <- NAT: IPA ID ACK"
        x.send(IPA().id_ack())
    elif "0001fe00" == s:
        if (verbose):
            print "\tBSC <- NAT: PONG!"
    else:
        if (verbose):
            print "\tBSC <- NAT: ", s
def ipa_handle_resp(x, tk, verbose=False, proc=None):
    s = data2str(x.recv(38))
    if "0023fe040108010701020103010401050101010011" in s:
        retries = 3
        while True:
            print "\tsending IPA identity(%s) at %s" % (tk,
                                                        time.strftime("%T"))
            try:
                x.send(IPA().id_resp(IPA().identity(name=tk.encode('utf-8'))))
                print "\tdone sending IPA identity(%s) at %s" % (
                    tk, time.strftime("%T"))
                break
            except:
                print "\tfailed sending IPA identity at", time.strftime("%T")
                if proc:
                    print "\tproc.poll() = %r" % proc.poll()
                if retries < 1:
                    print "\tgiving up"
                    raise
                print "\tretrying (%d attempts left)" % retries
                retries -= 1
    else:
        if (verbose):
            print "\tBSC <- NAT: ", s
 def handle_CCM(self, data, proto, msgt):
     """
     CCM (IPA Connection Management)
     Only basic logic necessary for tests is implemented (ping-pong, id ack etc)
     """
     if msgt == IPA.MSGT['ID_GET']:
         self.transport.getHandle().sendall(IPA().id_resp(self.factory.ccm_id))
         # if we call
         # self.transport.write(IPA().id_resp(self.factory.test_id))
         # instead, than we would have to also call
         # reactor.callLater(1, self.ack)
         # instead of self.ack()
         # otherwise the writes will be glued together - hence the necessity for ugly hack with 1s timeout
         # Note: this still might work depending on the IPA implementation details on the other side
         self.ack()
         # schedule PING in 4s
         reactor.callLater(4, self.ping)
     if msgt == IPA.MSGT['PING']:
         self.pong()
Exemplo n.º 10
0
 def pong(self):
     self.transport.write(IPA().pong())
Exemplo n.º 11
0
 def ack(self):
     self.transport.write(IPA().id_ack())
Exemplo n.º 12
0
 def handle_UNKNOWN(self, data, proto, extension):
     """
     Default protocol handler
     """
     self.dbg('IPA received message for %s (%s) protocol with attribute %s' % (IPA().proto(proto), proto, extension))
Exemplo n.º 13
0
 def handle_OSMO(self, data, proto, extension):
     """
     Dispatcher point for OSMO subprotocols based on extension name, lambda default should never happen
     """
     method = getattr(self, 'osmo_' + IPA().ext(extension), lambda: "extension dispatch failure")
     method(data)