void Control::MOSMSController(const L3CMServiceRequest *req, LogicalChannel *LCH) { assert(req); assert(LCH); LOG(INFO) << "MOSMS, req " << *req; // If we got a TMSI, find the IMSI. // Note that this is a copy, not a reference. L3MobileIdentity mobileIdentity = req->mobileIdentity(); resolveIMSI(mobileIdentity,LCH); // See GSM 04.11 Arrow Diagram A5 for the transaction // Step 1 MS->Network CP-DATA containing RP-DATA // Step 2 Network->MS CP-ACK // Step 3 Network->MS CP-DATA containing RP-ACK // Step 4 MS->Network CP-ACK // LAPDm operation, from GSM 04.11, Annex F: // """ // Case A: Mobile originating short message transfer, no parallel call: // The mobile station side will initiate SAPI 3 establishment by a SABM command // on the SDCCH after the cipher mode has been set. If no hand over occurs, the // SAPI 3 link will stay up until the last CP-ACK is received by the MSC, and // the clearing procedure is invoked. // """ // FIXME: check provisioning // Let the phone know we're going ahead with the transaction. LOG(INFO) << "sending CMServiceAccept"; LCH->send(L3CMServiceAccept()); // Wait for SAP3 to connect. // The first read on SAP3 is the ESTABLISH primitive. delete getFrameSMS(LCH,ESTABLISH); // Step 1 // Now get the first message. // Should be CP-DATA, containing RP-DATA. L3Frame *CM = getFrameSMS(LCH); LOG(DEBUG) << "data from MS " << *CM; if (CM->MTI()!=CPMessage::DATA) { LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI(); throw UnexpectedMessage(); } unsigned TI = CM->TIValue(); // Step 2 // Respond with CP-ACK. // This just means that we got the message. LOG(INFO) << "sending CPAck"; LCH->send(CPAck(1,TI),3); // Parse the message in CM and process RP part. // This is where we actually parse the message and send it out. // FIXME -- We need to set the message ref correctly, // even if the parsing fails. // The compiler gives a warning here. Let it. It will remind someone to fix it. unsigned ref; bool success = false; try { CPData data; data.parse(*CM); delete CM; LOG(INFO) << "CPData " << data; // Transfer out the RPDU -> TPDU -> delivery. ref = data.RPDU().reference(); // This handler invokes higher-layer parsers, too. success = handleRPDU(mobileIdentity,data.RPDU()); } catch (SMSReadError) { LOG(WARN) << "SMS parsing failed (above L3)"; // Cause 95, "semantically incorrect message". LCH->send(CPData(1,TI,RPError(95,ref)),3); throw UnexpectedMessage(); } catch (L3ReadError) { LOG(WARN) << "SMS parsing failed (in L3)"; throw UnsupportedMessage(); } // Step 3 // Send CP-DATA containing RP-ACK and message reference. if (success) { LOG(INFO) << "sending RPAck in CPData"; LCH->send(CPData(1,TI,RPAck(ref)),3); } else { LOG(INFO) << "sending RPError in CPData"; // Cause 127 is "internetworking error, unspecified". // See GSM 04.11 Table 8.4. LCH->send(CPData(1,TI,RPError(127,ref)),3); } // Step 4 // Get CP-ACK from the MS. CM = getFrameSMS(LCH); if (CM->MTI()!=CPMessage::ACK) { LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI(); throw UnexpectedMessage(); } LOG(DEBUG) << "ack from MS: " << *CM; CPAck ack; ack.parse(*CM); LOG(INFO) << "CPAck " << ack; // RRLP Here if enabled if (gConfig.defines("GSM.RRLP") && gConfig.getNum("GSM.RRLP") == 1 && gConfig.defines("RRLP.LocationUpdate") && gConfig.getNum("RRLP.LocationUpdate") == 1 /* RRLP? */) { Timeval start; RRLP::collectMSInfo(mobileIdentity, LCH, true /* DO RRLP */); LOG(INFO) << "submitSMS with RRLP took " << start.elapsed() << " for IMSI " << mobileIdentity; } // Done. LOG(INFO) << "closing"; LCH->send(L3ChannelRelease()); }
void Control::MOSMSController(const GSM::L3CMServiceRequest *req, GSM::LogicalChannel *LCH) { assert(req); assert(req->serviceType().type() == GSM::L3CMServiceType::ShortMessage); assert(LCH); assert(LCH->type() != GSM::SACCHType); LOG(INFO) << "MOSMS, req " << *req; // If we got a TMSI, find the IMSI. // Note that this is a copy, not a reference. GSM::L3MobileIdentity mobileID = req->mobileID(); resolveIMSI(mobileID,LCH); // Create a transaction record. TransactionEntry *transaction = new TransactionEntry(gConfig.getStr("SIP.Proxy.SMS").c_str(),mobileID,LCH); gTransactionTable.add(transaction); LOG(DEBUG) << "MOSMS: transaction: " << *transaction; // See GSM 04.11 Arrow Diagram A5 for the transaction // Step 1 MS->Network CP-DATA containing RP-DATA // Step 2 Network->MS CP-ACK // Step 3 Network->MS CP-DATA containing RP-ACK // Step 4 MS->Network CP-ACK // LAPDm operation, from GSM 04.11, Annex F: // """ // Case A: Mobile originating short message transfer, no parallel call: // The mobile station side will initiate SAPI 3 establishment by a SABM command // on the DCCH after the cipher mode has been set. If no hand over occurs, the // SAPI 3 link will stay up until the last CP-ACK is received by the MSC, and // the clearing procedure is invoked. // """ // FIXME: check provisioning if (gConfig.getNum("GSM.Authentication")||gConfig.getNum("GSM.Encryption")) { AuthenticationParameters authParams(mobileID); registerIMSI(authParams, LCH); authenticate(authParams, LCH); } // Let the phone know we're going ahead with the transaction. if (LCH->isDecrypting()) { LOG(INFO) << "Decryption ACTIVE for:" << mobileID << " CMServiceAccept NOT sent, because CipherModeCommand implies it."; } else { LOG(INFO) << "Decryption NOT active for: " << mobileID << " Sending CMServiceAccept"; LCH->send(GSM::L3CMServiceAccept()); } // Wait for SAP3 to connect. // The first read on SAP3 is the ESTABLISH primitive. delete getFrameSMS(LCH,GSM::ESTABLISH); // Step 1 // Now get the first message. // Should be CP-DATA, containing RP-DATA. GSM::L3Frame *CM = getFrameSMS(LCH); LOG(DEBUG) << "data from MS " << *CM; if (CM->MTI()!=CPMessage::DATA) { LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI(); delete CM; throw UnexpectedMessage(); } unsigned L3TI = CM->TI() | 0x08; transaction->L3TI(L3TI); // Step 2 // Respond with CP-ACK. // This just means that we got the message. LOG(INFO) << "sending CPAck"; LCH->send(CPAck(L3TI),3); // Parse the message in CM and process RP part. // This is where we actually parse the message and send it out. // FIXME -- We need to set the message ref correctly, // even if the parsing fails. // The compiler gives a warning here. Let it. It will remind someone to fix it. unsigned ref; bool success = false; try { CPData data; data.parse(*CM); LOG(INFO) << "CPData " << data; // Transfer out the RPDU -> TPDU -> delivery. ref = data.RPDU().reference(); // This handler invokes higher-layer parsers, too. success = handleRPDU(transaction,data.RPDU()); } catch (SMSReadError) { LOG(WARNING) << "SMS parsing failed (above L3)"; // Cause 95, "semantically incorrect message". LCH->send(CPData(L3TI,RPError(95,ref)),3); delete CM; throw UnexpectedMessage(); } catch (GSM::L3ReadError) { LOG(WARNING) << "SMS parsing failed (in L3)"; delete CM; throw UnsupportedMessage(); } delete CM; // Step 3 // Send CP-DATA containing RP-ACK and message reference. if (success) { LOG(INFO) << "sending RPAck in CPData"; LCH->send(CPData(L3TI,RPAck(ref)),3); } else { LOG(INFO) << "sending RPError in CPData"; // Cause 127 is "internetworking error, unspecified". // See GSM 04.11 Table 8.4. LCH->send(CPData(L3TI,RPError(127,ref)),3); } // Step 4 // Get CP-ACK from the MS. CM = getFrameSMS(LCH); if (CM->MTI()!=CPMessage::ACK) { LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI(); throw UnexpectedMessage(); } LOG(DEBUG) << "ack from MS: " << *CM; CPAck ack; ack.parse(*CM); delete CM; LOG(INFO) << "CPAck " << ack; /* MOSMS RLLP request */ if (gConfig.defines("Control.SMS.QueryRRLP")) { // Query for RRLP if (!sendRRLP(mobileID, LCH)) { LOG(INFO) << "RRLP request failed"; } } // Done. LCH->send(GSM::L3ChannelRelease()); gTransactionTable.remove(transaction); LOG(INFO) << "closing the Um channel"; }
void Control::InCallMOSMSController(const CPData *cpData, TransactionEntry* transaction, GSM::SACCHLogicalChannel *LCH) { LOG(INFO) << *cpData; // See GSM 04.11 Arrow Diagram A5 for the transaction // Step 1 MS->Network CP-DATA containing RP-DATA // Step 2 Network->MS CP-ACK // Step 3 Network->MS CP-DATA containing RP-ACK // Step 4 MS->Network CP-ACK // LAPDm operation, from GSM 04.11, Annex F: // """ // Case C: Mobile originating short message transfer, parallel call. // The mobile station will send a SABM command on the SACCH when a CM_SERV_ACC // message has been received from the network, allowing the short message // transfer to start. If no hand over occurs the link will stay up until the // MSC orders a explicit release, or the clearing procedure is invoked. If the // parallel call is cleared before the short message transfer is finalized, the // MSC will delay the clearing procedure toward the BSS, i.e. the channel // release procedure is delayed. // """ // Since there's a parallel call, we will assume correct provisioning. // And we know that CM and SABM are established. // Step 1 already happened in the SACCH service loop. // Just get the L3 TI and set the high bit since it originated in the MS. unsigned L3TI = cpData->TI() | 0x08; transaction->L3TI(L3TI); // Step 2 // Respond with CP-ACK. // This just means that we got the message. LOG(INFO) << "sending CPAck"; LCH->send(CPAck(L3TI),3); // Parse the message in CM and process RP part. // This is where we actually parse the message and send it out. // FIXME -- We need to set the message ref correctly, // even if the parsing fails. // The compiler gives a warning here. Let it. It will remind someone to fix it. unsigned ref; bool success = false; try { CPData data; data.parse(*cpData); LOG(INFO) << "CPData " << data; // Transfer out the RPDU -> TPDU -> delivery. ref = data.RPDU().reference(); // This handler invokes higher-layer parsers, too. success = handleRPDU(transaction,data.RPDU()); } catch (SMSReadError) { LOG(WARNING) << "SMS parsing failed (above L3)"; // Cause 95, "semantically incorrect message". LCH->send(CPData(L3TI,RPError(95,ref)),3); throw UnexpectedMessage(transaction->ID()); } catch (GSM::L3ReadError) { LOG(WARNING) << "SMS parsing failed (in L3)"; throw UnsupportedMessage(transaction->ID()); } // Step 3 // Send CP-DATA containing RP-ACK and message reference. if (success) { LOG(INFO) << "sending RPAck in CPData"; LCH->send(CPData(L3TI,RPAck(ref)),3); } else { LOG(INFO) << "sending RPError in CPData"; // Cause 127 is "internetworking error, unspecified". // See GSM 04.11 Table 8.4. LCH->send(CPData(L3TI,RPError(127,ref)),3); } // Step 4 // Get CP-ACK from the MS. GSM::L3Frame* CM = getFrameSMS(LCH); if (CM->MTI()!=CPMessage::ACK) { LOG(NOTICE) << "unexpected SMS CP message with MTI=" << CM->MTI() << " " << *CM; throw UnexpectedMessage(transaction->ID()); } LOG(DEBUG) << "ack from MS: " << *CM; CPAck ack; ack.parse(*CM); LOG(INFO) << "CPAck " << ack; /* I had a hell of a time testing this with my B100 I know it went off, that's all. If things fail, look here -kurtis */ /* MOSMS RLLP request */ if (gConfig.defines("Control.SMS.QueryRRLP")) { // Query for RRLP if (!sendRRLP(transaction->subscriber(), LCH)) { LOG(INFO) << "RRLP request failed"; } } gTransactionTable.remove(transaction); }
void Control::InCallMOSMSController(const CPData *cpData, TransactionEntry* transaction, UMTS::DCCHLogicalChannel *LCH) { LOG(INFO) << *cpData; // FIXME -- We know this will be broken in UMTS. // Step 1 already happened in the SACCH service loop. // Just get the L3 TI and set the high bit since it originated in the MS. unsigned L3TI = cpData->TI() | 0x08; transaction->L3TI(L3TI); // Step 2 // Respond with CP-ACK. // This just means that we got the message. LOG(INFO) << "sending CPAck"; LCH->send(CPAck(L3TI),3); // Parse the message in CM and process RP part. // This is where we actually parse the message and send it out. // FIXME -- We need to set the message ref correctly, // even if the parsing fails. // The compiler gives a warning here. Let it. It will remind someone to fix it. unsigned ref; bool success = false; try { CPData data; data.parse(*cpData); LOG(INFO) << "CPData " << data; // Transfer out the RPDU -> TPDU -> delivery. ref = data.RPDU().reference(); // This handler invokes higher-layer parsers, too. success = handleRPDU(transaction,data.RPDU()); } catch (SMSReadError) { LOG(WARNING) << "SMS parsing failed (above L3)"; // Cause 95, "semantically incorrect message". LCH->send(CPData(L3TI,RPError(95,ref)),3); throw UnexpectedMessage(transaction->ID()); } catch (GSM::L3ReadError) { LOG(WARNING) << "SMS parsing failed (in L3)"; throw UnsupportedMessage(transaction->ID()); } // Step 3 // Send CP-DATA containing RP-ACK and message reference. if (success) { LOG(INFO) << "sending RPAck in CPData"; LCH->send(CPData(L3TI,RPAck(ref)),3); } else { LOG(INFO) << "sending RPError in CPData"; // Cause 127 is "internetworking error, unspecified". // See GSM 04.11 Table 8.4. LCH->send(CPData(L3TI,RPError(127,ref)),3); } // Step 4 // Get CP-ACK from the MS. GSM::L3Frame* CM = getFrameSMS(LCH); if (CM->MTI()!=CPMessage::ACK) { LOG(NOTICE) << "unexpected SMS CP message with MTI=" << CM->MTI() << " " << *CM; throw UnexpectedMessage(transaction->ID()); } LOG(DEBUG) << "ack from MS: " << *CM; CPAck ack; ack.parse(*CM); LOG(INFO) << "CPAck " << ack; gTransactionTable.remove(transaction); }