00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <osp/osp.h>
00036 #include "../rr/api.h"
00037 #include "../../usr_avp.h"
00038 #include "usage.h"
00039 #include "destination.h"
00040 #include "osptoolkit.h"
00041 #include "sipheader.h"
00042
00043 #define OSP_ORIG_COOKIE "osp-o"
00044 #define OSP_TERM_COOKIE "osp-t"
00045
00046 #define OSP_RELEASE_ORIG 0
00047 #define OSP_RELEASE_TERM 1
00048
00049
00050 #define OSP_COOKIE_TRANSID 't'
00051 #define OSP_COOKIE_TRANSIDUP 'T'
00052 #define OSP_COOKIE_SRCIP 's'
00053 #define OSP_COOKIE_SRCIPUP 'S'
00054 #define OSP_COOKIE_AUTHTIME 'a'
00055 #define OSP_COOKIE_AUTHTIMEUP 'A'
00056 #define OSP_COOKIE_DSTCOUNT 'c'
00057 #define OSP_COOKIE_DSTCOUNTUP 'C'
00058
00059
00060 #define OSP_COOKIEHAS_TRANSID (1 << 0)
00061 #define OSP_COOKIEHAS_SRCIP (1 << 1)
00062 #define OSP_COOKIEHAS_AUTHTIME (1 << 2)
00063 #define OSP_COOKIEHAS_DSTCOUNT (1 << 3)
00064 #define OSP_COOKIEHAS_ORIGALL (OSP_COOKIEHAS_TRANSID | OSP_COOKIEHAS_SRCIP | OSP_COOKIEHAS_AUTHTIME | OSP_COOKIEHAS_DSTCOUNT)
00065 #define OSP_COOKIEHAS_TERMALL (OSP_COOKIEHAS_TRANSID | OSP_COOKIEHAS_SRCIP | OSP_COOKIEHAS_AUTHTIME)
00066
00067 extern char* _osp_device_ip;
00068 extern OSPTPROVHANDLE _osp_provider;
00069 extern str OSP_ORIGDEST_NAME;
00070 extern struct rr_binds osp_rr;
00071
00072 static void ospRecordTransaction(struct sip_msg* msg, unsigned long long transid, char* uac, char* from, char* to, time_t authtime, int isorig, unsigned destinationCount);
00073 static int ospBuildUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest, int lastcode);
00074 static int ospReportUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest);
00075 static int ospReportUsageFromCookie(struct sip_msg* msg, char* cooky, OSPTCALLID* callid, int release, OSPE_MSG_ROLETYPES type);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static void ospRecordTransaction(
00089 struct sip_msg* msg,
00090 unsigned long long transid,
00091 char* uac,
00092 char* from,
00093 char* to,
00094 time_t authtime,
00095 int isorig,
00096 unsigned destinationCount)
00097 {
00098 str cookie;
00099 char buffer[OSP_STRBUF_SIZE];
00100
00101 if (osp_rr.add_rr_param == 0) {
00102 LM_WARN("add_rr_param function is not found, cannot record information about the OSP transaction\n");
00103 return;
00104 }
00105
00106 cookie.s = buffer;
00107
00108 if (isorig == 1) {
00109 cookie.len = snprintf(
00110 buffer,
00111 sizeof(buffer),
00112 ";%s=%c%llu_%c%s_%c%d_%c%d",
00113 OSP_ORIG_COOKIE,
00114 OSP_COOKIE_TRANSID,
00115 transid,
00116 OSP_COOKIE_SRCIP,
00117 uac,
00118 OSP_COOKIE_AUTHTIME,
00119 (unsigned int)authtime,
00120 OSP_COOKIE_DSTCOUNT,
00121 destinationCount);
00122 } else {
00123 cookie.len = snprintf(
00124 buffer,
00125 sizeof(buffer),
00126 ";%s=%c%llu_%c%s_%c%d",
00127 OSP_TERM_COOKIE,
00128 OSP_COOKIE_TRANSID,
00129 transid,
00130 OSP_COOKIE_SRCIP,
00131 uac,
00132 OSP_COOKIE_AUTHTIME,
00133 (unsigned int)authtime);
00134 }
00135
00136 if (cookie.len < 0) {
00137 LM_ERR("failed to create OSP cookie\n");
00138 return;
00139 }
00140
00141 LM_DBG("adding RR parameter '%s'\n", buffer);
00142 osp_rr.add_rr_param(msg, &cookie);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 void ospRecordOrigTransaction(
00156 struct sip_msg* msg,
00157 unsigned long long transid,
00158 char* uac,
00159 char* from,
00160 char* to,
00161 time_t authtime,
00162 unsigned destinationCount)
00163 {
00164 int isorig = 1;
00165
00166 ospRecordTransaction(msg, transid, uac, from, to, authtime, isorig, destinationCount);
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 void ospRecordTermTransaction(
00179 struct sip_msg* msg,
00180 unsigned long long transid,
00181 char* uac,
00182 char* from,
00183 char* to,
00184 time_t authtime)
00185 {
00186 int isorig = 0;
00187 unsigned destinationCount = 0;
00188
00189 ospRecordTransaction(msg, transid, uac, from, to, authtime, isorig, destinationCount);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 static int ospReportUsageFromCookie(
00202 struct sip_msg* msg,
00203 char* cookie,
00204 OSPTCALLID* callid,
00205 int release,
00206 OSPE_MSG_ROLETYPES type)
00207 {
00208 char* tmp;
00209 char* token;
00210 char tag;
00211 char* value;
00212 unsigned long long transid = 0;
00213 time_t authtime = 0;
00214 unsigned destinationCount = 0;
00215 time_t duration = 0;
00216 time_t endtime = time(NULL);
00217 int cookieflags = 0;
00218 unsigned releasecode;
00219 char firstvia[OSP_STRBUF_SIZE];
00220 char from[OSP_STRBUF_SIZE];
00221 char to[OSP_STRBUF_SIZE];
00222 char nexthop[OSP_STRBUF_SIZE];
00223 char* calling;
00224 char* called;
00225 char* originator = NULL;
00226 char* terminator;
00227 char* source;
00228 char srcbuf[OSP_STRBUF_SIZE];
00229 char* destination;
00230 char dstbuf[OSP_STRBUF_SIZE];
00231 char* srcdev;
00232 char devbuf[OSP_STRBUF_SIZE];
00233 OSPTTRANHANDLE transaction = -1;
00234 int errorcode;
00235
00236 LM_DBG("'%s' type '%d'\n", cookie, type);
00237 if (cookie != NULL) {
00238 for (token = strtok_r(cookie, "_", &tmp);
00239 token;
00240 token = strtok_r(NULL, "_", &tmp))
00241 {
00242 tag = *token;
00243 value= token + 1;
00244
00245 switch (tag) {
00246 case OSP_COOKIE_TRANSID:
00247 case OSP_COOKIE_TRANSIDUP:
00248 transid = atoll(value);
00249 cookieflags |= OSP_COOKIEHAS_TRANSID;
00250 break;
00251 case OSP_COOKIE_AUTHTIME:
00252 case OSP_COOKIE_AUTHTIMEUP:
00253 authtime = atoi(value);
00254 duration = endtime - authtime;
00255 cookieflags |= OSP_COOKIEHAS_AUTHTIME;
00256 break;
00257 case OSP_COOKIE_SRCIP:
00258 case OSP_COOKIE_SRCIPUP:
00259 originator = value;
00260 cookieflags |= OSP_COOKIEHAS_SRCIP;
00261 break;
00262 case OSP_COOKIE_DSTCOUNT:
00263 case OSP_COOKIE_DSTCOUNTUP:
00264 destinationCount = (unsigned)atoi(value);
00265 cookieflags |= OSP_COOKIEHAS_DSTCOUNT;
00266 break;
00267 default:
00268 LM_ERR("unexpected tag '%c' / value '%s'\n", tag, value);
00269 break;
00270 }
00271 }
00272 }
00273
00274 switch (type) {
00275 case OSPC_DESTINATION:
00276 if (cookieflags == OSP_COOKIEHAS_TERMALL) {
00277 releasecode = 10016;
00278 } else {
00279 releasecode = 9016;
00280 }
00281 break;
00282 case OSPC_SOURCE:
00283 case OSPC_OTHER:
00284 case OSPC_UNDEFINED_ROLE:
00285 default:
00286 if (cookieflags == OSP_COOKIEHAS_ORIGALL) {
00287 releasecode = 10016;
00288 } else {
00289 releasecode = 9016;
00290 }
00291 break;
00292 }
00293
00294 if (releasecode == 9016) {
00295 transid = 0;
00296 originator = NULL;
00297 authtime = 0;
00298 duration = 0;
00299 destinationCount = 0;
00300 }
00301
00302 ospGetSourceAddress(msg, firstvia, sizeof(firstvia));
00303 ospGetFromUserpart(msg, from, sizeof(from));
00304 ospGetToUserpart(msg, to, sizeof(to));
00305 ospGetNextHop(msg, nexthop, sizeof(nexthop));
00306
00307 LM_DBG("first via '%s' from '%s' to '%s' next hop '%s'\n",
00308 firstvia,
00309 from,
00310 to,
00311 nexthop);
00312
00313 if (release == OSP_RELEASE_ORIG) {
00314 LM_DBG("orig '%s' released the call, call_id '%.*s' transaction_id '%llu'\n",
00315 firstvia,
00316 callid->ospmCallIdLen,
00317 callid->ospmCallIdVal,
00318 transid);
00319 if (originator == NULL) {
00320 originator = firstvia;
00321 }
00322 calling = from;
00323 called = to;
00324 terminator = nexthop;
00325 } else {
00326 release = OSP_RELEASE_TERM;
00327 LM_DBG("term '%s' released the call, call_id '%.*s' transaction_id '%llu'\n",
00328 firstvia,
00329 callid->ospmCallIdLen,
00330 callid->ospmCallIdVal,
00331 transid);
00332 if (originator == NULL) {
00333 originator = nexthop;
00334 }
00335 calling = to;
00336 called = from;
00337 terminator = firstvia;
00338 }
00339
00340 errorcode = OSPPTransactionNew(_osp_provider, &transaction);
00341
00342 LM_DBG("created transaction handle '%d' (%d)\n", transaction, errorcode);
00343
00344 switch (type) {
00345 case OSPC_DESTINATION:
00346 ospConvertAddress(originator, srcbuf, sizeof(srcbuf));
00347 source = srcbuf;
00348 destination = _osp_device_ip;
00349 srcdev = "";
00350 break;
00351 case OSPC_SOURCE:
00352 case OSPC_OTHER:
00353 case OSPC_UNDEFINED_ROLE:
00354 default:
00355 source = _osp_device_ip;
00356 ospConvertAddress(terminator, dstbuf, sizeof(dstbuf));
00357 destination = dstbuf;
00358 ospConvertAddress(originator, devbuf, sizeof(devbuf));
00359 srcdev = devbuf;
00360 break;
00361 }
00362
00363 errorcode = OSPPTransactionBuildUsageFromScratch(
00364 transaction,
00365 transid,
00366 type,
00367 source,
00368 destination,
00369 srcdev,
00370 "",
00371 calling,
00372 OSPC_E164,
00373 called,
00374 OSPC_E164,
00375 callid->ospmCallIdLen,
00376 callid->ospmCallIdVal,
00377 (enum OSPEFAILREASON)0,
00378 NULL,
00379 NULL);
00380
00381 LM_DBG("built usage handle '%d' (%d)\n", transaction, errorcode);
00382
00383 if ((errorcode == OSPC_ERR_NO_ERROR) && (destinationCount > 0)) {
00384 errorcode = OSPPTransactionSetDestinationCount(
00385 transaction,
00386 destinationCount);
00387 }
00388
00389 ospReportUsageWrapper(
00390 transaction,
00391 releasecode,
00392 duration,
00393 authtime,
00394 endtime,
00395 0,
00396 0,
00397 0,
00398 0,
00399 release);
00400
00401 return errorcode;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411 int ospReportUsage(
00412 struct sip_msg* msg,
00413 char* whorelease,
00414 char* ignore2)
00415 {
00416 int release;
00417 char* tmp;
00418 char* token;
00419 char parameters[OSP_HEADERBUF_SIZE];
00420 OSPTCALLID* callid = NULL;
00421 int result = MODULE_RETURNCODE_FALSE;
00422
00423 ospGetCallId(msg, &callid);
00424
00425 if (callid != NULL) {
00426
00427 if (sscanf(whorelease, "%d", &release) != 1 || (release != OSP_RELEASE_ORIG && release != OSP_RELEASE_TERM)) {
00428 release = OSP_RELEASE_ORIG;
00429 }
00430 LM_DBG("who releases the call first '%d'\n", release);
00431
00432 if (ospGetRouteParameters(msg, parameters, sizeof(parameters)) == 0) {
00433 for (token = strtok_r(parameters, ";", &tmp);
00434 token;
00435 token = strtok_r(NULL, ";", &tmp))
00436 {
00437 if (strncmp(token, OSP_ORIG_COOKIE, strlen(OSP_ORIG_COOKIE)) == 0) {
00438 LM_INFO("report orig duration for call_id '%.*s'\n",
00439 callid->ospmCallIdLen,
00440 callid->ospmCallIdVal);
00441 ospReportUsageFromCookie(msg, token + strlen(OSP_ORIG_COOKIE) + 1, callid, release, OSPC_SOURCE);
00442 result = MODULE_RETURNCODE_TRUE;
00443 } else if (strncmp(token, OSP_TERM_COOKIE, strlen(OSP_TERM_COOKIE)) == 0) {
00444 LM_INFO("report term duration for call_id '%.*s'\n",
00445 callid->ospmCallIdLen,
00446 callid->ospmCallIdVal);
00447 ospReportUsageFromCookie(msg, token + strlen(OSP_TERM_COOKIE) + 1, callid, release, OSPC_DESTINATION);
00448 result = MODULE_RETURNCODE_TRUE;
00449 } else {
00450 LM_DBG("ignoring parameter '%s'\n", token);
00451 }
00452 }
00453 }
00454
00455 if (result == MODULE_RETURNCODE_FALSE) {
00456 LM_DBG("without orig or term OSP information\n");
00457 LM_INFO("report other duration for call_id '%.*s'\n",
00458 callid->ospmCallIdLen,
00459 callid->ospmCallIdVal);
00460 ospReportUsageFromCookie(msg, NULL, callid, release, OSPC_SOURCE);
00461 result = MODULE_RETURNCODE_TRUE;
00462 }
00463
00464 OSPPCallIdDelete(&callid);
00465 }
00466
00467 if (result == MODULE_RETURNCODE_FALSE) {
00468 LM_ERR("failed to report usage\n");
00469 }
00470
00471 return result;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481 static int ospBuildUsageFromDestination(
00482 OSPTTRANHANDLE transaction,
00483 osp_dest* dest,
00484 int lastcode)
00485 {
00486 int errorcode;
00487 char addr[OSP_STRBUF_SIZE];
00488 char* source;
00489 char* srcdev;
00490
00491 if (dest->type == OSPC_SOURCE) {
00492 ospConvertAddress(dest->srcdev, addr, sizeof(addr));
00493 source = dest->source;
00494 srcdev = addr;
00495 } else {
00496 ospConvertAddress(dest->source, addr, sizeof(addr));
00497 source = addr;
00498 srcdev = dest->srcdev;
00499 }
00500
00501 errorcode = OSPPTransactionBuildUsageFromScratch(
00502 transaction,
00503 dest->transid,
00504 dest->type,
00505 source,
00506 dest->host,
00507 srcdev,
00508 dest->destdev,
00509 dest->calling,
00510 OSPC_E164,
00511 dest->origcalled,
00512 OSPC_E164,
00513 dest->callidsize,
00514 dest->callid,
00515 (enum OSPEFAILREASON)lastcode,
00516 NULL,
00517 NULL);
00518
00519 return errorcode;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528 static int ospReportUsageFromDestination(
00529 OSPTTRANHANDLE transaction,
00530 osp_dest* dest)
00531 {
00532 ospReportUsageWrapper(
00533 transaction,
00534 dest->lastcode,
00535 0,
00536 dest->authtime,
00537 0,
00538 dest->time180,
00539 dest->time200,
00540 dest->time180 ? 1 : 0,
00541 dest->time180 ? dest->time180 - dest->authtime : 0,
00542 0);
00543
00544 return 0;
00545 }
00546
00547
00548
00549
00550 void ospReportOrigSetupUsage(void)
00551 {
00552 osp_dest* dest = NULL;
00553 osp_dest* lastused = NULL;
00554 struct usr_avp* destavp = NULL;
00555 int_str destval;
00556 OSPTTRANHANDLE transaction = -1;
00557 int lastcode = 0;
00558 int errorcode;
00559
00560 errorcode = OSPPTransactionNew(_osp_provider, &transaction);
00561
00562 for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, 0);
00563 destavp != NULL;
00564 destavp = search_next_avp(destavp, NULL))
00565 {
00566 get_avp_val(destavp, &destval);
00567
00568
00569 dest = (osp_dest*)destval.s.s;
00570
00571 if (dest->used == 1) {
00572 if (dest->reported == 1) {
00573 LM_DBG("orig setup already reported\n");
00574 break;
00575 } else {
00576 dest->reported = 1;
00577 }
00578
00579 LM_DBG("iterating through used destination\n");
00580
00581 ospDumpDestination(dest);
00582
00583 lastused = dest;
00584
00585 errorcode = ospBuildUsageFromDestination(transaction, dest, lastcode);
00586
00587 lastcode = dest->lastcode;
00588 } else {
00589 LM_DBG("destination has not been used, breaking out\n");
00590 break;
00591 }
00592 }
00593
00594 if (lastused) {
00595 LM_INFO("report orig setup for call_id '%.*s' transaction_id '%llu'\n",
00596 lastused->callidsize,
00597 lastused->callid,
00598 lastused->transid);
00599 errorcode = ospReportUsageFromDestination(transaction, lastused);
00600 } else {
00601
00602
00603
00604
00605 OSPPTransactionDelete(transaction);
00606 }
00607 }
00608
00609
00610
00611
00612 void ospReportTermSetupUsage(void)
00613 {
00614 osp_dest* dest = NULL;
00615 OSPTTRANHANDLE transaction = -1;
00616 int errorcode;
00617
00618 if ((dest = ospGetTermDestination())) {
00619 if (dest->reported == 0) {
00620 dest->reported = 1;
00621 LM_INFO("report term setup for call_id '%.*s' transaction_id '%llu'\n",
00622 dest->callidsize,
00623 dest->callid,
00624 dest->transid);
00625 errorcode = OSPPTransactionNew(_osp_provider, &transaction);
00626 errorcode = ospBuildUsageFromDestination(transaction, dest, 0);
00627 errorcode = ospReportUsageFromDestination(transaction, dest);
00628 } else {
00629 LM_DBG("term setup already reported\n");
00630 }
00631 } else {
00632 LM_ERR("without term setup to report\n");
00633 }
00634 }