short_code_action sendSIP_init(const char *imsi, const TLSubmit& submit, const std::string &body, short_code_params *scp) { const char *address = submit.DA().digits(); const TLUserData& tl_ud = submit.UD(); const char *from = scp->scp_qmsg_it->parsed->from->url->username; LOG(INFO) << "from " << imsi << " to " << address; if (scp == NULL) { LOG(WARN) << "short_code_params is NULL. Error."; return SCA_INTERNAL_ERROR; } // START OF THE SIP PROCESSING osip_message_t *omsg = scp->scp_qmsg_it->parsed; // Req.URI osip_free(omsg->req_uri->username); omsg->req_uri->username = (char *)osip_malloc (strlen(address)+1); strcpy(omsg->req_uri->username, address); // To: set_to_for_smsc(address, scp->scp_qmsg_it); // Let them know that parsed part has been changed. scp->scp_qmsg_it->parsed_was_changed(); if (ISLOGGING(DEBUG)) { // Call make_text_valid() is needed for debug only. scp->scp_qmsg_it->make_text_valid(); LOG(DEBUG) << "Updated SMS message: " << scp->scp_qmsg_it->text; } return SCA_RESTART_PROCESSING; }
bool recode_tpdu(const std::string &body, short_msg_p_list::iterator &smsg) { bool return_action = true; // Safety check if (smsg->tl_message == NULL) { LOG(WARN) << "TLMessage is not available. Error during SMS decoding occurred?"; return false; } switch ((TLMessage::MessageType)smsg->tl_message->MTI()) { case TLMessage::SUBMIT: { TLSubmit *submit = (TLSubmit*)smsg->tl_message; const TLUserData& tl_ud = submit->UD(); create_sms_delivery(body, tl_ud, smsg); pack_tpdu(smsg); return_action = true; break; } case TLMessage::DELIVER_REPORT: case TLMessage::STATUS_REPORT: // TODO LOG(WARN) << "TPDU must be of SMS-SUBMIT type, we have MTI=" << (TLMessage::MessageType)smsg->tl_message->MTI(); return false; } // Now we have MS->SC message smsg->ms_to_sc = false; return return_action; }
TLMessage *SMS::parseTPDU(const TLFrame& TPDU, bool directionUplink) { LOG(DEBUG) << "SMS: parseTPDU MTI=" << (TLMessage::MessageType)TPDU.MTI(); if (directionUplink) { // Handle just the uplink cases. switch ((TLMessage::MessageType)TPDU.MTI()) { case TLMessage::DELIVER_REPORT: case TLMessage::STATUS_REPORT: // FIXME -- Not implemented yet. LOG(WARNING) << "Unsupported TPDU type: " << (TLMessage::MessageType)TPDU.MTI(); return NULL; case TLMessage::SUBMIT: { TLSubmit *submit = new TLSubmit; submit->parse(TPDU); LOG(INFO) << "SMS SMS-SUBMIT " << *submit; return submit; } default: return NULL; } } else { switch ((TLMessage::MessageType)TPDU.MTI()) { // 10-2013: Pat added the DELIVER which is the downlink message so we can parse it for reporting purposes. case TLMessage::DELIVER: { TLDeliver *deliver = new TLDeliver(TPDU); return deliver; } default: LOG(WARNING) << "parsing unsupported TPDU type: " << (TLMessage::MessageType)TPDU.MTI(); return NULL; } } }
/** Send a TPDU through whatever gateway is available. */ short_code_action submitSMS(const char *imsi, const TLSubmit& submit, const std::string &body, short_code_params *scp) { LOG(INFO) << "from " << imsi << " message: " << submit; const TLAddress& address = submit.DA(); // Check for direct e-mail address at start of message body. // FIXME -- This doesn't really follow the spec. See GSM 03.40 3.8. static const Regexp emailAddress("^[[:graph:]]+@[[:graph:]]+ "); if (emailAddress.match(body.data())) { // FIXME -- Get the sender's E.164 to put in the subject line. char bodyCopy[body.length()+2]; strcpy(bodyCopy,body.data()); char* SMTPAddress = bodyCopy; char* term = strchr(bodyCopy,' '); // If term's NULL, the regexp is broken. assert(term); *term = '\0'; char* SMTPPayload = term+1; LOG(INFO) << "sending SMTP to " << SMTPAddress << ": " << SMTPPayload; if (SMTPPayload) return sendEMail(SMTPAddress,SMTPPayload,"from OpenBTS gateway"); else return sendEMail(SMTPAddress,"(empty)","from OpenBTS gateway"); } // Send to smqueue or HTTP gateway, depending on what's defined in the config. if (gConfig.defines("SMS.HTTP.Gateway")) // If there is an external HTTP gateway, use it. return sendHTTP(address.digits(), body); else // Otherwise, we are looking for a SIP interface to smqueue. return sendSIP_init(imsi, submit, body, scp); }
/** Process the incomming RPDU. @param mobileID The sender's IMSI. @param RPDU The RPDU to process. @return true if successful. */ bool MOSMSMachine::handleRPDU(const RLFrame& RPDU) { LOG(DEBUG) << "SMS: handleRPDU MTI=" << RPDU.MTI(); switch ((RPMessage::MessageType)RPDU.MTI()) { case RPMessage::Data: { string contentType = gConfig.getStr("SMS.MIMEType"); ostringstream body; string toAddress = ""; if (contentType == "text/plain") { RPData data; data.parse(RPDU); TLSubmit submit; submit.parse(data.TPDU()); body << submit.UD().decode(); // (pat) TODO: efficiencize this. toAddress = string(submit.DA().digits()); } else if (contentType == "application/vnd.3gpp.sms") { toAddress = "smsc"; // If encoded this is expected in destination address RPDU.hex(body); } else { LOG(ERR) << "\"" << contentType << "\" is not a valid SMS payload type"; } // Steps: // 1 -- Complete transaction record. // 2 -- Send TL-SUBMIT to the server. // 3 -- Wait for response or timeout. // 4 -- Return true for OK or ACCEPTED, false otherwise. // Step 1 and 2 -- Complete the transaction record and send TL-SUMBIT to server. // Form the TLAddress into a CalledPartyNumber for the transaction. // Attach calledParty and message body to the transaction. SipDialog::newSipDialogMOSMS(tran()->tranID(), tran()->subscriber(), toAddress, body.str(), contentType); return true; } case RPMessage::Ack: case RPMessage::SMMA: return true; case RPMessage::Error: default: return false; } }
TLMessage *SMS::parseTPDU(const TLFrame& TPDU) { LOG(DEBUG) << "SMS: parseTPDU MTI=" << TPDU.MTI(); // Handle just the uplink cases. switch ((TLMessage::MessageType)TPDU.MTI()) { case TLMessage::DELIVER_REPORT: case TLMessage::STATUS_REPORT: // FIXME -- Not implemented yet. LOG(WARNING) << "Unsupported TPDU type: " << (TLMessage::MessageType)TPDU.MTI(); return NULL; case TLMessage::SUBMIT: { TLSubmit *submit = new TLSubmit; submit->parse(TPDU); LOG(INFO) << "SMS SMS-SUBMIT " << *submit; return submit; } default: return NULL; } }
/** Send a TPDU through whatever gateway is available. */ short_code_action submitSMS(const char *imsi, const TLSubmit& submit, const std::string &body, short_code_params *scp) { LOG(INFO) << "from " << imsi << " message: " << submit; const TLAddress& address = submit.DA(); //#if 0 //This is broken under Unbuntu becasue of changes in the "mail" program. // Check for direct e-mail address at start of message body. // FIXME -- This doesn't really follow the spec. See GSM 03.40 3.8. static const Regexp emailAddress("^[[:graph:]]+@[[:graph:]]+ "); if (emailAddress.match(body.data())) { char bodyCopy[body.length()+2]; strcpy(bodyCopy,body.data()); char* SMTPAddress = bodyCopy; char* term = strchr(bodyCopy,' '); // If term's NULL, the regexp emailAddress is broken. assert(term); *term = '\0'; char* SMTPPayload = term+1; // Get the sender's E.164 to put in the subject line. char* clid = scp->scp_smq->my_hlr.getCLIDLocal(imsi); char subjectLine[200]; if (!clid) sprintf(subjectLine,"from %s",imsi); else { sprintf(subjectLine,"from %s",clid); free(clid); } // Send it. LOG(INFO) << "sending SMTP to " << SMTPAddress << ": " << SMTPPayload; if (SMTPPayload) return sendEMail(SMTPAddress,SMTPPayload,subjectLine); else return sendEMail(SMTPAddress,"(empty)","from OpenBTS gateway"); } //#endif char* destinationNumber = scp->scp_smq->my_hlr.getIMSI2(address.digits()); // Send to smqueue or HTTP gateway, depending on what's defined in the config. // And whether of not we can resolve the destination, and a global relay does not exist, // AND the message is not to a shortcode. if (gConfig.getStr("SIP.GlobalRelay.IP").length() == 0 && gConfig.getStr("SMS.HTTPGateway.URL").length() != 0 && !destinationNumber) // If there is an external HTTP gateway, use it. return sendHTTP(address.digits(), body); free(destinationNumber); return sendSIP_init(imsi, submit, body, scp); }
/** Process the RPDU. @param mobileID The sender's IMSI. @param RPDU The RPDU to process. @return true if successful. */ bool handleRPDU(TransactionEntry *transaction, const RLFrame& RPDU) { LOG(DEBUG) << "SMS: handleRPDU MTI=" << RPDU.MTI(); switch ((RPMessage::MessageType)RPDU.MTI()) { case RPMessage::Data: { string contentType = gConfig.getStr("SMS.MIMEType"); ostringstream body; if (contentType == "text/plain") { // TODO: Clean this mess up! RPData data; data.parse(RPDU); TLSubmit submit; submit.parse(data.TPDU()); body << submit.UD().decode(); } else if (contentType == "application/vnd.3gpp.sms") { RPDU.hex(body); } else { LOG(ALERT) << "\"" << contentType << "\" is not a valid SMS payload type"; } const char* address = NULL; if (gConfig.defines("SIP.SMSC")) address = gConfig.getStr("SIP.SMSC").c_str(); /* The SMSC is not defined, we are using an older version */ if (address == NULL) { RPData data; data.parse(RPDU); TLSubmit submit; submit.parse(data.TPDU()); address = submit.DA().digits(); } return sendSIP(transaction, address, body.str().data(),contentType.c_str()); } case RPMessage::Ack: case RPMessage::SMMA: return true; case RPMessage::Error: default: return false; } }