mirror of
https://github.com/RangeNetworks/openbts.git
synced 2025-11-03 13:23:16 +00:00
RRLP Additions: New config fields enable RRLP messages before mobile terminated calls and SMS.
git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3048 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include "MobilityManagement.h"
|
||||
#include "SMSControl.h"
|
||||
#include "CallControl.h"
|
||||
#include "RRLPServer.h"
|
||||
|
||||
#include <GSMCommon.h>
|
||||
#include <GSMLogicalChannel.h>
|
||||
@@ -909,6 +910,19 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
|
||||
assert(LCH);
|
||||
LOG(INFO) << "MTC on " << LCH->type() << " transaction: "<< *transaction;
|
||||
|
||||
/* first RLLP request */
|
||||
if (gConfig.defines("Control.Call.QueryRRLP")) {
|
||||
// Query for RRLP
|
||||
RRLPServer wRRLPServer(transaction->subscriber(), LCH);
|
||||
if (!wRRLPServer.assist()) {
|
||||
LOG(INFO) << "RRLPServer::assist problem";
|
||||
}
|
||||
// can still try to check location even if assist didn't work
|
||||
if (!wRRLPServer.locate()) {
|
||||
LOG(INFO) << "RRLPServer::locate problem";
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if very early assigment already happened.
|
||||
bool veryEarly = false;
|
||||
if (LCH->type()==GSM::FACCHType) veryEarly=true;
|
||||
|
||||
@@ -37,7 +37,8 @@ libcontrol_la_SOURCES = \
|
||||
ControlCommon.cpp \
|
||||
MobilityManagement.cpp \
|
||||
RadioResource.cpp \
|
||||
DCCHDispatch.cpp
|
||||
DCCHDispatch.cpp \
|
||||
RRLPServer.cpp
|
||||
|
||||
|
||||
noinst_HEADERS = \
|
||||
@@ -48,4 +49,5 @@ noinst_HEADERS = \
|
||||
RadioResource.h \
|
||||
MobilityManagement.h \
|
||||
CallControl.h \
|
||||
TMSITable.h
|
||||
TMSITable.h \
|
||||
RRLPServer.h
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "MobilityManagement.h"
|
||||
#include "SMSControl.h"
|
||||
#include "CallControl.h"
|
||||
#include "RRLPServer.h"
|
||||
|
||||
#include <GSMLogicalChannel.h>
|
||||
#include <GSML3RRMessages.h>
|
||||
@@ -132,261 +133,6 @@ bool sendWelcomeMessage(const char* messageName, const char* shortCodeName, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class RRLPServer
|
||||
{
|
||||
public:
|
||||
RRLPServer(L3MobileIdentity wMobileID, LogicalChannel *wDCCH);
|
||||
// tell server to send location assistance to mobile
|
||||
bool assist();
|
||||
// tell server to ask mobile for location
|
||||
bool locate();
|
||||
private:
|
||||
RRLPServer(); // not allowed
|
||||
string url;
|
||||
L3MobileIdentity mobileID;
|
||||
LogicalChannel *DCCH;
|
||||
string query;
|
||||
string name;
|
||||
bool transact();
|
||||
bool trouble;
|
||||
};
|
||||
|
||||
RRLPServer::RRLPServer(L3MobileIdentity wMobileID, LogicalChannel *wDCCH)
|
||||
{
|
||||
trouble = false;
|
||||
url = gConfig.getStr("GSM.RRLP.SERVER.URL", "");
|
||||
if (url.length() == 0) {
|
||||
LOG(INFO) << "RRLP not configured";
|
||||
trouble = true;
|
||||
return;
|
||||
}
|
||||
mobileID = wMobileID;
|
||||
DCCH = wDCCH;
|
||||
// name of subscriber
|
||||
name = string("IMSI") + mobileID.digits();
|
||||
// don't continue if IMSI has a RRLP support flag and it's false
|
||||
unsigned int supported = 0;
|
||||
if (sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "name", name.c_str(),
|
||||
"RRLPSupported", supported) && !supported) {
|
||||
LOG(INFO) << "RRLP not supported for " << name;
|
||||
trouble = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool RRLPServer::assist()
|
||||
{
|
||||
if (trouble) return false;
|
||||
query = "query=assist";
|
||||
return transact();
|
||||
}
|
||||
|
||||
bool RRLPServer::locate()
|
||||
{
|
||||
if (trouble) return false;
|
||||
query = "query=loc";
|
||||
return transact();
|
||||
}
|
||||
|
||||
void clean(char *line)
|
||||
{
|
||||
char *p = line + strlen(line) - 1;
|
||||
while (p > line && *p <= ' ') *p-- = 0;
|
||||
}
|
||||
|
||||
string getConfig()
|
||||
{
|
||||
const char *configs[] = {
|
||||
"GSM.RRLP.ACCURACY",
|
||||
"GSM.RRLP.RESPONSETIME",
|
||||
"GSM.RRLP.ALMANAC.URL",
|
||||
"GSM.RRLP.EPHEMERIS.URL",
|
||||
"GSM.RRLP.ALMANAC.REFRESH.TIME",
|
||||
"GSM.RRLP.EPHEMERIS.REFRESH.TIME",
|
||||
"GSM.RRLP.SEED.LATITUDE",
|
||||
"GSM.RRLP.SEED.LONGITUDE",
|
||||
"GSM.RRLP.SEED.ALTITUDE",
|
||||
"GSM.RRLP.EPHEMERIS.ASSIST.COUNT",
|
||||
"GSM.RRLP.ALMANAC.ASSIST.PRESENT",
|
||||
0
|
||||
};
|
||||
string config = "";
|
||||
for (const char **p = configs; *p; p++) {
|
||||
string configValue = gConfig.getStr(*p, "");
|
||||
if (configValue.length() == 0) return "";
|
||||
config.append("&");
|
||||
config.append(*p);
|
||||
config.append("=");
|
||||
if (0 == strcmp((*p) + strlen(*p) - 3, "URL")) {
|
||||
// TODO - better to have urlencode and decode, but then I'd have to look for them
|
||||
char buf[3];
|
||||
buf[2] = 0;
|
||||
for (const char *q = configValue.c_str(); *q; q++) {
|
||||
sprintf(buf, "%02x", *q);
|
||||
config.append(buf);
|
||||
}
|
||||
} else {
|
||||
config.append(configValue);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
bool RRLPServer::transact()
|
||||
{
|
||||
vector<string> apdus;
|
||||
while (true) {
|
||||
// bounce off server
|
||||
string esc = "'";
|
||||
string config = getConfig();
|
||||
if (config.length() == 0) return false;
|
||||
string cmd = "wget -qO- " + esc + url + "?" + query + config + esc;
|
||||
LOG(INFO) << "*************** " << cmd;
|
||||
FILE *result = popen(cmd.c_str(), "r");
|
||||
if (!result) {
|
||||
LOG(CRIT) << "popen call \"" << cmd << "\" failed";
|
||||
return NULL;
|
||||
}
|
||||
// build map of responses, and list of apdus
|
||||
map<string,string> response;
|
||||
size_t nbytes = 1500;
|
||||
char *line = (char*)malloc(nbytes+1);
|
||||
while (!feof(result)) {
|
||||
if (!fgets(line, nbytes, result)) break;
|
||||
clean(line);
|
||||
LOG(INFO) << "server return: " << line;
|
||||
char *p = strchr(line, '=');
|
||||
if (!p) continue;
|
||||
string lhs = string(line, 0, p-line);
|
||||
string rhs = string(line, p+1-line, string::npos);
|
||||
if (lhs == "apdu") {
|
||||
apdus.push_back(rhs);
|
||||
} else {
|
||||
response[lhs] = rhs;
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
pclose(result);
|
||||
|
||||
// quit if error
|
||||
if (response.find("error") != response.end()) {
|
||||
LOG(INFO) << "error from server: " << response["error"];
|
||||
return false;
|
||||
}
|
||||
|
||||
// quit if ack from assist unless there are more apdu messages
|
||||
if (response.find("ack") != response.end()) {
|
||||
LOG(INFO) << "ack from mobile, decoded by server";
|
||||
if (apdus.size() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
LOG(INFO) << "more apdu messages";
|
||||
}
|
||||
}
|
||||
|
||||
// quit if location decoded
|
||||
if (response.find("latitude") != response.end() && response.find("longitude") != response.end() && response.find("positionError") != response.end()) {
|
||||
ostringstream os;
|
||||
os << "insert into RRLP (name, latitude, longitude, error, time) values (" <<
|
||||
'"' << name << '"' << "," <<
|
||||
response["latitude"] << "," <<
|
||||
response["longitude"] << "," <<
|
||||
response["positionError"] << "," <<
|
||||
"datetime('now')"
|
||||
")";
|
||||
LOG(INFO) << os.str();
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) {
|
||||
LOG(INFO) << "sqlite3_command problem";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// bounce off mobile
|
||||
if (apdus.size() == 0) {
|
||||
LOG(INFO) << "missing apdu for mobile";
|
||||
return false;
|
||||
}
|
||||
string apdu = apdus[0];
|
||||
apdus.erase(apdus.begin());
|
||||
BitVector bv(apdu.size()*4);
|
||||
if (!bv.unhex(apdu.c_str())) {
|
||||
LOG(INFO) << "BitVector::unhex problem";
|
||||
return false;
|
||||
}
|
||||
|
||||
DCCH->send(L3ApplicationInformation(bv));
|
||||
// Receive an L3 frame with a timeout. Timeout loc req response time max + 2 seconds.
|
||||
L3Frame* resp = DCCH->recv(130000);
|
||||
if (!resp) {
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "RRLPQuery returned " << *resp;
|
||||
if (resp->primitive() != DATA) {
|
||||
LOG(INFO) << "didn't receive data";
|
||||
switch (resp->primitive()) {
|
||||
case ESTABLISH: LOG(INFO) << "channel establihsment"; break;
|
||||
case RELEASE: LOG(INFO) << "normal channel release"; break;
|
||||
case DATA: LOG(INFO) << "multiframe data transfer"; break;
|
||||
case UNIT_DATA: LOG(INFO) << "datagram-type data transfer"; break;
|
||||
case ERROR: LOG(INFO) << "channel error"; break;
|
||||
case HARDRELEASE: LOG(INFO) << "forced release after an assignment"; break;
|
||||
default: LOG(INFO) << "unrecognized primitive response"; break;
|
||||
}
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
const unsigned PD_RR = 6;
|
||||
LOG(INFO) << "resp.pd = " << resp->PD();
|
||||
if (resp->PD() != PD_RR) {
|
||||
LOG(INFO) << "didn't receive an RR message";
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
const unsigned MTI_RR_STATUS = 18;
|
||||
if (resp->MTI() == MTI_RR_STATUS) {
|
||||
ostringstream os2;
|
||||
int cause = resp->peekField(16, 8);
|
||||
delete resp;
|
||||
switch (cause) {
|
||||
case 97:
|
||||
LOG(INFO) << "MS says: message not implemented";
|
||||
// flag unsupported in SR so we don't waste time on it again
|
||||
os2 << "update sip_buddies set RRLPSupported = \"0\" where name = \"" << name << "\"";
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
|
||||
LOG(INFO) << "sqlite3_command problem";
|
||||
}
|
||||
return false;
|
||||
case 98:
|
||||
LOG(INFO) << "MS says: message type not compatible with protocol state";
|
||||
return false;
|
||||
default:
|
||||
LOG(INFO) << "unknown RR_STATUS response, cause = " << cause;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const unsigned MTI_RR_APDU = 56;
|
||||
if (resp->MTI() != MTI_RR_APDU) {
|
||||
LOG(INFO) << "received unexpected RR Message " << resp->MTI();
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
|
||||
// looks like a good APDU
|
||||
BitVector *bv2 = (BitVector*)resp;
|
||||
BitVector bv3 = bv2->tail(32);
|
||||
ostringstream os;
|
||||
bv3.hex(os);
|
||||
apdu = os.str();
|
||||
delete resp;
|
||||
|
||||
// next query for server
|
||||
query = "query=apdu&apdu=" + apdu;
|
||||
}
|
||||
// not reached
|
||||
}
|
||||
|
||||
/**
|
||||
Controller for the Location Updating transaction, GSM 04.08 4.4.4.
|
||||
@param lur The location updating request.
|
||||
|
||||
274
Control/RRLPServer.cpp
Normal file
274
Control/RRLPServer.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
/**@file RRLPServer */
|
||||
/*
|
||||
* Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
* Copyright 2011 Range Networks, 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 <Timeval.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "ControlCommon.h"
|
||||
#include "RRLPServer.h"
|
||||
|
||||
#include <GSMLogicalChannel.h>
|
||||
#include <GSML3MMMessages.h>
|
||||
|
||||
#include <Logger.h>
|
||||
|
||||
using namespace GSM;
|
||||
using namespace Control;
|
||||
|
||||
void clean(char *line)
|
||||
{
|
||||
char *p = line + strlen(line) - 1;
|
||||
while (p > line && *p <= ' ') *p-- = 0;
|
||||
}
|
||||
|
||||
string getConfig()
|
||||
{
|
||||
const char *configs[] = {
|
||||
"GSM.RRLP.ACCURACY",
|
||||
"GSM.RRLP.RESPONSETIME",
|
||||
"GSM.RRLP.ALMANAC.URL",
|
||||
"GSM.RRLP.EPHEMERIS.URL",
|
||||
"GSM.RRLP.ALMANAC.REFRESH.TIME",
|
||||
"GSM.RRLP.EPHEMERIS.REFRESH.TIME",
|
||||
"GSM.RRLP.SEED.LATITUDE",
|
||||
"GSM.RRLP.SEED.LONGITUDE",
|
||||
"GSM.RRLP.SEED.ALTITUDE",
|
||||
"GSM.RRLP.EPHEMERIS.ASSIST.COUNT",
|
||||
"GSM.RRLP.ALMANAC.ASSIST.PRESENT",
|
||||
0
|
||||
};
|
||||
string config = "";
|
||||
for (const char **p = configs; *p; p++) {
|
||||
string configValue = gConfig.getStr(*p, "");
|
||||
if (configValue.length() == 0) return "";
|
||||
config.append("&");
|
||||
config.append(*p);
|
||||
config.append("=");
|
||||
if (0 == strcmp((*p) + strlen(*p) - 3, "URL")) {
|
||||
// TODO - better to have urlencode and decode, but then I'd have to look for them
|
||||
char buf[3];
|
||||
buf[2] = 0;
|
||||
for (const char *q = configValue.c_str(); *q; q++) {
|
||||
sprintf(buf, "%02x", *q);
|
||||
config.append(buf);
|
||||
}
|
||||
} else {
|
||||
config.append(configValue);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
RRLPServer::RRLPServer(L3MobileIdentity wMobileID, LogicalChannel *wDCCH)
|
||||
{
|
||||
trouble = false;
|
||||
url = gConfig.getStr("GSM.RRLP.SERVER.URL", "");
|
||||
if (url.length() == 0) {
|
||||
LOG(INFO) << "RRLP not configured";
|
||||
trouble = true;
|
||||
return;
|
||||
}
|
||||
mobileID = wMobileID;
|
||||
DCCH = wDCCH;
|
||||
// name of subscriber
|
||||
name = string("IMSI") + mobileID.digits();
|
||||
// don't continue if IMSI has a RRLP support flag and it's false
|
||||
unsigned int supported = 0;
|
||||
if (false && sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "name", name.c_str(),
|
||||
"RRLPSupported", supported) && !supported) {
|
||||
LOG(INFO) << "RRLP not supported for " << name;
|
||||
trouble = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool RRLPServer::assist()
|
||||
{
|
||||
if (trouble) return false;
|
||||
query = "query=assist";
|
||||
return transact();
|
||||
}
|
||||
|
||||
bool RRLPServer::locate()
|
||||
{
|
||||
if (trouble) return false;
|
||||
query = "query=loc";
|
||||
return transact();
|
||||
}
|
||||
|
||||
bool RRLPServer::transact()
|
||||
{
|
||||
vector<string> apdus;
|
||||
while (true) {
|
||||
// bounce off server
|
||||
string esc = "'";
|
||||
string config = getConfig();
|
||||
if (config.length() == 0) return false;
|
||||
string cmd = "wget -qO- " + esc + url + "?" + query + config + esc;
|
||||
LOG(INFO) << "*************** " << cmd;
|
||||
FILE *result = popen(cmd.c_str(), "r");
|
||||
if (!result) {
|
||||
LOG(CRIT) << "popen call \"" << cmd << "\" failed";
|
||||
return NULL;
|
||||
}
|
||||
// build map of responses, and list of apdus
|
||||
map<string,string> response;
|
||||
size_t nbytes = 1500;
|
||||
char *line = (char*)malloc(nbytes+1);
|
||||
while (!feof(result)) {
|
||||
if (!fgets(line, nbytes, result)) break;
|
||||
clean(line);
|
||||
LOG(INFO) << "server return: " << line;
|
||||
char *p = strchr(line, '=');
|
||||
if (!p) continue;
|
||||
string lhs = string(line, 0, p-line);
|
||||
string rhs = string(line, p+1-line, string::npos);
|
||||
if (lhs == "apdu") {
|
||||
apdus.push_back(rhs);
|
||||
} else {
|
||||
response[lhs] = rhs;
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
pclose(result);
|
||||
|
||||
// quit if error
|
||||
if (response.find("error") != response.end()) {
|
||||
LOG(INFO) << "error from server: " << response["error"];
|
||||
return false;
|
||||
}
|
||||
|
||||
// quit if ack from assist unless there are more apdu messages
|
||||
if (response.find("ack") != response.end()) {
|
||||
LOG(INFO) << "ack from mobile, decoded by server";
|
||||
if (apdus.size() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
LOG(INFO) << "more apdu messages";
|
||||
}
|
||||
}
|
||||
|
||||
// quit if location decoded
|
||||
if (response.find("latitude") != response.end() && response.find("longitude") != response.end() && response.find("positionError") != response.end()) {
|
||||
ostringstream os;
|
||||
os << "insert into RRLP (name, latitude, longitude, error, time) values (" <<
|
||||
'"' << name << '"' << "," <<
|
||||
response["latitude"] << "," <<
|
||||
response["longitude"] << "," <<
|
||||
response["positionError"] << "," <<
|
||||
"datetime('now')"
|
||||
")";
|
||||
LOG(INFO) << os.str();
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) {
|
||||
LOG(INFO) << "sqlite3_command problem";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// bounce off mobile
|
||||
if (apdus.size() == 0) {
|
||||
LOG(INFO) << "missing apdu for mobile";
|
||||
return false;
|
||||
}
|
||||
string apdu = apdus[0];
|
||||
apdus.erase(apdus.begin());
|
||||
BitVector bv(apdu.size()*4);
|
||||
if (!bv.unhex(apdu.c_str())) {
|
||||
LOG(INFO) << "BitVector::unhex problem";
|
||||
return false;
|
||||
}
|
||||
|
||||
DCCH->send(L3ApplicationInformation(bv));
|
||||
// Receive an L3 frame with a timeout. Timeout loc req response time max + 2 seconds.
|
||||
L3Frame* resp = DCCH->recv(130000);
|
||||
if (!resp) {
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "RRLPQuery returned " << *resp;
|
||||
if (resp->primitive() != DATA) {
|
||||
LOG(INFO) << "didn't receive data";
|
||||
switch (resp->primitive()) {
|
||||
case ESTABLISH: LOG(INFO) << "channel establihsment"; break;
|
||||
case RELEASE: LOG(INFO) << "normal channel release"; break;
|
||||
case DATA: LOG(INFO) << "multiframe data transfer"; break;
|
||||
case UNIT_DATA: LOG(INFO) << "datagram-type data transfer"; break;
|
||||
case ERROR: LOG(INFO) << "channel error"; break;
|
||||
case HARDRELEASE: LOG(INFO) << "forced release after an assignment"; break;
|
||||
default: LOG(INFO) << "unrecognized primitive response"; break;
|
||||
}
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
const unsigned PD_RR = 6;
|
||||
LOG(INFO) << "resp.pd = " << resp->PD();
|
||||
if (resp->PD() != PD_RR) {
|
||||
LOG(INFO) << "didn't receive an RR message";
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
const unsigned MTI_RR_STATUS = 18;
|
||||
if (resp->MTI() == MTI_RR_STATUS) {
|
||||
ostringstream os2;
|
||||
int cause = resp->peekField(16, 8);
|
||||
delete resp;
|
||||
switch (cause) {
|
||||
case 97:
|
||||
LOG(INFO) << "MS says: message not implemented";
|
||||
// flag unsupported in SR so we don't waste time on it again
|
||||
os2 << "update sip_buddies set RRLPSupported = \"0\" where name = \"" << name << "\"";
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
|
||||
LOG(INFO) << "sqlite3_command problem";
|
||||
}
|
||||
return false;
|
||||
case 98:
|
||||
LOG(INFO) << "MS says: message type not compatible with protocol state";
|
||||
return false;
|
||||
default:
|
||||
LOG(INFO) << "unknown RR_STATUS response, cause = " << cause;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const unsigned MTI_RR_APDU = 56;
|
||||
if (resp->MTI() != MTI_RR_APDU) {
|
||||
LOG(INFO) << "received unexpected RR Message " << resp->MTI();
|
||||
delete resp;
|
||||
return false;
|
||||
}
|
||||
|
||||
// looks like a good APDU
|
||||
BitVector *bv2 = (BitVector*)resp;
|
||||
BitVector bv3 = bv2->tail(32);
|
||||
ostringstream os;
|
||||
bv3.hex(os);
|
||||
apdu = os.str();
|
||||
delete resp;
|
||||
|
||||
// next query for server
|
||||
query = "query=apdu&apdu=" + apdu;
|
||||
}
|
||||
// not reached
|
||||
}
|
||||
|
||||
54
Control/RRLPServer.h
Normal file
54
Control/RRLPServer.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**@file RRLPServer */
|
||||
/*
|
||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright 2010 Kestrel Signal Processing, 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/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RRLPSERVER_H
|
||||
#define RRLPSERVER_H
|
||||
|
||||
namespace GSM {
|
||||
class LogicalChannel;
|
||||
class L3MobileIdentity;
|
||||
};
|
||||
|
||||
class RRLPServer
|
||||
{
|
||||
public:
|
||||
RRLPServer(GSM::L3MobileIdentity wMobileID, GSM::LogicalChannel *wDCCH);
|
||||
// tell server to send location assistance to mobile
|
||||
bool assist();
|
||||
// tell server to ask mobile for location
|
||||
bool locate();
|
||||
private:
|
||||
RRLPServer(); // not allowed
|
||||
string url;
|
||||
GSM::L3MobileIdentity mobileID;
|
||||
GSM::LogicalChannel *DCCH;
|
||||
string query;
|
||||
string name;
|
||||
bool transact();
|
||||
bool trouble;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "SMSControl.h"
|
||||
#include "ControlCommon.h"
|
||||
#include "TransactionTable.h"
|
||||
#include "RRLPServer.h"
|
||||
#include <Regexp.h>
|
||||
|
||||
|
||||
@@ -455,6 +456,19 @@ void Control::MTSMSController(TransactionEntry *transaction, GSM::LogicalChannel
|
||||
transaction->GSMState(GSM::SMSDelivering);
|
||||
LOG(INFO) << "transaction: "<< *transaction;
|
||||
|
||||
/* first RLLP request */
|
||||
if (gConfig.defines("Control.SMS.QueryRRLP")) {
|
||||
// Query for RRLP
|
||||
RRLPServer wRRLPServer(transaction->subscriber(), LCH);
|
||||
if (!wRRLPServer.assist()) {
|
||||
LOG(INFO) << "RRLPServer::assist problem";
|
||||
}
|
||||
// can still try to check location even if assist didn't work
|
||||
if (!wRRLPServer.locate()) {
|
||||
LOG(INFO) << "RRLPServer::locate problem";
|
||||
}
|
||||
}
|
||||
|
||||
bool success = deliverSMSToMS(transaction->calling().digits(),transaction->message(),
|
||||
transaction->messageType(),transaction->L3TI(),LCH);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user