mirror of
https://github.com/fairwaves/openbts-2.8.git
synced 2025-10-23 16:13:51 +00:00
Added support for performance-reporting counters. and Patch 4588 in private: For some reason, ReportingTest won't build on all systems. Since it is not part of the actuall application, I am commenting it out from the Makefile.am for now. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4627 19bc5d8c-e614-43d4-8b26-e1612bc8e597
202 lines
6.0 KiB
C++
202 lines
6.0 KiB
C++
/**@file Common-use functions for the control layer. */
|
|
|
|
/*
|
|
* Copyright 2008, 2010 Free Software Foundation, Inc.
|
|
*
|
|
* This software is distributed under the terms of the GNU Affero Public License.
|
|
* See the COPYING file in the main directory for details.
|
|
*
|
|
* This use of this software may be subject to additional restrictions.
|
|
* See the LEGAL file in the main directory for details.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
#include "ControlCommon.h"
|
|
#include "TransactionTable.h"
|
|
|
|
#include <GSMLogicalChannel.h>
|
|
#include <GSML3Message.h>
|
|
#include <GSML3CCMessages.h>
|
|
#include <GSML3RRMessages.h>
|
|
#include <GSML3MMMessages.h>
|
|
#include <GSMConfig.h>
|
|
|
|
#include <SIPEngine.h>
|
|
#include <SIPInterface.h>
|
|
|
|
#include <Logger.h>
|
|
#include <Reporting.h>
|
|
#undef WARNING
|
|
|
|
|
|
using namespace std;
|
|
using namespace GSM;
|
|
using namespace Control;
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME -- getMessage should return an L3Frame, not an L3Message.
|
|
// This will mean moving all of the parsing into the control layer.
|
|
// FIXME -- This needs an adjustable timeout.
|
|
|
|
L3Message* getMessageCore(LogicalChannel *LCH, unsigned SAPI)
|
|
{
|
|
unsigned timeout_ms = LCH->N200() * T200ms;
|
|
L3Frame *rcv = LCH->recv(timeout_ms,SAPI);
|
|
if (rcv==NULL) {
|
|
LOG(NOTICE) << "timeout";
|
|
throw ChannelReadTimeout();
|
|
}
|
|
LOG(DEBUG) << "received " << *rcv;
|
|
Primitive primitive = rcv->primitive();
|
|
if (primitive!=DATA) {
|
|
LOG(NOTICE) << "unexpected primitive " << primitive;
|
|
delete rcv;
|
|
throw UnexpectedPrimitive();
|
|
}
|
|
L3Message *msg = parseL3(*rcv);
|
|
delete rcv;
|
|
if (msg==NULL) {
|
|
LOG(NOTICE) << "unparsed message";
|
|
throw UnsupportedMessage();
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
// FIXME -- getMessage should return an L3Frame, not an L3Message.
|
|
// This will mean moving all of the parsing into the control layer.
|
|
// FIXME -- This needs an adjustable timeout.
|
|
|
|
L3Message* Control::getMessage(LogicalChannel *LCH, unsigned SAPI)
|
|
{
|
|
L3Message *msg = getMessageCore(LCH,SAPI);
|
|
// Handsets should not be sending us GPRS suspension requests.
|
|
// But if they do, we should ignore them.
|
|
// They should not send more than one in any case, but we need to be
|
|
// ready for whatever crazy behavior they throw at us.
|
|
unsigned count = gConfig.getNum("GSM.Control.GPRSMaxIgnore",5);
|
|
while (count && dynamic_cast<const GSM::L3GPRSSuspensionRequest*>(msg)) {
|
|
LOG(NOTICE) << "ignoring GPRS suspension request";
|
|
msg = getMessageCore(LCH,SAPI);
|
|
count--;
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
|
|
/* Resolve a mobile ID to an IMSI and return TMSI if it is assigned. */
|
|
unsigned Control::resolveIMSI(bool sameLAI, L3MobileIdentity& mobileID, LogicalChannel* LCH)
|
|
{
|
|
// Returns known or assigned TMSI.
|
|
assert(LCH);
|
|
LOG(DEBUG) << "resolving mobile ID " << mobileID << ", sameLAI: " << sameLAI;
|
|
|
|
// IMSI already? See if there's a TMSI already, too.
|
|
if (mobileID.type()==IMSIType) return gTMSITable.TMSI(mobileID.digits());
|
|
|
|
// IMEI? WTF?!
|
|
// FIXME -- Should send MM Reject, cause 0x60, "invalid mandatory information".
|
|
if (mobileID.type()==IMEIType) throw UnexpectedMessage();
|
|
|
|
// Must be a TMSI.
|
|
// Look in the table to see if it's one we assigned.
|
|
unsigned TMSI = mobileID.TMSI();
|
|
char* IMSI = NULL;
|
|
if (sameLAI) IMSI = gTMSITable.IMSI(TMSI);
|
|
if (IMSI) {
|
|
// We assigned this TMSI already; the TMSI/IMSI pair is already in the table.
|
|
mobileID = L3MobileIdentity(IMSI);
|
|
LOG(DEBUG) << "resolving mobile ID (table): " << mobileID;
|
|
free(IMSI);
|
|
return TMSI;
|
|
}
|
|
// Not our TMSI.
|
|
// Phones are not supposed to do this, but many will.
|
|
// If the IMSI's not in the table, ASK for it.
|
|
LCH->send(L3IdentityRequest(IMSIType));
|
|
// FIXME -- This request times out on T3260, 12 sec. See GSM 04.08 Table 11.2.
|
|
L3Message* msg = getMessage(LCH);
|
|
L3IdentityResponse *resp = dynamic_cast<L3IdentityResponse*>(msg);
|
|
if (!resp) {
|
|
if (msg) delete msg;
|
|
throw UnexpectedMessage();
|
|
}
|
|
mobileID = resp->mobileID();
|
|
LOG(INFO) << resp;
|
|
delete msg;
|
|
LOG(DEBUG) << "resolving mobile ID (requested): " << mobileID;
|
|
// FIXME -- Should send MM Reject, cause 0x60, "invalid mandatory information".
|
|
if (mobileID.type()!=IMSIType) throw UnexpectedMessage();
|
|
// Return 0 to indicate that we have not yet assigned our own TMSI for this phone.
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/* Resolve a mobile ID to an IMSI. */
|
|
void Control::resolveIMSI(L3MobileIdentity& mobileIdentity, LogicalChannel* LCH)
|
|
{
|
|
// Are we done already?
|
|
if (mobileIdentity.type()==IMSIType){
|
|
//Cause the tmsi table to be touched
|
|
gTMSITable.TMSI(mobileIdentity.digits());
|
|
return;
|
|
}
|
|
|
|
// If we got a TMSI, find the IMSI.
|
|
if (mobileIdentity.type()==TMSIType) {
|
|
char *IMSI = gTMSITable.IMSI(mobileIdentity.TMSI());
|
|
if (IMSI) mobileIdentity = L3MobileIdentity(IMSI);
|
|
free(IMSI);
|
|
}
|
|
|
|
// Still no IMSI? Ask for one.
|
|
if (mobileIdentity.type()!=IMSIType) {
|
|
LOG(NOTICE) << "MOC with no IMSI or valid TMSI. Reqesting IMSI.";
|
|
LCH->send(L3IdentityRequest(IMSIType));
|
|
// FIXME -- This request times out on T3260, 12 sec. See GSM 04.08 Table 11.2.
|
|
L3Message* msg = getMessage(LCH);
|
|
L3IdentityResponse *resp = dynamic_cast<L3IdentityResponse*>(msg);
|
|
if (!resp) {
|
|
if (msg) delete msg;
|
|
throw UnexpectedMessage();
|
|
}
|
|
mobileIdentity = resp->mobileID();
|
|
delete msg;
|
|
}
|
|
|
|
// Still no IMSI??
|
|
if (mobileIdentity.type()!=IMSIType) {
|
|
// FIXME -- This is quick-and-dirty, not following GSM 04.08 5.
|
|
LOG(WARNING) << "MOC setup with no IMSI";
|
|
// Cause 0x60 "Invalid mandatory information"
|
|
LCH->send(L3CMServiceReject(L3RejectCause(0x60)));
|
|
LCH->send(L3ChannelRelease());
|
|
// The SIP side and transaction record don't exist yet.
|
|
// So we're done.
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// vim: ts=4 sw=4
|