/* * Report OSP usage from OSP cookie * param msg SIP message * param cookie OSP cookie (buffer owned by ospReportUsage, can be modified) * param callid Call ID * param release Who releases the call first. 0 orig, 1 term * param type Usage type * return */ static int ospReportUsageFromCookie( struct sip_msg* msg, char* cookie, OSPT_CALL_ID* callid, OSPE_RELEASE release, OSPE_ROLE type) { char* tmp; char* token; char tag; char* value; unsigned long long transid = 0; time_t authtime = 0; unsigned destcount = 0; time_t duration = 0; time_t endtime = time(NULL); int cookieflags = 0; unsigned releasecode; char firstvia[OSP_STRBUF_SIZE]; char from[OSP_STRBUF_SIZE]; char rpid[OSP_STRBUF_SIZE]; char pai[OSP_STRBUF_SIZE]; char divuser[OSP_STRBUF_SIZE]; char divhost[OSP_STRBUF_SIZE]; char pci[OSP_STRBUF_SIZE]; char to[OSP_STRBUF_SIZE]; char nexthop[OSP_STRBUF_SIZE]; char* snid = NULL; char* dnid = NULL; char* calling; char* called; char* originator = NULL; char* terminator; char source[OSP_STRBUF_SIZE]; char dest[OSP_STRBUF_SIZE]; char srcdev[OSP_STRBUF_SIZE]; OSPTTRANHANDLE transaction = -1; int errorcode; LM_DBG("cookie '%s' type '%d'\n", cookie == NULL ? "NULL" : cookie, type); if (cookie != NULL) { for (token = strtok_r(cookie, "_", &tmp); token; token = strtok_r(NULL, "_", &tmp)) { tag = *token; value= token + 1; switch (tag) { case OSP_COOKIE_TRANSID: case OSP_COOKIE_TRANSIDUP: transid = atoll(value); cookieflags |= OSP_COOKIEHAS_TRANSID; break; case OSP_COOKIE_AUTHTIME: case OSP_COOKIE_AUTHTIMEUP: authtime = atoi(value); duration = endtime - authtime; cookieflags |= OSP_COOKIEHAS_AUTHTIME; break; case OSP_COOKIE_SRCIP: case OSP_COOKIE_SRCIPUP: originator = value; cookieflags |= OSP_COOKIEHAS_SRCIP; break; case OSP_COOKIE_DCOUNT: case OSP_COOKIE_DCOUNTUP: destcount = (unsigned)atoi(value); cookieflags |= OSP_COOKIEHAS_DSTCOUNT; break; case OSP_COOKIE_SNID: case OSP_COOKIE_SNIDUP: snid = value; break; case OSP_COOKIE_DNID: case OSP_COOKIE_DNIDUP: dnid = value; break; default: LM_ERR("unexpected tag '%c' / value '%s'\n", tag, value); break; } } } switch (type) { case OSPC_ROLE_DESTINATION: if (cookieflags == OSP_COOKIEHAS_TERMALL) { releasecode = 10016; } else { releasecode = 9016; } break; case OSPC_ROLE_SOURCE: case OSPC_ROLE_OTHER: case OSPC_ROLE_UNDEFINED: default: if (cookieflags == OSP_COOKIEHAS_ORIGALL) { releasecode = 10016; } else { releasecode = 9016; } break; } if (releasecode == 9016) { transid = 0; originator = NULL; authtime = 0; duration = 0; destcount = 0; } ospGetViaAddress(msg, firstvia, sizeof(firstvia)); ospGetFromUserpart(msg, from, sizeof(from)); ospGetRpidUserpart(msg, rpid, sizeof(rpid)); ospGetPaiUserpart(msg, pai, sizeof(pai)); ospGetDiversion(msg, divuser, sizeof(divuser), divhost, sizeof(divhost)); ospGetPChargeInfoUserpart(msg, pci, sizeof(pci)); ospGetToUserpart(msg, to, sizeof(to)); ospGetNextHop(msg, nexthop, sizeof(nexthop)); LM_DBG("first via '%s' from '%s' to '%s' next hop '%s'\n", firstvia, from, to, nexthop); if (release == OSPC_RELEASE_DESTINATION) { LM_DBG("term '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->Length, callid->Value, transid); if (originator == NULL) { originator = nexthop; } calling = to; called = from; terminator = firstvia; } else { if (release == OSPC_RELEASE_SOURCE) { LM_DBG("orig '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->Length, callid->Value, transid); } else { LM_DBG("unknown '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->Length, callid->Value, transid); } if (originator == NULL) { originator = firstvia; } calling = from; called = to; terminator = nexthop; } errorcode = OSPPTransactionNew(_osp_provider, &transaction); LM_DBG("created transaction handle '%d' (%d)\n", transaction, errorcode); switch (type) { case OSPC_ROLE_DESTINATION: srcdev[0] = '\0'; ospConvertToOutAddress(originator, source, sizeof(source)); strncpy(dest, _osp_out_device, sizeof(dest)); dest[sizeof(dest) - 1] = '\0'; break; case OSPC_ROLE_SOURCE: case OSPC_ROLE_OTHER: case OSPC_ROLE_UNDEFINED: default: ospConvertToOutAddress(originator, srcdev, sizeof(srcdev)); strncpy(source, _osp_out_device, sizeof(source)); source[sizeof(source) - 1] = '\0'; ospConvertToOutAddress(terminator, dest, sizeof(dest)); break; } /* RoleInfo must be set before BuildUsageFromScratch */ OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_OPENSIPS); errorcode = OSPPTransactionBuildUsageFromScratch( transaction, transid, type, source, dest, srcdev, "", calling, OSPC_NFORMAT_E164, called, OSPC_NFORMAT_E164, callid->Length, callid->Value, 0, NULL, NULL); LM_DBG("built usage handle '%d' (%d)\n", transaction, errorcode); if ((errorcode == OSPC_ERR_NO_ERROR) && (destcount > 0)) { errorcode = OSPPTransactionSetDestinationCount( transaction, destcount); } if (errorcode == OSPC_ERR_NO_ERROR) { OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_SOURCE, OSPC_PROTNAME_SIP); OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_DESTINATION, OSPC_PROTNAME_SIP); OSPPTransactionSetSrcNetworkId(transaction, snid); OSPPTransactionSetDestNetworkId(transaction, dnid); OSPPTransactionSetRemotePartyId(transaction, OSPC_NFORMAT_E164, rpid); OSPPTransactionSetAssertedId(transaction, OSPC_NFORMAT_E164, pai); OSPPTransactionSetDiversion(transaction, divuser, divhost); OSPPTransactionSetChargeInfo(transaction, OSPC_NFORMAT_E164, pci); ospReportUsageWrapper( transaction, releasecode, duration, authtime, endtime, 0, 0, 0, 0, release); } return errorcode; }
/* * Report OSP usage from OSP cookie * SER checks ftag by itself, without release parameter * param msg SIP message * param cookie OSP cookie * param callid Call ID * param type Usage type * return */ static int ospReportUsageFromCookie( struct sip_msg* msg, char* cookie, OSPTCALLID* callid, OSPE_MSG_ROLETYPES type) { int release; char* tmp; char* token; char tag; char* value; unsigned long long transid = 0; time_t authtime = 0; unsigned destinationCount = 0; time_t endtime = time(NULL); char firstvia[OSP_STRBUF_SIZE]; char from[OSP_STRBUF_SIZE]; char to[OSP_STRBUF_SIZE]; char nexthop[OSP_STRBUF_SIZE]; char* calling; char* called; char* originator = NULL; char* terminator; char* source; char srcbuf[OSP_STRBUF_SIZE]; char* destination; char dstbuf[OSP_STRBUF_SIZE]; char* srcdev; char devbuf[OSP_STRBUF_SIZE]; OSPTTRANHANDLE transaction = -1; int errorcode; LOG(L_DBG, "osp: ospReportUsageFromCookie\n"); LOG(L_DBG, "osp: '%s' type '%d'\n", cookie, type); if (cookie != NULL) { for (token = strtok_r(cookie, "_", &tmp); token; token = strtok_r(NULL, "_", &tmp)) { tag = *token; value= token + 1; switch (tag) { case OSP_COOKIE_TRANSID: case OSP_COOKIE_TRANSIDUP: transid = atoll(value); break; case OSP_COOKIE_AUTHTIME: case OSP_COOKIE_AUTHTIMEUP: authtime = atoi(value); break; case OSP_COOKIE_SRCIP: case OSP_COOKIE_SRCIPUP: originator = value; break; case OSP_COOKIE_DSTCOUNT: case OSP_COOKIE_DSTCOUNTUP: destinationCount = (unsigned)atoi(value); break; default: LOG(L_ERR, "osp: ERROR: unexpected tag '%c' / value '%s'\n", tag, value); break; } } } ospGetSourceAddress(msg, firstvia, sizeof(firstvia)); ospGetFromUserpart(msg, from, sizeof(from)); ospGetToUserpart(msg, to, sizeof(to)); ospGetNextHop(msg, nexthop, sizeof(nexthop)); LOG(L_DBG, "osp: first via '%s' from '%s' to '%s' next hop '%s'\n", firstvia, from, to, nexthop); /* SER checks ftag by itself */ errorcode = ospGetDirection(msg); switch (errorcode) { case 0: release = OSP_RELEASE_ORIG; break; case 1: release = OSP_RELEASE_TERM; break; default: /* This approach has a problem of flipping called/calling number */ if (strcmp(firstvia, originator) == 0) { release = OSP_RELEASE_ORIG; } else { release = OSP_RELEASE_TERM; } } if (release == OSP_RELEASE_ORIG) { LOG(L_DBG, "osp: orig '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->ospmCallIdLen, callid->ospmCallIdVal, transid); if (originator == NULL) { originator = firstvia; } calling = from; called = to; terminator = nexthop; } else { release = OSP_RELEASE_TERM; LOG(L_DBG, "osp: term '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->ospmCallIdLen, callid->ospmCallIdVal, transid); if (originator == NULL) { originator = nexthop; } calling = to; called = from; terminator = firstvia; } errorcode = OSPPTransactionNew(_osp_provider, &transaction); LOG(L_DBG, "osp: created transaction handle '%d' (%d)\n", transaction, errorcode); switch (type) { case OSPC_DESTINATION: ospConvertAddress(originator, srcbuf, sizeof(srcbuf)); source = srcbuf; destination = _osp_device_ip; srcdev = ""; break; case OSPC_SOURCE: case OSPC_OTHER: case OSPC_UNDEFINED_ROLE: default: source = _osp_device_ip; ospConvertAddress(terminator, dstbuf, sizeof(dstbuf)); destination = dstbuf; ospConvertAddress(originator, devbuf, sizeof(devbuf)); srcdev = devbuf; break; } errorcode = OSPPTransactionBuildUsageFromScratch( transaction, transid, type, source, destination, srcdev, "", calling, OSPC_E164, called, OSPC_E164, callid->ospmCallIdLen, callid->ospmCallIdVal, (enum OSPEFAILREASON)0, NULL, NULL); LOG(L_DBG, "osp: built usage handle '%d' (%d)\n", transaction, errorcode); if ((errorcode == OSPC_ERR_NO_ERROR) && (destinationCount > 0)) { errorcode = OSPPTransactionSetDestinationCount( transaction, destinationCount); } ospReportUsageWrapper( transaction, cookie == NULL ? 9016 : 10016, cookie == NULL ? 0 : endtime - authtime, authtime, endtime, 0,0, 0,0, release); return errorcode; }
/* * Report OSP usage from OSP cookie * param msg SIP message * param cookie OSP cookie (buffer owned by ospReportUsage, can be modified) * param callid Call ID * param release Who releases the call first. 0 orig, 1 term * param type Usage type * return */ static int ospReportUsageFromCookie( struct sip_msg* msg, char* cookie, OSPTCALLID* callid, int release, OSPE_MSG_ROLETYPES type) { char* tmp; char* token; char tag; char* value; unsigned long long transid = 0; time_t authtime = 0; unsigned destinationCount = 0; time_t duration = 0; time_t endtime = time(NULL); int cookieflags = 0; unsigned releasecode; char firstvia[OSP_STRBUF_SIZE]; char from[OSP_STRBUF_SIZE]; char to[OSP_STRBUF_SIZE]; char nexthop[OSP_STRBUF_SIZE]; char* calling; char* called; char* originator = NULL; char* terminator; char* source; char srcbuf[OSP_STRBUF_SIZE]; char* destination; char dstbuf[OSP_STRBUF_SIZE]; char* srcdev; char devbuf[OSP_STRBUF_SIZE]; OSPTTRANHANDLE transaction = -1; int errorcode; LM_DBG("'%s' type '%d'\n", cookie, type); if (cookie != NULL) { for (token = strtok_r(cookie, "_", &tmp); token; token = strtok_r(NULL, "_", &tmp)) { tag = *token; value= token + 1; switch (tag) { case OSP_COOKIE_TRANSID: case OSP_COOKIE_TRANSIDUP: transid = atoll(value); cookieflags |= OSP_COOKIEHAS_TRANSID; break; case OSP_COOKIE_AUTHTIME: case OSP_COOKIE_AUTHTIMEUP: authtime = atoi(value); duration = endtime - authtime; cookieflags |= OSP_COOKIEHAS_AUTHTIME; break; case OSP_COOKIE_SRCIP: case OSP_COOKIE_SRCIPUP: originator = value; cookieflags |= OSP_COOKIEHAS_SRCIP; break; case OSP_COOKIE_DSTCOUNT: case OSP_COOKIE_DSTCOUNTUP: destinationCount = (unsigned)atoi(value); cookieflags |= OSP_COOKIEHAS_DSTCOUNT; break; default: LM_ERR("unexpected tag '%c' / value '%s'\n", tag, value); break; } } } switch (type) { case OSPC_DESTINATION: if (cookieflags == OSP_COOKIEHAS_TERMALL) { releasecode = 10016; } else { releasecode = 9016; } break; case OSPC_SOURCE: case OSPC_OTHER: case OSPC_UNDEFINED_ROLE: default: if (cookieflags == OSP_COOKIEHAS_ORIGALL) { releasecode = 10016; } else { releasecode = 9016; } break; } if (releasecode == 9016) { transid = 0; originator = NULL; authtime = 0; duration = 0; destinationCount = 0; } ospGetSourceAddress(msg, firstvia, sizeof(firstvia)); ospGetFromUserpart(msg, from, sizeof(from)); ospGetToUserpart(msg, to, sizeof(to)); ospGetNextHop(msg, nexthop, sizeof(nexthop)); LM_DBG("first via '%s' from '%s' to '%s' next hop '%s'\n", firstvia, from, to, nexthop); if (release == OSP_RELEASE_ORIG) { LM_DBG("orig '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->ospmCallIdLen, callid->ospmCallIdVal, transid); if (originator == NULL) { originator = firstvia; } calling = from; called = to; terminator = nexthop; } else { release = OSP_RELEASE_TERM; LM_DBG("term '%s' released the call, call_id '%.*s' transaction_id '%llu'\n", firstvia, callid->ospmCallIdLen, callid->ospmCallIdVal, transid); if (originator == NULL) { originator = nexthop; } calling = to; called = from; terminator = firstvia; } errorcode = OSPPTransactionNew(_osp_provider, &transaction); LM_DBG("created transaction handle '%d' (%d)\n", transaction, errorcode); switch (type) { case OSPC_DESTINATION: ospConvertAddress(originator, srcbuf, sizeof(srcbuf)); source = srcbuf; destination = _osp_device_ip; srcdev = ""; break; case OSPC_SOURCE: case OSPC_OTHER: case OSPC_UNDEFINED_ROLE: default: source = _osp_device_ip; ospConvertAddress(terminator, dstbuf, sizeof(dstbuf)); destination = dstbuf; ospConvertAddress(originator, devbuf, sizeof(devbuf)); srcdev = devbuf; break; } errorcode = OSPPTransactionBuildUsageFromScratch( transaction, transid, type, source, destination, srcdev, "", calling, OSPC_E164, called, OSPC_E164, callid->ospmCallIdLen, callid->ospmCallIdVal, (enum OSPEFAILREASON)0, NULL, NULL); LM_DBG("built usage handle '%d' (%d)\n", transaction, errorcode); if ((errorcode == OSPC_ERR_NO_ERROR) && (destinationCount > 0)) { errorcode = OSPPTransactionSetDestinationCount( transaction, destinationCount); } ospReportUsageWrapper( transaction, releasecode, duration, authtime, endtime, 0, 0, 0, 0, release); return errorcode; }