mirror of
https://github.com/PentHertz/OpenBTS.git
synced 2026-05-10 12:00:03 +00:00
r4677 in commercial:
syncing SR across trees. Will merge later. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@5477 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
parent
d21140203b
commit
40e14f52a3
2 changed files with 351 additions and 87 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
* Copyright 2011 Free Software Foundation, Inc.
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011, 2012 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.
|
||||
|
|
@ -59,6 +59,10 @@ static const char* createDDTable = {
|
|||
")"
|
||||
};
|
||||
|
||||
static const char* createRateTable = {
|
||||
"create table if not exists rates (service varchar(30) not null, rate integer not null)"
|
||||
};
|
||||
|
||||
static const char* createSBTable = {
|
||||
"CREATE TABLE IF NOT EXISTS SIP_BUDDIES ("
|
||||
"id integer primary key, "
|
||||
|
|
@ -79,7 +83,7 @@ static const char* createSBTable = {
|
|||
"callgroup VARCHAR(10), "
|
||||
"callerid VARCHAR(80), "
|
||||
"defaultip VARCHAR(40) DEFAULT '0.0.0.0', "
|
||||
"dtmfmode VARCHAR(7) DEFAULT 'rfc2833', "
|
||||
"dtmfmode VARCHAR(7) DEFAULT 'info', "
|
||||
"fromuser VARCHAR(80), "
|
||||
"fromdomain VARCHAR(80), "
|
||||
"insecure VARCHAR(4), "
|
||||
|
|
@ -92,10 +96,10 @@ static const char* createSBTable = {
|
|||
"rtpholdtimeout CHAR(3), "
|
||||
"setvar VARCHAR(100), "
|
||||
"disallow VARCHAR(100) DEFAULT 'all', "
|
||||
"allow VARCHAR(100) DEFAULT 'g729;ilbc;gsm;ulaw;alaw' not null, "
|
||||
"allow VARCHAR(100) DEFAULT 'gsm' not null, "
|
||||
"fullcontact VARCHAR(80), "
|
||||
"ipaddr VARCHAR(45), "
|
||||
"port int(5) DEFAULT 0, "
|
||||
"port int(5) DEFAULT 5062, "
|
||||
"username VARCHAR(80), "
|
||||
"defaultuser VARCHAR(80), "
|
||||
"subscribecontext VARCHAR(80), "
|
||||
|
|
@ -106,10 +110,10 @@ static const char* createSBTable = {
|
|||
"promiscredir VARCHAR(3), "
|
||||
"useclientcode VARCHAR(3), "
|
||||
"callcounter VARCHAR(3), "
|
||||
"busylevel int(11), "
|
||||
"allowoverlap VARCHAR(3) DEFAULT 'yes', "
|
||||
"allowsubscribe VARCHAR(3) DEFAULT 'yes', "
|
||||
"allowtransfer VARCHAR(3) DEFAULT 'yes', "
|
||||
"busylevel int(11) default 1, "
|
||||
"allowoverlap VARCHAR(3) DEFAULT 'no', "
|
||||
"allowsubscribe VARCHAR(3) DEFAULT 'no', "
|
||||
"allowtransfer VARCHAR(3) DEFAULT 'no', "
|
||||
"ignoresdpversion VARCHAR(3) DEFAULT 'no', "
|
||||
"template VARCHAR(100), "
|
||||
"videosupport VARCHAR(6) DEFAULT 'no', "
|
||||
|
|
@ -133,20 +137,22 @@ static const char* createSBTable = {
|
|||
"regseconds int(11) DEFAULT 0 not null, "
|
||||
"useragent VARCHAR(100), "
|
||||
"cancallforward CHAR(3) DEFAULT 'yes' not null, "
|
||||
"canreinvite CHAR(3) DEFAULT 'yes' not null, "
|
||||
"canreinvite CHAR(3) DEFAULT 'no' not null, "
|
||||
"mask VARCHAR(95), "
|
||||
"musiconhold VARCHAR(100), "
|
||||
"restrictcid CHAR(3), "
|
||||
"calllimit int(5), "
|
||||
"calllimit int(5) default 1, "
|
||||
"WhiteListFlag timestamp not null default '0', "
|
||||
"WhiteListCode varchar(8) not null default '0', "
|
||||
"rand varchar(33) default '', "
|
||||
"sres varchar(33) default '', "
|
||||
"ki varchar(33) default '', "
|
||||
"kc varchar(33) default '', "
|
||||
"prepaid int(1) DEFAULT 0 not null, " // flag to indicate prepaid customer
|
||||
"account_balance int(9) default 0 not null, " // current account, neg is debt, pos is credit
|
||||
"RRLPSupported int(1) default 1 not null, "
|
||||
"hardware VARCHAR(20), "
|
||||
"regTime INTEGER default 0 NOT NULL," // Unix time of most recent registration
|
||||
"hardware VARCHAR(20), "
|
||||
"regTime INTEGER default 0 NOT NULL, " // Unix time of most recent registration
|
||||
"a3_a8 varchar(45) default NULL"
|
||||
")"
|
||||
};
|
||||
|
|
@ -155,26 +161,49 @@ static const char* createSBTable = {
|
|||
int SubscriberRegistry::init()
|
||||
{
|
||||
string ldb = gConfig.getStr("SubscriberRegistry.db");
|
||||
size_t p = ldb.find_last_of('/');
|
||||
if (p == string::npos) {
|
||||
LOG(EMERG) << "SubscriberRegistry.db not in a directory?";
|
||||
mDB = NULL;
|
||||
return 1;
|
||||
}
|
||||
string dir = ldb.substr(0, p);
|
||||
struct stat buf;
|
||||
if (stat(dir.c_str(), &buf)) {
|
||||
LOG(EMERG) << dir << " does not exist";
|
||||
mDB = NULL;
|
||||
return 1;
|
||||
}
|
||||
int rc = sqlite3_open(ldb.c_str(),&mDB);
|
||||
if (rc) {
|
||||
LOG(EMERG) << "Cannot open SubscriberRegistry database: " << sqlite3_errmsg(mDB);
|
||||
LOG(EMERG) << "Cannot open SubscriberRegistry database: " << ldb << " error: " << sqlite3_errmsg(mDB);
|
||||
sqlite3_close(mDB);
|
||||
mDB = NULL;
|
||||
return FAILURE;
|
||||
return 1;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createRRLPTable)) {
|
||||
LOG(EMERG) << "Cannot create RRLP table";
|
||||
return FAILURE;
|
||||
return 1;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createDDTable)) {
|
||||
LOG(EMERG) << "Cannot create DIALDATA_TABLE table";
|
||||
return FAILURE;
|
||||
return 1;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createRateTable)) {
|
||||
LOG(EMERG) << "Cannot create rate table";
|
||||
return 1;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createSBTable)) {
|
||||
LOG(EMERG) << "Cannot create SIP_BUDDIES table";
|
||||
return FAILURE;
|
||||
return 1;
|
||||
}
|
||||
return SUCCESS;
|
||||
if (!getCLIDLocal("IMSI001010000000000")) {
|
||||
// This is a test SIM provided with the BTS.
|
||||
if (addUser("IMSI001010000000000", "2100") != SUCCESS) {
|
||||
LOG(EMERG) << "Cannot insert test SIM";
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -184,10 +213,7 @@ SubscriberRegistry::~SubscriberRegistry()
|
|||
if (mDB) sqlite3_close(mDB);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char* query, char **resultptr)
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr)
|
||||
{
|
||||
LOG(INFO) << query;
|
||||
|
||||
|
|
@ -198,7 +224,7 @@ SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char* query, char
|
|||
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_statement(db(), &stmt, query)) {
|
||||
LOG(ERR) << "sqlite3_prepare_statement problem";
|
||||
LOG(ERR) << "sqlite3_prepare_statement problem with query \"" << query << "\"";
|
||||
return FAILURE;
|
||||
}
|
||||
int src = sqlite3_run_query(db(), stmt);
|
||||
|
|
@ -219,48 +245,53 @@ SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char* query, char
|
|||
|
||||
|
||||
|
||||
string SubscriberRegistry::sqlQuery(string unknownColumn, string table, string knownColumn, string knownValue)
|
||||
char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue)
|
||||
{
|
||||
char *result = NULL;
|
||||
SubscriberRegistry::Status st;
|
||||
ostringstream os;
|
||||
os << "select " << unknownColumn << " from " << table << " where " << knownColumn << " = \"" << knownValue << "\"";
|
||||
// try to find locally
|
||||
st = sqlLocal(os.str().c_str(), &result);
|
||||
if ((st == SUCCESS) && result) {
|
||||
// got it. return it.
|
||||
LOG(INFO) << "result = " << result;
|
||||
return result;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
LOG(INFO) << "not found: " << os.str();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(string stmt)
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt)
|
||||
{
|
||||
LOG(INFO) << stmt;
|
||||
return sqlLocal(stmt.c_str(), NULL);
|
||||
SubscriberRegistry::Status st = sqlLocal(stmt, NULL);
|
||||
// status of local is only important one because asterisk talks to that db directly
|
||||
// must update local no matter what
|
||||
return st;
|
||||
}
|
||||
|
||||
string SubscriberRegistry::imsiGet(string imsi, string key)
|
||||
{
|
||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||
return sqlQuery(key, "sip_buddies", "name", imsi);
|
||||
return sqlQuery(key.c_str(), "sip_buddies", "name", imsi.c_str());
|
||||
}
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::imsiSet(string imsi, string key, string value)
|
||||
bool 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());
|
||||
return sqlUpdate(os.str().c_str()) == FAILURE;
|
||||
}
|
||||
|
||||
string SubscriberRegistry::getIMSI(string ISDN)
|
||||
char *SubscriberRegistry::getIMSI(const char *ISDN)
|
||||
{
|
||||
if (ISDN.empty()) {
|
||||
if (!ISDN) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getIMSI attempting lookup of NULL ISDN";
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getIMSI(" << ISDN << ")";
|
||||
return sqlQuery("dial", "dialdata_table", "exten", ISDN);
|
||||
|
|
@ -268,74 +299,69 @@ string SubscriberRegistry::getIMSI(string ISDN)
|
|||
|
||||
|
||||
|
||||
string SubscriberRegistry::getCLIDLocal(string IMSI)
|
||||
char *SubscriberRegistry::getCLIDLocal(const char* IMSI)
|
||||
{
|
||||
if (IMSI.empty()) {
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getCLIDLocal attempting lookup of NULL IMSI";
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getCLIDLocal(" << IMSI << ")";
|
||||
return sqlQuery("callerid", "sip_buddies", "name", IMSI);
|
||||
return sqlQuery("callerid", "sip_buddies", "username", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string SubscriberRegistry::getCLIDGlobal(string IMSI)
|
||||
char *SubscriberRegistry::getCLIDGlobal(const char* IMSI)
|
||||
{
|
||||
if (IMSI.empty()) {
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getCLIDGlobal attempting lookup of NULL IMSI";
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getCLIDGlobal(" << IMSI << ")";
|
||||
return sqlQuery("callerid", "sip_buddies", "name", IMSI);
|
||||
return sqlQuery("callerid", "sip_buddies", "username", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string SubscriberRegistry::getRegistrationIP(string IMSI)
|
||||
char *SubscriberRegistry::getRegistrationIP(const char* IMSI)
|
||||
{
|
||||
if (IMSI.empty()) {
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getRegistrationIP attempting lookup of NULL IMSI";
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getRegistrationIP(" << IMSI << ")";
|
||||
return sqlQuery("ipaddr", "sip_buddies", "name", IMSI);
|
||||
return sqlQuery("ipaddr", "sip_buddies", "username", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::setRegTime(string IMSI)
|
||||
SubscriberRegistry::Status SubscriberRegistry::setRegTime(const char* IMSI)
|
||||
{
|
||||
if (IMSI.empty()) {
|
||||
if (!IMSI) {
|
||||
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());
|
||||
os << "update sip_buddies set regTime = " << now << " where username = " << '"' << IMSI << '"';
|
||||
return sqlUpdate(os.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::addUser(string IMSI, string CLID)
|
||||
SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const char* CLID)
|
||||
{
|
||||
if (IMSI.empty()) {
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI";
|
||||
return FAILURE;
|
||||
}
|
||||
if (CLID.empty()) {
|
||||
if (!CLID) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL CLID";
|
||||
return FAILURE;
|
||||
}
|
||||
if (!getIMSI(CLID).empty() || !getCLIDLocal(IMSI).empty()) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting user duplication";
|
||||
//technically failure, but let's move on
|
||||
return SUCCESS;
|
||||
}
|
||||
LOG(INFO) << "addUser(" << IMSI << "," << CLID << ")";
|
||||
ostringstream os;
|
||||
os << "insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode, ipaddr) values (";
|
||||
os << "insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode, ipaddr, port) values (";
|
||||
os << "\"" << IMSI << "\"";
|
||||
os << ",";
|
||||
os << "\"" << IMSI << "\"";
|
||||
|
|
@ -355,31 +381,63 @@ SubscriberRegistry::Status SubscriberRegistry::addUser(string IMSI, string CLID)
|
|||
os << "\"" << "info" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "127.0.0.1" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "5062" << "\"";
|
||||
os << ")";
|
||||
os << ";";
|
||||
SubscriberRegistry::Status st = sqlUpdate(os.str());
|
||||
SubscriberRegistry::Status st = sqlUpdate(os.str().c_str());
|
||||
ostringstream os2;
|
||||
os2 << "insert into dialdata_table (exten, dial) values (";
|
||||
os2 << "\"" << CLID << "\"";
|
||||
os2 << ",";
|
||||
os2 << "\"" << IMSI << "\"";
|
||||
os2 << ")";
|
||||
SubscriberRegistry::Status st2 = sqlUpdate(os2.str());
|
||||
SubscriberRegistry::Status st2 = sqlUpdate(os2.str().c_str());
|
||||
return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// For handover. Only remove the local cache. BS2 will have updated the global.
|
||||
SubscriberRegistry::Status SubscriberRegistry::removeUser(const char* IMSI)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI";
|
||||
return FAILURE;
|
||||
}
|
||||
LOG(INFO) << "removeUser(" << IMSI << ")";
|
||||
string server = gConfig.getStr("SubscriberRegistry.UpstreamServer");
|
||||
if (server.length() == 0) {
|
||||
LOG(INFO) << "not removing user if no upstream server";
|
||||
return FAILURE;
|
||||
}
|
||||
ostringstream os;
|
||||
os << "delete from sip_buddies where name = ";
|
||||
os << "\"" << IMSI << "\"";
|
||||
os << ";";
|
||||
LOG(INFO) << os.str();
|
||||
SubscriberRegistry::Status st = sqlLocal(os.str().c_str(), NULL);
|
||||
ostringstream os2;
|
||||
os2 << "delete from dialdata_table where dial = ";
|
||||
os2 << "\"" << IMSI << "\"";
|
||||
LOG(INFO) << os2.str();
|
||||
SubscriberRegistry::Status st2 = sqlLocal(os2.str().c_str(), NULL);
|
||||
return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string SubscriberRegistry::mapCLIDGlobal(string local)
|
||||
char *SubscriberRegistry::mapCLIDGlobal(const char *local)
|
||||
{
|
||||
if (local.empty()) {
|
||||
if (!local) {
|
||||
LOG(WARNING) << "SubscriberRegistry::mapCLIDGlobal attempting lookup of NULL local";
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "mapCLIDGlobal(" << local << ")";
|
||||
string IMSI = getIMSI(local);
|
||||
if (IMSI.empty()) return "";
|
||||
return getCLIDGlobal(IMSI);
|
||||
char *IMSI = getIMSI(local);
|
||||
if (!IMSI) return NULL;
|
||||
char *global = getCLIDGlobal(IMSI);
|
||||
free(IMSI);
|
||||
return global;
|
||||
}
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string lat, string lon, string err){
|
||||
|
|
@ -392,20 +450,135 @@ SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string la
|
|||
"datetime('now')"
|
||||
")";
|
||||
LOG(INFO) << os.str();
|
||||
return sqlUpdate(os.str());
|
||||
return sqlUpdate(os.str().c_str());
|
||||
}
|
||||
|
||||
bool SubscriberRegistry::useGateway(string ISDN)
|
||||
void SubscriberRegistry::stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND)
|
||||
{
|
||||
assert(strRAND.size() == 32);
|
||||
string strhRAND = strRAND.substr(0, 16);
|
||||
string strlRAND = strRAND.substr(16, 16);
|
||||
stringstream ssh;
|
||||
ssh << hex << strhRAND;
|
||||
ssh >> *hRAND;
|
||||
stringstream ssl;
|
||||
ssl << hex << strlRAND;
|
||||
ssl >> *lRAND;
|
||||
}
|
||||
|
||||
string SubscriberRegistry::uintToString(uint64_t h, uint64_t l)
|
||||
{
|
||||
ostringstream os1;
|
||||
os1.width(16);
|
||||
os1.fill('0');
|
||||
os1 << hex << h;
|
||||
ostringstream os2;
|
||||
os2.width(16);
|
||||
os2.fill('0');
|
||||
os2 << hex << l;
|
||||
ostringstream os3;
|
||||
os3 << os1.str() << os2.str();
|
||||
return os3.str();
|
||||
}
|
||||
|
||||
string SubscriberRegistry::uintToString(uint32_t x)
|
||||
{
|
||||
ostringstream os;
|
||||
os.width(8);
|
||||
os.fill('0');
|
||||
os << hex << x;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool SubscriberRegistry::useGateway(const char* ISDN)
|
||||
{
|
||||
// FIXME -- Do something more general in Asterisk.
|
||||
// This is a hack for Burning Man.
|
||||
int cmp = strncmp(ISDN.c_str(),"88351000125",11);
|
||||
int cmp = strncmp(ISDN,"88351000125",11);
|
||||
return cmp!=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::setPrepaid(const char *IMSI, bool yes)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "update sip_buddies set prepaid = " << (yes ? 1 : 0) << " where username = " << '"' << IMSI << '"';
|
||||
return sqlUpdate(os.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::isPrepaid(const char *IMSI, bool &yes)
|
||||
{
|
||||
char *st = sqlQuery("prepaid", "sip_buddies", "username", IMSI);
|
||||
if (!st) {
|
||||
LOG(NOTICE) << "cannot get prepaid status for username " << IMSI;
|
||||
return FAILURE;
|
||||
}
|
||||
yes = *st == '1';
|
||||
free(st);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::balanceRemaining(const char *IMSI, int &balance)
|
||||
{
|
||||
char *st = sqlQuery("account_balance", "sip_buddies", "username", IMSI);
|
||||
if (!st) {
|
||||
LOG(NOTICE) << "cannot get balance for " << IMSI;
|
||||
return FAILURE;
|
||||
}
|
||||
balance = (int)strtol(st, (char **)NULL, 10);
|
||||
free(st);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::addMoney(const char *IMSI, int moneyToAdd)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "update sip_buddies set account_balance = account_balance + " << moneyToAdd << " where username = " << '"' << IMSI << '"';
|
||||
if (sqlUpdate(os.str().c_str()) == FAILURE) {
|
||||
LOG(NOTICE) << "cannot update rate for username " << IMSI;
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int SubscriberRegistry::serviceCost(const char* service)
|
||||
{
|
||||
char *rateSt = sqlQuery("rate", "rates", "service", service);
|
||||
if (!rateSt) {
|
||||
LOG(ALERT) << "cannot get rate for service " << service;
|
||||
return -1;
|
||||
}
|
||||
int rate = (int)strtol(rateSt, (char **)NULL, 10);
|
||||
free(rateSt);
|
||||
return rate;
|
||||
}
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::serviceUnits(const char *IMSI, const char* service, int &units)
|
||||
{
|
||||
int balance;
|
||||
Status stat = balanceRemaining(IMSI,balance);
|
||||
if (stat == FAILURE) return FAILURE;
|
||||
int rate = serviceCost(service);
|
||||
if (rate<0) return FAILURE;
|
||||
units = balance / rate;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// vim: ts=4 sw=4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Free Software Foundation, Inc.
|
||||
* Copyright 2011, 2012 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.
|
||||
|
|
@ -72,29 +72,34 @@ 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.
|
||||
*/
|
||||
string getIMSI(string ISDN);
|
||||
char* getIMSI(const char* 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.
|
||||
*/
|
||||
string getCLIDLocal(string IMSI);
|
||||
char* getCLIDLocal(const char* 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.
|
||||
*/
|
||||
string getCLIDGlobal(string IMSI);
|
||||
char* getCLIDGlobal(const char* IMSI);
|
||||
|
||||
/**
|
||||
Given an IMSI, return the IP address of the most recent registration.
|
||||
@param IMSI The subscriber IMSI
|
||||
@return The Registration IP for this IMSI, "111.222.333.444:port",
|
||||
|
||||
@return A C-string to be freed by the caller, "111.222.333.444:port",
|
||||
NULL if the ISMI isn't registered.
|
||||
*/
|
||||
string getRegistrationIP(string IMSI);
|
||||
char* getRegistrationIP(const char* IMSI);
|
||||
|
||||
/**
|
||||
Set a specific variable indexed by imsi from sip_buddies
|
||||
|
|
@ -109,28 +114,95 @@ class SubscriberRegistry {
|
|||
@param key to index into table
|
||||
@param value to set indexed by the key
|
||||
*/
|
||||
Status imsiSet(string imsi, string key, string value);
|
||||
bool 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(string IMSI, string CLID);
|
||||
Status addUser(const char* IMSI, const char* CLID);
|
||||
|
||||
|
||||
/**
|
||||
Remove a user from the SubscriberRegistry.
|
||||
@param IMSI The user's IMSI or SIP username.
|
||||
*/
|
||||
Status removeUser(const char* IMSI);
|
||||
|
||||
|
||||
/**
|
||||
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(string IMSI);
|
||||
Status setRegTime(const char* IMSI);
|
||||
|
||||
|
||||
string mapCLIDGlobal(string local);
|
||||
char *mapCLIDGlobal(const char *local);
|
||||
|
||||
|
||||
bool useGateway(string ISDN);
|
||||
|
||||
void stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND);
|
||||
|
||||
string uintToString(uint64_t h, uint64_t l);
|
||||
|
||||
string uintToString(uint32_t x);
|
||||
|
||||
SubscriberRegistry::Status authenticate(bool sip, string IMSI, uint64_t hRAND, uint64_t lRAND, uint32_t SRES);
|
||||
|
||||
|
||||
|
||||
bool useGateway(const char* ISDN);
|
||||
|
||||
|
||||
/**
|
||||
Set whether a subscriber is prepaid.
|
||||
@param IMSI Subscriber's IMSI
|
||||
@param yes true for prepaid, false for postpaid
|
||||
@return SUCCESS or FAILURE
|
||||
*/
|
||||
Status setPrepaid(const char *IMSI, bool yes);
|
||||
|
||||
|
||||
/**
|
||||
Is a subscriber postpaid?
|
||||
@param IMSI Subscriber's IMSI
|
||||
@param yes set to true if subscriber is postpaid, false if prepaid
|
||||
@return SUCCESS or FAILURE
|
||||
*/
|
||||
Status isPrepaid(const char *IMSI, bool &yes);
|
||||
|
||||
|
||||
/**
|
||||
Get the balance remaining in a subscriber's account.
|
||||
@param IMSI Subscriber's IMSI
|
||||
@param balance current account balance
|
||||
@return SUCCESS or FAILURE
|
||||
*/
|
||||
Status balanceRemaining(const char *IMSI, int &balance);
|
||||
|
||||
|
||||
/**
|
||||
Atomic operation to add to the account balance
|
||||
@param IMSI subscriber's IMSI
|
||||
@param moneyToAdd money to add (negative to subtract)
|
||||
@return SUCCESS or FAILURE
|
||||
*/
|
||||
Status addMoney(const char *IMSI, int moneyToAdd);
|
||||
|
||||
/**
|
||||
Return the number of "units" of a particular transcation type available in the user's account.
|
||||
@param IMSI subscriber's IMSI
|
||||
@param service the service type
|
||||
@param units number of units of this service type remaining
|
||||
@return SUCCESS or FAILURE
|
||||
*/
|
||||
Status serviceUnits(const char *IMSI, const char* service, int &units);
|
||||
|
||||
/**
|
||||
Return the cost per unit of a specific service type.
|
||||
*/
|
||||
int serviceCost(const char* service);
|
||||
|
||||
/**
|
||||
Update the RRLP location for user
|
||||
|
|
@ -141,23 +213,42 @@ class SubscriberRegistry {
|
|||
*/
|
||||
Status RRLPUpdate(string name, string lat, string lon, string err);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Run sql statments locally.
|
||||
@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);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
|
||||
string sqlQuery(string unknownColumn, string table, string knownColumn, string knownValue);
|
||||
|
||||
/**
|
||||
Run an sql update.
|
||||
@param stmt The update statement.
|
||||
*/
|
||||
Status sqlUpdate(string stmt);
|
||||
Status sqlUpdate(const char *stmt);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue