From ec026dfe2eebfbe7c8bd77f7943fa855c2d4f095 Mon Sep 17 00:00:00 2001 From: Kurtis Heimerl Date: Sat, 25 Feb 2012 21:07:11 +0000 Subject: [PATCH] Fixes #692 in public. This updates the SR (ip/port) for a user on every SIP transaction. Also standardizes SR interface to use just strings, no more external char*. Will modify actual SR later. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3236 19bc5d8c-e614-43d4-8b26-e1612bc8e597 --- Control/MobilityManagement.cpp | 19 +++--- Control/RRLPServer.cpp | 30 +++------ SIP/SIPInterface.cpp | 10 +++ SR/SubscriberRegistry.cpp | 110 +++++++++++++++++++-------------- SR/SubscriberRegistry.h | 75 +++++++++++----------- 5 files changed, 129 insertions(+), 115 deletions(-) diff --git a/Control/MobilityManagement.cpp b/Control/MobilityManagement.cpp index 0812c1e..fbd3e7f 100644 --- a/Control/MobilityManagement.cpp +++ b/Control/MobilityManagement.cpp @@ -201,26 +201,25 @@ void Control::LocationUpdatingController(const L3LocationUpdatingRequest* lur, L throw UnexpectedMessage(); } LOG(INFO) << *resp; - const char* new_imei = resp->mobileID().digits(); - if (!gTMSITable.IMEI(IMSI,new_imei)){ + string new_imei = resp->mobileID().digits(); + if (!gTMSITable.IMEI(IMSI,new_imei.c_str())){ LOG(WARNING) << "failed access to TMSITable"; } //query subscriber registry for old imei, update if neccessary string name = string("IMSI") + IMSI; - char* old_imei = gSubscriberRegistry.sqlQuery("hardware", "sip_buddies", "name", name.c_str()); + string old_imei = gSubscriberRegistry.imsiGet(name, "hardware"); //if we have a new imei and either there's no old one, or it is different... - if (new_imei && (!old_imei || strncmp(old_imei,new_imei, 15) != 0)){ - ostringstream os2; - os2 << "update sip_buddies set RRLPSupported = \"1\", hardware = \"" << new_imei << "\" where name = \"IMSI" << IMSI << "\""; + if (!new_imei.empty() && (old_imei.empty() || old_imei != new_imei)){ LOG(INFO) << "Updating IMSI" << IMSI << " to IMEI:" << new_imei; - if (!gSubscriberRegistry.sqlUpdate(os2.str().c_str())) { - LOG(INFO) << "SR update problem"; + if (!gSubscriberRegistry.imsiSet(name,"RRLPSupported", "1")) { + LOG(INFO) << "SR RRLPSupported update problem"; + } + if (!gSubscriberRegistry.imsiSet(name,"hardware", new_imei)) { + LOG(INFO) << "SR hardware update problem"; } } - if (old_imei) - free(old_imei); delete msg; } diff --git a/Control/RRLPServer.cpp b/Control/RRLPServer.cpp index 0c77723..becb0e3 100644 --- a/Control/RRLPServer.cpp +++ b/Control/RRLPServer.cpp @@ -100,14 +100,9 @@ RRLPServer::RRLPServer(L3MobileIdentity wMobileID, LogicalChannel *wDCCH) //if IMEI tagging enabled, check if this IMEI (which is updated elsewhere) has RRLP disabled //otherwise just go on if (gConfig.defines("Control.LUR.QueryIMEI")){ - unsigned int supported = 0; - char* supported_str; //check supported bit - supported_str = gSubscriberRegistry.sqlQuery("RRLPSupported", "sip_buddies", "name", name.c_str()); - if (supported_str) - supported = atoi(supported_str); - free(supported_str); - if(!supported){ + string supported= gSubscriberRegistry.imsiGet(name, "RRLPSupported"); + if(supported.empty() || supported == "0"){ LOG(INFO) << "RRLP not supported for " << name; trouble = true; } @@ -181,17 +176,12 @@ bool RRLPServer::transact() } // 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 (!gSubscriberRegistry.sqlUpdate(os.str().c_str())) { + if (response.find("latitude") != response.end() && + response.find("longitude") != response.end() && + response.find("positionError") != response.end()) { + if (!gSubscriberRegistry.RRLPUpdate(name, response["latitude"], + response["longitude"], + response["positionError"])){ LOG(INFO) << "SR update problem"; return false; } @@ -241,7 +231,6 @@ bool RRLPServer::transact() } const unsigned MTI_RR_STATUS = 18; if (resp->MTI() == MTI_RR_STATUS) { - ostringstream os2; int cause = resp->peekField(16, 8); delete resp; switch (cause) { @@ -250,8 +239,7 @@ bool RRLPServer::transact() //Rejection code only useful if we're gathering IMEIs if (gConfig.defines("Control.LUR.QueryIMEI")){ // flag unsupported in SR so we don't waste time on it again - os2 << "update sip_buddies set RRLPSupported = \"0\" where name = \"" << name.c_str() << "\""; - if (!gSubscriberRegistry.sqlUpdate(os2.str().c_str())) { + if (!gSubscriberRegistry.imsiSet(name, "RRLPSupported", "0")) { LOG(INFO) << "SR update problem"; } } diff --git a/SIP/SIPInterface.cpp b/SIP/SIPInterface.cpp index ed59135..8a038b7 100644 --- a/SIP/SIPInterface.cpp +++ b/SIP/SIPInterface.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -59,6 +60,15 @@ using namespace Control; void SIPMessageMap::write(const std::string& call_id, osip_message_t * msg) { LOG(DEBUG) << "call_id=" << call_id << " msg=" << msg; + string name = osip_message_get_from(msg)->url->username; + if (!gSubscriberRegistry.imsiSet(name, "ipaddr", + osip_message_get_from(msg)->url->host)){ + LOG(INFO) << "SR ipaddr Update Problem"; + } + if (!gSubscriberRegistry.imsiSet(name, "port", + gConfig.getStr("SIP.Local.Port"))){ + LOG(INFO) << "SR port Update Problem"; + } OSIPMessageFIFO * fifo = mMap.readNoBlock(call_id); if( fifo==NULL ) { // FIXME -- If this write fails, send "call leg non-existent" response on SIP interface. diff --git a/SR/SubscriberRegistry.cpp b/SR/SubscriberRegistry.cpp index d7e9cc6..4bcbf1f 100644 --- a/SR/SubscriberRegistry.cpp +++ b/SR/SubscriberRegistry.cpp @@ -187,7 +187,7 @@ SubscriberRegistry::~SubscriberRegistry() -SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr) +SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char* query, char **resultptr) { LOG(INFO) << query; @@ -219,36 +219,48 @@ SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char -char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue) +string SubscriberRegistry::sqlQuery(string unknownColumn, string table, string knownColumn, string knownValue) { char *result = NULL; SubscriberRegistry::Status st; ostringstream os; os << "select " << unknownColumn << " from " << table << " where " << knownColumn << " = \"" << knownValue << "\""; st = sqlLocal(os.str().c_str(), &result); - if (st == SUCCESS) { + if ((st == SUCCESS) && result) { LOG(INFO) << "result = " << result; return result; } else { - return NULL; + return ""; } } -SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt) +SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(string stmt) { LOG(INFO) << stmt; - return sqlLocal(stmt, NULL); + return sqlLocal(stmt.c_str(), NULL); } - - -char *SubscriberRegistry::getIMSI(const char *ISDN) +string SubscriberRegistry::imsiGet(string imsi, string key) { - if (!ISDN) { + string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; + return sqlQuery(key, "sip_buddies", "name", imsi); +} + +SubscriberRegistry::Status SubscriberRegistry::imsiSet(string imsi, string key, string value) +{ + string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; + ostringstream os; + os << "update sip_buddies set " << key << " = \"" << value << "\" where name = \"" << name << "\""; + return sqlUpdate(os.str()); +} + +string SubscriberRegistry::getIMSI(string ISDN) +{ + if (ISDN.empty()) { LOG(WARNING) << "SubscriberRegistry::getIMSI attempting lookup of NULL ISDN"; - return NULL; + return ""; } LOG(INFO) << "getIMSI(" << ISDN << ")"; return sqlQuery("dial", "dialdata_table", "exten", ISDN); @@ -256,11 +268,11 @@ char *SubscriberRegistry::getIMSI(const char *ISDN) -char *SubscriberRegistry::getCLIDLocal(const char* IMSI) +string SubscriberRegistry::getCLIDLocal(string IMSI) { - if (!IMSI) { + if (IMSI.empty()) { LOG(WARNING) << "SubscriberRegistry::getCLIDLocal attempting lookup of NULL IMSI"; - return NULL; + return ""; } LOG(INFO) << "getCLIDLocal(" << IMSI << ")"; return sqlQuery("callerid", "sip_buddies", "name", IMSI); @@ -268,11 +280,11 @@ char *SubscriberRegistry::getCLIDLocal(const char* IMSI) -char *SubscriberRegistry::getCLIDGlobal(const char* IMSI) +string SubscriberRegistry::getCLIDGlobal(string IMSI) { - if (!IMSI) { + if (IMSI.empty()) { LOG(WARNING) << "SubscriberRegistry::getCLIDGlobal attempting lookup of NULL IMSI"; - return NULL; + return ""; } LOG(INFO) << "getCLIDGlobal(" << IMSI << ")"; return sqlQuery("callerid", "sip_buddies", "name", IMSI); @@ -280,11 +292,11 @@ char *SubscriberRegistry::getCLIDGlobal(const char* IMSI) -char *SubscriberRegistry::getRegistrationIP(const char* IMSI) +string SubscriberRegistry::getRegistrationIP(string IMSI) { - if (!IMSI) { + if (IMSI.empty()) { LOG(WARNING) << "SubscriberRegistry::getRegistrationIP attempting lookup of NULL IMSI"; - return NULL; + return ""; } LOG(INFO) << "getRegistrationIP(" << IMSI << ")"; return sqlQuery("ipaddr", "sip_buddies", "name", IMSI); @@ -292,40 +304,33 @@ char *SubscriberRegistry::getRegistrationIP(const char* IMSI) -SubscriberRegistry::Status SubscriberRegistry::setRegTime(const char* IMSI) +SubscriberRegistry::Status SubscriberRegistry::setRegTime(string IMSI) { - if (!IMSI) { + if (IMSI.empty()) { LOG(WARNING) << "SubscriberRegistry::setRegTime attempting set for NULL IMSI"; return FAILURE; } unsigned now = (unsigned)time(NULL); ostringstream os; os << "update sip_buddies set regTime = " << now << " where name = " << '"' << IMSI << '"'; - return sqlUpdate(os.str().c_str()); + return sqlUpdate(os.str()); } -SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const char* CLID) +SubscriberRegistry::Status SubscriberRegistry::addUser(string IMSI, string CLID) { - if (!IMSI) { + if (IMSI.empty()) { LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI"; return FAILURE; } - if (!CLID) { + if (CLID.empty()) { LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL CLID"; return FAILURE; } - //this was a memory leak -kurtis - char* old_imsi = getIMSI(CLID); - char* old_clid = getCLIDLocal(IMSI); - if (old_imsi || old_clid) { + if (!getIMSI(CLID).empty() || !getCLIDLocal(IMSI).empty()) { LOG(WARNING) << "SubscriberRegistry::addUser attempting user duplication"; - // technically this is a failure, but I don't want it to keep trying - if (old_imsi) - free(old_imsi); - if (old_clid) - free(old_clid); + //technically failure, but let's move on return SUCCESS; } LOG(INFO) << "addUser(" << IMSI << "," << CLID << ")"; @@ -352,40 +357,49 @@ SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const c os << "\"" << "127.0.0.1" << "\""; os << ")"; os << ";"; - SubscriberRegistry::Status st = sqlUpdate(os.str().c_str()); + SubscriberRegistry::Status st = sqlUpdate(os.str()); ostringstream os2; os2 << "insert into dialdata_table (exten, dial) values ("; os2 << "\"" << CLID << "\""; os2 << ","; os2 << "\"" << IMSI << "\""; os2 << ")"; - SubscriberRegistry::Status st2 = sqlUpdate(os2.str().c_str()); + SubscriberRegistry::Status st2 = sqlUpdate(os2.str()); return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE; } -char *SubscriberRegistry::mapCLIDGlobal(const char *local) +string SubscriberRegistry::mapCLIDGlobal(string local) { - if (!local) { + if (local.empty()) { LOG(WARNING) << "SubscriberRegistry::mapCLIDGlobal attempting lookup of NULL local"; - return NULL; + return ""; } LOG(INFO) << "mapCLIDGlobal(" << local << ")"; - char *IMSI = getIMSI(local); - if (!IMSI) return NULL; - char *global = getCLIDGlobal(IMSI); - free(IMSI); - return global; + string IMSI = getIMSI(local); + if (IMSI.empty()) return ""; + return getCLIDGlobal(IMSI); } +SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string lat, string lon, string err){ + ostringstream os; + os << "insert into RRLP (name, latitude, longitude, error, time) values (" << + '"' << name << '"' << "," << + lat << "," << + lon << "," << + err << "," << + "datetime('now')" + ")"; + LOG(INFO) << os.str(); + return sqlUpdate(os.str()); +} - -bool SubscriberRegistry::useGateway(const char* ISDN) +bool SubscriberRegistry::useGateway(string ISDN) { // FIXME -- Do something more general in Asterisk. // This is a hack for Burning Man. - int cmp = strncmp(ISDN,"88351000125",11); + int cmp = strncmp(ISDN.c_str(),"88351000125",11); return cmp!=0; } diff --git a/SR/SubscriberRegistry.h b/SR/SubscriberRegistry.h index e11e0e4..c0c7547 100644 --- a/SR/SubscriberRegistry.h +++ b/SR/SubscriberRegistry.h @@ -72,77 +72,74 @@ class SubscriberRegistry { /** Resolve an ISDN or other numeric address to an IMSI. @param ISDN Any numeric address, E.164, local extension, etc. - @return A C-string to be freed by the caller, - NULL if the ISDN cannot be resolved. */ - char* getIMSI(const char* ISDN); + string getIMSI(string ISDN); /** Given an IMSI, return the local CLID, which should be a numeric address. @param IMSI The subscriber IMSI. - @return A C-string to be freed by the caller, - NULL if the IMSI isn't found. */ - char* getCLIDLocal(const char* IMSI); + string getCLIDLocal(string IMSI); /** Given an IMSI, return the global CLID, which should be a numeric address. @param IMSI The subscriber IMSI. - @return A C-string to be freed by the caller, - NULL if the IMSI isn't found. + */ - char* getCLIDGlobal(const char* IMSI); + string getCLIDGlobal(string IMSI); /** Given an IMSI, return the IP address of the most recent registration. @param IMSI The subscriber IMSI - @return A C-string to be freed by the caller, "111.222.333.444:port", - NULL if the ISMI isn't registered. + @return The Registration IP for this IMSI, "111.222.333.444:port", + */ - char* getRegistrationIP(const char* IMSI); + string getRegistrationIP(string IMSI); + + /** + Set a specific variable indexed by imsi from sip_buddies + @param imsi The user's IMSI or SIP username. + @param key to index into table + */ + string imsiGet(string imsi, string key); + + /** + Set a specific variable indexed by imsi_from sip_buddies + @param imsi The user's IMSI or SIP username. + @param key to index into table + @param value to set indexed by the key + */ + Status imsiSet(string imsi, string key, string value); /** Add a new user to the SubscriberRegistry. @param IMSI The user's IMSI or SIP username. @param CLID The user's local CLID. */ - Status addUser(const char* IMSI, const char* CLID); + Status addUser(string IMSI, string CLID); /** Set the current time as the time of the most recent registration for an IMSI. @param IMSI The user's IMSI or SIP username. */ - Status setRegTime(const char* IMSI); + Status setRegTime(string IMSI); - char *mapCLIDGlobal(const char *local); + string mapCLIDGlobal(string local); - bool useGateway(const char* ISDN); - - - /* Generic Update/Get functions. - Make sure your SQL is generic too */ - /** - Run an sql query (select unknownColumn from table where knownColumn = knownValue). - @param unknownColumn The column whose value you want. - @param table The table to look in. - @param knownColumn The column with the value you know. - @param knownValue The known value of knownColumn. - */ - char *sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue); - + bool useGateway(string ISDN); /** - Run an sql update. - @param stmt The update statement. + Update the RRLP location for user + @param name IMSI to be updated + @param lat Latitude + @param lon Longitude + @param err Approximate Error */ - Status sqlUpdate(const char *stmt); - - - + Status RRLPUpdate(string name, string lat, string lon, string err); private: @@ -152,9 +149,15 @@ class SubscriberRegistry { @param stmt The sql statements. @param resultptr Set this to point to the result of executing the statements. */ - Status sqlLocal(const char *stmt, char **resultptr); + Status sqlLocal(const char* stmt, char **resultptr); + string sqlQuery(string unknownColumn, string table, string knownColumn, string knownValue); + /** + Run an sql update. + @param stmt The update statement. + */ + Status sqlUpdate(string stmt); };