def concatDeliverSMs(self, HSetReturn, hashKey, splitMethod, total_segments, msg_ref_num, segment_seqnum): if HSetReturn == 0: self.log.warn('This hashKey %s already exists, will not reset it !', hashKey) return # @TODO: longDeliverSm part expiry must be configurable yield self.redisClient.expire(hashKey, 300) # This is the last part if segment_seqnum == total_segments: hvals = yield self.redisClient.hvals(hashKey) if len(hvals) != total_segments: self.log.warn( 'Received the last part (msg_ref_num:%s) and did not find all parts in redis, data lost !', msg_ref_num) return # Get PDUs pdus = {} for pickledValue in hvals: value = pickle.loads(pickledValue) pdus[value['segment_seqnum']] = value['pdu'] # Where is the message content to be found ? if 'short_message' in pdus[1].params: msg_content_key = 'short_message' elif 'message_payload' in pdus[1].params: msg_content_key = 'message_payload' else: self.log.warn('Cannot find message content in first pdu params: %s', pdus[1].params) return # Build concat_message_content concat_message_content = '' for i in range(total_segments): if splitMethod == 'sar': concat_message_content += pdus[i + 1].params[msg_content_key] else: concat_message_content += pdus[i + 1].params[msg_content_key][6:] # Build the final pdu and return it back to deliver_sm_event pdu = pdus[1] # Take the first part as a base of work # 1. Remove message splitting information from pdu if splitMethod == 'sar': del pdu.params['sar_segment_seqnum'] del pdu.params['sar_total_segments'] del pdu.params['sar_msg_ref_num'] else: pdu.params['esm_class'] = None # 2. Set the new concat_message_content pdu.params[msg_content_key] = concat_message_content routable = RoutableDeliverSm(pdu, Connector(self.SMPPClientFactory.config.id)) yield self.deliver_sm_event_post_interception(routable=routable, smpp=None, concatenated=True)
def deliver_sm_event_interceptor(self, smpp, pdu): self.log.debug('Intercepting deliver_sm event in smppc %s', self.SMPPClientFactory.config.id) if self.RouterPB is None: self.log.error( '(deliver_sm_event_interceptor/%s) RouterPB not set: deliver_sm will not be routed', self.SMPPClientFactory.config.id) return # Prepare for interception # this is a temporary routable instance to be used in interception routable = RoutableDeliverSm( pdu, Connector(self.SMPPClientFactory.config.id)) # Interception inline # @TODO: make Interception in a thread, just like httpapi interception interceptor = self.RouterPB.getMOInterceptionTable().getInterceptorFor( routable) if interceptor is not None: self.log.debug( "RouterPB selected %s interceptor for this DeliverSmPDU", interceptor) if self.interceptorpb_client is None: smpp.factory.stats.inc('interceptor_error_count') self.log.error("InterceptorPB not set !") raise InterceptorNotSetError('InterceptorPB not set !') if not self.interceptorpb_client.isConnected: smpp.factory.stats.inc('interceptor_error_count') self.log.error("InterceptorPB not connected !") raise InterceptorNotConnectedError( 'InterceptorPB not connected !') script = interceptor.getScript() self.log.debug("Interceptor script loaded: %s", script) # Run ! d = self.interceptorpb_client.run_script(script, routable) d.addCallback(self.deliver_sm_event_post_interception, routable=routable, smpp=smpp) d.addErrback(self.deliver_sm_event_post_interception) return d else: return self.deliver_sm_event_post_interception(routable=routable, smpp=smpp)
def deliver_sm_callback(self, message): """This callback is a queue listener It will only decide where to send the input message and republish it to the routedConnector The consumer will execute the remaining job of final delivery c.f. test_router.DeliverSmDeliveryTestCases for use cases """ msgid = message.content.properties['message-id'] scid = message.content.properties['headers']['connector-id'] concatenated = message.content.properties['headers']['concatenated'] will_be_concatenated = message.content.properties['headers'][ 'will_be_concatenated'] connector = Connector(scid) DeliverSmPDU = pickle.loads(message.content.body) self.log.debug( "Callbacked a deliver_sm with a DeliverSmPDU[%s] (?): %s" % (msgid, DeliverSmPDU)) # @todo: Implement MO throttling here, same as in jasmin.managers.listeners.SMPPClientSMListener.submit_sm_callback self.deliver_sm_q.get().addCallback( self.deliver_sm_callback).addErrback(self.deliver_sm_errback) # Routing routable = RoutableDeliverSm(DeliverSmPDU, connector) route = self.getMORoutingTable().getRouteFor(routable) if route is None: self.log.debug( "No route matched this DeliverSmPDU with scid:%s and msgid:%s" % (scid, msgid)) yield self.rejectMessage(message) else: # Get connector from selected route self.log.debug("RouterPB selected %s for this SubmitSmPDU" % route) routedConnector = route.getConnector() # Smpps will not route any concatenated content, it must instead route # multiparted messages # Only http connector needs concatenated content if concatenated and routedConnector.type != 'http': self.log.debug( "DeliverSmPDU [msgid:%s] not routed because its content is concatenated and the routedConnector is not http: %s" % (msgid, routedConnector.type)) yield self.rejectMessage(message) # Http will not route any multipart messages, it must instead route # concatenated messages # Only smpps connector needs multipart content elif will_be_concatenated and routedConnector.type == 'http': self.log.debug( "DeliverSmPDU [msgid:%s] not routed because there will be a one concatenated message for all parts: %s" % (msgid)) yield self.rejectMessage(message) else: self.log.debug( "Connector '%s'(%s) is set to be a route for this DeliverSmPDU" % (routedConnector.cid, routedConnector.type)) yield self.ackMessage(message) # Enqueue DeliverSm for delivery through publishing it to deliver_sm_thrower.(type) content = RoutedDeliverSmContent(DeliverSmPDU, msgid, scid, routedConnector) self.log.debug( "Publishing RoutedDeliverSmContent [msgid:%s] in deliver_sm_thrower.%s with [dcid:%s]" % (msgid, routedConnector.type, routedConnector.cid)) yield self.amqpBroker.publish( exchange='messaging', routing_key='deliver_sm_thrower.%s' % routedConnector.type, content=content)
source_addr=submit_sm.params['source_addr'], dest_addr_ton=submit_sm.params['dest_addr_ton'], dest_addr_npi=submit_sm.params['dest_addr_npi'], destination_addr=submit_sm.params['destination_addr'], esm_class=submit_sm.params['esm_class'], protocol_id=submit_sm.params['protocol_id'], priority_flag=submit_sm.params['priority_flag'], registered_delivery=submit_sm.params['registered_delivery'], replace_if_present_flag=submit_sm.params['replace_if_present_flag'], data_coding=submit_sm.params['data_coding'], short_message=submit_sm.params['short_message'], sm_default_msg_id=submit_sm.params['sm_default_msg_id']) logger.debug("Prepared a new deliver_sm: %s", deliver_sm) # Prepare for deliver_sm injection _routable = RoutableDeliverSm(deliver_sm, Connector(routable.user.uid)) content = DeliverSmContent(_routable, routable.user.uid, pickleProtocol=pickle.HIGHEST_PROTOCOL) routing_key = 'deliver.sm.%s' % routable.user.uid # Connecto RabbitMQ and publish deliver_sm logger.debug('Init pika and publish..') connection = pika.BlockingConnection(pika.URLParameters(RABBITMQ_URL)) channel = connection.channel() logger.debug('RabbitMQ channel ready, publishing now msgid %s ...', content.properties['message-id']) channel.basic_publish( 'messaging', routing_key, content.body, pika.BasicProperties(message_id=content.properties['message-id'], headers=content.properties['headers']))