def __init__(self, config, msgHandler=None): self.reconnectTimer = None self.smpp = None self.connectionRetry = True self.config = config # Setup statistics collector self.stats = SMPPClientStatsCollector().get(cid=self.config.id) self.stats.set('created_at', datetime.now()) # Set up a dedicated logger self.log = logging.getLogger(LOG_CATEGORY_CLIENT_BASE + ".%s" % config.id) if len(self.log.handlers) != 1: self.log.setLevel(self.config.log_level) _when = self.config.log_rotate if hasattr( self.config, 'log_rotate') else 'midnight' if 'stdout' in self.config.log_file: handler = logging.StreamHandler(sys.stdout) else: handler = TimedRotatingFileHandler( filename=self.config.log_file, when=_when) formatter = logging.Formatter(self.config.log_format, self.config.log_date_format) handler.setFormatter(formatter) self.log.addHandler(handler) self.log.propagate = False if msgHandler is None: self.msgHandler = self.msgHandlerStub else: self.msgHandler = msgHandler
def smppcs(self, arg, opts): sc = SMPPClientStatsCollector() headers = ["#Connector id", "Connected at", "Bound at", "Disconnected at", "Submits", "Delivers", "QoS errs", "Other errs"] table = [] connectors = self.pb['smppcm'].perspective_connector_list() for connector in connectors: row = [] row.append('#%s' % connector['id']) row.append(formatDateTime(sc.get(connector['id']).get('connected_at'))) row.append(formatDateTime(sc.get(connector['id']).get('bound_at'))) row.append(formatDateTime(sc.get(connector['id']).get('disconnected_at'))) row.append('%s/%s' % ( sc.get(connector['id']).get('submit_sm_request_count'), sc.get(connector['id']).get('submit_sm_count'))) row.append('%s/%s' % ( sc.get(connector['id']).get('deliver_sm_count'), sc.get(connector['id']).get('data_sm_count'))) row.append(sc.get(connector['id']).get('throttling_error_count')) row.append(sc.get(connector['id']).get('other_submit_error_count')) table.append(row) self.protocol.sendData( tabulate(table, headers, tablefmt="plain", numalign="left").encode('ascii'), prompt=False) self.protocol.sendData('Total connectors: %s' % (len(table)))
def test_get_will_reuse_existent_connector(self): c = SMPPClientStatsCollector() self.assertTrue('test_get_will_reuse_existent_connector' not in c.connectors) i1 = c.get(cid = 'test_get_will_reuse_existent_connector') i2 = c.get(cid = 'test_get_will_reuse_existent_connector') self.assertEqual(i1, i2)
def test_exceptions(self): stats = SMPPClientStatsCollector().get(cid = 'test_exceptions') self.assertRaises(KeyNotFound, stats.get, 'anything') self.assertRaises(KeyNotFound, stats.set, 'anything', 22) self.assertRaises(KeyNotFound, stats.inc, 'anything') stats.set('created_at', datetime.now()) self.assertRaises(KeyNotIncrementable, stats.inc, 'created_at')
def test_stats_inc(self): stats = SMPPClientStatsCollector().get(cid = 'test_stats_inc') self.assertEqual(stats.get('bound_count'), 0) stats.inc('bound_count') self.assertEqual(stats.get('bound_count'), 1) stats.inc('bound_count', 5) self.assertEqual(stats.get('bound_count'), 6)
def smppcs(self, arg, opts): sc = SMPPClientStatsCollector() headers = [ "#Connector id", "Bound count", "Connected at", "Bound at", "Disconnected at", "Sent elink at", "Received elink at" ] table = [] connectors = self.pb['smppcm'].perspective_connector_list() for connector in connectors: row = [] row.append('#%s' % connector['id']) row.append(sc.get(connector['id']).get('bound_count')) row.append( formatDateTime(sc.get(connector['id']).get('connected_at'))) row.append(formatDateTime(sc.get(connector['id']).get('bound_at'))) row.append( formatDateTime(sc.get(connector['id']).get('disconnected_at'))) row.append( formatDateTime( sc.get(connector['id']).get('last_sent_elink_at'))) row.append( formatDateTime( sc.get(connector['id']).get('last_received_elink_at'))) table.append(row) self.protocol.sendData(tabulate(table, headers, tablefmt="plain", numalign="left").encode('ascii'), prompt=False) self.protocol.sendData('Total connectors: %s' % (len(table)))
def test_stats(self): stats = SMPPClientStatsCollector().get(cid='test_stats') self.assertEqual( stats._stats, { 'bound_at': 0, 'bound_count': 0, 'connected_at': 0, 'connected_count': 0, 'created_at': 0, 'data_sm_count': 0, 'deliver_sm_count': 0, 'disconnected_at': 0, 'disconnected_count': 0, 'elink_count': 0, 'interceptor_count': 0, 'interceptor_error_count': 0, 'last_received_elink_at': 0, 'last_received_pdu_at': 0, 'last_sent_elink_at': 0, 'last_sent_pdu_at': 0, 'last_seqNum': None, 'last_seqNum_at': 0, 'other_submit_error_count': 0, 'submit_sm_count': 0, 'submit_sm_request_count': 0, 'throttling_error_count': 0, })
def smppc(self, arg, opts): sc = SMPPClientStatsCollector() headers = ["#Item", "Value"] table = [] for k, v in sc.get(opts.smppc)._stats.iteritems(): row = [] row.append('#%s' % k) if k[-3:] == '_at': row.append(formatDateTime(v)) else: row.append(v) table.append(row) self.protocol.sendData(tabulate(table, headers, tablefmt = "plain", numalign = "left").encode('ascii'))
def smppc(self, arg, opts): sc = SMPPClientStatsCollector() headers = ["#Item", "Value"] table = [] for k, v in sc.get(opts.smppc).getStats().iteritems(): row = [] row.append('#%s' % k) if k[-3:] == '_at': row.append(formatDateTime(v)) else: row.append(v) table.append(row) self.protocol.sendData( tabulate(table, headers, tablefmt="plain", numalign="left").encode('ascii'))
def test_is_singleton(self): i1 = SMPPClientStatsCollector() i2 = SMPPClientStatsCollector() self.assertEqual(i1, i2) i1.get(cid = 'testing').set('last_seqNum', 100) self.assertEqual(i1.get(cid = 'testing').get('last_seqNum'), i2.get(cid = 'testing').get('last_seqNum'), )
def prepareRoutingsAndStartConnector(self): yield SubmitSmTestCaseTools.prepareRoutingsAndStartConnector(self) # Add a MO Route to a SmppServerSystemIdConnector c2_destination = SmppServerSystemIdConnector(system_id=self.smppc_factory.config.username) # Set the route yield self.moroute_add(DefaultRoute(c2_destination), 0) # Get stats singletons self.stats_smppc = SMPPClientStatsCollector().get(self.c1.cid)
def test_stats(self): stats = SMPPClientStatsCollector().get(cid = 'test_stats') self.assertEqual(stats._stats, { 'created_at': 0, 'last_received_pdu_at': 0, 'last_sent_pdu_at': 0, 'last_received_elink_at': 0, 'last_sent_elink_at': 0, 'last_seqNum_at': 0, 'last_seqNum': None, 'connected_at': 0, 'bound_at': 0, 'disconnected_at': 0, 'connected_count': 0, 'bound_count': 0, 'disconnected_count': 0, })
def smppcs(self, arg, opts): sc = SMPPClientStatsCollector() headers = ["#Connector id", "Bound count", "Connected at", "Bound at", "Disconnected at", "Sent elink at", "Received elink at"] table = [] connectors = self.pb['smppcm'].perspective_connector_list() for connector in connectors: row = [] row.append('#%s' % connector['id']) row.append(sc.get(connector['id']).get('bound_count')) row.append(formatDateTime(sc.get(connector['id']).get('connected_at'))) row.append(formatDateTime(sc.get(connector['id']).get('bound_at'))) row.append(formatDateTime(sc.get(connector['id']).get('disconnected_at'))) row.append(formatDateTime(sc.get(connector['id']).get('last_sent_elink_at'))) row.append(formatDateTime(sc.get(connector['id']).get('last_received_elink_at'))) table.append(row) self.protocol.sendData(tabulate(table, headers, tablefmt = "plain", numalign = "left").encode('ascii'), prompt = False) self.protocol.sendData('Total connectors: %s' % (len(table)))
def smppcs(self, arg, opts): sc = SMPPClientStatsCollector() headers = [ "#Connector id", "Connected at", "Bound at", "Disconnected at", "Submits", "Delivers", "QoS errs", "Other errs" ] table = [] connectors = self.pb['smppcm'].perspective_connector_list() for connector in connectors: row = [] row.append('#%s' % connector['id']) row.append( formatDateTime(sc.get(connector['id']).get('connected_at'))) row.append(formatDateTime(sc.get(connector['id']).get('bound_at'))) row.append( formatDateTime(sc.get(connector['id']).get('disconnected_at'))) row.append('%s/%s' % (sc.get(connector['id']).get('submit_sm_request_count'), sc.get(connector['id']).get('submit_sm_count'))) row.append('%s/%s' % (sc.get(connector['id']).get('deliver_sm_count'), sc.get(connector['id']).get('data_sm_count'))) row.append(sc.get(connector['id']).get('throttling_error_count')) row.append(sc.get(connector['id']).get('other_submit_error_count')) table.append(row) self.protocol.sendData(tabulate(table, headers, tablefmt="plain", numalign="left").encode('ascii'), prompt=False) self.protocol.sendData('Total connectors: %s' % (len(table)))
class SMPPClientFactory(ClientFactory): protocol = SMPPClientProtocol def __init__(self, config, msgHandler=None): self.reconnectTimer = None self.smpp = None self.connectionRetry = True self.config = config # Setup statistics collector self.stats = SMPPClientStatsCollector().get(cid=self.config.id) self.stats.set('created_at', datetime.now()) # Set up a dedicated logger self.log = logging.getLogger(LOG_CATEGORY_CLIENT_BASE + ".%s" % config.id) if len(self.log.handlers) != 1: self.log.setLevel(self.config.log_level) _when = self.config.log_rotate if hasattr( self.config, 'log_rotate') else 'midnight' if 'stdout' in self.config.log_file: handler = logging.StreamHandler(sys.stdout) else: handler = TimedRotatingFileHandler( filename=self.config.log_file, when=_when) formatter = logging.Formatter(self.config.log_format, self.config.log_date_format) handler.setFormatter(formatter) self.log.addHandler(handler) self.log.propagate = False if msgHandler is None: self.msgHandler = self.msgHandlerStub else: self.msgHandler = msgHandler def buildProtocol(self, addr): """Provision protocol """ proto = ClientFactory.buildProtocol(self, addr) # Setup logger proto.log = self.log return proto def getConfig(self): return self.config def msgHandlerStub(self, smpp, pdu): self.log.warn("msgHandlerStub: Received an unhandled message %s ...", pdu) def startedConnecting(self, connector): self.log.info("Connecting to %s ...", connector.getDestination()) def getExitDeferred(self): """Get a Deferred so you can be notified on disconnect and exited This deferred is called once disconnection occurs without a further reconnection retrys """ return self.exitDeferred def clientConnectionFailed(self, connector, reason): """Connection failed """ self.log.error("Connection failed. Reason: %s", str(reason)) if self.config.reconnectOnConnectionFailure and self.connectionRetry: self.log.info("Reconnecting after %d seconds ...", self.config.reconnectOnConnectionFailureDelay) self.reconnectTimer = reactor.callLater( self.config.reconnectOnConnectionFailureDelay, self.reConnect, connector) else: self.connectDeferred.errback(reason) self.exitDeferred.callback(None) self.log.info("Exiting.") def clientConnectionLost(self, connector, reason): """Connection lost """ self.log.error("Connection lost. Reason: %s", str(reason)) if self.config.reconnectOnConnectionLoss and self.connectionRetry: self.log.info("Reconnecting after %d seconds ...", self.config.reconnectOnConnectionLossDelay) self.reconnectTimer = reactor.callLater( self.config.reconnectOnConnectionLossDelay, self.reConnect, connector) else: self.exitDeferred.callback(None) self.log.info("Exiting.") def reConnect(self, connector=None): if connector is None: self.log.error("No connector to retry !") else: # Reset deferred if it were called before if self.connectDeferred.called is True: self.connectDeferred = defer.Deferred() self.connectDeferred.addCallback(self.bind) # And try to connect again connector.connect() def _connect(self): self.connectionRetry = True if self.config.useSSL: self.log.info('Establishing SSL connection to %s:%d', self.config.host, self.config.port) reactor.connectSSL(self.config.host, self.config.port, self, CtxFactory(self.config)) else: self.log.info('Establishing TCP connection to %s:%d', self.config.host, self.config.port) reactor.connectTCP(self.config.host, self.config.port, self) self.exitDeferred = defer.Deferred() self.connectDeferred = defer.Deferred() return self.connectDeferred def connectAndBind(self): self._connect() self.connectDeferred.addCallback(self.bind) return self.connectDeferred def disconnect(self): if self.smpp is not None: self.log.info('Disconnecting SMPP client') return self.smpp.unbindAndDisconnect() else: return None def stopConnectionRetrying(self): """This will stop the factory from reconnecting It is used whenever a service stop has been requested, the connectionRetry flag is reset to True upon connect() call """ self.log.info('Stopped automatic connection retrying.') if self.reconnectTimer and self.reconnectTimer.active(): self.reconnectTimer.cancel() self.reconnectTimer = None self.connectionRetry = False def disconnectAndDontRetryToConnect(self): self.log.info('Ordering a disconnect with no further reconnections.') self.stopConnectionRetrying() return self.disconnect() def bind(self, smpp): self.smpp = smpp if self.config.bindOperation == 'transceiver': return smpp.bindAsTransceiver() elif self.config.bindOperation == 'receiver': return smpp.bindAsReceiver() elif self.config.bindOperation == 'transmitter': return smpp.bindAsTransmitter() else: raise SMPPClientError("Invalid bind operation: %s" % self.config.bindOperation) def getSessionState(self): if self.smpp is None: return SMPPSessionStates.NONE else: return self.smpp.sessionState
def test_stats_set(self): stats = SMPPClientStatsCollector().get(cid = 'test_stats_set') self.assertEqual(stats.get('last_seqNum'), None) stats.set('last_seqNum', 2) self.assertEqual(stats.get('last_seqNum'), 2)
def test_get_will_create_connector(self): c = SMPPClientStatsCollector() self.assertTrue('test_get_will_create_connector' not in c.connectors) c.get(cid = 'test_get_will_create_connector') self.assertTrue('test_get_will_create_connector' in c.connectors)