~ubuntu-branches/debian/sid/kamailio/sid

« back to all changes in this revision

Viewing changes to modules/mohqueue/mohq_funcs.c

  • Committer: Package Import Robot
  • Author(s): Victor Seva
  • Date: 2014-01-06 11:47:13 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140106114713-t8xidp4arzrnyeya
Tags: 4.1.1-1
* New upstream release
* debian/patches:
  - add upstream fixes
* Added tls outbound websocket autheph dnssec modules
  - openssl exception added to their license
* removing sparc and ia64 from supported archs
  for mono module (Closes: #728915)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id$
 
3
 *
 
4
 * Copyright (C) 2013 Robert Boisvert
 
5
 *
 
6
 * This file is part of the mohqueue module for sip-router, a free SIP server.
 
7
 *
 
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
 
12
 *
 
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.
 
17
 *
 
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
 
21
 *
 
22
 */
 
23
 
 
24
#include <stdarg.h>
 
25
 
 
26
#include "mohq.h"
 
27
#include "mohq_db.h"
 
28
#include "mohq_funcs.h"
 
29
 
 
30
/**********
 
31
* definitions
 
32
**********/
 
33
 
 
34
#define ALLOWHDR "Allow: INVITE, ACK, BYE, CANCEL, NOTIFY, PRACK"
 
35
#define CLENHDR "Content-Length"
 
36
#define SIPEOL  "\r\n"
 
37
#define USRAGNT "Kamailio MOH Queue v1.0"
 
38
 
 
39
/**********
 
40
* local constants
 
41
**********/
 
42
 
 
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")};
 
61
 
 
62
rtpmap prtpmap [] =
 
63
  {
 
64
  {9, "G722/8000"},
 
65
  {0, "PCMU/8000"},
 
66
  {8, "PCMA/8000"},
 
67
  {18, "G729/8000"},
 
68
  {3, "GSM/8000"},
 
69
  {4, "G723/8000"},
 
70
  {15, "G728/8000"},
 
71
  {5, "DVI4/8000"},
 
72
  {7, "LPC/8000"},
 
73
  {12, "QCELP/8000"},
 
74
  {13, "CN/8000"},
 
75
  {16, "DVI4/11025"},
 
76
  {6, "DVI4/16000"},
 
77
  {17, "DVI4/22050"},
 
78
  {10, "L16/44100"},
 
79
  {11, "L16/44100"},
 
80
  {14, "MPA/90000"},
 
81
  {0, 0}
 
82
  };
 
83
 
 
84
rtpmap *pmohfiles [30]; // element count should be equal or greater than prtpmap
 
85
 
 
86
str pallowhdr [1] = { STR_STATIC_INIT (ALLOWHDR SIPEOL) };
 
87
 
 
88
char pbyemsg [] =
 
89
  {
 
90
  "%s"
 
91
  "Max-Forwards: 70" SIPEOL
 
92
  "Contact: <%s>" SIPEOL
 
93
  "User-Agent: " USRAGNT SIPEOL
 
94
  };
 
95
 
 
96
str pextrahdr [1] =
 
97
  {
 
98
  STR_STATIC_INIT (
 
99
  ALLOWHDR SIPEOL
 
100
  "Supported: 100rel" SIPEOL
 
101
  "Accept-Language: en" SIPEOL
 
102
  "Content-Type: application/sdp" SIPEOL
 
103
  "User-Agent: " USRAGNT SIPEOL
 
104
  )
 
105
  };
 
106
 
 
107
char pinvitesdp [] =
 
108
  {
 
109
  "v=0" SIPEOL
 
110
  "o=- %d %d IN %s" SIPEOL
 
111
  "s=" USRAGNT SIPEOL
 
112
  "c=IN %s" SIPEOL
 
113
  "t=0 0" SIPEOL
 
114
  "a=send%s" SIPEOL
 
115
  "m=audio %d RTP/AVP "
 
116
  };
 
117
 
 
118
char prefermsg [] =
 
119
  {
 
120
  "%s"
 
121
  "Max-Forwards: 70" SIPEOL
 
122
  "Refer-To: <%s>" SIPEOL
 
123
  "Referred-By: <%.*s>" SIPEOL
 
124
  "User-Agent: " USRAGNT SIPEOL
 
125
  };
 
126
 
 
127
char preinvitemsg [] =
 
128
  {
 
129
  "%s"
 
130
  "Max-Forwards: 70" SIPEOL
 
131
  "Contact: <%s>" SIPEOL
 
132
  ALLOWHDR SIPEOL
 
133
  "Supported: 100rel" SIPEOL
 
134
  "User-Agent: " USRAGNT SIPEOL
 
135
  "Accept-Language: en" SIPEOL
 
136
  "Content-Type: application/sdp" SIPEOL
 
137
  };
 
138
 
 
139
char prtpsdp [] =
 
140
  {
 
141
  "v=0" SIPEOL
 
142
  // IP address and audio port faked since they will be replaced
 
143
  "o=- 1 1 IN IP4 1.1.1.1" SIPEOL
 
144
  "s=" USRAGNT SIPEOL
 
145
  "c=IN IP4 1.1.1.1" SIPEOL
 
146
  "t=0 0" SIPEOL
 
147
  "a=sendrecv" SIPEOL
 
148
  "m=audio 1 RTP/AVP"
 
149
  };
 
150
 
 
151
/**********
 
152
* local function declarations
 
153
**********/
 
154
 
 
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);
 
167
 
 
168
/**********
 
169
* local functions
 
170
**********/
 
171
 
 
172
/**********
 
173
* Process ACK Message
 
174
*
 
175
* INPUT:
 
176
*   Arg (1) = SIP message pointer
 
177
*   Arg (2) = call pointer
 
178
* OUTPUT: 0=failed
 
179
**********/
 
180
 
 
181
int ack_msg (sip_msg_t *pmsg, call_lst *pcall)
 
182
 
 
183
{
 
184
/**********
 
185
* part of INVITE?
 
186
**********/
 
187
 
 
188
char *pfncname = "ack_msg: ";
 
189
struct cell *ptrans;
 
190
tm_api_t *ptm = pmod_data->ptm;
 
191
if (pcall->call_state != CLSTA_INVITED)
 
192
  {
 
193
  /**********
 
194
  * ignore if from rejected re-INVITE
 
195
  **********/
 
196
 
 
197
  if (pcall->call_state != CLSTA_INQUEUE)
 
198
    { LM_ERR ("%sUnexpected ACK (%s)!", pfncname, pcall->call_from); }
 
199
  else
 
200
    {
 
201
    mohq_debug (pcall->pmohq, "%sACK from refused re-INVITE (%s)!",
 
202
      pfncname, pcall->call_from);
 
203
    }
 
204
  return 1;
 
205
  }
 
206
 
 
207
/**********
 
208
* o release INVITE transaction
 
209
* o save SDP address info
 
210
* o put in queue
 
211
**********/
 
212
 
 
213
if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
 
214
  {
 
215
  LM_ERR ("%sINVITE transaction missing for call (%s)!",
 
216
    pfncname, pcall->call_from);
 
217
  return 1;
 
218
  }
 
219
else
 
220
  {
 
221
  if (ptm->t_release (pcall->call_pmsg) < 0)
 
222
    {
 
223
    LM_ERR ("%sRelease transaction failed for call (%s)!",
 
224
      pfncname, pcall->call_from);
 
225
    return 1;
 
226
    }
 
227
  }
 
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);
 
238
return 1;
 
239
}
 
240
 
 
241
/**********
 
242
* BYE Callback
 
243
*
 
244
* INPUT:
 
245
*   Arg (1) = cell pointer
 
246
*   Arg (2) = callback type
 
247
*   Arg (3) = callback parms
 
248
* OUTPUT: none
 
249
**********/
 
250
 
 
251
static void bye_cb
 
252
  (struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
 
253
 
 
254
{
 
255
/**********
 
256
* o error means must have hung after REFER
 
257
* o delete the call
 
258
**********/
 
259
 
 
260
char *pfncname = "bye_cb: ";
 
261
call_lst *pcall = (call_lst *)*pcbp->param;
 
262
if (ntype == TMCB_ON_FAILURE)
 
263
  {
 
264
  LM_ERR ("%sCall (%s) did not respond to BYE", pfncname,
 
265
    pcall->call_from);
 
266
  }
 
267
else
 
268
  {
 
269
  int nreply = pcbp->code;
 
270
  if ((nreply / 100) != 2)
 
271
    {
 
272
    LM_ERR ("%sCall (%s) BYE error (%d)", pfncname,
 
273
      pcall->call_from, nreply);
 
274
    }
 
275
  else
 
276
    {
 
277
    mohq_debug (pcall->pmohq, "%sCall (%s) BYE reply=%d", pfncname,
 
278
      pcall->call_from, nreply);
 
279
    }
 
280
  }
 
281
delete_call (pcall);
 
282
return;
 
283
}
 
284
 
 
285
/**********
 
286
* Process BYE Message
 
287
*
 
288
* INPUT:
 
289
*   Arg (1) = SIP message pointer
 
290
*   Arg (2) = call pointer
 
291
* OUTPUT: 0=failed
 
292
**********/
 
293
 
 
294
int bye_msg (sip_msg_t *pmsg, call_lst *pcall)
 
295
 
 
296
{
 
297
/**********
 
298
* o send OK
 
299
* o teardown call
 
300
**********/
 
301
 
 
302
char *pfncname = "bye_msg: ";
 
303
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
 
304
  {
 
305
  LM_ERR ("%sUnable to create reply to call (%s)", pfncname,
 
306
    pcall->call_from);
 
307
  return 1;
 
308
  }
 
309
if (pcall->call_state >= CLSTA_INQUEUE)
 
310
  { drop_call (pmsg, pcall); }
 
311
else
 
312
  {
 
313
  LM_ERR ("%sEnding call (%s) before placed in queue!",
 
314
    pfncname, pcall->call_from);
 
315
  delete_call (pcall);
 
316
  }
 
317
return 1;
 
318
}
 
319
 
 
320
/**********
 
321
* Process CANCEL Message
 
322
*
 
323
* INPUT:
 
324
*   Arg (1) = SIP message pointer
 
325
*   Arg (2) = call pointer
 
326
* OUTPUT: 0=failed
 
327
**********/
 
328
 
 
329
int cancel_msg (sip_msg_t *pmsg, call_lst *pcall)
 
330
 
 
331
{
 
332
/**********
 
333
* still in INVITE dialog?
 
334
**********/
 
335
 
 
336
char *pfncname = "cancel_msg: ";
 
337
if (pcall->call_state < CLSTA_INQUEUE)
 
338
  {
 
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); }
 
344
  }
 
345
else
 
346
  {
 
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); }
 
351
  }
 
352
return 1;
 
353
}
 
354
 
 
355
/**********
 
356
* Close the Call
 
357
*
 
358
* INPUT:
 
359
*   Arg (1) = SIP message pointer
 
360
*   Arg (2) = call pointer
 
361
* OUTPUT: none
 
362
**********/
 
363
 
 
364
void close_call (sip_msg_t *pmsg, call_lst *pcall)
 
365
 
 
366
{
 
367
/**********
 
368
* o destroy proxy connection
 
369
* o create dialog
 
370
**********/
 
371
 
 
372
char *pfncname = "close_call: ";
 
373
int bsent = 0;
 
374
char *phdr = 0;
 
375
if (pmsg != FAKED_REPLY)
 
376
  {
 
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)
 
380
    {
 
381
    LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
 
382
      pfncname, pcall->call_from);
 
383
    }
 
384
  }
 
385
struct to_body ptob [2];
 
386
dlg_t *pdlg = form_dialog (pcall, ptob);
 
387
if (!pdlg)
 
388
  { goto bye_err; }
 
389
pdlg->state = DLG_CONFIRMED;
 
390
 
 
391
/**********
 
392
* form BYE header
 
393
* o calculate size
 
394
* o create buffer
 
395
**********/
 
396
 
 
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);
 
403
if (!phdr)
 
404
  {
 
405
  LM_ERR ("%sNo more memory!", pfncname);
 
406
  goto bye_err;
 
407
  }
 
408
sprintf (phdr, pbyemsg,
 
409
  pcall->call_via, // Via
 
410
  pquri); // Contact
 
411
str phdrs [1];
 
412
phdrs->s = phdr;
 
413
phdrs->len = strlen (phdr);
 
414
 
 
415
/**********
 
416
* send BYE request
 
417
**********/
 
418
 
 
419
uac_req_t puac [1];
 
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)
 
424
  {
 
425
  LM_ERR ("%sUnable to create BYE request for call (%s)!",
 
426
    pfncname, pcall->call_from);
 
427
  goto bye_err;
 
428
  }
 
429
mohq_debug (pcall->pmohq, "%sSent BYE request for call (%s)",
 
430
  pfncname, pcall->call_from);
 
431
bsent = 1;
 
432
 
 
433
/**********
 
434
* o free memory
 
435
* o delete call
 
436
**********/
 
437
 
 
438
bye_err:
 
439
if (pdlg)
 
440
  { pkg_free (pdlg); }
 
441
if (phdr)
 
442
  { pkg_free (phdr); }
 
443
if (!bsent)
 
444
  { delete_call (pcall); }
 
445
return;
 
446
}
 
447
 
 
448
/**********
 
449
* Create New Call Record
 
450
*
 
451
* INPUT:
 
452
*   Arg (1) = queue index
 
453
*   Arg (2) = SIP message pointer
 
454
* OUTPUT: call index; -1 if unable to create
 
455
**********/
 
456
 
 
457
int create_call (int mohq_idx, sip_msg_t *pmsg)
 
458
 
 
459
{
 
460
/**********
 
461
* o lock calls
 
462
* o already in use?
 
463
* o find inactive slot
 
464
**********/
 
465
 
 
466
char *pfncname = "create_call: ";
 
467
if (!mohq_lock_set (pmod_data->pcall_lock, 1, 2000))
 
468
  {
 
469
  LM_ERR ("%sUnable to lock calls!", pfncname);
 
470
  return -1;
 
471
  }
 
472
call_lst *pcall;
 
473
int ncall_idx = find_call (pmsg, &pcall);
 
474
if (pcall)
 
475
  {
 
476
  mohq_lock_release (pmod_data->pcall_lock);
 
477
  LM_ERR ("%sCall already in use (%s)!", pfncname, pcall->call_from);
 
478
  return -1;
 
479
  }
 
480
for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
 
481
  {
 
482
  if (!pmod_data->pcall_lst [ncall_idx].call_active)
 
483
    { break; }
 
484
  }
 
485
if (ncall_idx == pmod_data->call_cnt)
 
486
  {
 
487
  mohq_lock_release (pmod_data->pcall_lock);
 
488
  LM_ERR ("%sNo call slots available!", pfncname);
 
489
  return -1;
 
490
  }
 
491
 
 
492
/**********
 
493
* add values to new entry
 
494
**********/
 
495
 
 
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';
 
507
if (!pmsg->contact)
 
508
  { *pcall->call_contact = '\0'; }
 
509
else
 
510
  {
 
511
  pstr = &pmsg->contact->body;
 
512
  strncpy (pcall->call_contact, pstr->s, pstr->len);
 
513
  pcall->call_contact [pstr->len] = '\0';
 
514
  }
 
515
 
 
516
/**********
 
517
* extract Via headers
 
518
**********/
 
519
 
 
520
hdr_field_t *phdr = pmsg->h_via1;
 
521
if (phdr)
 
522
  {
 
523
  int npos1 = 0;
 
524
  while ((phdr = next_sibling_hdr (phdr)))
 
525
    {
 
526
    struct via_body *pvia;
 
527
    char *pviabuf;
 
528
    int bovrflow = 0;
 
529
    int npos2;
 
530
    int nvia_max = sizeof (pcall->call_via);
 
531
    for (pvia = (struct via_body *)phdr->parsed; pvia; pvia = pvia->next)
 
532
      {
 
533
      /**********
 
534
      * o skip trailing whitespace
 
535
      * o check if overflow
 
536
      **********/
 
537
 
 
538
      npos2 = pvia->bsize;
 
539
      pviabuf = pvia->name.s;
 
540
      while (npos2)
 
541
        {
 
542
        --npos2;
 
543
        if (pviabuf [npos2] == ' ' || pviabuf [npos2] == '\r'
 
544
          || pviabuf [npos2] == '\n' || pviabuf [npos2] == '\t' || pviabuf [npos2] == ',')
 
545
          { continue; }
 
546
        break;
 
547
        }
 
548
      if ((npos2 + npos1 + 7) >= nvia_max)
 
549
        {
 
550
        LM_WARN ("%sVia buffer overflowed!", pfncname);
 
551
        bovrflow = 1;
 
552
        break;
 
553
        }
 
554
 
 
555
      /**********
 
556
      * copy via
 
557
      **********/
 
558
 
 
559
      strcpy (&pcall->call_via [npos1], "Via: ");
 
560
      npos1 += 5;
 
561
      strncpy (&pcall->call_via [npos1], pviabuf, npos2);
 
562
      npos1 += npos2;
 
563
      strcpy (&pcall->call_via [npos1], SIPEOL);
 
564
      npos1 += 2;
 
565
      }
 
566
    if (bovrflow)
 
567
      { break; }
 
568
    }
 
569
  }
 
570
 
 
571
/**********
 
572
* o release call lock
 
573
* o update DB
 
574
* o lock MOH queue
 
575
**********/
 
576
 
 
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);
 
583
return ncall_idx;
 
584
}
 
585
 
 
586
/**********
 
587
* Delete Call
 
588
*
 
589
* INPUT:
 
590
*   Arg (1) = call pointer
 
591
* OUTPUT: none
 
592
**********/
 
593
 
 
594
void delete_call (call_lst *pcall)
 
595
 
 
596
{
 
597
/**********
 
598
* release transaction
 
599
**********/
 
600
 
 
601
char *pfncname = "delete_call: ";
 
602
struct cell *ptrans;
 
603
tm_api_t *ptm = pmod_data->ptm;
 
604
if (pcall->call_hash || pcall->call_label)
 
605
  {
 
606
  if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
 
607
    {
 
608
    LM_ERR ("%sLookup transaction failed for call (%s)!", pfncname,
 
609
      pcall->call_from);
 
610
    }
 
611
  else
 
612
    {
 
613
    if (ptm->t_release (pcall->call_pmsg) < 0)
 
614
      {
 
615
      LM_ERR ("%sRelease transaction failed for call (%s)!",
 
616
        pfncname, pcall->call_from);
 
617
      }
 
618
    }
 
619
  pcall->call_hash = pcall->call_label = 0;
 
620
  }
 
621
 
 
622
/**********
 
623
* o update DB
 
624
* o inactivate slot
 
625
* o release MOH queue
 
626
**********/
 
627
 
 
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);
 
633
return;
 
634
}
 
635
 
 
636
/**********
 
637
* Deny Method
 
638
*
 
639
* INPUT:
 
640
*   Arg (1) = SIP message pointer
 
641
*   Arg (2) = call pointer
 
642
* OUTPUT: none
 
643
**********/
 
644
 
 
645
void deny_method (sip_msg_t *pmsg, call_lst *pcall)
 
646
 
 
647
{
 
648
/**********
 
649
* RFC 3261 section 8.2.1
 
650
* o get transaction
 
651
* o respond with 405 and Allow header
 
652
**********/
 
653
 
 
654
char *pfncname = "deny_method: ";
 
655
tm_api_t *ptm = pmod_data->ptm;
 
656
if (ptm->t_newtran (pmsg) < 0)
 
657
  {
 
658
  LM_ERR ("%sUnable to create new transaction!", pfncname);
 
659
  if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
 
660
    {
 
661
    LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
 
662
      STR_FMT (&REQ_LINE (pmsg).method));
 
663
    }
 
664
  return;
 
665
  }
 
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)
 
671
  {
 
672
  LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
 
673
    STR_FMT (&REQ_LINE (pmsg).method));
 
674
  }
 
675
return;
 
676
}
 
677
 
 
678
/**********
 
679
* Drop the Call
 
680
*
 
681
* INPUT:
 
682
*   Arg (1) = SIP message pointer
 
683
*   Arg (2) = call pointer
 
684
* OUTPUT: none
 
685
**********/
 
686
 
 
687
void drop_call (sip_msg_t *pmsg, call_lst *pcall)
 
688
 
 
689
{
 
690
/**********
 
691
* o destroy proxy connection
 
692
* o delete call
 
693
**********/
 
694
 
 
695
char *pfncname = "drop_call: ";
 
696
if (pmsg != FAKED_REPLY)
 
697
  {
 
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)
 
701
    {
 
702
    LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
 
703
      pfncname, pcall->call_from);
 
704
    }
 
705
  }
 
706
delete_call (pcall);
 
707
return;
 
708
}
 
709
 
 
710
/**********
 
711
* Find Call
 
712
*
 
713
* INPUT:
 
714
*   Arg (1) = SIP message pointer
 
715
*   Arg (2) = pointer to call pointer
 
716
* OUTPUT: queue index; -1 if unable to find
 
717
**********/
 
718
 
 
719
int find_call (sip_msg_t *pmsg, call_lst **ppcall)
 
720
 
 
721
{
 
722
/**********
 
723
* o find current RURI
 
724
* o strip off parms or headers
 
725
* o search MOH queue
 
726
**********/
 
727
 
 
728
str *pruri =
 
729
  pmsg->new_uri.s ? &pmsg->new_uri : &pmsg->first_line.u.request.uri;
 
730
int nidx;
 
731
str pstr [1];
 
732
pstr->s = pruri->s;
 
733
pstr->len = pruri->len;
 
734
for (nidx = 0; nidx < pruri->len; nidx++)
 
735
  {
 
736
  if (pstr->s [nidx] == ';' || pstr->s [nidx] == '?')
 
737
    {
 
738
    pstr->len = nidx;
 
739
    break;
 
740
    }
 
741
  }
 
742
mohq_lst *pqlst = pmod_data->pmohq_lst;
 
743
int nqidx;
 
744
for (nqidx = 0; nqidx < pmod_data->mohq_cnt; nqidx++)
 
745
  {
 
746
  str pmohstr [1];
 
747
  pmohstr->s = pqlst [nqidx].mohq_uri;
 
748
  pmohstr->len = strlen (pmohstr->s);
 
749
  if (STR_EQ (*pmohstr, *pstr))
 
750
    { break; }
 
751
  }
 
752
*ppcall = 0;
 
753
if (nqidx == pmod_data->mohq_cnt)
 
754
  { return -1;}
 
755
 
 
756
/**********
 
757
* o get to tag
 
758
* o get callID
 
759
* o ignore to tag if CANCEL on first INVITE
 
760
* o search call queue
 
761
**********/
 
762
 
 
763
str *ptotag = &(get_to (pmsg)->tag_value);
 
764
if (!ptotag->len)
 
765
  { ptotag = 0; }
 
766
if (!pmsg->callid)
 
767
  { return -1; }
 
768
str *pcallid = &pmsg->callid->body;
 
769
if (!pcallid)
 
770
  { return -1; }
 
771
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
 
772
  {
 
773
  /**********
 
774
  * o call active?
 
775
  * o call timed out on ACK?
 
776
  * o callID matches?
 
777
  * o to tag matches?
 
778
  * o return call pointer
 
779
  **********/
 
780
 
 
781
  call_lst *pcall = &pmod_data->pcall_lst [nidx];
 
782
  if (!pcall->call_active)
 
783
    { continue; }
 
784
  if (pcall->call_time && (pcall->call_state < CLSTA_INQUEUE))
 
785
    {
 
786
    if ((pcall->call_time + 32) < time (0))
 
787
      {
 
788
      LM_ERR ("find_call: No ACK response for call (%s)", pcall->call_from);
 
789
      delete_call (pcall);
 
790
      continue;
 
791
      }
 
792
    }
 
793
  str tmpstr [1];
 
794
  tmpstr->s = pcall->call_id;
 
795
  tmpstr->len = strlen (tmpstr->s);
 
796
  if (!STR_EQ (*tmpstr, *pcallid))
 
797
    { continue; }
 
798
  if (ptotag)
 
799
    {
 
800
    tmpstr->s = pcall->call_tag;
 
801
    tmpstr->len = strlen (tmpstr->s);
 
802
    if (!STR_EQ (*tmpstr, *ptotag))
 
803
      { continue; }
 
804
    }
 
805
  *ppcall = pcall;
 
806
  return nqidx;
 
807
  }
 
808
 
 
809
/**********
 
810
* first INVITE?
 
811
**********/
 
812
 
 
813
if (pmsg->REQ_METHOD == METHOD_INVITE)
 
814
  { return 0; }
 
815
return -1;
 
816
}
 
817
 
 
818
/**********
 
819
* Find Queue
 
820
*
 
821
* INPUT:
 
822
*   Arg (1) = queue name str pointer
 
823
* OUTPUT: queue index; -1 if unable to find
 
824
**********/
 
825
 
 
826
int find_queue (str *pqname)
 
827
 
 
828
{
 
829
char *pfncname = "find_queue: ";
 
830
int nidx;
 
831
str tmpstr;
 
832
if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 500))
 
833
  {
 
834
  LM_ERR ("%sUnable to lock queues!", pfncname);
 
835
  return -1;
 
836
  }
 
837
for (nidx = 0; nidx < pmod_data->mohq_cnt; nidx++)
 
838
  {
 
839
  tmpstr.s = pmod_data->pmohq_lst [nidx].mohq_name;
 
840
  tmpstr.len = strlen (tmpstr.s);
 
841
  if (STR_EQ (tmpstr, *pqname))
 
842
    { break; }
 
843
  }
 
844
if (nidx == pmod_data->mohq_cnt)
 
845
  {
 
846
  LM_ERR ("%sUnable to find queue (%.*s)!", pfncname, STR_FMT (pqname));
 
847
  nidx = -1;
 
848
  }
 
849
mohq_lock_release (pmod_data->pmohq_lock);
 
850
return nidx;
 
851
}
 
852
 
 
853
/**********
 
854
* Find Referred Call
 
855
*
 
856
* INPUT:
 
857
*   Arg (1) = referred-by value
 
858
* OUTPUT: call index; -1 if unable to find
 
859
**********/
 
860
 
 
861
int find_referred_call (str *pvalue)
 
862
 
 
863
{
 
864
/**********
 
865
* get URI
 
866
**********/
 
867
 
 
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)
 
872
  {
 
873
  // should never happen
 
874
  LM_ERR ("%sInvalid Referred-By URI (%.*s)!", pfncname, STR_FMT (pvalue));
 
875
  return -1;
 
876
  }
 
877
if (pref->param_lst)
 
878
  { free_to_params (pref); }
 
879
 
 
880
/**********
 
881
* search calls for matching
 
882
**********/
 
883
 
 
884
int nidx;
 
885
str tmpstr;
 
886
struct to_body pfrom [1];
 
887
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
 
888
  {
 
889
  if (!pmod_data->pcall_lst [nidx].call_active)
 
890
    { continue; }
 
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)
 
895
    {
 
896
    // should never happen
 
897
    LM_ERR ("%sInvalid From URI (%.*s)!", pfncname, STR_FMT (&tmpstr));
 
898
    continue;
 
899
    }
 
900
  if (pfrom->param_lst)
 
901
    { free_to_params (pfrom); }
 
902
  if (STR_EQ (pfrom->uri, pref->uri))
 
903
    { return nidx; }
 
904
  }
 
905
return -1;
 
906
}
 
907
 
 
908
/**********
 
909
* Process First INVITE Message
 
910
*
 
911
* INPUT:
 
912
*   Arg (1) = SIP message pointer
 
913
*   Arg (2) = queue index
 
914
* OUTPUT: 0=failed
 
915
**********/
 
916
 
 
917
int first_invite_msg (sip_msg_t *pmsg, int mohq_idx)
 
918
 
 
919
{
 
920
/**********
 
921
* create call record
 
922
**********/
 
923
 
 
924
char *pfncname = "first_invite_msg: ";
 
925
int ncall_idx = create_call (mohq_idx, pmsg);
 
926
if (ncall_idx == -1)
 
927
  { return 0; }
 
928
call_lst *pcall = &pmod_data->pcall_lst [ncall_idx];
 
929
 
 
930
/**********
 
931
* o SDP exists?
 
932
* o accepts REFER?
 
933
* o send rtpproxy offer
 
934
**********/
 
935
 
 
936
if (!(pmsg->msg_flags & FL_SDP_BODY))
 
937
  {
 
938
  if (parse_sdp (pmsg))
 
939
    {
 
940
    LM_ERR ("%sINVITE lacks SDP (%s)!", pfncname, pcall->call_from);
 
941
    delete_call (pcall);
 
942
    return 0;
 
943
    }
 
944
  }
 
945
if (pmsg->allow)
 
946
  {
 
947
  if (!search_hdr_ext (pmsg->allow, prefer))
 
948
    {
 
949
    LM_ERR ("%sMissing REFER support (%s)!", pfncname, pcall->call_from);
 
950
    delete_call (pcall);
 
951
    return 0;
 
952
    }
 
953
  }
 
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)
 
957
  {
 
958
  LM_ERR ("%srtpproxy_offer refused for call (%s)!",
 
959
    pfncname, pcall->call_from);
 
960
  delete_call (pcall);
 
961
  return 0;
 
962
  }
 
963
 
 
964
/**********
 
965
* o create new transaction
 
966
* o save To tag
 
967
* o catch failures
 
968
* o save transaction data
 
969
**********/
 
970
 
 
971
tm_api_t *ptm = pmod_data->ptm;
 
972
if (ptm->t_newtran (pmsg) < 0)
 
973
  {
 
974
  LM_ERR ("%sUnable to create new transaction for call (%s)!",
 
975
    pfncname, pcall->call_from);
 
976
  delete_call (pcall);
 
977
  return 0;
 
978
  }
 
979
struct cell *ptrans = ptm->t_gett ();
 
980
pcall->call_hash = ptrans->hash_index;
 
981
pcall->call_label = ptrans->label;
 
982
str ptotag [1];
 
983
if (ptm->t_get_reply_totag (pmsg, ptotag) != 1)
 
984
  {
 
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); }
 
989
  delete_call (pcall);
 
990
  return 1;
 
991
  }
 
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)
 
997
  {
 
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);
 
1003
  return 1;
 
1004
  }
 
1005
 
 
1006
/**********
 
1007
* o add contact to reply
 
1008
* o supports/requires PRACK? (RFC 3262 section 3)
 
1009
* o exit if not ringing
 
1010
**********/
 
1011
 
 
1012
str pcontact [1];
 
1013
char *pcontacthdr = "Contact: <%s>" SIPEOL;
 
1014
pcontact->s = pkg_malloc (strlen (pmod_data->pmohq_lst [mohq_idx].mohq_uri)
 
1015
  + strlen (pcontacthdr));
 
1016
if (!pcontact->s)
 
1017
  {
 
1018
  LM_ERR ("%sNo more memory!", pfncname);
 
1019
  delete_call (pcall);
 
1020
  return 1;
 
1021
  }
 
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))
 
1025
  {
 
1026
  LM_ERR ("%sUnable to add contact (%s) to call (%s)!",
 
1027
    pfncname, pcontact->s, pcall->call_from);
 
1028
  }
 
1029
pkg_free (pcontact->s);
 
1030
pcall->call_pmsg = pmsg;
 
1031
if (search_hdr_ext (pmsg->require, p100rel))
 
1032
  {
 
1033
  if (!send_prov_rsp (pmsg, pcall))
 
1034
    {
 
1035
    delete_call (pcall);
 
1036
    return 1;
 
1037
    }
 
1038
  }
 
1039
else
 
1040
  {
 
1041
  if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0)
 
1042
    {
 
1043
    LM_ERR ("%sUnable to reply to INVITE!", pfncname);
 
1044
    return 1;
 
1045
    }
 
1046
  else
 
1047
    {
 
1048
    pcall->call_state = CLSTA_RINGING;
 
1049
    mohq_debug (pcall->pmohq, "%sSent RINGING for call (%s)",
 
1050
      pfncname, pcall->call_from);
 
1051
    }
 
1052
  }
 
1053
 
 
1054
/**********
 
1055
* o call cancelled?
 
1056
* o accept call with RTP
 
1057
**********/
 
1058
 
 
1059
if (pcall->call_state == CLSTA_CANCEL)
 
1060
  {
 
1061
  delete_call (pcall);
 
1062
  return 1;
 
1063
  }
 
1064
if (!send_rtp_answer (pmsg, pcall))
 
1065
  {
 
1066
  if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
 
1067
    { LM_ERR ("%sUnable to create reply!", pfncname); }
 
1068
  delete_call (pcall);
 
1069
  }
 
1070
return 1;
 
1071
}
 
1072
 
 
1073
/**********
 
1074
* Form Dialog
 
1075
*
 
1076
* INPUT:
 
1077
*   Arg (1) = call pointer
 
1078
*   Arg (2) = to_body [2] pointer
 
1079
* OUTPUT: dlg_t * if successful; 0=if not
 
1080
**********/
 
1081
 
 
1082
dlg_t *form_dialog (call_lst *pcall, struct to_body *pto_body)
 
1083
 
 
1084
{
 
1085
/**********
 
1086
* get from/to values
 
1087
**********/
 
1088
 
 
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)
 
1095
  {
 
1096
  // should never happen
 
1097
  LM_ERR ("%sInvalid from URI (%s)!", pfncname, pcall->call_from);
 
1098
  return 0;
 
1099
  }
 
1100
if (ptob->param_lst)
 
1101
  { free_to_params (ptob); }
 
1102
str ptarget [1];
 
1103
if (!*pcall->call_contact)
 
1104
  {
 
1105
  ptarget->s = ptob->uri.s;
 
1106
  ptarget->len = ptob->uri.len;
 
1107
  }
 
1108
else
 
1109
  {
 
1110
  parse_to (pcall->call_contact,
 
1111
    &pcall->call_contact [strlen (pcall->call_contact) + 1], pcontact);
 
1112
  if (pcontact->error != PARSE_OK)
 
1113
    {
 
1114
    // should never happen
 
1115
    LM_ERR ("%sInvalid contact (%s) for call (%s)!", pfncname,
 
1116
      pcall->call_contact, pcall->call_from);
 
1117
    return 0;
 
1118
    }
 
1119
  if (pcontact->param_lst)
 
1120
    { free_to_params (pcontact); }
 
1121
  ptarget->s = pcontact->uri.s;
 
1122
  ptarget->len = pcontact->uri.len;
 
1123
  }
 
1124
 
 
1125
/**********
 
1126
* create dialog
 
1127
**********/
 
1128
 
 
1129
dlg_t *pdlg = (dlg_t *)pkg_malloc (sizeof (dlg_t));
 
1130
if (!pdlg)
 
1131
  {
 
1132
  LM_ERR ("%sNo more memory!", pfncname);
 
1133
  return 0;
 
1134
  }
 
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;
 
1150
return pdlg;
 
1151
}
 
1152
 
 
1153
/**********
 
1154
* Form RTP SDP String
 
1155
*
 
1156
* INPUT:
 
1157
*   Arg (1) = string pointer
 
1158
*   Arg (2) = call pointer
 
1159
*   Arg (3) = SDP body pointer
 
1160
* OUTPUT: 0 if failed
 
1161
**********/
 
1162
 
 
1163
int form_rtp_SDP (str *pstr, call_lst *pcall, char *pSDP)
 
1164
 
 
1165
{
 
1166
/**********
 
1167
* o find available files
 
1168
* o calculate size of SDP
 
1169
**********/
 
1170
 
 
1171
char *pfncname = "form_rtp_SDP: ";
 
1172
rtpmap **pmohfiles = find_MOH (pcall->pmohq->mohq_mohdir,
 
1173
  pcall->pmohq->mohq_mohfile);
 
1174
if (!pmohfiles [0])
 
1175
  {
 
1176
  LM_ERR ("%sUnable to find any MOH files for queue (%s)!", pfncname,
 
1177
    pcall->pmohq->mohq_name);
 
1178
  return 0;
 
1179
  }
 
1180
int nsize = strlen (pSDP) + 2;
 
1181
int nidx;
 
1182
for (nidx = 0; pmohfiles [nidx]; nidx++)
 
1183
  {
 
1184
  nsize += strlen (pmohfiles [nidx]->pencode) // encode length
 
1185
    + 19; // space, type number, "a=rtpmap:%d ", EOL
 
1186
  }
 
1187
 
 
1188
/**********
 
1189
* o allocate memory
 
1190
* o form SDP
 
1191
**********/
 
1192
 
 
1193
pstr->s = pkg_malloc (nsize + 1);
 
1194
if (!pstr->s)
 
1195
  {
 
1196
  LM_ERR ("%sNo more memory!", pfncname);
 
1197
  return 0;
 
1198
  }
 
1199
strcpy (pstr->s, pSDP);
 
1200
nsize = strlen (pstr->s);
 
1201
for (nidx = 0; pmohfiles [nidx]; nidx++)
 
1202
  {
 
1203
  /**********
 
1204
  * add payload types to media description
 
1205
  **********/
 
1206
 
 
1207
  sprintf (&pstr->s [nsize], " %d", pmohfiles [nidx]->ntype);
 
1208
  nsize += strlen (&pstr->s [nsize]);
 
1209
  }
 
1210
strcpy (&pstr->s [nsize], SIPEOL);
 
1211
nsize += 2;
 
1212
for (nidx = 0; pmohfiles [nidx]; nidx++)
 
1213
  {
 
1214
  /**********
 
1215
  * add rtpmap attributes
 
1216
  **********/
 
1217
 
 
1218
  sprintf (&pstr->s [nsize], "a=rtpmap:%d %s %s",
 
1219
    pmohfiles [nidx]->ntype, pmohfiles [nidx]->pencode, SIPEOL);
 
1220
  nsize += strlen (&pstr->s [nsize]);
 
1221
  }
 
1222
pstr->len = nsize;
 
1223
return 1;
 
1224
}
 
1225
 
 
1226
/**********
 
1227
* Invite Callback
 
1228
*
 
1229
* INPUT:
 
1230
*   Arg (1) = cell pointer
 
1231
*   Arg (2) = callback type
 
1232
*   Arg (3) = callback parms
 
1233
* OUTPUT: none
 
1234
**********/
 
1235
 
 
1236
static void
 
1237
  invite_cb (struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
 
1238
 
 
1239
{
 
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);
 
1245
return;
 
1246
}
 
1247
 
 
1248
/**********
 
1249
* Process NOTIFY Message
 
1250
*
 
1251
* INPUT:
 
1252
*   Arg (1) = SIP message pointer
 
1253
*   Arg (2) = call pointer
 
1254
* OUTPUT: 0=failed
 
1255
**********/
 
1256
 
 
1257
int notify_msg (sip_msg_t *pmsg, call_lst *pcall)
 
1258
 
 
1259
{
 
1260
/**********
 
1261
* waiting on REFER?
 
1262
**********/
 
1263
 
 
1264
char *pfncname = "notify_msg: ";
 
1265
if (pcall->call_state != CLSTA_RFRWAIT)
 
1266
  {
 
1267
  LM_ERR ("%sNot waiting on a REFER for call (%s)!", pfncname,
 
1268
    pcall->call_from);
 
1269
  if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0)
 
1270
    { LM_ERR ("%sUnable to create reply!", pfncname); }
 
1271
  return 1;
 
1272
  }
 
1273
 
 
1274
/**********
 
1275
* o sipfrag?
 
1276
* o get status from body
 
1277
* o add CRLF so parser can go beyond first line
 
1278
**********/
 
1279
 
 
1280
if (!search_hdr_ext (pmsg->content_type, psipfrag))
 
1281
  {
 
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); }
 
1286
  return 1;
 
1287
  }
 
1288
char *pfrag = get_body (pmsg);
 
1289
if (!pfrag)
 
1290
  {
 
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); }
 
1295
  return 1;
 
1296
  }
 
1297
str pbody [1];
 
1298
pbody->len = pmsg->len - (int)(pfrag - pmsg->buf);
 
1299
pbody->s = pkg_malloc (pbody->len + 2);
 
1300
if (!pbody->s)
 
1301
  {
 
1302
  LM_ERR ("%sNo more memory!", pfncname);
 
1303
  return 1;
 
1304
  }
 
1305
strncpy (pbody->s, pfrag, pbody->len);
 
1306
if (pbody->s [pbody->len - 1] != '\n')
 
1307
  {
 
1308
  strncpy (&pbody->s [pbody->len], SIPEOL, 2);
 
1309
  pbody->len += 2;
 
1310
  }
 
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)
 
1315
  {
 
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); }
 
1319
  return 1;
 
1320
  }
 
1321
 
 
1322
/**********
 
1323
* o send OK
 
1324
* o REFER done?
 
1325
**********/
 
1326
 
 
1327
if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
 
1328
  {
 
1329
  LM_ERR ("%sUnable to create reply for call (%s)!",
 
1330
    pfncname, pcall->call_from);
 
1331
  return 1;
 
1332
  }
 
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)
 
1337
  {
 
1338
  case 1:
 
1339
    break;
 
1340
  case 2:
 
1341
    close_call (pmsg, pcall);
 
1342
    break;
 
1343
  default:
 
1344
    LM_WARN ("%sUnable to redirect call (%s)!", pfncname, pcall->call_from);
 
1345
    if (nreply == 487)
 
1346
      {
 
1347
      /**********
 
1348
      * call was canceled
 
1349
      **********/
 
1350
 
 
1351
      drop_call (pmsg, pcall);
 
1352
      return 1;
 
1353
      }
 
1354
 
 
1355
    /**********
 
1356
    * return call to queue
 
1357
    **********/
 
1358
 
 
1359
    pcall->call_state = CLSTA_INQUEUE;
 
1360
    update_call_rec (pcall);
 
1361
    break;
 
1362
  }
 
1363
return 1;
 
1364
}
 
1365
 
 
1366
/**********
 
1367
* Process PRACK Message
 
1368
*
 
1369
* INPUT:
 
1370
*   Arg (1) = SIP message pointer
 
1371
*   Arg (2) = call pointer
 
1372
* OUTPUT: 0=failed
 
1373
**********/
 
1374
 
 
1375
int prack_msg (sip_msg_t *pmsg, call_lst *pcall)
 
1376
 
 
1377
{
 
1378
/**********
 
1379
* waiting on PRACK?
 
1380
**********/
 
1381
 
 
1382
char *pfncname = "prack_msg: ";
 
1383
tm_api_t *ptm = pmod_data->ptm;
 
1384
if (pcall->call_state != CLSTA_PRACKSTRT)
 
1385
  {
 
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); }
 
1389
  return 1;
 
1390
  }
 
1391
 
 
1392
/**********
 
1393
* o check RAck ??? need to check
 
1394
* o accept PRACK
 
1395
**********/
 
1396
 
 
1397
if (ptm->t_newtran (pmsg) < 0)
 
1398
  {
 
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); }
 
1403
  return 1;
 
1404
  }
 
1405
if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0)
 
1406
  {
 
1407
  LM_ERR ("%sUnable to reply to PRACK for call (%s)!",
 
1408
    pfncname, pcall->call_from);
 
1409
  return 1;
 
1410
  }
 
1411
pcall->call_state = CLSTA_PRACKRPLY;
 
1412
return 1;
 
1413
}
 
1414
 
 
1415
/**********
 
1416
* Refer Call
 
1417
*
 
1418
* INPUT:
 
1419
*   Arg (1) = call pointer
 
1420
*   Arg (2) = lock pointer
 
1421
* OUTPUT: 0 if failed
 
1422
**********/
 
1423
 
 
1424
int refer_call (call_lst *pcall, mohq_lock *plock)
 
1425
 
 
1426
{
 
1427
/**********
 
1428
* create dialog
 
1429
**********/
 
1430
 
 
1431
char *pfncname = "refer_call: ";
 
1432
int nret = 0;
 
1433
struct to_body ptob [2];
 
1434
dlg_t *pdlg = form_dialog (pcall, ptob);
 
1435
if (!pdlg)
 
1436
  {
 
1437
  mohq_lock_release (plock);
 
1438
  return 0;
 
1439
  }
 
1440
pdlg->state = DLG_CONFIRMED;
 
1441
 
 
1442
/**********
 
1443
* form REFER message
 
1444
* o calculate basic size
 
1445
* o create buffer
 
1446
**********/
 
1447
 
 
1448
str puri [1];
 
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);
 
1456
if (!pbuf)
 
1457
  {
 
1458
  LM_ERR ("%sNo more memory!", pfncname);
 
1459
  goto refererr;
 
1460
  }
 
1461
sprintf (pbuf, prefermsg,
 
1462
  pcall->call_via, // Via
 
1463
  puri->s, // Refer-To
 
1464
  STR_FMT (&ptob->uri)); // Referred-By
 
1465
 
 
1466
/**********
 
1467
* send REFER request
 
1468
**********/
 
1469
 
 
1470
tm_api_t *ptm = pmod_data->ptm;
 
1471
uac_req_t puac [1];
 
1472
str phdrs [1];
 
1473
phdrs->s = pbuf;
 
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)
 
1481
  {
 
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);
 
1486
  goto refererr;
 
1487
  }
 
1488
mohq_debug (pcall->pmohq, "%sSent REFER request for call (%s) to %s",
 
1489
  pfncname, pcall->call_from, pcall->call_referto);
 
1490
nret = -1;
 
1491
 
 
1492
refererr:
 
1493
if (pdlg)
 
1494
  { pkg_free (pdlg); }
 
1495
pkg_free (pbuf);
 
1496
return nret;
 
1497
}
 
1498
 
 
1499
/**********
 
1500
* REFER Callback
 
1501
*
 
1502
* INPUT:
 
1503
*   Arg (1) = cell pointer
 
1504
*   Arg (2) = callback type
 
1505
*   Arg (3) = callback parms
 
1506
* OUTPUT: none
 
1507
**********/
 
1508
 
 
1509
static void refer_cb
 
1510
  (struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
 
1511
 
 
1512
{
 
1513
char *pfncname = "refer_cb: ";
 
1514
call_lst *pcall = (call_lst *)*pcbp->param;
 
1515
if ((ntype == TMCB_ON_FAILURE) || (pcbp->req == FAKED_REPLY))
 
1516
  {
 
1517
  LM_ERR ("%sCall (%s) did not respond to REFER", pfncname,
 
1518
    pcall->call_from);
 
1519
  drop_call (pcbp->req, pcall);
 
1520
  return;
 
1521
  }
 
1522
int nreply = pcbp->code;
 
1523
if ((nreply / 100) == 2)
 
1524
  {
 
1525
  pcall->call_state = CLSTA_RFRWAIT;
 
1526
  mohq_debug (pcall->pmohq, "%sCall (%s) REFER reply=%d",
 
1527
    pfncname, pcall->call_from, nreply);
 
1528
  }
 
1529
else
 
1530
  {
 
1531
  LM_ERR ("%sCall (%s) REFER error (%d)", pfncname,
 
1532
    pcall->call_from, nreply);
 
1533
  if (nreply == 481)
 
1534
    { delete_call (pcall); }
 
1535
  else
 
1536
    {
 
1537
    pcall->call_state = CLSTA_INQUEUE;
 
1538
    update_call_rec (pcall);
 
1539
    }
 
1540
  }
 
1541
return;
 
1542
}
 
1543
 
 
1544
/**********
 
1545
* Process re-INVITE Message
 
1546
*
 
1547
* INPUT:
 
1548
*   Arg (1) = SIP message pointer
 
1549
*   Arg (2) = call pointer
 
1550
* OUTPUT: 0=failed
 
1551
**********/
 
1552
 
 
1553
int reinvite_msg (sip_msg_t *pmsg, call_lst *pcall)
 
1554
 
 
1555
{
 
1556
/**********
 
1557
* RFC 3261 section 14.2
 
1558
* o dialog pending?
 
1559
* o get SDP
 
1560
**********/
 
1561
 
 
1562
char *pfncname = "reinvite_msg: ";
 
1563
if ((pcall->call_state / 100) < 2)
 
1564
  {
 
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); }
 
1569
  return 1;
 
1570
  }
 
1571
if (!(pmsg->msg_flags & FL_SDP_BODY))
 
1572
  {
 
1573
  if (parse_sdp (pmsg))
 
1574
    {
 
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); }
 
1578
    return 1;
 
1579
    }
 
1580
  }
 
1581
 
 
1582
/**********
 
1583
* o find available MOH files
 
1584
* o look for hold condition and matching payload type
 
1585
**********/
 
1586
 
 
1587
rtpmap **pmohfiles = find_MOH (pcall->pmohq->mohq_mohdir,
 
1588
  pcall->pmohq->mohq_mohfile);
 
1589
int bhold = 0;
 
1590
int bmatch = 0;
 
1591
int nsession;
 
1592
sdp_session_cell_t *psession;
 
1593
for (nsession = 0; (psession = get_sdp_session (pmsg, nsession)); nsession++)
 
1594
  {
 
1595
  int nstream;
 
1596
  sdp_stream_cell_t *pstream;
 
1597
  for (nstream = 0; (pstream = get_sdp_stream (pmsg, nsession, nstream));
 
1598
    nstream++)
 
1599
    {
 
1600
    /**********
 
1601
    * o RTP?
 
1602
    * o audio?
 
1603
    * o hold?
 
1604
    * o at least one payload matches?
 
1605
    **********/
 
1606
 
 
1607
    if (!pstream->is_rtp)
 
1608
      { continue; }
 
1609
    if (!STR_EQ (*paudio, pstream->media))
 
1610
      { continue; }
 
1611
    if (pstream->is_on_hold)
 
1612
      {
 
1613
      bhold = 1;
 
1614
      break;
 
1615
      }
 
1616
    if (bmatch)
 
1617
      { continue; }
 
1618
 
 
1619
    /**********
 
1620
    * check payload types for a match
 
1621
    **********/
 
1622
 
 
1623
    sdp_payload_attr_t *ppayload;
 
1624
    for (ppayload = pstream->payload_attr; ppayload; ppayload = ppayload->next)
 
1625
      {
 
1626
      int ntype = atoi (ppayload->rtp_payload.s);
 
1627
      int nidx;
 
1628
      for (nidx = 0; pmohfiles [nidx]; nidx++)
 
1629
        {
 
1630
        if (pmohfiles [nidx]->ntype == ntype)
 
1631
          {
 
1632
          bmatch = 1;
 
1633
          break;
 
1634
          }
 
1635
        }
 
1636
      }
 
1637
    }
 
1638
  }
 
1639
 
 
1640
/**********
 
1641
* if no hold, allow re-INVITE if matching file
 
1642
**********/
 
1643
 
 
1644
if (!bhold)
 
1645
  {
 
1646
  if (!bmatch)
 
1647
    {
 
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)
 
1651
      {
 
1652
      LM_ERR ("%sUnable to create reply!", pfncname);
 
1653
      return 1;
 
1654
      }
 
1655
    }
 
1656
  else
 
1657
    {
 
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)
 
1661
      {
 
1662
      LM_ERR ("%sUnable to create reply!", pfncname);
 
1663
      return 1;
 
1664
      }
 
1665
    }
 
1666
  return 1;
 
1667
  }
 
1668
 
 
1669
/**********
 
1670
* hold not allowed, say good-bye
 
1671
**********/
 
1672
 
 
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)
 
1676
  {
 
1677
  LM_ERR ("%sUnable to create reply!", pfncname);
 
1678
  return 1;
 
1679
  }
 
1680
close_call (pmsg, pcall);
 
1681
return 1;
 
1682
}
 
1683
 
 
1684
/**********
 
1685
* Search Header for Extension
 
1686
*
 
1687
* INPUT:
 
1688
*   Arg (1) = header field pointer
 
1689
*   Arg (2) = extension str pointer
 
1690
* OUTPUT: 0=not found
 
1691
**********/
 
1692
 
 
1693
int search_hdr_ext (struct hdr_field *phdr, str *pext)
 
1694
 
 
1695
{
 
1696
if (!phdr)
 
1697
  { return 0; }
 
1698
str *pstr = &phdr->body;
 
1699
int npos1, npos2;
 
1700
for (npos1 = 0; npos1 < pstr->len; npos1++)
 
1701
  {
 
1702
  /**********
 
1703
  * o find non-space
 
1704
  * o search to end, space or comma
 
1705
  * o same size?
 
1706
  * o same name?
 
1707
  **********/
 
1708
 
 
1709
  if (pstr->s [npos1] == ' ')
 
1710
    { continue; }
 
1711
  for (npos2 = npos1++; npos1 < pstr->len; npos1++)
 
1712
    {
 
1713
    if (pstr->s [npos1] == ' ' || pstr->s [npos1] == ',')
 
1714
      { break; }
 
1715
    }
 
1716
  if (npos1 - npos2 != pext->len)
 
1717
    { continue; }
 
1718
  if (!strncasecmp (&pstr->s [npos2], pext->s, pext->len))
 
1719
    { return 1; }
 
1720
  }
 
1721
return 0;
 
1722
}
 
1723
 
 
1724
/**********
 
1725
* Send Provisional Response
 
1726
*
 
1727
* INPUT:
 
1728
*   Arg (1) = SIP message pointer
 
1729
*   Arg (2) = call pointer
 
1730
* OUTPUT: 0=unable to process; 1=processed
 
1731
**********/
 
1732
 
 
1733
int send_prov_rsp (sip_msg_t *pmsg, call_lst *pcall)
 
1734
 
 
1735
{
 
1736
/**********
 
1737
* o send ringing response with require
 
1738
* o update record
 
1739
**********/
 
1740
 
 
1741
char *pfncname = "send_prov_rsp: ";
 
1742
tm_api_t *ptm = pmod_data->ptm;
 
1743
pcall->call_cseq = rand ();
 
1744
char phdrtmp [200];
 
1745
char *phdrtmplt =
 
1746
  "Accept-Language: en" SIPEOL
 
1747
  "Require: 100rel" SIPEOL
 
1748
  "RSeq: %d" SIPEOL
 
1749
  "User-Agent: " USRAGNT SIPEOL
 
1750
  ;
 
1751
sprintf (phdrtmp, phdrtmplt, pcall->call_cseq);
 
1752
struct lump_rpl **phdrlump = add_lump_rpl2 (pmsg, phdrtmp,
 
1753
  strlen (phdrtmp), LUMP_RPL_HDR);
 
1754
if (!phdrlump)
 
1755
  {
 
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); }
 
1760
  return 0;
 
1761
  }
 
1762
if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0)
 
1763
  {
 
1764
  LM_ERR ("%sUnable to reply to INVITE for call (%s)",
 
1765
    pfncname, pcall->call_from);
 
1766
  return 0;
 
1767
  }
 
1768
pcall->call_state = CLSTA_PRACKSTRT;
 
1769
mohq_debug (pcall->pmohq, "%sSent PRACK RINGING for call (%s)",
 
1770
  pfncname, pcall->call_from);
 
1771
 
 
1772
/**********
 
1773
* o wait until PRACK (64*T1 RFC 3261 section 7.1.1)
 
1774
* o remove header lump
 
1775
**********/
 
1776
 
 
1777
time_t nstart = time (0) + 32;
 
1778
while (1)
 
1779
  {
 
1780
  usleep (USLEEP_LEN);
 
1781
  if (pcall->call_state != CLSTA_PRACKSTRT)
 
1782
    { break; }
 
1783
  if (nstart < time (0))
 
1784
    {
 
1785
    LM_ERR ("%sNo PRACK response for call (%s)",
 
1786
      pfncname, pcall->call_from);
 
1787
    break;
 
1788
    }
 
1789
  }
 
1790
unlink_lump_rpl (pmsg, *phdrlump);
 
1791
if (pcall->call_state != CLSTA_PRACKRPLY)
 
1792
  { return 0; }
 
1793
return 1;
 
1794
}
 
1795
 
 
1796
/**********
 
1797
* Send RTPProxy Answer
 
1798
*
 
1799
* INPUT:
 
1800
*   Arg (1) = SIP message pointer
 
1801
*   Arg (2) = call pointer
 
1802
* OUTPUT: 0=unable to process; 1=processed
 
1803
**********/
 
1804
 
 
1805
int send_rtp_answer (sip_msg_t *pmsg, call_lst *pcall)
 
1806
 
 
1807
{
 
1808
/**********
 
1809
* build response from request
 
1810
**********/
 
1811
 
 
1812
char *pfncname = "send_rtp_answer: ";
 
1813
int nret = 0;
 
1814
tm_api_t *ptm = pmod_data->ptm;
 
1815
struct cell *ptrans = ptm->t_gett ();
 
1816
str ptotag [1];
 
1817
ptotag->s = pcall->call_tag;
 
1818
ptotag->len = strlen (pcall->call_tag);
 
1819
str pbuf [1];
 
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)
 
1824
  {
 
1825
  LM_ERR ("%sUnable to create SDP response for call (%s)!",
 
1826
    pfncname, pcall->call_from);
 
1827
  return 0;
 
1828
  }
 
1829
 
 
1830
/**********
 
1831
* parse out first line and headers
 
1832
**********/
 
1833
 
 
1834
char *pclenhdr = CLENHDR;
 
1835
str pparse [20];
 
1836
int npos1, npos2;
 
1837
int nhdrcnt = 0;
 
1838
for (npos1 = 0; npos1 < pbuf->len; npos1++)
 
1839
  {
 
1840
  /**********
 
1841
  * find EOL
 
1842
  **********/
 
1843
 
 
1844
  for (npos2 = npos1++; npos1 < pbuf->len; npos1++)
 
1845
    {
 
1846
    /**********
 
1847
    * o not EOL? (CRLF assumed)
 
1848
    * o next line a continuation? (RFC 3261 section 7.3.1)
 
1849
    **********/
 
1850
 
 
1851
    if (pbuf->s [npos1] != '\n')
 
1852
      { continue; }
 
1853
    if (npos1 + 1 == pbuf->len)
 
1854
      { break; }
 
1855
    if (pbuf->s [npos1 + 1] == ' '
 
1856
      || pbuf->s [npos1 + 1] == '\t')
 
1857
      { continue; }
 
1858
    break;
 
1859
    }
 
1860
 
 
1861
  /**********
 
1862
  * o blank is end of header (RFC 3261 section 7)
 
1863
  * o ignore Content-Length (assume followed by colon)
 
1864
  * o save header
 
1865
  **********/
 
1866
 
 
1867
  if (npos1 - npos2 == 1)
 
1868
    { break; }
 
1869
  if (npos1 - npos2 > 14)
 
1870
    {
 
1871
    if (!strncasecmp (&pbuf->s [npos2], pclenhdr, 14))
 
1872
      { continue; }
 
1873
    }
 
1874
  pparse [nhdrcnt].s = &pbuf->s [npos2];
 
1875
  pparse [nhdrcnt++].len = npos1 - npos2 + 1;
 
1876
  }
 
1877
 
 
1878
/**********
 
1879
* recreate buffer with extra headers and SDP
 
1880
* o form SDP
 
1881
* o count hdrs, extra hdrs, content-length hdr, SDP
 
1882
* o alloc new buffer
 
1883
* o form new buffer
 
1884
* o replace orig buffer
 
1885
**********/
 
1886
 
 
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; }
 
1892
char pbodylen [30];
 
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);
 
1896
if (!pnewbuf)
 
1897
  {
 
1898
  LM_ERR ("%sNo more memory!", pfncname);
 
1899
  goto answer_done;
 
1900
  }
 
1901
for (npos1 = npos2 = 0; npos2 < nhdrcnt; npos2++)
 
1902
  {
 
1903
  memcpy (&pnewbuf [npos1], pparse [npos2].s, pparse [npos2].len);
 
1904
  npos1 += pparse [npos2].len;
 
1905
  }
 
1906
npos2 = pextrahdr->len;
 
1907
memcpy (&pnewbuf [npos1], pextrahdr->s, npos2);
 
1908
npos1 += npos2;
 
1909
npos2 = strlen (pbodylen);
 
1910
memcpy (&pnewbuf [npos1], pbodylen, npos2);
 
1911
npos1 += npos2;
 
1912
npos2 = pSDP->len;
 
1913
memcpy (&pnewbuf [npos1], pSDP->s, npos2);
 
1914
npos1 += npos2;
 
1915
pkg_free (pbuf->s);
 
1916
pbuf->s = pnewbuf;
 
1917
pbuf->len = npos1;
 
1918
 
 
1919
/**********
 
1920
* build SIP msg
 
1921
**********/
 
1922
 
 
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));
 
1926
 
 
1927
/**********
 
1928
* o send rtpproxy answer
 
1929
* o form stream file
 
1930
* o send stream
 
1931
**********/
 
1932
 
 
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)
 
1936
  {
 
1937
  LM_ERR ("%srtpproxy_answer refused for call (%s)!",
 
1938
    pfncname, pcall->call_from);
 
1939
  goto answer_done;
 
1940
  }
 
1941
if (!start_stream (pnmsg, pcall, 0))
 
1942
  { goto answer_done; }
 
1943
 
 
1944
/**********
 
1945
* o create buffer from response
 
1946
* o find SDP
 
1947
**********/
 
1948
 
 
1949
pbuf->s = build_res_buf_from_sip_res (pnmsg, (unsigned int *)&pbuf->len);
 
1950
pkg_free (pnewbuf);
 
1951
free_sip_msg (pnmsg);
 
1952
if (!pbuf->s || !pbuf->len)
 
1953
  {
 
1954
  LM_ERR ("%sUnable to create SDP response for call (%s)!",
 
1955
    pfncname, pcall->call_from);
 
1956
  goto answer_done;
 
1957
  }
 
1958
str pnewSDP [1];
 
1959
for (npos1 = 0; npos1 < pbuf->len; npos1++)
 
1960
  {
 
1961
  if (pbuf->s [npos1] != '\n')
 
1962
    { continue; }
 
1963
  if (pbuf->s [npos1 - 3] == '\r')
 
1964
    { break; }
 
1965
  }
 
1966
pnewSDP->s = &pbuf->s [npos1 + 1];
 
1967
pnewSDP->len = pbuf->len - npos1 - 1;
 
1968
 
 
1969
/**********
 
1970
* o save media port number
 
1971
* o send adjusted reply
 
1972
**********/
 
1973
 
 
1974
char *pfnd = strstr (pnewSDP->s, "m=audio ");
 
1975
if (!pfnd)
 
1976
  {
 
1977
  // should not happen
 
1978
  LM_ERR ("%sUnable to find audio port for call (%s)!",
 
1979
    pfncname, pcall->call_from);
 
1980
  goto answer_done;
 
1981
  }
 
1982
pcall->call_aport = strtol (pfnd + 8, NULL, 10);
 
1983
if (!add_lump_rpl2 (pmsg, pextrahdr->s, pextrahdr->len, LUMP_RPL_HDR))
 
1984
  {
 
1985
  LM_ERR ("%sUnable to add header for call (%s)!",
 
1986
    pfncname, pcall->call_from);
 
1987
  goto answer_done;
 
1988
  }
 
1989
if (!add_lump_rpl2 (pmsg, pnewSDP->s, pnewSDP->len, LUMP_RPL_BODY))
 
1990
  {
 
1991
  LM_ERR ("%sUnable to add SDP body for call (%s)!",
 
1992
    pfncname, pcall->call_from);
 
1993
  goto answer_done;
 
1994
  }
 
1995
if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0)
 
1996
  {
 
1997
  LM_ERR ("%sUnable to reply to INVITE for call (%s)!",
 
1998
    pfncname, pcall->call_from);
 
1999
  goto answer_done;
 
2000
  }
 
2001
pcall->call_state = CLSTA_INVITED;
 
2002
mohq_debug (pcall->pmohq, "%sResponded to INVITE with RTP for call (%s)",
 
2003
  pfncname, pcall->call_from);
 
2004
nret = 1;
 
2005
 
 
2006
/**********
 
2007
* free buffer and return
 
2008
**********/
 
2009
 
 
2010
answer_done:
 
2011
if (pSDP->s)
 
2012
  { pkg_free (pSDP->s); }
 
2013
pkg_free (pbuf->s);
 
2014
return nret;
 
2015
}
 
2016
 
 
2017
/**********
 
2018
* Start Streaming
 
2019
*
 
2020
* INPUT:
 
2021
*   Arg (1) = SIP message pointer
 
2022
*   Arg (2) = call pointer
 
2023
*   Arg (3) = server flag
 
2024
* OUTPUT: 0 if failed
 
2025
**********/
 
2026
 
 
2027
int start_stream (sip_msg_t *pmsg, call_lst *pcall, int bserver)
 
2028
 
 
2029
{
 
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}};
 
2038
pv_elem_t *pmodel;
 
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)
 
2045
  {
 
2046
  LM_ERR ("%srtpproxy_stream refused for call (%s)!",
 
2047
    pfncname, pcall->call_from);
 
2048
  return 0;
 
2049
  }
 
2050
return 1;
 
2051
}
 
2052
 
 
2053
/**********
 
2054
* Form Char Array from STR
 
2055
*
 
2056
* INPUT:
 
2057
*   Arg (1) = str pointer
 
2058
* OUTPUT: char pointer; NULL if unable to allocate
 
2059
**********/
 
2060
 
 
2061
char *form_tmpstr (str *pstr)
 
2062
 
 
2063
{
 
2064
char *pcstr = malloc (pstr->len + 1);
 
2065
if (!pcstr)
 
2066
  {
 
2067
  LM_ERR ("No more memory!");
 
2068
  return NULL;
 
2069
  }
 
2070
memcpy (pcstr, pstr->s, pstr->len);
 
2071
pcstr [pstr->len] = 0;
 
2072
return pcstr;
 
2073
}
 
2074
 
 
2075
/**********
 
2076
* Release Char Array
 
2077
*
 
2078
* INPUT:
 
2079
*   Arg (1) = char pointer
 
2080
* OUTPUT: none
 
2081
**********/
 
2082
 
 
2083
void free_tmpstr (char *pcstr)
 
2084
 
 
2085
{
 
2086
if (pcstr)
 
2087
  { free (pcstr); }
 
2088
return;
 
2089
}
 
2090
 
 
2091
/**********
 
2092
* external functions
 
2093
**********/
 
2094
 
 
2095
/**********
 
2096
* Find MOH Files
 
2097
*
 
2098
* INPUT:
 
2099
*   Arg (1) = mohdir pointer
 
2100
*   Arg (2) = mohfile pointer
 
2101
* OUTPUT: array of pointers for matching files; last element=0
 
2102
**********/
 
2103
 
 
2104
rtpmap **find_MOH (char *pmohdir, char *pmohfile)
 
2105
 
 
2106
{
 
2107
/**********
 
2108
* form base file name
 
2109
**********/
 
2110
 
 
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++] = '.';
 
2118
 
 
2119
/**********
 
2120
* find available files based on RTP payload type
 
2121
**********/
 
2122
 
 
2123
int nidx;
 
2124
int nfound = 0;
 
2125
for (nidx = 0; prtpmap [nidx].pencode; nidx++)
 
2126
  {
 
2127
  /**********
 
2128
  * o form file name based on payload type
 
2129
  * o exists?
 
2130
  **********/
 
2131
 
 
2132
  sprintf (&pfile [nflen], "%d", prtpmap [nidx].ntype);
 
2133
  struct stat psb [1];
 
2134
  if (lstat (pfile, psb))
 
2135
    { continue; }
 
2136
  pmohfiles [nfound++] = &prtpmap [nidx];
 
2137
  }
 
2138
pmohfiles [nfound] = 0;
 
2139
return pmohfiles;
 
2140
}
 
2141
 
 
2142
/**********
 
2143
* MI Debug
 
2144
*
 
2145
* PARAMETERS:
 
2146
* queue name = queue to use
 
2147
* state = 0=off, <>0=on
 
2148
*
 
2149
* INPUT:
 
2150
*   Arg (1) = command tree pointer
 
2151
*   Arg (2) = parms pointer
 
2152
* OUTPUT: root pointer
 
2153
**********/
 
2154
 
 
2155
struct mi_root *mi_debug (struct mi_root *pcmd_tree, void *parms)
 
2156
 
 
2157
{
 
2158
/**********
 
2159
* o parm count correct?
 
2160
* o find queue
 
2161
* o lock queue
 
2162
**********/
 
2163
 
 
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);
 
2168
if (nq_idx == -1)
 
2169
  { return init_mi_tree (400, pmi_noqueue->s, pmi_noqueue->len); }
 
2170
char pint [20];
 
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); }
 
2178
 
 
2179
/**********
 
2180
* o set flag
 
2181
* o update queue table
 
2182
* o release lock
 
2183
**********/
 
2184
 
 
2185
mohq_lst *pqueue = &pmod_data->pmohq_lst [nq_idx];
 
2186
if (bdebug)
 
2187
  { pqueue->mohq_flags |= MOHQF_DBG; }
 
2188
else
 
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);
 
2193
}
 
2194
 
 
2195
/**********
 
2196
* MI Drop Call
 
2197
*
 
2198
* PARAMETERS:
 
2199
* queue name = queue to use
 
2200
* callID = *=all, otherwise callID
 
2201
*
 
2202
* INPUT:
 
2203
*   Arg (1) = command tree pointer
 
2204
*   Arg (2) = parms pointer
 
2205
* OUTPUT: root pointer
 
2206
**********/
 
2207
 
 
2208
struct mi_root *mi_drop_call (struct mi_root *pcmd_tree, void *parms)
 
2209
 
 
2210
{
 
2211
/**********
 
2212
* o parm count correct?
 
2213
* o find queue
 
2214
* o lock calls
 
2215
**********/
 
2216
 
 
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);
 
2221
if (nq_idx == -1)
 
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); }
 
2225
 
 
2226
/**********
 
2227
* o find matching calls
 
2228
* o release lock
 
2229
**********/
 
2230
 
 
2231
mohq_lst *pqueue = &pmod_data->pmohq_lst [nq_idx];
 
2232
int nidx;
 
2233
str *pcallid = &pnode->next->value;
 
2234
for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
 
2235
  {
 
2236
  /**********
 
2237
  * o call active?
 
2238
  * o callID matches?
 
2239
  * o close call
 
2240
  **********/
 
2241
 
 
2242
  call_lst *pcall = &pmod_data->pcall_lst [nidx];
 
2243
  if (!pcall->call_active)
 
2244
    { continue; }
 
2245
  if (pqueue->mohq_id != pcall->pmohq->mohq_id)
 
2246
    { continue; }
 
2247
  str tmpstr [1];
 
2248
  if (!STR_EQ (*pcallid, *pallq))
 
2249
    {
 
2250
    tmpstr->s = pcall->call_id;
 
2251
    tmpstr->len = strlen (tmpstr->s);
 
2252
    if (!STR_EQ (*tmpstr, *pcallid))
 
2253
      { continue; }
 
2254
    }
 
2255
  close_call (FAKED_REPLY, pcall);
 
2256
  }
 
2257
mohq_lock_release (pmod_data->pcall_lock);
 
2258
return init_mi_tree (200, MI_OK_S, MI_OK_LEN);
 
2259
}
 
2260
 
 
2261
/**********
 
2262
* Count Messages
 
2263
*
 
2264
* INPUT:
 
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
 
2269
**********/
 
2270
 
 
2271
int mohq_count (sip_msg_t *pmsg, char *pqueue, pv_spec_t *presult)
 
2272
 
 
2273
{
 
2274
/**********
 
2275
* get queue and pv names
 
2276
**********/
 
2277
 
 
2278
char *pfncname = "mohq_count: ";
 
2279
str pqname [1];
 
2280
if (!pqueue || !presult)
 
2281
  {
 
2282
  LM_ERR ("%sParameters missing!", pfncname);
 
2283
  return -1;
 
2284
  }
 
2285
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
 
2286
  {
 
2287
  LM_ERR ("%sInvalid queue name!", pfncname);
 
2288
  return -1;
 
2289
  }
 
2290
 
 
2291
/**********
 
2292
* o find queue
 
2293
* o lock calls
 
2294
* o count items in queue
 
2295
**********/
 
2296
 
 
2297
int nq_idx = find_queue (pqname);
 
2298
int ncount = 0;
 
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); }
 
2303
else
 
2304
  {
 
2305
  if (nq_idx != -1)
 
2306
    {
 
2307
    mohq_id = pmod_data->pmohq_lst [nq_idx].mohq_id;
 
2308
    for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
 
2309
      {
 
2310
      if (!pcalls [ncall_idx].call_active)
 
2311
        { continue; }
 
2312
      if (pcalls [ncall_idx].pmohq->mohq_id == mohq_id
 
2313
        && pcalls [ncall_idx].call_state == CLSTA_INQUEUE)
 
2314
        { ncount++; }
 
2315
      }
 
2316
    }
 
2317
  mohq_lock_release (pmod_data->pcall_lock);
 
2318
  }
 
2319
 
 
2320
/**********
 
2321
* o set pv result
 
2322
* o exit with result
 
2323
**********/
 
2324
 
 
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)
 
2330
  {
 
2331
  LM_ERR ("%sUnable to set pv value for mohq_count ()!", pfncname);
 
2332
  return -1;
 
2333
  }
 
2334
return 1;
 
2335
}
 
2336
 
 
2337
/**********
 
2338
* Log Debug Statement
 
2339
*
 
2340
* INPUT:
 
2341
*   Arg (1) = MOH queue pointer
 
2342
*   Arg (2) = format pointer
 
2343
*   Arg (...) = optional format values
 
2344
* OUTPUT: outputs debugging values
 
2345
**********/
 
2346
 
 
2347
void mohq_debug (mohq_lst *pmohq, char *pfmt, ...)
 
2348
 
 
2349
{
 
2350
/**********
 
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
 
2355
* o reset log level
 
2356
**********/
 
2357
 
 
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)
 
2361
  { return; }
 
2362
if (nsys_log < nmohq_log)
 
2363
  { set_local_debug_level (nmohq_log); }
 
2364
char ptext [1024];
 
2365
va_list ap;
 
2366
va_start (ap, pfmt);
 
2367
vsnprintf (ptext, sizeof (ptext), pfmt, ap);
 
2368
va_end (ap);
 
2369
LM_DBG ("%s", ptext);
 
2370
if (nsys_log < nmohq_log)
 
2371
  { reset_local_debug_level (); }
 
2372
return;
 
2373
}
 
2374
 
 
2375
/**********
 
2376
* Process Message
 
2377
*
 
2378
* INPUT:
 
2379
*   Arg (1) = SIP message pointer
 
2380
* OUTPUT: -1=not directed to queue; 1=successfully processed
 
2381
**********/
 
2382
 
 
2383
int mohq_process (sip_msg_t *pmsg)
 
2384
 
 
2385
{
 
2386
/**********
 
2387
* o parse headers
 
2388
* o lock MOH queue
 
2389
* o directed to message queue?
 
2390
* o connect to database
 
2391
**********/
 
2392
 
 
2393
char *pfncname = "mohq_process: ";
 
2394
if (parse_headers (pmsg, HDR_EOH_F, 0) < 0)
 
2395
  {
 
2396
  LM_ERR ("%sUnable to parse header!", pfncname);
 
2397
  return -1;
 
2398
  }
 
2399
if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 2000))
 
2400
  {
 
2401
  LM_ERR ("%sUnable to lock calls!", pfncname);
 
2402
  return -1;
 
2403
  }
 
2404
call_lst *pcall;
 
2405
int mohq_idx = find_call (pmsg, &pcall);
 
2406
db1_con_t *pconn = mohq_dbconnect ();
 
2407
if (pconn)
 
2408
  {
 
2409
  /**********
 
2410
  * o last update older than 1 minute?
 
2411
  * o exclusively lock MOH queue
 
2412
  * o update queue
 
2413
  **********/
 
2414
 
 
2415
  if (pmod_data->mohq_update + 60 < time (0))
 
2416
    {
 
2417
    if (mohq_lock_change (pmod_data->pmohq_lock, 1))
 
2418
      {
 
2419
      update_mohq_lst (pconn);
 
2420
      mohq_lock_change (pmod_data->pmohq_lock, 0);
 
2421
      pmod_data->mohq_update = time (0);
 
2422
      }
 
2423
    }
 
2424
  mohq_dbdisconnect (pconn);
 
2425
  }
 
2426
if (mohq_idx < 0)
 
2427
  {
 
2428
  mohq_lock_release (pmod_data->pmohq_lock);
 
2429
  return -1;
 
2430
  }
 
2431
 
 
2432
/**********
 
2433
* o process message
 
2434
* o release MOH queue
 
2435
**********/
 
2436
 
 
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);
 
2441
int ret;
 
2442
switch (pmsg->REQ_METHOD)
 
2443
  {
 
2444
  case METHOD_INVITE:
 
2445
    /**********
 
2446
    * initial INVITE?
 
2447
    **********/
 
2448
 
 
2449
    if (!pcall)
 
2450
      { ret = first_invite_msg (pmsg, mohq_idx); }
 
2451
    else
 
2452
      { ret = reinvite_msg (pmsg, pcall); }
 
2453
    break;
 
2454
  case METHOD_NOTIFY:
 
2455
    ret = notify_msg (pmsg, pcall);
 
2456
    break;
 
2457
  case METHOD_PRACK:
 
2458
    ret = prack_msg (pmsg, pcall);
 
2459
    break;
 
2460
  case METHOD_ACK:
 
2461
    ret = ack_msg (pmsg, pcall);
 
2462
    break;
 
2463
  case METHOD_BYE:
 
2464
    ret = bye_msg (pmsg, pcall);
 
2465
    break;
 
2466
  case METHOD_CANCEL:
 
2467
    ret = cancel_msg (pmsg, pcall);
 
2468
    break;
 
2469
  default:
 
2470
    deny_method (pmsg, pcall);
 
2471
    ret = 1;
 
2472
    break;
 
2473
  }
 
2474
mohq_lock_release (pmod_data->pmohq_lock);
 
2475
return ret ? 1 : -1;
 
2476
}
 
2477
 
 
2478
/**********
 
2479
* Retrieve Oldest Queued Call
 
2480
*
 
2481
* INPUT:
 
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
 
2486
**********/
 
2487
 
 
2488
int mohq_retrieve (sip_msg_t *pmsg, char *pqueue, char *pURI)
 
2489
 
 
2490
{
 
2491
/**********
 
2492
* o get queue name and URI
 
2493
* o check URI
 
2494
**********/
 
2495
 
 
2496
char *pfncname = "mohq_retrieve: ";
 
2497
str puri [1], pqname [1];
 
2498
if (!pqueue || !pURI)
 
2499
  {
 
2500
  LM_ERR ("%sParameters missing!", pfncname);
 
2501
  return -1;
 
2502
  }
 
2503
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
 
2504
  {
 
2505
  LM_ERR ("%sInvalid queue name!", pfncname);
 
2506
  return -1;
 
2507
  }
 
2508
if (fixup_get_svalue (pmsg, (gparam_p)pURI, puri))
 
2509
  {
 
2510
  LM_ERR ("%sInvalid URI!", pfncname);
 
2511
  return -1;
 
2512
  }
 
2513
if (puri->len > URI_LEN)
 
2514
  {
 
2515
  LM_ERR ("%sURI too long!", pfncname);
 
2516
  return -1;
 
2517
  }
 
2518
struct sip_uri puri_parsed [1];
 
2519
if (parse_uri (puri->s, puri->len, puri_parsed))
 
2520
  {
 
2521
  LM_ERR ("%sInvalid URI (%.*s)!", pfncname, STR_FMT (puri));
 
2522
  return -1;
 
2523
  }
 
2524
 
 
2525
/**********
 
2526
* o find queue
 
2527
* o lock calls
 
2528
* o find oldest call
 
2529
**********/
 
2530
 
 
2531
int nq_idx = find_queue (pqname);
 
2532
if (nq_idx == -1)
 
2533
  { return -1; }
 
2534
if (!mohq_lock_set (pmod_data->pcall_lock, 0, 200))
 
2535
  {
 
2536
  LM_ERR ("%sUnable to lock calls!", pfncname);
 
2537
  return -1;
 
2538
  }
 
2539
call_lst *pcall = 0;
 
2540
int ncall_idx;
 
2541
time_t ntime = 0;
 
2542
int nfound = -1;
 
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++)
 
2545
  {
 
2546
  /**********
 
2547
  * o active call?
 
2548
  * o matching queue?
 
2549
  * o in queue?
 
2550
  * o check age
 
2551
  **********/
 
2552
 
 
2553
  pcall = &pmod_data->pcall_lst [ncall_idx];
 
2554
  if (!pcall->call_active)
 
2555
    { continue; }
 
2556
  if (pcall->pmohq->mohq_id != mohq_id)
 
2557
    { continue; }
 
2558
  if (pcall->call_state != CLSTA_INQUEUE)
 
2559
    { continue; }
 
2560
  if (!ntime)
 
2561
    {
 
2562
    nfound = ncall_idx;
 
2563
    ntime = pcall->call_time;
 
2564
    }
 
2565
  else
 
2566
    {
 
2567
    if (pcall->call_time < ntime)
 
2568
      {
 
2569
      nfound = ncall_idx;
 
2570
      ntime = pcall->call_time;
 
2571
      }
 
2572
    }
 
2573
  }
 
2574
if (nfound == -1)
 
2575
  {
 
2576
  LM_WARN ("%sNo calls in queue (%.*s)", pfncname, STR_FMT (pqname));
 
2577
  mohq_lock_release (pmod_data->pcall_lock);
 
2578
  return -1;
 
2579
  }
 
2580
pcall = &pmod_data->pcall_lst [nfound];
 
2581
 
 
2582
/**********
 
2583
* o save refer-to URI
 
2584
* o send refer
 
2585
**********/
 
2586
 
 
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))
 
2590
  { return 1; }
 
2591
LM_ERR ("%sUnable to refer call (%s)!", pfncname, pcall->call_from);
 
2592
return -1;
 
2593
}
 
2594
 
 
2595
/**********
 
2596
* Send Message to Queue
 
2597
*
 
2598
* INPUT:
 
2599
*   Arg (1) = SIP message pointer
 
2600
*   Arg (2) = queue name
 
2601
* OUTPUT: -1 if no items in queue; 1 if successfull
 
2602
**********/
 
2603
 
 
2604
int mohq_send (sip_msg_t *pmsg, char *pqueue)
 
2605
 
 
2606
{
 
2607
/**********
 
2608
* o first INVITE?
 
2609
* o get queue name
 
2610
**********/
 
2611
 
 
2612
char *pfncname = "mohq_send: ";
 
2613
if (pmsg->REQ_METHOD != METHOD_INVITE)
 
2614
  {
 
2615
  LM_ERR ("%sNot an INVITE message!", pfncname);
 
2616
  return -1;
 
2617
  }
 
2618
to_body_t *pto_body = get_to (pmsg);
 
2619
if (pto_body->tag_value.len)
 
2620
  {
 
2621
  LM_ERR ("%sNot a first INVITE message!", pfncname);
 
2622
  return -1;
 
2623
  }
 
2624
str pqname [1];
 
2625
if (!pqueue)
 
2626
  {
 
2627
  LM_ERR ("%sParameters missing!", pfncname);
 
2628
  return -1;
 
2629
  }
 
2630
if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname))
 
2631
  {
 
2632
  LM_ERR ("%sInvalid queue name!", pfncname);
 
2633
  return -1;
 
2634
  }
 
2635
 
 
2636
/**********
 
2637
* o find queue
 
2638
* o change RURI
 
2639
* o relay message
 
2640
**********/
 
2641
 
 
2642
int nq_idx = find_queue (pqname);
 
2643
if (nq_idx == -1)
 
2644
  { return -1; }
 
2645
str pruri [1] = {{0, strlen (pmod_data->pmohq_lst [nq_idx].mohq_uri)}};
 
2646
pruri->s = pkg_malloc (pruri->len + 1);
 
2647
if (!pruri->s)
 
2648
  {
 
2649
  LM_ERR ("%sNo more memory!", pfncname);
 
2650
  return -1;
 
2651
  }
 
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)
 
2660
  {
 
2661
  LM_ERR ("%sUnable to relay INVITE!", pfncname);
 
2662
  return -1;
 
2663
  }
 
2664
return 1;
 
2665
}
 
 
b'\\ No newline at end of file'