blob: 9036a02769186ec6a86b434ff5a69ea79c8ee72a [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pjsip/sip_util.h>
21#include <pjsip/sip_module.h>
22#include <pjsip/sip_endpoint.h>
23#include <pjsip/sip_transaction.h>
24#include <pjsip/sip_event.h>
25#include <pjsip/sip_errno.h>
26#include <pj/assert.h>
27#include <pj/log.h>
28#include <pj/pool.h>
29#include <pj/string.h>
30
31struct tsx_data
32{
33 void *token;
34 void (*cb)(void*, pjsip_event*);
35};
36
37static void mod_util_on_tsx_state(pjsip_transaction*, pjsip_event*);
38
39/* This module will be registered in pjsip_endpt.c */
40
41pjsip_module mod_stateful_util =
42{
43 NULL, NULL, /* prev, next. */
44 { "mod-stateful-util", 17 }, /* Name. */
45 -1, /* Id */
46 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
47 NULL, /* load() */
48 NULL, /* start() */
49 NULL, /* stop() */
50 NULL, /* unload() */
51 NULL, /* on_rx_request() */
52 NULL, /* on_rx_response() */
53 NULL, /* on_tx_request. */
54 NULL, /* on_tx_response() */
55 &mod_util_on_tsx_state, /* on_tsx_state() */
56};
57
58static void mod_util_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event)
59{
60 struct tsx_data *tsx_data;
61
62 /* Check if the module has been unregistered (see ticket #1535) and also
63 * verify the event type.
64 */
65 if (mod_stateful_util.id < 0 || event->type != PJSIP_EVENT_TSX_STATE)
66 return;
67
68 tsx_data = (struct tsx_data*) tsx->mod_data[mod_stateful_util.id];
69 if (tsx_data == NULL)
70 return;
71
72 if (tsx->status_code < 200)
73 return;
74
75 /* Call the callback, if any, and prevent the callback to be called again
76 * by clearing the transaction's module_data.
77 */
78 tsx->mod_data[mod_stateful_util.id] = NULL;
79
80 if (tsx_data->cb) {
81 (*tsx_data->cb)(tsx_data->token, event);
82 }
83}
84
85
86PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
87 pjsip_tx_data *tdata,
88 pj_int32_t timeout,
89 void *token,
90 pjsip_endpt_send_callback cb)
91{
92 pjsip_transaction *tsx;
93 struct tsx_data *tsx_data;
94 pj_status_t status;
95
96 PJ_ASSERT_RETURN(endpt && tdata && (timeout==-1 || timeout>0), PJ_EINVAL);
97
98 /* Check that transaction layer module is registered to endpoint */
99 PJ_ASSERT_RETURN(mod_stateful_util.id != -1, PJ_EINVALIDOP);
100
101 PJ_UNUSED_ARG(timeout);
102
103 status = pjsip_tsx_create_uac(&mod_stateful_util, tdata, &tsx);
104 if (status != PJ_SUCCESS) {
105 pjsip_tx_data_dec_ref(tdata);
106 return status;
107 }
108
109 pjsip_tsx_set_transport(tsx, &tdata->tp_sel);
110
111 tsx_data = PJ_POOL_ALLOC_T(tsx->pool, struct tsx_data);
112 tsx_data->token = token;
113 tsx_data->cb = cb;
114
115 tsx->mod_data[mod_stateful_util.id] = tsx_data;
116
117 status = pjsip_tsx_send_msg(tsx, NULL);
118 if (status != PJ_SUCCESS)
119 pjsip_tx_data_dec_ref(tdata);
120
121 return status;
122}
123
124
125/*
126 * Send response statefully.
127 */
128PJ_DEF(pj_status_t) pjsip_endpt_respond( pjsip_endpoint *endpt,
129 pjsip_module *tsx_user,
130 pjsip_rx_data *rdata,
131 int st_code,
132 const pj_str_t *st_text,
133 const pjsip_hdr *hdr_list,
134 const pjsip_msg_body *body,
135 pjsip_transaction **p_tsx )
136{
137 pj_status_t status;
138 pjsip_tx_data *tdata;
139 pjsip_transaction *tsx;
140
141 /* Validate arguments. */
142 PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL);
143
144 if (p_tsx) *p_tsx = NULL;
145
146 /* Create response message */
147 status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text,
148 &tdata);
149 if (status != PJ_SUCCESS)
150 return status;
151
152 /* Add the message headers, if any */
153 if (hdr_list) {
154 const pjsip_hdr *hdr = hdr_list->next;
155 while (hdr != hdr_list) {
156 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)
157 pjsip_hdr_clone(tdata->pool, hdr) );
158 hdr = hdr->next;
159 }
160 }
161
162 /* Add the message body, if any. */
163 if (body) {
164 tdata->msg->body = pjsip_msg_body_clone( tdata->pool, body );
165 if (tdata->msg->body == NULL) {
166 pjsip_tx_data_dec_ref(tdata);
167 return status;
168 }
169 }
170
171 /* Create UAS transaction. */
172 status = pjsip_tsx_create_uas(tsx_user, rdata, &tsx);
173 if (status != PJ_SUCCESS) {
174 pjsip_tx_data_dec_ref(tdata);
175 return status;
176 }
177
178 /* Feed the request to the transaction. */
179 pjsip_tsx_recv_msg(tsx, rdata);
180
181 /* Send the message. */
182 status = pjsip_tsx_send_msg(tsx, tdata);
183 if (status != PJ_SUCCESS) {
184 pjsip_tx_data_dec_ref(tdata);
185 } else if (p_tsx) {
186 *p_tsx = tsx;
187 }
188
189 return status;
190}
191
192