File: osptoolkit.c

package info (click to toggle)
kamailio 4.2.0-2%2Bdeb8u3
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 56,276 kB
  • sloc: ansic: 552,836; xml: 166,484; sh: 8,659; makefile: 7,676; sql: 6,235; perl: 3,487; yacc: 3,428; python: 1,457; cpp: 1,219; php: 1,047; java: 449; pascal: 194; cs: 40; awk: 27
file content (180 lines) | stat: -rw-r--r-- 5,853 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Kamailio osp module. 
 *
 * This module enables Kamailio to communicate with an Open Settlement 
 * Protocol (OSP) server.  The Open Settlement Protocol is an ETSI 
 * defined standard for Inter-Domain VoIP pricing, authorization
 * and usage exchange.  The technical specifications for OSP 
 * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
 *
 * Uli Abend was the original contributor to this module.
 * 
 * Copyright (C) 2001-2005 Fhg Fokus
 *
 * This file is part of Kamailio, a free SIP server.
 *
 * Kamailio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version
 *
 * Kamailio 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <osp/osptrans.h>
#include "../../dprint.h"
#include "osptoolkit.h"

static OSPTTHREADRETURN ospReportUsageWork(void* usagearg);

typedef struct _osp_usage
{
    OSPTTRANHANDLE ospvTransaction;     /* Transaction handle */
    unsigned ospvReleaseCode;           /* Release code */
    unsigned ospvDuration;              /* Length of call */
    time_t ospvStartTime;               /* Call start time */
    time_t ospvEndTime;                 /* Call end time */
    time_t ospvAlertTime;               /* Call alert time */
    time_t ospvConnectTime;             /* Call connect time */
    unsigned ospvIsPDDInfoPresent;      /* Is PDD Info present */
    unsigned ospvPostDialDelay;         /* Post Dial Delay */
    unsigned ospvReleaseSource;         /* EP that released the call */
} osp_usage;

/*
 * Get OSP transaction ID from transaction handle
 * param transaction OSP transaction headle
 * return OSP transaction ID
 */
unsigned long long ospGetTransactionId(
    OSPTTRANHANDLE transaction)
{
    OSPTTRANS* context = NULL;
    unsigned long long id = 0;
    int errorcode = OSPC_ERR_NO_ERROR;

    context = OSPPTransactionGetContext(transaction, &errorcode);

    if (errorcode == OSPC_ERR_NO_ERROR) {
        id = (unsigned long long)context->TransactionID;
    } else {
        LM_ERR("failed to extract transaction_id from transaction handle %d (%d)\n",
            transaction,
            errorcode);
    }

    return id;
}

/*
 * Create a thread to report OSP usage
 * param ospvTransaction OSP transaction handle
 * param ospvReleaseCode Call release reason
 * param ospvDurating Call duration
 * param ospvStartTime Call start time
 * param ospvEndTime Call end time
 * param ospvAlertTime Call alert time
 * param ospvConnectTime Call connected  time
 * param ospvIsPDDInfoPresent If post dial delay information avaliable
 * param ospvPostDialDelay Post dial delay information
 * param ospvReleaseSource Which side release the call
 */
void ospReportUsageWrapper(
    OSPTTRANHANDLE ospvTransaction,
    unsigned ospvReleaseCode,
    unsigned ospvDuration,
    time_t ospvStartTime,
    time_t ospvEndTime,
    time_t ospvAlertTime,
    time_t ospvConnectTime,
    unsigned ospvIsPDDInfoPresent,
    unsigned ospvPostDialDelay,
    unsigned ospvReleaseSource)
{
    osp_usage* usage;
    OSPTTHREADID threadid;
    OSPTTHRATTR threadattr;
    int errorcode;

    LM_DBG("schedule usage report for '%llu'\n", ospGetTransactionId(ospvTransaction));

    usage = (osp_usage*)malloc(sizeof(osp_usage));

    usage->ospvTransaction = ospvTransaction;
    usage->ospvReleaseCode = ospvReleaseCode;
    usage->ospvDuration = ospvDuration;
    usage->ospvStartTime = ospvStartTime;
    usage->ospvEndTime = ospvEndTime;
    usage->ospvAlertTime = ospvAlertTime;
    usage->ospvConnectTime = ospvConnectTime;
    usage->ospvIsPDDInfoPresent = ospvIsPDDInfoPresent;
    usage->ospvPostDialDelay = ospvPostDialDelay;
    usage->ospvReleaseSource = ospvReleaseSource;

    OSPM_THRATTR_INIT(threadattr, errorcode);

    OSPM_SETDETACHED_STATE(threadattr, errorcode);

    OSPM_CREATE_THREAD(threadid, &threadattr, ospReportUsageWork, usage, errorcode);

    OSPM_THRATTR_DESTROY(threadattr);
}

/*
 * Report OSP usage thread function
 * param usagearg OSP usage information
 * return
 */
static OSPTTHREADRETURN ospReportUsageWork(
    void* usagearg)
{
    int i;
    const int MAX_RETRIES = 5;
    osp_usage* usage;
    int errorcode;

    usage = (osp_usage*)usagearg;

    OSPPTransactionRecordFailure(
        usage->ospvTransaction,
        (enum OSPEFAILREASON)usage->ospvReleaseCode);

    for (i = 1; i <= MAX_RETRIES; i++) {
        errorcode = OSPPTransactionReportUsage(
            usage->ospvTransaction,
            usage->ospvDuration,
            usage->ospvStartTime,
            usage->ospvEndTime,
            usage->ospvAlertTime,
            usage->ospvConnectTime,
            usage->ospvIsPDDInfoPresent,
            usage->ospvPostDialDelay,
            usage->ospvReleaseSource,
            (unsigned char*)"", 0, 0, 0, 0, NULL, NULL);

        if (errorcode == OSPC_ERR_NO_ERROR) {
            LM_DBG("reporte usage for '%llu'\n", 
                ospGetTransactionId(usage->ospvTransaction));
            break;
        } else {
            LM_ERR("failed to report usage for '%llu' (%d) attempt '%d' of '%d'\n",
                ospGetTransactionId(usage->ospvTransaction), 
                errorcode,
                i,
                MAX_RETRIES);
        }
    }

    OSPPTransactionDelete(usage->ospvTransaction);

    free(usage);

    OSPTTHREADRETURN_NULL();
}