1
/* $Id: stateless_proxy.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#define THIS_FILE "stateless_proxy.c"
22
/* Common proxy functions */
27
/* Callback to be called to handle incoming requests. */
28
static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
30
/* Callback to be called to handle incoming response. */
31
static pj_bool_t on_rx_response( pjsip_rx_data *rdata );
34
static pj_status_t init_stateless_proxy(void)
36
static pjsip_module mod_stateless_proxy =
38
NULL, NULL, /* prev, next. */
39
{ "mod-stateless-proxy", 19 }, /* Name. */
41
PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */
46
&on_rx_request, /* on_rx_request() */
47
&on_rx_response, /* on_rx_response() */
48
NULL, /* on_tx_request. */
49
NULL, /* on_tx_response() */
50
NULL, /* on_tsx_state() */
55
/* Register our module to receive incoming requests. */
56
status = pjsip_endpt_register_module( global.endpt, &mod_stateless_proxy);
57
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
63
/* Callback to be called to handle incoming requests. */
64
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
70
/* Verify incoming request */
71
status = proxy_verify_request(rdata);
72
if (status != PJ_SUCCESS) {
73
app_perror("RX invalid request", status);
78
* Request looks sane, next clone the request to create transmit data.
80
status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL,
82
if (status != PJ_SUCCESS) {
83
pjsip_endpt_respond_stateless(global.endpt, rdata,
84
PJSIP_SC_INTERNAL_SERVER_ERROR, NULL,
91
status = proxy_process_routing(tdata);
92
if (status != PJ_SUCCESS) {
93
app_perror("Error processing route", status);
97
/* Calculate target */
98
status = proxy_calculate_target(rdata, tdata);
99
if (status != PJ_SUCCESS) {
100
app_perror("Error calculating target", status);
104
/* Target is set, forward the request */
105
status = pjsip_endpt_send_request_stateless(global.endpt, tdata,
107
if (status != PJ_SUCCESS) {
108
app_perror("Error forwarding request", status);
116
/* Callback to be called to handle incoming response. */
117
static pj_bool_t on_rx_response( pjsip_rx_data *rdata )
119
pjsip_tx_data *tdata;
120
pjsip_response_addr res_addr;
124
/* Create response to be forwarded upstream (Via will be stripped here) */
125
status = pjsip_endpt_create_response_fwd(global.endpt, rdata, 0, &tdata);
126
if (status != PJ_SUCCESS) {
127
app_perror("Error creating response", status);
131
/* Get topmost Via header */
132
hvia = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
134
/* Invalid response! Just drop it */
135
pjsip_tx_data_dec_ref(tdata);
139
/* Calculate the address to forward the response */
140
pj_bzero(&res_addr, sizeof(res_addr));
141
res_addr.dst_host.type = PJSIP_TRANSPORT_UDP;
142
res_addr.dst_host.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
144
/* Destination address is Via's received param */
145
res_addr.dst_host.addr.host = hvia->recvd_param;
146
if (res_addr.dst_host.addr.host.slen == 0) {
147
/* Someone has messed up our Via header! */
148
res_addr.dst_host.addr.host = hvia->sent_by.host;
151
/* Destination port is the rpot */
152
if (hvia->rport_param != 0 && hvia->rport_param != -1)
153
res_addr.dst_host.addr.port = hvia->rport_param;
155
if (res_addr.dst_host.addr.port == 0) {
156
/* Ugh, original sender didn't put rport!
157
* At best, can only send the response to the port in Via.
159
res_addr.dst_host.addr.port = hvia->sent_by.port;
162
/* Forward response */
163
status = pjsip_endpt_send_response(global.endpt, &res_addr, tdata,
165
if (status != PJ_SUCCESS) {
166
app_perror("Error forwarding response", status);
177
int main(int argc, char *argv[])
184
status = init_options(argc, argv);
185
if (status != PJ_SUCCESS)
188
status = init_stack();
189
if (status != PJ_SUCCESS) {
190
app_perror("Error initializing stack", status);
194
status = init_proxy();
195
if (status != PJ_SUCCESS) {
196
app_perror("Error initializing proxy", status);
200
status = init_stateless_proxy();
201
if (status != PJ_SUCCESS) {
202
app_perror("Error initializing stateless proxy", status);
207
status = pj_thread_create(global.pool, "sproxy", &worker_thread,
208
NULL, 0, 0, &global.thread);
209
if (status != PJ_SUCCESS) {
210
app_perror("Error creating thread", status);
214
while (!global.quit_flag) {
221
" dd dump detailed status\n"
224
if (fgets(line, sizeof(line), stdin) == NULL) {
225
puts("EOF while reading stdin, will quit now..");
226
global.quit_flag = PJ_TRUE;
230
if (line[0] == 'q') {
231
global.quit_flag = PJ_TRUE;
232
} else if (line[0] == 'd') {
233
pj_bool_t detail = (line[1] == 'd');
234
pjsip_endpt_dump(global.endpt, detail);
236
pjsip_tsx_layer_dump(detail);
241
pj_thread_join(global.thread);
244
puts("\nPress Ctrl-C to quit\n");
246
pj_time_val delay = {0, 0};
247
pjsip_endpt_handle_events(global.endpt, &delay);