4
* Copyright (C) 2013 Robert Boisvert
6
* This file is part of the mohqueue module for sip-router, a free SIP server.
8
* The mohqueue module is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version
13
* The mohqueue module is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
#include "mohq_funcs.h"
34
#define ALLOWHDR "Allow: INVITE, ACK, BYE, CANCEL, NOTIFY, PRACK"
35
#define CLENHDR "Content-Length"
37
#define USRAGNT "Kamailio MOH Queue v1.0"
43
str p100rel [1] = {STR_STATIC_INIT ("100rel")};
44
str pallq [1] = {STR_STATIC_INIT ("*")};
45
str paudio [1] = {STR_STATIC_INIT ("audio")};
46
str pbye [1] = {STR_STATIC_INIT ("BYE")};
47
str pinvite [1] = {STR_STATIC_INIT ("INVITE")};
48
str pmi_nolock [1] = {STR_STATIC_INIT ("Unable to lock queue")};
49
str pmi_noqueue [1] = {STR_STATIC_INIT ("No matching queue name found")};
50
str prefer [1] = {STR_STATIC_INIT ("REFER")};
51
str presp_noaccept [1] = {STR_STATIC_INIT ("Not Acceptable Here")};
52
str presp_noallow [1] = {STR_STATIC_INIT ("Method Not Allowed")};
53
str presp_nocall [1] = {STR_STATIC_INIT ("Call/Transaction Does Not Exist")};
54
str presp_ok [1] = {STR_STATIC_INIT ("OK")};
55
str presp_reqpend [1] = {STR_STATIC_INIT ("Request Pending")};
56
str presp_reqterm [1] = {STR_STATIC_INIT ("Request Terminated")};
57
str presp_ring [1] = {STR_STATIC_INIT ("Ringing")};
58
str psipfrag [1] = {STR_STATIC_INIT ("message/sipfrag")};
59
str presp_srverr [1] = {STR_STATIC_INIT ("Server Internal Error")};
60
str presp_unsupp [1] = {STR_STATIC_INIT ("Unsupported Media Type")};
84
rtpmap *pmohfiles [30]; // element count should be equal or greater than prtpmap
86
str pallowhdr [1] = { STR_STATIC_INIT (ALLOWHDR SIPEOL) };
91
"Max-Forwards: 70" SIPEOL
92
"Contact: <%s>" SIPEOL
93
"User-Agent: " USRAGNT SIPEOL
100
"Supported: 100rel" SIPEOL
101
"Accept-Language: en" SIPEOL
102
"Content-Type: application/sdp" SIPEOL
103
"User-Agent: " USRAGNT SIPEOL
110
"o=- %d %d IN %s" SIPEOL
115
"m=audio %d RTP/AVP "
121
"Max-Forwards: 70" SIPEOL
122
"Refer-To: <%s>" SIPEOL
123
"Referred-By: <%.*s>" SIPEOL
124
"User-Agent: " USRAGNT SIPEOL
127
char preinvitemsg [] =
130
"Max-Forwards: 70" SIPEOL
131
"Contact: <%s>" SIPEOL
133
"Supported: 100rel" SIPEOL
134
"User-Agent: " USRAGNT SIPEOL
135
"Accept-Language: en" SIPEOL
136
"Content-Type: application/sdp" SIPEOL
142
// IP address and audio port faked since they will be replaced
143
"o=- 1 1 IN IP4 1.1.1.1" SIPEOL
145
"c=IN IP4 1.1.1.1" SIPEOL
152
* local function declarations
155
void delete_call (call_lst *);
156
void drop_call (sip_msg_t *, call_lst *);
157
int find_call (sip_msg_t *, call_lst **);
158
dlg_t *form_dialog (call_lst *, struct to_body *);
159
int form_rtp_SDP (str *, call_lst *, char *);
160
static void invite_cb (struct cell *, int, struct tmcb_params *);
161
int refer_call (call_lst *, mohq_lock *);
162
static void refer_cb (struct cell *, int, struct tmcb_params *);
163
int send_prov_rsp (sip_msg_t *, call_lst *);
164
int send_rtp_answer (sip_msg_t *, call_lst *);
165
int search_hdr_ext (struct hdr_field *, str *);
166
int start_stream (sip_msg_t *, call_lst *, int);
173
* Process ACK Message
176
* Arg (1) = SIP message pointer
177
* Arg (2) = call pointer
181
int ack_msg (sip_msg_t *pmsg, call_lst *pcall)
188
char *pfncname = "ack_msg: ";
190
tm_api_t *ptm = pmod_data->ptm;
191
if (pcall->call_state != CLSTA_INVITED)
194
* ignore if from rejected re-INVITE
197
if (pcall->call_state != CLSTA_INQUEUE)
198
{ LM_ERR ("%sUnexpected ACK (%s)!", pfncname, pcall->call_from); }
201
mohq_debug (pcall->pmohq, "%sACK from refused re-INVITE (%s)!",
202
pfncname, pcall->call_from);
208
* o release INVITE transaction
209
* o save SDP address info
213
if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
215
LM_ERR ("%sINVITE transaction missing for call (%s)!",
216
pfncname, pcall->call_from);
221
if (ptm->t_release (pcall->call_pmsg) < 0)
223
LM_ERR ("%sRelease transaction failed for call (%s)!",
224
pfncname, pcall->call_from);
228
pcall->call_hash = pcall->call_label = 0;
229
sprintf (pcall->call_addr, "%s %s",
230
pmsg->rcv.dst_ip.af == AF_INET ? "IP4" : "IP6",
231
ip_addr2a (&pmsg->rcv.dst_ip));
232
pcall->call_state = CLSTA_INQUEUE;
233
update_call_rec (pcall);
234
pcall->call_cseq = 1;
235
mohq_debug (pcall->pmohq,
236
"%sACK received for call (%s); placed in queue (%s)",
237
pfncname, pcall->call_from, pcall->pmohq->mohq_name);
245
* Arg (1) = cell pointer
246
* Arg (2) = callback type
247
* Arg (3) = callback parms
252
(struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
256
* o error means must have hung after REFER
260
char *pfncname = "bye_cb: ";
261
call_lst *pcall = (call_lst *)*pcbp->param;
262
if (ntype == TMCB_ON_FAILURE)
264
LM_ERR ("%sCall (%s) did not respond to BYE", pfncname,
269
int nreply = pcbp->code;
270
if ((nreply / 100) != 2)
272
LM_ERR ("%sCall (%s) BYE error (%d)", pfncname,
273
pcall->call_from, nreply);
277
mohq_debug (pcall->pmohq, "%sCall (%s) BYE reply=%d", pfncname,
278
pcall->call_from, nreply);
286
* Process BYE Message
289
* Arg (1) = SIP message pointer
290
* Arg (2) = call pointer
294
int bye_msg (sip_msg_t *pmsg, call_lst *pcall)
302
char *pfncname = "bye_msg: ";
303
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
305
LM_ERR ("%sUnable to create reply to call (%s)", pfncname,
309
if (pcall->call_state >= CLSTA_INQUEUE)
310
{ drop_call (pmsg, pcall); }
313
LM_ERR ("%sEnding call (%s) before placed in queue!",
314
pfncname, pcall->call_from);
321
* Process CANCEL Message
324
* Arg (1) = SIP message pointer
325
* Arg (2) = call pointer
329
int cancel_msg (sip_msg_t *pmsg, call_lst *pcall)
333
* still in INVITE dialog?
336
char *pfncname = "cancel_msg: ";
337
if (pcall->call_state < CLSTA_INQUEUE)
339
pcall->call_state = CLSTA_CANCEL;
340
mohq_debug (pcall->pmohq, "%sCANCELed call (%s)",
341
pfncname, pcall->call_from);
342
if (pmod_data->psl->freply (pmsg, 487, presp_reqterm) < 0)
343
{ LM_ERR ("%sUnable to create reply!", pfncname); }
347
LM_ERR ("%sUnable to CANCEL because accepted INVITE for call (%s)!",
348
pfncname, pcall->call_from);
349
if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0)
350
{ LM_ERR ("%sUnable to create reply!", pfncname); }
359
* Arg (1) = SIP message pointer
360
* Arg (2) = call pointer
364
void close_call (sip_msg_t *pmsg, call_lst *pcall)
368
* o destroy proxy connection
372
char *pfncname = "close_call: ";
375
if (pmsg != FAKED_REPLY)
377
mohq_debug (pcall->pmohq, "%sDestroying RTP link for call (%s)",
378
pfncname, pcall->call_from);
379
if (pmod_data->fn_rtp_destroy (pmsg, 0, 0) != 1)
381
LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
382
pfncname, pcall->call_from);
385
struct to_body ptob [2];
386
dlg_t *pdlg = form_dialog (pcall, ptob);
389
pdlg->state = DLG_CONFIRMED;
397
tm_api_t *ptm = pmod_data->ptm;
398
char *pquri = pcall->pmohq->mohq_uri;
399
int npos1 = sizeof (pbyemsg) // BYE template
400
+ strlen (pcall->call_via) // Via
401
+ strlen (pquri); // Contact
402
phdr = pkg_malloc (npos1);
405
LM_ERR ("%sNo more memory!", pfncname);
408
sprintf (phdr, pbyemsg,
409
pcall->call_via, // Via
413
phdrs->len = strlen (phdr);
420
set_uac_req (puac, pbye, phdrs, 0, pdlg,
421
TMCB_LOCAL_COMPLETED | TMCB_ON_FAILURE, bye_cb, pcall);
422
pcall->call_state = CLSTA_BYE;
423
if (ptm->t_request_within (puac) < 0)
425
LM_ERR ("%sUnable to create BYE request for call (%s)!",
426
pfncname, pcall->call_from);
429
mohq_debug (pcall->pmohq, "%sSent BYE request for call (%s)",
430
pfncname, pcall->call_from);
444
{ delete_call (pcall); }
449
* Create New Call Record
452
* Arg (1) = queue index
453
* Arg (2) = SIP message pointer
454
* OUTPUT: call index; -1 if unable to create
457
int create_call (int mohq_idx, sip_msg_t *pmsg)
463
* o find inactive slot
466
char *pfncname = "create_call: ";
467
if (!mohq_lock_set (pmod_data->pcall_lock, 1, 2000))
469
LM_ERR ("%sUnable to lock calls!", pfncname);
473
int ncall_idx = find_call (pmsg, &pcall);
476
mohq_lock_release (pmod_data->pcall_lock);
477
LM_ERR ("%sCall already in use (%s)!", pfncname, pcall->call_from);
480
for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
482
if (!pmod_data->pcall_lst [ncall_idx].call_active)
485
if (ncall_idx == pmod_data->call_cnt)
487
mohq_lock_release (pmod_data->pcall_lock);
488
LM_ERR ("%sNo call slots available!", pfncname);
493
* add values to new entry
496
pcall = &pmod_data->pcall_lst [ncall_idx];
497
pcall->call_active = 1;
498
pcall->pmohq = &pmod_data->pmohq_lst [mohq_idx];
499
pcall->call_state = 0;
500
str *pstr = &pmsg->callid->body;
501
strncpy (pcall->call_id, pstr->s, pstr->len);
502
pcall->call_id [pstr->len] = '\0';
503
pstr = &pmsg->from->body;
504
strncpy (pcall->call_from, pstr->s, pstr->len);
505
pcall->call_from [pstr->len] = '\0';
506
*pcall->call_tag = '\0';
508
{ *pcall->call_contact = '\0'; }
511
pstr = &pmsg->contact->body;
512
strncpy (pcall->call_contact, pstr->s, pstr->len);
513
pcall->call_contact [pstr->len] = '\0';
517
* extract Via headers
520
hdr_field_t *phdr = pmsg->h_via1;
524
while ((phdr = next_sibling_hdr (phdr)))
526
struct via_body *pvia;
530
int nvia_max = sizeof (pcall->call_via);
531
for (pvia = (struct via_body *)phdr->parsed; pvia; pvia = pvia->next)
534
* o skip trailing whitespace
535
* o check if overflow
539
pviabuf = pvia->name.s;
543
if (pviabuf [npos2] == ' ' || pviabuf [npos2] == '\r'
544
|| pviabuf [npos2] == '\n' || pviabuf [npos2] == '\t' || pviabuf [npos2] == ',')
548
if ((npos2 + npos1 + 7) >= nvia_max)
550
LM_WARN ("%sVia buffer overflowed!", pfncname);
559
strcpy (&pcall->call_via [npos1], "Via: ");
561
strncpy (&pcall->call_via [npos1], pviabuf, npos2);
563
strcpy (&pcall->call_via [npos1], SIPEOL);
572
* o release call lock
577
pcall->call_state = CLSTA_ENTER;
578
mohq_lock_release (pmod_data->pcall_lock);
579
add_call_rec (ncall_idx);
580
mohq_lock_set (pmod_data->pmohq_lock, 0, 0);
581
mohq_debug (pcall->pmohq, "%sAdded call (%s) to queue (%s)",
582
pfncname, pcall->call_from, pcall->pmohq->mohq_name);
590
* Arg (1) = call pointer
594
void delete_call (call_lst *pcall)
598
* release transaction
601
char *pfncname = "delete_call: ";
603
tm_api_t *ptm = pmod_data->ptm;
604
if (pcall->call_hash || pcall->call_label)
606
if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
608
LM_ERR ("%sLookup transaction failed for call (%s)!", pfncname,
613
if (ptm->t_release (pcall->call_pmsg) < 0)
615
LM_ERR ("%sRelease transaction failed for call (%s)!",
616
pfncname, pcall->call_from);
619
pcall->call_hash = pcall->call_label = 0;
625
* o release MOH queue
628
mohq_debug (pcall->pmohq, "delete_call: Deleting call (%s) from queue (%s)",
629
pcall->call_from, pcall->pmohq->mohq_name);
630
delete_call_rec (pcall);
631
pcall->call_active = 0;
632
mohq_lock_release (pmod_data->pmohq_lock);
640
* Arg (1) = SIP message pointer
641
* Arg (2) = call pointer
645
void deny_method (sip_msg_t *pmsg, call_lst *pcall)
649
* RFC 3261 section 8.2.1
651
* o respond with 405 and Allow header
654
char *pfncname = "deny_method: ";
655
tm_api_t *ptm = pmod_data->ptm;
656
if (ptm->t_newtran (pmsg) < 0)
658
LM_ERR ("%sUnable to create new transaction!", pfncname);
659
if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
661
LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
662
STR_FMT (&REQ_LINE (pmsg).method));
666
if (!add_lump_rpl2 (pmsg, pallowhdr->s, pallowhdr->len, LUMP_RPL_HDR))
667
{ LM_ERR ("%sUnable to add Allow header!", pfncname); }
668
LM_ERR ("%sRefused %.*s for call (%s)!", pfncname,
669
STR_FMT (&REQ_LINE (pmsg).method), pcall->call_from);
670
if (ptm->t_reply (pmsg, 405, presp_noallow->s) < 0)
672
LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
673
STR_FMT (&REQ_LINE (pmsg).method));
682
* Arg (1) = SIP message pointer
683
* Arg (2) = call pointer
687
void drop_call (sip_msg_t *pmsg, call_lst *pcall)
691
* o destroy proxy connection
695
char *pfncname = "drop_call: ";
696
if (pmsg != FAKED_REPLY)
698
mohq_debug (pcall->pmohq, "%sDestroying RTP link for call (%s)",
699
pfncname, pcall->call_from);
700
if (pmod_data->fn_rtp_destroy (pmsg, 0, 0) != 1)
702
LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
703
pfncname, pcall->call_from);
714
* Arg (1) = SIP message pointer
715
* Arg (2) = pointer to call pointer
716
* OUTPUT: queue index; -1 if unable to find
719
int find_call (sip_msg_t *pmsg, call_lst **ppcall)
723
* o find current RURI
724
* o strip off parms or headers
729
pmsg->new_uri.s ? &pmsg->new_uri : &pmsg->first_line.u.request.uri;
733
pstr->len = pruri->len;
734
for (nidx = 0; nidx < pruri->len; nidx++)
736
if (pstr->s [nidx] == ';' || pstr->s [nidx] == '?')
742
mohq_lst *pqlst = pmod_data->pmohq_lst;
744
for (nqidx = 0; nqidx < pmod_data->mohq_cnt; nqidx++)
747
pmohstr->s = pqlst [nqidx].mohq_uri;
748
pmohstr->len = strlen (pmohstr->s);
749
if (STR_EQ (*pmohstr, *pstr))
753
if (nqidx == pmod_data->mohq_cnt)
759
* o ignore to tag if CANCEL on first INVITE
760
* o search call queue
763
str *ptotag = &(get_to (pmsg)->tag_value);
768
str *pcallid = &pmsg->callid->body;
771
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
775
* o call timed out on ACK?
778
* o return call pointer
781
call_lst *pcall = &pmod_data->pcall_lst [nidx];
782
if (!pcall->call_active)
784
if (pcall->call_time && (pcall->call_state < CLSTA_INQUEUE))
786
if ((pcall->call_time + 32) < time (0))
788
LM_ERR ("find_call: No ACK response for call (%s)", pcall->call_from);
794
tmpstr->s = pcall->call_id;
795
tmpstr->len = strlen (tmpstr->s);
796
if (!STR_EQ (*tmpstr, *pcallid))
800
tmpstr->s = pcall->call_tag;
801
tmpstr->len = strlen (tmpstr->s);
802
if (!STR_EQ (*tmpstr, *ptotag))
813
if (pmsg->REQ_METHOD == METHOD_INVITE)
822
* Arg (1) = queue name str pointer
823
* OUTPUT: queue index; -1 if unable to find
826
int find_queue (str *pqname)
829
char *pfncname = "find_queue: ";
832
if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 500))
834
LM_ERR ("%sUnable to lock queues!", pfncname);
837
for (nidx = 0; nidx < pmod_data->mohq_cnt; nidx++)
839
tmpstr.s = pmod_data->pmohq_lst [nidx].mohq_name;
840
tmpstr.len = strlen (tmpstr.s);
841
if (STR_EQ (tmpstr, *pqname))
844
if (nidx == pmod_data->mohq_cnt)
846
LM_ERR ("%sUnable to find queue (%.*s)!", pfncname, STR_FMT (pqname));
849
mohq_lock_release (pmod_data->pmohq_lock);
857
* Arg (1) = referred-by value
858
* OUTPUT: call index; -1 if unable to find
861
int find_referred_call (str *pvalue)
868
char *pfncname = "find_referred_call: ";
869
struct to_body pref [1];
870
parse_to (pvalue->s, &pvalue->s [pvalue->len + 1], pref);
871
if (pref->error != PARSE_OK)
873
// should never happen
874
LM_ERR ("%sInvalid Referred-By URI (%.*s)!", pfncname, STR_FMT (pvalue));
878
{ free_to_params (pref); }
881
* search calls for matching
886
struct to_body pfrom [1];
887
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
889
if (!pmod_data->pcall_lst [nidx].call_active)
891
tmpstr.s = pmod_data->pcall_lst [nidx].call_from;
892
tmpstr.len = strlen (tmpstr.s);
893
parse_to (tmpstr.s, &tmpstr.s [tmpstr.len + 1], pfrom);
894
if (pfrom->error != PARSE_OK)
896
// should never happen
897
LM_ERR ("%sInvalid From URI (%.*s)!", pfncname, STR_FMT (&tmpstr));
900
if (pfrom->param_lst)
901
{ free_to_params (pfrom); }
902
if (STR_EQ (pfrom->uri, pref->uri))
909
* Process First INVITE Message
912
* Arg (1) = SIP message pointer
913
* Arg (2) = queue index
917
int first_invite_msg (sip_msg_t *pmsg, int mohq_idx)
924
char *pfncname = "first_invite_msg: ";
925
int ncall_idx = create_call (mohq_idx, pmsg);
928
call_lst *pcall = &pmod_data->pcall_lst [ncall_idx];
933
* o send rtpproxy offer
936
if (!(pmsg->msg_flags & FL_SDP_BODY))
938
if (parse_sdp (pmsg))
940
LM_ERR ("%sINVITE lacks SDP (%s)!", pfncname, pcall->call_from);
947
if (!search_hdr_ext (pmsg->allow, prefer))
949
LM_ERR ("%sMissing REFER support (%s)!", pfncname, pcall->call_from);
954
mohq_debug (pcall->pmohq, "%sMaking offer for RTP link for call (%s)",
955
pfncname, pcall->call_from);
956
if (pmod_data->fn_rtp_offer (pmsg, 0, 0) != 1)
958
LM_ERR ("%srtpproxy_offer refused for call (%s)!",
959
pfncname, pcall->call_from);
965
* o create new transaction
968
* o save transaction data
971
tm_api_t *ptm = pmod_data->ptm;
972
if (ptm->t_newtran (pmsg) < 0)
974
LM_ERR ("%sUnable to create new transaction for call (%s)!",
975
pfncname, pcall->call_from);
979
struct cell *ptrans = ptm->t_gett ();
980
pcall->call_hash = ptrans->hash_index;
981
pcall->call_label = ptrans->label;
983
if (ptm->t_get_reply_totag (pmsg, ptotag) != 1)
985
LM_ERR ("%sUnable to create totag for call (%s)!",
986
pfncname, pcall->call_from);
987
if (ptm->t_reply (pmsg, 500, presp_srverr->s) < 0)
988
{ LM_ERR ("%sUnable to reply to INVITE!", pfncname); }
992
strncpy (pcall->call_tag, ptotag->s, ptotag->len);
993
pcall->call_tag [ptotag->len] = '\0';
994
pcall->call_cseq = 1;
995
if (ptm->register_tmcb (pmsg, 0, TMCB_DESTROY | TMCB_ON_FAILURE,
996
invite_cb, pcall, 0) < 0)
998
LM_ERR ("%sUnable to set callback for call (%s)!",
999
pfncname, pcall->call_from);
1000
if (ptm->t_reply (pmsg, 500, presp_srverr->s) < 0)
1001
{ LM_ERR ("%sUnable to reply to INVITE!", pfncname); }
1002
delete_call (pcall);
1007
* o add contact to reply
1008
* o supports/requires PRACK? (RFC 3262 section 3)
1009
* o exit if not ringing
1013
char *pcontacthdr = "Contact: <%s>" SIPEOL;
1014
pcontact->s = pkg_malloc (strlen (pmod_data->pmohq_lst [mohq_idx].mohq_uri)
1015
+ strlen (pcontacthdr));
1018
LM_ERR ("%sNo more memory!", pfncname);
1019
delete_call (pcall);
1022
sprintf (pcontact->s, pcontacthdr, pmod_data->pmohq_lst [mohq_idx].mohq_uri);
1023
pcontact->len = strlen (pcontact->s);
1024
if (!add_lump_rpl2 (pmsg, pcontact->s, pcontact->len, LUMP_RPL_HDR))
1026
LM_ERR ("%sUnable to add contact (%s) to call (%s)!",
1027
pfncname, pcontact->s, pcall->call_from);
1029
pkg_free (pcontact->s);
1030
pcall->call_pmsg = pmsg;
1031
if (search_hdr_ext (pmsg->require, p100rel))
1033
if (!send_prov_rsp (pmsg, pcall))
1035
delete_call (pcall);
1041
if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0)
1043
LM_ERR ("%sUnable to reply to INVITE!", pfncname);
1048
pcall->call_state = CLSTA_RINGING;
1049
mohq_debug (pcall->pmohq, "%sSent RINGING for call (%s)",
1050
pfncname, pcall->call_from);
1056
* o accept call with RTP
1059
if (pcall->call_state == CLSTA_CANCEL)
1061
delete_call (pcall);
1064
if (!send_rtp_answer (pmsg, pcall))
1066
if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
1067
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1068
delete_call (pcall);
1077
* Arg (1) = call pointer
1078
* Arg (2) = to_body [2] pointer
1079
* OUTPUT: dlg_t * if successful; 0=if not
1082
dlg_t *form_dialog (call_lst *pcall, struct to_body *pto_body)
1086
* get from/to values
1089
char *pfncname = "form_dialog: ";
1090
struct to_body *ptob = &pto_body [0];
1091
struct to_body *pcontact = &pto_body [1];
1092
parse_to (pcall->call_from,
1093
&pcall->call_from [strlen (pcall->call_from) + 1], ptob);
1094
if (ptob->error != PARSE_OK)
1096
// should never happen
1097
LM_ERR ("%sInvalid from URI (%s)!", pfncname, pcall->call_from);
1100
if (ptob->param_lst)
1101
{ free_to_params (ptob); }
1103
if (!*pcall->call_contact)
1105
ptarget->s = ptob->uri.s;
1106
ptarget->len = ptob->uri.len;
1110
parse_to (pcall->call_contact,
1111
&pcall->call_contact [strlen (pcall->call_contact) + 1], pcontact);
1112
if (pcontact->error != PARSE_OK)
1114
// should never happen
1115
LM_ERR ("%sInvalid contact (%s) for call (%s)!", pfncname,
1116
pcall->call_contact, pcall->call_from);
1119
if (pcontact->param_lst)
1120
{ free_to_params (pcontact); }
1121
ptarget->s = pcontact->uri.s;
1122
ptarget->len = pcontact->uri.len;
1129
dlg_t *pdlg = (dlg_t *)pkg_malloc (sizeof (dlg_t));
1132
LM_ERR ("%sNo more memory!", pfncname);
1135
memset (pdlg, 0, sizeof (dlg_t));
1136
pdlg->loc_seq.value = pcall->call_cseq++;
1137
pdlg->loc_seq.is_set = 1;
1138
pdlg->id.call_id.s = pcall->call_id;
1139
pdlg->id.call_id.len = strlen (pcall->call_id);
1140
pdlg->id.loc_tag.s = pcall->call_tag;
1141
pdlg->id.loc_tag.len = strlen (pcall->call_tag);
1142
pdlg->id.rem_tag.s = ptob->tag_value.s;
1143
pdlg->id.rem_tag.len = ptob->tag_value.len;
1144
pdlg->rem_target.s = ptarget->s;
1145
pdlg->rem_target.len = ptarget->len;
1146
pdlg->loc_uri.s = pcall->pmohq->mohq_uri;
1147
pdlg->loc_uri.len = strlen (pdlg->loc_uri.s);
1148
pdlg->rem_uri.s = ptob->uri.s;
1149
pdlg->rem_uri.len = ptob->uri.len;
1154
* Form RTP SDP String
1157
* Arg (1) = string pointer
1158
* Arg (2) = call pointer
1159
* Arg (3) = SDP body pointer
1160
* OUTPUT: 0 if failed
1163
int form_rtp_SDP (str *pstr, call_lst *pcall, char *pSDP)
1167
* o find available files
1168
* o calculate size of SDP
1171
char *pfncname = "form_rtp_SDP: ";
1172
rtpmap **pmohfiles = find_MOH (pcall->pmohq->mohq_mohdir,
1173
pcall->pmohq->mohq_mohfile);
1176
LM_ERR ("%sUnable to find any MOH files for queue (%s)!", pfncname,
1177
pcall->pmohq->mohq_name);
1180
int nsize = strlen (pSDP) + 2;
1182
for (nidx = 0; pmohfiles [nidx]; nidx++)
1184
nsize += strlen (pmohfiles [nidx]->pencode) // encode length
1185
+ 19; // space, type number, "a=rtpmap:%d ", EOL
1193
pstr->s = pkg_malloc (nsize + 1);
1196
LM_ERR ("%sNo more memory!", pfncname);
1199
strcpy (pstr->s, pSDP);
1200
nsize = strlen (pstr->s);
1201
for (nidx = 0; pmohfiles [nidx]; nidx++)
1204
* add payload types to media description
1207
sprintf (&pstr->s [nsize], " %d", pmohfiles [nidx]->ntype);
1208
nsize += strlen (&pstr->s [nsize]);
1210
strcpy (&pstr->s [nsize], SIPEOL);
1212
for (nidx = 0; pmohfiles [nidx]; nidx++)
1215
* add rtpmap attributes
1218
sprintf (&pstr->s [nsize], "a=rtpmap:%d %s %s",
1219
pmohfiles [nidx]->ntype, pmohfiles [nidx]->pencode, SIPEOL);
1220
nsize += strlen (&pstr->s [nsize]);
1230
* Arg (1) = cell pointer
1231
* Arg (2) = callback type
1232
* Arg (3) = callback parms
1237
invite_cb (struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
1240
call_lst *pcall = (call_lst *)*pcbp->param;
1241
if (ntype == TMCB_DESTROY)
1242
{ pcall->call_hash = pcall->call_label = 0; }
1243
LM_ERR ("invite_cb: INVITE failed for call (%s)!", pcall->call_from);
1244
delete_call (pcall);
1249
* Process NOTIFY Message
1252
* Arg (1) = SIP message pointer
1253
* Arg (2) = call pointer
1257
int notify_msg (sip_msg_t *pmsg, call_lst *pcall)
1264
char *pfncname = "notify_msg: ";
1265
if (pcall->call_state != CLSTA_RFRWAIT)
1267
LM_ERR ("%sNot waiting on a REFER for call (%s)!", pfncname,
1269
if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0)
1270
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1276
* o get status from body
1277
* o add CRLF so parser can go beyond first line
1280
if (!search_hdr_ext (pmsg->content_type, psipfrag))
1282
LM_ERR ("%sNot a %s type for call (%s)!", pfncname,
1283
psipfrag->s, pcall->call_from);
1284
if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0)
1285
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1288
char *pfrag = get_body (pmsg);
1291
LM_ERR ("%s%s body missing for call (%s)!", pfncname,
1292
psipfrag->s, pcall->call_from);
1293
if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0)
1294
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1298
pbody->len = pmsg->len - (int)(pfrag - pmsg->buf);
1299
pbody->s = pkg_malloc (pbody->len + 2);
1302
LM_ERR ("%sNo more memory!", pfncname);
1305
strncpy (pbody->s, pfrag, pbody->len);
1306
if (pbody->s [pbody->len - 1] != '\n')
1308
strncpy (&pbody->s [pbody->len], SIPEOL, 2);
1311
struct msg_start pstart [1];
1312
parse_first_line (pbody->s, pbody->len + 1, pstart);
1313
pkg_free (pbody->s);
1314
if (pstart->type != SIP_REPLY)
1316
LM_ERR ("%sReply missing for call (%s)!", pfncname, pcall->call_from);
1317
if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0)
1318
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1327
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
1329
LM_ERR ("%sUnable to create reply for call (%s)!",
1330
pfncname, pcall->call_from);
1333
int nreply = pstart->u.reply.statuscode;
1334
mohq_debug (pcall->pmohq, "%sNOTIFY received reply (%d) for call (%s)",
1335
pfncname, nreply, pcall->call_from);
1336
switch (nreply / 100)
1341
close_call (pmsg, pcall);
1344
LM_WARN ("%sUnable to redirect call (%s)!", pfncname, pcall->call_from);
1351
drop_call (pmsg, pcall);
1356
* return call to queue
1359
pcall->call_state = CLSTA_INQUEUE;
1360
update_call_rec (pcall);
1367
* Process PRACK Message
1370
* Arg (1) = SIP message pointer
1371
* Arg (2) = call pointer
1375
int prack_msg (sip_msg_t *pmsg, call_lst *pcall)
1382
char *pfncname = "prack_msg: ";
1383
tm_api_t *ptm = pmod_data->ptm;
1384
if (pcall->call_state != CLSTA_PRACKSTRT)
1386
LM_ERR ("%sUnexpected PRACK (%s)!", pfncname, pcall->call_from);
1387
if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0)
1388
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1393
* o check RAck ??? need to check
1397
if (ptm->t_newtran (pmsg) < 0)
1399
LM_ERR ("%sUnable to create new transaction for call (%s)!",
1400
pfncname, pcall->call_from);
1401
if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
1402
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1405
if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0)
1407
LM_ERR ("%sUnable to reply to PRACK for call (%s)!",
1408
pfncname, pcall->call_from);
1411
pcall->call_state = CLSTA_PRACKRPLY;
1419
* Arg (1) = call pointer
1420
* Arg (2) = lock pointer
1421
* OUTPUT: 0 if failed
1424
int refer_call (call_lst *pcall, mohq_lock *plock)
1431
char *pfncname = "refer_call: ";
1433
struct to_body ptob [2];
1434
dlg_t *pdlg = form_dialog (pcall, ptob);
1437
mohq_lock_release (plock);
1440
pdlg->state = DLG_CONFIRMED;
1443
* form REFER message
1444
* o calculate basic size
1449
puri->s = pcall->call_referto;
1450
puri->len = strlen (puri->s);
1451
int npos1 = sizeof (prefermsg) // REFER template
1452
+ strlen (pcall->call_via) // Via
1453
+ puri->len // Refer-To
1454
+ ptob->uri.len; // Referred-By
1455
char *pbuf = pkg_malloc (npos1);
1458
LM_ERR ("%sNo more memory!", pfncname);
1461
sprintf (pbuf, prefermsg,
1462
pcall->call_via, // Via
1463
puri->s, // Refer-To
1464
STR_FMT (&ptob->uri)); // Referred-By
1467
* send REFER request
1470
tm_api_t *ptm = pmod_data->ptm;
1474
phdrs->len = strlen (pbuf);
1475
set_uac_req (puac, prefer, phdrs, 0, pdlg,
1476
TMCB_LOCAL_COMPLETED | TMCB_ON_FAILURE, refer_cb, pcall);
1477
pcall->call_state = CLSTA_REFER;
1478
update_call_rec (pcall);
1479
mohq_lock_release (plock);
1480
if (ptm->t_request_within (puac) < 0)
1482
pcall->call_state = CLSTA_INQUEUE;
1483
LM_ERR ("%sUnable to create REFER request for call (%s)!",
1484
pfncname, pcall->call_from);
1485
update_call_rec (pcall);
1488
mohq_debug (pcall->pmohq, "%sSent REFER request for call (%s) to %s",
1489
pfncname, pcall->call_from, pcall->call_referto);
1494
{ pkg_free (pdlg); }
1503
* Arg (1) = cell pointer
1504
* Arg (2) = callback type
1505
* Arg (3) = callback parms
1509
static void refer_cb
1510
(struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
1513
char *pfncname = "refer_cb: ";
1514
call_lst *pcall = (call_lst *)*pcbp->param;
1515
if ((ntype == TMCB_ON_FAILURE) || (pcbp->req == FAKED_REPLY))
1517
LM_ERR ("%sCall (%s) did not respond to REFER", pfncname,
1519
drop_call (pcbp->req, pcall);
1522
int nreply = pcbp->code;
1523
if ((nreply / 100) == 2)
1525
pcall->call_state = CLSTA_RFRWAIT;
1526
mohq_debug (pcall->pmohq, "%sCall (%s) REFER reply=%d",
1527
pfncname, pcall->call_from, nreply);
1531
LM_ERR ("%sCall (%s) REFER error (%d)", pfncname,
1532
pcall->call_from, nreply);
1534
{ delete_call (pcall); }
1537
pcall->call_state = CLSTA_INQUEUE;
1538
update_call_rec (pcall);
1545
* Process re-INVITE Message
1548
* Arg (1) = SIP message pointer
1549
* Arg (2) = call pointer
1553
int reinvite_msg (sip_msg_t *pmsg, call_lst *pcall)
1557
* RFC 3261 section 14.2
1562
char *pfncname = "reinvite_msg: ";
1563
if ((pcall->call_state / 100) < 2)
1565
mohq_debug (pcall->pmohq, "%sINVITE still pending for call (%s)",
1566
pfncname, pcall->call_from);
1567
if (pmod_data->psl->freply (pmsg, 491, presp_reqpend) < 0)
1568
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1571
if (!(pmsg->msg_flags & FL_SDP_BODY))
1573
if (parse_sdp (pmsg))
1575
LM_ERR ("%sre-INVITE lacks SDP (%s)!", pfncname, pcall->call_from);
1576
if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0)
1577
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1583
* o find available MOH files
1584
* o look for hold condition and matching payload type
1587
rtpmap **pmohfiles = find_MOH (pcall->pmohq->mohq_mohdir,
1588
pcall->pmohq->mohq_mohfile);
1592
sdp_session_cell_t *psession;
1593
for (nsession = 0; (psession = get_sdp_session (pmsg, nsession)); nsession++)
1596
sdp_stream_cell_t *pstream;
1597
for (nstream = 0; (pstream = get_sdp_stream (pmsg, nsession, nstream));
1604
* o at least one payload matches?
1607
if (!pstream->is_rtp)
1609
if (!STR_EQ (*paudio, pstream->media))
1611
if (pstream->is_on_hold)
1620
* check payload types for a match
1623
sdp_payload_attr_t *ppayload;
1624
for (ppayload = pstream->payload_attr; ppayload; ppayload = ppayload->next)
1626
int ntype = atoi (ppayload->rtp_payload.s);
1628
for (nidx = 0; pmohfiles [nidx]; nidx++)
1630
if (pmohfiles [nidx]->ntype == ntype)
1641
* if no hold, allow re-INVITE if matching file
1648
LM_ERR ("%sre-INVITE refused because no matching payload for call (%s)!",
1649
pfncname, pcall->call_from);
1650
if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0)
1652
LM_ERR ("%sUnable to create reply!", pfncname);
1658
mohq_debug (pcall->pmohq, "%sAccepted re-INVITE for call (%s)",
1659
pfncname, pcall->call_from);
1660
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
1662
LM_ERR ("%sUnable to create reply!", pfncname);
1670
* hold not allowed, say good-bye
1673
LM_ERR ("%sTerminating call (%s) because hold not allowed!",
1674
pfncname, pcall->call_from);
1675
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
1677
LM_ERR ("%sUnable to create reply!", pfncname);
1680
close_call (pmsg, pcall);
1685
* Search Header for Extension
1688
* Arg (1) = header field pointer
1689
* Arg (2) = extension str pointer
1690
* OUTPUT: 0=not found
1693
int search_hdr_ext (struct hdr_field *phdr, str *pext)
1698
str *pstr = &phdr->body;
1700
for (npos1 = 0; npos1 < pstr->len; npos1++)
1704
* o search to end, space or comma
1709
if (pstr->s [npos1] == ' ')
1711
for (npos2 = npos1++; npos1 < pstr->len; npos1++)
1713
if (pstr->s [npos1] == ' ' || pstr->s [npos1] == ',')
1716
if (npos1 - npos2 != pext->len)
1718
if (!strncasecmp (&pstr->s [npos2], pext->s, pext->len))
1725
* Send Provisional Response
1728
* Arg (1) = SIP message pointer
1729
* Arg (2) = call pointer
1730
* OUTPUT: 0=unable to process; 1=processed
1733
int send_prov_rsp (sip_msg_t *pmsg, call_lst *pcall)
1737
* o send ringing response with require
1741
char *pfncname = "send_prov_rsp: ";
1742
tm_api_t *ptm = pmod_data->ptm;
1743
pcall->call_cseq = rand ();
1746
"Accept-Language: en" SIPEOL
1747
"Require: 100rel" SIPEOL
1749
"User-Agent: " USRAGNT SIPEOL
1751
sprintf (phdrtmp, phdrtmplt, pcall->call_cseq);
1752
struct lump_rpl **phdrlump = add_lump_rpl2 (pmsg, phdrtmp,
1753
strlen (phdrtmp), LUMP_RPL_HDR);
1756
LM_ERR ("%sUnable to create new header for call (%s)!",
1757
pfncname, pcall->call_from);
1758
if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
1759
{ LM_ERR ("%sUnable to create reply!", pfncname); }
1762
if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0)
1764
LM_ERR ("%sUnable to reply to INVITE for call (%s)",
1765
pfncname, pcall->call_from);
1768
pcall->call_state = CLSTA_PRACKSTRT;
1769
mohq_debug (pcall->pmohq, "%sSent PRACK RINGING for call (%s)",
1770
pfncname, pcall->call_from);
1773
* o wait until PRACK (64*T1 RFC 3261 section 7.1.1)
1774
* o remove header lump
1777
time_t nstart = time (0) + 32;
1780
usleep (USLEEP_LEN);
1781
if (pcall->call_state != CLSTA_PRACKSTRT)
1783
if (nstart < time (0))
1785
LM_ERR ("%sNo PRACK response for call (%s)",
1786
pfncname, pcall->call_from);
1790
unlink_lump_rpl (pmsg, *phdrlump);
1791
if (pcall->call_state != CLSTA_PRACKRPLY)
1797
* Send RTPProxy Answer
1800
* Arg (1) = SIP message pointer
1801
* Arg (2) = call pointer
1802
* OUTPUT: 0=unable to process; 1=processed
1805
int send_rtp_answer (sip_msg_t *pmsg, call_lst *pcall)
1809
* build response from request
1812
char *pfncname = "send_rtp_answer: ";
1814
tm_api_t *ptm = pmod_data->ptm;
1815
struct cell *ptrans = ptm->t_gett ();
1817
ptotag->s = pcall->call_tag;
1818
ptotag->len = strlen (pcall->call_tag);
1820
struct bookmark pBM [1];
1821
pbuf->s = build_res_buf_from_sip_req (200, presp_ok, ptotag, ptrans->uas.request,
1822
(unsigned int *)&pbuf->len, pBM);
1823
if (!pbuf->s || !pbuf->len)
1825
LM_ERR ("%sUnable to create SDP response for call (%s)!",
1826
pfncname, pcall->call_from);
1831
* parse out first line and headers
1834
char *pclenhdr = CLENHDR;
1838
for (npos1 = 0; npos1 < pbuf->len; npos1++)
1844
for (npos2 = npos1++; npos1 < pbuf->len; npos1++)
1847
* o not EOL? (CRLF assumed)
1848
* o next line a continuation? (RFC 3261 section 7.3.1)
1851
if (pbuf->s [npos1] != '\n')
1853
if (npos1 + 1 == pbuf->len)
1855
if (pbuf->s [npos1 + 1] == ' '
1856
|| pbuf->s [npos1 + 1] == '\t')
1862
* o blank is end of header (RFC 3261 section 7)
1863
* o ignore Content-Length (assume followed by colon)
1867
if (npos1 - npos2 == 1)
1869
if (npos1 - npos2 > 14)
1871
if (!strncasecmp (&pbuf->s [npos2], pclenhdr, 14))
1874
pparse [nhdrcnt].s = &pbuf->s [npos2];
1875
pparse [nhdrcnt++].len = npos1 - npos2 + 1;
1879
* recreate buffer with extra headers and SDP
1881
* o count hdrs, extra hdrs, content-length hdr, SDP
1882
* o alloc new buffer
1884
* o replace orig buffer
1887
str pSDP [1] = {STR_NULL};
1888
if (!form_rtp_SDP (pSDP, pcall, prtpsdp))
1889
{ goto answer_done; }
1890
for (npos1 = npos2 = 0; npos2 < nhdrcnt; npos2++)
1891
{ npos1 += pparse [npos2].len; }
1893
sprintf (pbodylen, "%s: %d\r\n\r\n", pclenhdr, pSDP->len);
1894
npos1 += pextrahdr->len + strlen (pbodylen) + pSDP->len + 1;
1895
char *pnewbuf = pkg_malloc (npos1);
1898
LM_ERR ("%sNo more memory!", pfncname);
1901
for (npos1 = npos2 = 0; npos2 < nhdrcnt; npos2++)
1903
memcpy (&pnewbuf [npos1], pparse [npos2].s, pparse [npos2].len);
1904
npos1 += pparse [npos2].len;
1906
npos2 = pextrahdr->len;
1907
memcpy (&pnewbuf [npos1], pextrahdr->s, npos2);
1909
npos2 = strlen (pbodylen);
1910
memcpy (&pnewbuf [npos1], pbodylen, npos2);
1913
memcpy (&pnewbuf [npos1], pSDP->s, npos2);
1923
struct sip_msg pnmsg [1];
1924
build_sip_msg_from_buf (pnmsg, pbuf->s, pbuf->len, 0);
1925
memcpy (&pnmsg->rcv, &pmsg->rcv, sizeof (struct receive_info));
1928
* o send rtpproxy answer
1929
* o form stream file
1933
mohq_debug (pcall->pmohq, "%sAnswering RTP link for call (%s)",
1934
pfncname, pcall->call_from);
1935
if (pmod_data->fn_rtp_answer (pnmsg, 0, 0) != 1)
1937
LM_ERR ("%srtpproxy_answer refused for call (%s)!",
1938
pfncname, pcall->call_from);
1941
if (!start_stream (pnmsg, pcall, 0))
1942
{ goto answer_done; }
1945
* o create buffer from response
1949
pbuf->s = build_res_buf_from_sip_res (pnmsg, (unsigned int *)&pbuf->len);
1951
free_sip_msg (pnmsg);
1952
if (!pbuf->s || !pbuf->len)
1954
LM_ERR ("%sUnable to create SDP response for call (%s)!",
1955
pfncname, pcall->call_from);
1959
for (npos1 = 0; npos1 < pbuf->len; npos1++)
1961
if (pbuf->s [npos1] != '\n')
1963
if (pbuf->s [npos1 - 3] == '\r')
1966
pnewSDP->s = &pbuf->s [npos1 + 1];
1967
pnewSDP->len = pbuf->len - npos1 - 1;
1970
* o save media port number
1971
* o send adjusted reply
1974
char *pfnd = strstr (pnewSDP->s, "m=audio ");
1977
// should not happen
1978
LM_ERR ("%sUnable to find audio port for call (%s)!",
1979
pfncname, pcall->call_from);
1982
pcall->call_aport = strtol (pfnd + 8, NULL, 10);
1983
if (!add_lump_rpl2 (pmsg, pextrahdr->s, pextrahdr->len, LUMP_RPL_HDR))
1985
LM_ERR ("%sUnable to add header for call (%s)!",
1986
pfncname, pcall->call_from);
1989
if (!add_lump_rpl2 (pmsg, pnewSDP->s, pnewSDP->len, LUMP_RPL_BODY))
1991
LM_ERR ("%sUnable to add SDP body for call (%s)!",
1992
pfncname, pcall->call_from);
1995
if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0)
1997
LM_ERR ("%sUnable to reply to INVITE for call (%s)!",
1998
pfncname, pcall->call_from);
2001
pcall->call_state = CLSTA_INVITED;
2002
mohq_debug (pcall->pmohq, "%sResponded to INVITE with RTP for call (%s)",
2003
pfncname, pcall->call_from);
2007
* free buffer and return
2012
{ pkg_free (pSDP->s); }
2021
* Arg (1) = SIP message pointer
2022
* Arg (2) = call pointer
2023
* Arg (3) = server flag
2024
* OUTPUT: 0 if failed
2027
int start_stream (sip_msg_t *pmsg, call_lst *pcall, int bserver)
2030
char *pfncname = "start_stream: ";
2031
char pfile [MOHDIRLEN + MOHFILELEN + 2];
2032
strcpy (pfile, pcall->pmohq->mohq_mohdir);
2033
int npos = strlen (pfile);
2034
pfile [npos++] = '/';
2035
strcpy (&pfile [npos], pcall->pmohq->mohq_mohfile);
2036
npos += strlen (&pfile [npos]);
2037
str pMOH [1] = {{pfile, npos}};
2039
pv_parse_format (pMOH, &pmodel);
2040
cmd_function fn_stream = bserver ? pmod_data->fn_rtp_stream_s
2041
: pmod_data->fn_rtp_stream_c;
2042
mohq_debug (pcall->pmohq, "%sStarting RTP link for call (%s)",
2043
pfncname, pcall->call_from);
2044
if (fn_stream (pmsg, (char *)pmodel, (char *)-1) != 1)
2046
LM_ERR ("%srtpproxy_stream refused for call (%s)!",
2047
pfncname, pcall->call_from);
2054
* Form Char Array from STR
2057
* Arg (1) = str pointer
2058
* OUTPUT: char pointer; NULL if unable to allocate
2061
char *form_tmpstr (str *pstr)
2064
char *pcstr = malloc (pstr->len + 1);
2067
LM_ERR ("No more memory!");
2070
memcpy (pcstr, pstr->s, pstr->len);
2071
pcstr [pstr->len] = 0;
2076
* Release Char Array
2079
* Arg (1) = char pointer
2083
void free_tmpstr (char *pcstr)
2092
* external functions
2099
* Arg (1) = mohdir pointer
2100
* Arg (2) = mohfile pointer
2101
* OUTPUT: array of pointers for matching files; last element=0
2104
rtpmap **find_MOH (char *pmohdir, char *pmohfile)
2108
* form base file name
2111
char pfile [MOHDIRLEN + MOHFILELEN + 6];
2112
strcpy (pfile, pmohdir);
2113
int nflen = strlen (pfile);
2114
pfile [nflen++] = '/';
2115
strcpy (&pfile [nflen], pmohfile);
2116
nflen += strlen (&pfile [nflen]);
2117
pfile [nflen++] = '.';
2120
* find available files based on RTP payload type
2125
for (nidx = 0; prtpmap [nidx].pencode; nidx++)
2128
* o form file name based on payload type
2132
sprintf (&pfile [nflen], "%d", prtpmap [nidx].ntype);
2133
struct stat psb [1];
2134
if (lstat (pfile, psb))
2136
pmohfiles [nfound++] = &prtpmap [nidx];
2138
pmohfiles [nfound] = 0;
2146
* queue name = queue to use
2147
* state = 0=off, <>0=on
2150
* Arg (1) = command tree pointer
2151
* Arg (2) = parms pointer
2152
* OUTPUT: root pointer
2155
struct mi_root *mi_debug (struct mi_root *pcmd_tree, void *parms)
2159
* o parm count correct?
2164
struct mi_node *pnode = pcmd_tree->node.kids;
2165
if (!pnode || !pnode->next || pnode->next->next)
2166
{ return init_mi_tree (400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); }
2167
int nq_idx = find_queue (&pnode->value);
2169
{ return init_mi_tree (400, pmi_noqueue->s, pmi_noqueue->len); }
2171
int nsize = (pnode->next->value.len >= sizeof (pint))
2172
? sizeof (pint) - 1 : pnode->next->value.len;
2173
strncpy (pint, pnode->next->value.s, nsize);
2174
pint [nsize] = '\0';
2175
int bdebug = atoi (pint) ? 1 : 0;
2176
if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 5000))
2177
{ return init_mi_tree (400, pmi_nolock->s, pmi_nolock->len); }
2181
* o update queue table
2185
mohq_lst *pqueue = &pmod_data->pmohq_lst [nq_idx];
2187
{ pqueue->mohq_flags |= MOHQF_DBG; }
2189
{ pqueue->mohq_flags &= ~MOHQF_DBG; }
2190
update_debug (pqueue, bdebug);
2191
mohq_lock_release (pmod_data->pmohq_lock);
2192
return init_mi_tree (200, MI_OK_S, MI_OK_LEN);
2199
* queue name = queue to use
2200
* callID = *=all, otherwise callID
2203
* Arg (1) = command tree pointer
2204
* Arg (2) = parms pointer
2205
* OUTPUT: root pointer
2208
struct mi_root *mi_drop_call (struct mi_root *pcmd_tree, void *parms)
2212
* o parm count correct?
2217
struct mi_node *pnode = pcmd_tree->node.kids;
2218
if (!pnode || !pnode->next || pnode->next->next)
2219
{ return init_mi_tree (400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); }
2220
int nq_idx = find_queue (&pnode->value);
2222
{ return init_mi_tree (400, pmi_noqueue->s, pmi_noqueue->len); }
2223
if (!mohq_lock_set (pmod_data->pcall_lock, 0, 5000))
2224
{ return init_mi_tree (400, pmi_nolock->s, pmi_nolock->len); }
2227
* o find matching calls
2231
mohq_lst *pqueue = &pmod_data->pmohq_lst [nq_idx];
2233
str *pcallid = &pnode->next->value;
2234
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
2242
call_lst *pcall = &pmod_data->pcall_lst [nidx];
2243
if (!pcall->call_active)
2245
if (pqueue->mohq_id != pcall->pmohq->mohq_id)
2248
if (!STR_EQ (*pcallid, *pallq))
2250
tmpstr->s = pcall->call_id;
2251
tmpstr->len = strlen (tmpstr->s);
2252
if (!STR_EQ (*tmpstr, *pcallid))
2255
close_call (FAKED_REPLY, pcall);
2257
mohq_lock_release (pmod_data->pcall_lock);
2258
return init_mi_tree (200, MI_OK_S, MI_OK_LEN);
2265
* Arg (1) = SIP message pointer
2266
* Arg (2) = queue name
2267
* Arg (3) = pv result name
2268
* OUTPUT: -1 if no items in queue; else result = count
2271
int mohq_count (sip_msg_t *pmsg, char *pqueue, pv_spec_t *presult)
2275
* get queue and pv names
2278
char *pfncname = "mohq_count: ";
2280
if (!pqueue || !presult)
2282
LM_ERR ("%sParameters missing!", pfncname);
2285
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
2287
LM_ERR ("%sInvalid queue name!", pfncname);
2294
* o count items in queue
2297
int nq_idx = find_queue (pqname);
2299
call_lst *pcalls = pmod_data->pcall_lst;
2300
int ncall_idx, mohq_id;
2301
if (!mohq_lock_set (pmod_data->pcall_lock, 0, 200))
2302
{ LM_ERR ("%sUnable to lock calls!", pfncname); }
2307
mohq_id = pmod_data->pmohq_lst [nq_idx].mohq_id;
2308
for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
2310
if (!pcalls [ncall_idx].call_active)
2312
if (pcalls [ncall_idx].pmohq->mohq_id == mohq_id
2313
&& pcalls [ncall_idx].call_state == CLSTA_INQUEUE)
2317
mohq_lock_release (pmod_data->pcall_lock);
2322
* o exit with result
2325
pv_value_t pavp_val [1];
2326
memset (pavp_val, 0, sizeof (pv_value_t));
2327
pavp_val->ri = ncount;
2328
pavp_val->flags = PV_TYPE_INT | PV_VAL_INT;
2329
if (presult->setf (pmsg, &presult->pvp, (int)EQ_T, pavp_val) < 0)
2331
LM_ERR ("%sUnable to set pv value for mohq_count ()!", pfncname);
2338
* Log Debug Statement
2341
* Arg (1) = MOH queue pointer
2342
* Arg (2) = format pointer
2343
* Arg (...) = optional format values
2344
* OUTPUT: outputs debugging values
2347
void mohq_debug (mohq_lst *pmohq, char *pfmt, ...)
2351
* o get system and MOHQ log level
2352
* o exit if no debug printing
2353
* o force local debug
2354
* o form message and log
2358
int nsys_log = get_debug_level (LOG_MNAME, LOG_MNAME_LEN);
2359
int nmohq_log = (pmohq->mohq_flags & MOHQF_DBG) ? L_DBG : L_INFO;
2360
if (nmohq_log < L_DBG && nsys_log < L_DBG)
2362
if (nsys_log < nmohq_log)
2363
{ set_local_debug_level (nmohq_log); }
2366
va_start (ap, pfmt);
2367
vsnprintf (ptext, sizeof (ptext), pfmt, ap);
2369
LM_DBG ("%s", ptext);
2370
if (nsys_log < nmohq_log)
2371
{ reset_local_debug_level (); }
2379
* Arg (1) = SIP message pointer
2380
* OUTPUT: -1=not directed to queue; 1=successfully processed
2383
int mohq_process (sip_msg_t *pmsg)
2389
* o directed to message queue?
2390
* o connect to database
2393
char *pfncname = "mohq_process: ";
2394
if (parse_headers (pmsg, HDR_EOH_F, 0) < 0)
2396
LM_ERR ("%sUnable to parse header!", pfncname);
2399
if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 2000))
2401
LM_ERR ("%sUnable to lock calls!", pfncname);
2405
int mohq_idx = find_call (pmsg, &pcall);
2406
db1_con_t *pconn = mohq_dbconnect ();
2410
* o last update older than 1 minute?
2411
* o exclusively lock MOH queue
2415
if (pmod_data->mohq_update + 60 < time (0))
2417
if (mohq_lock_change (pmod_data->pmohq_lock, 1))
2419
update_mohq_lst (pconn);
2420
mohq_lock_change (pmod_data->pmohq_lock, 0);
2421
pmod_data->mohq_update = time (0);
2424
mohq_dbdisconnect (pconn);
2428
mohq_lock_release (pmod_data->pmohq_lock);
2434
* o release MOH queue
2437
mohq_debug (&pmod_data->pmohq_lst [mohq_idx],
2438
"%sProcessing %.*s, queue (%s)", pfncname,
2439
STR_FMT (&REQ_LINE (pmsg).method),
2440
pmod_data->pmohq_lst [mohq_idx].mohq_name);
2442
switch (pmsg->REQ_METHOD)
2450
{ ret = first_invite_msg (pmsg, mohq_idx); }
2452
{ ret = reinvite_msg (pmsg, pcall); }
2455
ret = notify_msg (pmsg, pcall);
2458
ret = prack_msg (pmsg, pcall);
2461
ret = ack_msg (pmsg, pcall);
2464
ret = bye_msg (pmsg, pcall);
2467
ret = cancel_msg (pmsg, pcall);
2470
deny_method (pmsg, pcall);
2474
mohq_lock_release (pmod_data->pmohq_lock);
2475
return ret ? 1 : -1;
2479
* Retrieve Oldest Queued Call
2482
* Arg (1) = SIP message pointer
2483
* Arg (2) = queue name
2484
* Arg (3) = redirect URI
2485
* OUTPUT: -1 if no items in queue or error; 1 redirects oldest call
2488
int mohq_retrieve (sip_msg_t *pmsg, char *pqueue, char *pURI)
2492
* o get queue name and URI
2496
char *pfncname = "mohq_retrieve: ";
2497
str puri [1], pqname [1];
2498
if (!pqueue || !pURI)
2500
LM_ERR ("%sParameters missing!", pfncname);
2503
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
2505
LM_ERR ("%sInvalid queue name!", pfncname);
2508
if (fixup_get_svalue (pmsg, (gparam_p)pURI, puri))
2510
LM_ERR ("%sInvalid URI!", pfncname);
2513
if (puri->len > URI_LEN)
2515
LM_ERR ("%sURI too long!", pfncname);
2518
struct sip_uri puri_parsed [1];
2519
if (parse_uri (puri->s, puri->len, puri_parsed))
2521
LM_ERR ("%sInvalid URI (%.*s)!", pfncname, STR_FMT (puri));
2528
* o find oldest call
2531
int nq_idx = find_queue (pqname);
2534
if (!mohq_lock_set (pmod_data->pcall_lock, 0, 200))
2536
LM_ERR ("%sUnable to lock calls!", pfncname);
2539
call_lst *pcall = 0;
2543
int mohq_id = pmod_data->pmohq_lst [nq_idx].mohq_id;
2544
for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
2553
pcall = &pmod_data->pcall_lst [ncall_idx];
2554
if (!pcall->call_active)
2556
if (pcall->pmohq->mohq_id != mohq_id)
2558
if (pcall->call_state != CLSTA_INQUEUE)
2563
ntime = pcall->call_time;
2567
if (pcall->call_time < ntime)
2570
ntime = pcall->call_time;
2576
LM_WARN ("%sNo calls in queue (%.*s)", pfncname, STR_FMT (pqname));
2577
mohq_lock_release (pmod_data->pcall_lock);
2580
pcall = &pmod_data->pcall_lst [nfound];
2583
* o save refer-to URI
2587
strncpy (pcall->call_referto, puri->s, puri->len);
2588
pcall->call_referto [puri->len] = '\0';
2589
if (refer_call (pcall, pmod_data->pcall_lock))
2591
LM_ERR ("%sUnable to refer call (%s)!", pfncname, pcall->call_from);
2596
* Send Message to Queue
2599
* Arg (1) = SIP message pointer
2600
* Arg (2) = queue name
2601
* OUTPUT: -1 if no items in queue; 1 if successfull
2604
int mohq_send (sip_msg_t *pmsg, char *pqueue)
2612
char *pfncname = "mohq_send: ";
2613
if (pmsg->REQ_METHOD != METHOD_INVITE)
2615
LM_ERR ("%sNot an INVITE message!", pfncname);
2618
to_body_t *pto_body = get_to (pmsg);
2619
if (pto_body->tag_value.len)
2621
LM_ERR ("%sNot a first INVITE message!", pfncname);
2627
LM_ERR ("%sParameters missing!", pfncname);
2630
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
2632
LM_ERR ("%sInvalid queue name!", pfncname);
2642
int nq_idx = find_queue (pqname);
2645
str pruri [1] = {{0, strlen (pmod_data->pmohq_lst [nq_idx].mohq_uri)}};
2646
pruri->s = pkg_malloc (pruri->len + 1);
2649
LM_ERR ("%sNo more memory!", pfncname);
2652
strcpy (pruri->s, pmod_data->pmohq_lst [nq_idx].mohq_uri);
2653
if (pmsg->new_uri.s)
2654
{ pkg_free (pmsg->new_uri.s); }
2655
pmsg->new_uri.s = pruri->s;
2656
pmsg->new_uri.len = pruri->len;
2657
pmsg->parsed_uri_ok = 0;
2658
pmsg->parsed_orig_ruri_ok = 0;
2659
if (pmod_data->ptm->t_relay (pmsg, 0, 0) < 0)
2661
LM_ERR ("%sUnable to relay INVITE!", pfncname);
b'\\ No newline at end of file'