SIP Witch 1.9.15
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
call.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #include "server.h"
18 
19 namespace sipwitch {
20 
21 stack::call::call() : LinkedList(), segments()
22 {
24  count = 0;
25  forwarding = diverting = NULL;
26  answering = 16; // should set from cfna timer...
28  phone = false;
29  expires = 0l;
30  target = source = NULL;
31  state = INITIAL;
32  enlist(&stack::sip);
33  starting = ending = 0l;
34  reason = joined = NULL;
35  map = NULL;
36  timer = Timer::inf;
37 }
38 
39 void stack::call::arm(timeout_t timeout)
40 {
41  timer = timeout;
43 }
44 
46 {
47  timer = Timer::inf;
48 }
49 
51 {
52  if(state != INITIAL)
53  set(TERMINATE, 'q', "bye");
54  disconnectLocked();
55 }
56 
58 {
59  linked_pointer<segment> sp = segments.begin();
60  session *s;
61 
62  shell::debug(2, "cancelling call %08x:%u", source->sequence, source->cid);
63  while(sp) {
64  s = &(sp->sid);
65  if(s != source) {
66  if(!s->closed) {
68  s->closed = true;
69  }
70  if(s->state == session::REFER)
72  else if(s->cid > 0 && s->state != session::CLOSED) {
74  voip::release_call(s->context, s->cid, s->did);
75  }
76  }
77  sp.next();
78  }
79  invited = ringing = ringbusy = 0;
80 }
81 
83 {
84  linked_pointer<segment> sp = segments.begin();
85  session *s;
86 
87  if(target)
88  return;
89 
90  shell::debug(2, "joining call %08x:%u with session %08x:%u",
91  source->sequence, source->cid, join->sequence, join->cid);
92 
93  String::set(map->target, sizeof(map->target), join->sysident);
94  if(!map->active)
95  time(&map->active);
96 
97  // once we have joined, there is no more forwarding...
98  forwarding = diverting = NULL;
99  target = join;
100  while(sp) {
101  s = &(sp->sid);
102  if(s != source && s != target) {
103  if(!s->closed) {
105  s->closed = true;
106  }
107  if(s->state == session::REFER)
108  s->state = session::CLOSED;
109  else if(s->cid > 0 && s->state != session::CLOSED) {
110  s->state = session::CLOSED;
111  voip::release_call(s->context, s->cid, s->did);
112  }
113  }
114  sp.next();
115  }
116  source->state = target->state = session::OPEN;
117 }
118 
120 {
121  shell::debug(4, "disconnecting call %08x:%u\n", source->sequence, source->cid);
122 
123  switch(state) {
124  case RINGING:
125  case RINGBACK:
126  case TRYING:
127  reason = "declined";
128  reply_source(SIP_DECLINE);
129  break;
130  case REORDER:
131  reason = "rejected";
132  break;
133  case BUSY:
134  reason = "busy";
135  reply_source(SIP_BUSY_HERE);
136  break;
137  case ANSWERED:
138  case FAILED:
139  reason = "failed";
140  break;
141  case JOINED:
142  reason = "expired";
143  break;
144  case HOLDING:
145  case TERMINATE:
146  reason = "terminated";
147  break;
148  case TRANSFER:
149  reason = "transfer";
150  break;
151  case REDIRECT:
152  reason = "redirect";
153  break;
154  case INITIAL:
155  case FINAL:
156  break;
157  }
158 
159  linked_pointer<segment> sp = segments.begin();
160  while(sp) {
161  if(!sp->sid.closed) {
162  if(&(sp->sid) == sp->sid.parent->source)
163  registry::decUse(sp->sid.reg, stats::INCOMING);
164  else
165  registry::decUse(sp->sid.reg, stats::OUTGOING);
166  sp->sid.closed = true;
167  }
168  if(sp->sid.state == session::REFER)
169  sp->sid.state = session::CLOSED;
170  else if(sp->sid.cid > 0 && sp->sid.state != session::CLOSED) {
171  sp->sid.state = session::CLOSED;
172  voip::release_call(sp->sid.context, sp->sid.cid, sp->sid.did);
173  }
174  sp.next();
175  }
176 
177  if(state != INITIAL && state != FINAL) {
178  time(&ending);
179  set(FINAL, 'q', "exit");
180  }
181 
182  arm(stack::resetTimeout());
183 }
184 
186 {
187  assert(s != NULL);
188 
189  if(invited)
190  --invited;
191 
192  if(!invited) {
193  if(!stack::forward(this))
194  disconnectLocked();
195  if(state == RINGING) {
196  arm(1000);
197  reply_source(SIP_CALL_IS_BEING_FORWARDED);
198  }
199  }
200 }
201 
203 {
204  voip::msg_t reply = NULL;
205 
206  shell::debug(3, "sip: sending source reply %d", error);
207 
208  if(error == SIP_CALL_IS_BEING_FORWARDED && answering)
209  answering = 16;
210 
211  if(voip::make_answer_response(source->context, source->tid, error, &reply)) {
212  stack::siplog(reply);
213  voip::send_answer_response(source->context, source->tid, error, reply);
214  }
215  else {
216  shell::debug(3, "sip: source reply %d failed", error);
217  voip::send_answer_response(source->context, source->tid, SIP_BAD_REQUEST, NULL);
218  }
219 }
220 
221 void stack::call::set(state_t flag, char id, const char *text)
222 {
223  state = flag;
224  if(!map)
225  return;
226 
227  map->state[0] = id;
228  String::set(map->state + 1, sizeof(map->state) - 1, text);
229 }
230 
232 {
233  bool closing = false;
234 
235  Mutex::protect(this);
236  s->tid = 0; // cleared already....
237 
238  switch(state) {
239  case JOINED:
240  case ANSWERED:
241  case HOLDING:
242  if(s == source || s == target) {
243  s->state = session::CLOSED;
244  terminateLocked();
245  }
246  break;
247  case TRYING:
248  case RINGING:
249  case RINGBACK:
250  if(s == source) {
251  s->state = session::CLOSED;
252  disconnectLocked();
253  }
254  else
255  closing = true;
256  default:
257  break;
258  }
259  Mutex::release(this);
260  if(closing)
261  stack::close(s);
262 }
263 
265 {
266  assert(thread != NULL);
267 
268  Mutex::protect(this);
269  switch(state) {
270  case TRYING:
271  case INITIAL:
272  case BUSY:
273  // we offset the first ring by 1 second because some servers
274  // send a 180 immediately followed by a 200 because they do
275  // artificial ringback within a connected session (asterisk for
276  // example). Also, we might get a 200 OK accept from another
277  // invited ua, and so we do not want to start a partial ring
278  // followed by a connect...
279  set(RINGING, 'r', "ringin");
280  arm(1000);
281  case RINGING:
282  if(s && s != source && s->state != session::RING) {
283  ++ringing;
284  s->state = session::RING;
285  }
286  else if(!s)
287  ++ringing;
288  default:
289  break;
290  }
291  Mutex::release(this);
292 }
293 
295 {
296  assert(thread != NULL);
297 
298  Mutex::protect(this);
299  switch(state) {
300  case FINAL:
301  case TERMINATE:
302  case FAILED:
303  Mutex::release(this);
304  return;
305  default:
306  break;
307  }
308 
309  if(s->state == session::RING)
310  --ringing;
311  else if(s->state == session::BUSY)
312  --ringbusy;
313  else if(s->state == session::REFER)
314  s->state = session::CLOSED;
315  if(s->state != session::CLOSED)
316  s->state = session::OPEN;
317 
318  switch(state) {
319  case RINGING:
320  if(!ringing && ringbusy)
321  set(BUSY, 'b', "busy");
322  else if(!ringing) {
323  arm(stack::resetTimeout());
324  set(FAILED, '*', "failed");
325  }
326  break;
327  case INITIAL:
328  case ANSWERED:
329  set(FAILED, '*', "failed");
330  arm(stack::resetTimeout());
331  break;
332  case BUSY:
333  if(!ringbusy) {
334  set(FAILED, '*', "failed");
335  arm(stack::resetTimeout());
336  }
337  default:
338  break;
339  }
340  Mutex::release(this);
341  stack::close(s);
342 }
343 
345 {
346  voip::msg_t reply = NULL;
347  voip::body_t body = NULL;
348  voip::did_t did = source->did;
349  voip::context_t ctx = source->context;
350  session *update = source;
351  bool holding = false;
352  char *sdp;
353  int error = 200;
354 
355  assert(thread != NULL);
356  assert(s != NULL);
357 
358  Mutex::protect(this);
359  if(s == source) {
360  update = target;
361  if(target) {
362  ctx = target->context;
363  did = target->did;
364  }
365  else
366  goto unconnected;
367  }
368 
369  s->tid = thread->sevent->tid;
370 
371  body = NULL;
372  osip_message_get_body(thread->sevent->request, 0, &body);
373 
374  switch(state) {
375  case RINGING:
376  case RINGBACK:
377  case TRYING:
378  case ANSWERED:
379  if(s == source) {
380 unconnected:
381  Mutex::release(this);
382  if(voip::make_answer_response(source->context, source->tid, 500, &reply)) {
383  voip::header(reply, "Reply-After", "8");
384  stack::siplog(reply);
385  voip::send_answer_response(source->context, source->tid, 500, reply);
386  }
387  return;
388  }
389  if(state != ANSWERED && state != RINGBACK) {
390  joinLocked(s);
391  if(state != ANSWERED)
392  set(RINGBACK, 'r', "ringback");
393  }
394  if(thread->header_expires) {
395  time(&expires);
396  expires += thread->header_expires;
397  arm((timeout_t)(thread->header_expires * 1000l));
398  }
399  Mutex::release(this);
400  if(voip::make_answer_response(source->context, source->tid, 200, &reply)) {
401  voip::server_requires(reply, "100rel");
402  voip::header(reply, "RSeq", "1");
403  if(body && body->body) {
404  sdp = media::reinvite(s, body->body);
405  if(sdp)
406  voip::attach(reply, SDP_BODY, sdp);
407  else
409  }
410  stack::siplog(reply);
411  voip::send_answer_response(source->context, source->tid, error, reply);
412  }
413  return;
414  case HOLDING:
415  case JOINED:
416  if(holding)
417  set(HOLDING, 'h', "holding");
418  else
419  set(JOINED, 'j', "joined");
420  if(thread->header_expires) {
421  time(&expires);
422  expires += thread->header_expires;
423  arm((timeout_t)(thread->header_expires * 1000l));
424  }
425  Mutex::release(this);
426 
427  if(voip::make_dialog_request(ctx, did, "INVITE", &reply)) {
428  if(stack::sip_protocol == IPPROTO_UDP)
429  voip::server_supports(reply, "100rel,replaces");
430  if(body && body->body)
431  voip::attach(reply, SDP_BODY, body->body);
432  stack::siplog(reply);
433  voip::send_dialog_message(ctx, did, reply);
434  update->state = session::REINVITE;
435  }
436  if(!reply)
437  goto failed;
438  return;
439  default:
440  break;
441  }
442  Mutex::release(this);
443 failed:
444  shell::debug(2, "reinvite failed for call %08x:%u",
445  source->sequence, source->cid);
446  failed(thread, s);
447 }
448 
450 {
451  voip::msg_t reply = NULL;
452  voip::msg_t ack = NULL;
453  voip::did_t did;
454  voip::tid_t tid;
455  voip::context_t ctx;
456 
457  assert(thread != NULL);
458  assert(s != NULL);
459 
460  Mutex::protect(this);
461  if(s == source || (target != NULL && target != s)) {
462  Mutex::release(this);
463  shell::debug(2, "cannot answer call %08x:%u from specified session",
464  source->sequence, source->cid);
465  return;
466  }
467  switch(state) {
468  case RINGING:
469  case RINGBACK:
470  case TRYING:
471  joinLocked(s);
472  set(ANSWERED, 'a', "answered");
473  arm(16000l);
474  case ANSWERED:
475  if(thread->sevent->did > -1)
476  s->did = thread->sevent->did;
477  tid = source->tid;
478  ctx = source->context;
479  break;
480  case JOINED:
481  case HOLDING:
482  // if already joined, then we assume that the target ua never
483  // saw the ack the originating ua had sent although we did, and
484  // so we resend it.
485  if(thread->sevent->did > -1)
486  s->did = thread->sevent->did;
487  did = target->did;
488  ctx = target->context;
489  Mutex::release(this);
490  if(voip::make_ack_message(ctx, did, &ack))
491  voip::send_ack_message(ctx, did, ack);
492  return;
493  default:
494  Mutex::release(this);
495  shell::debug(2, "cannot answer non-ringing call %08x:%u",
496  source->sequence, source->cid);
497  return;
498  }
499  Mutex::release(this);
500  if(voip::make_answer_response(ctx, tid, SIP_OK, &reply)) {
501  voip::attach(reply, SDP_BODY, s->sdp);
502  stack::siplog(reply);
503  voip::send_answer_response(ctx, tid, SIP_OK, reply);
504  }
505  else {
506  shell::debug(2, "answer failed for call %08x:%u",
507  source->sequence, source->cid);
508  failed(thread, source);
509  }
510 }
511 
513 {
514  assert(thread != NULL);
515  assert(s != NULL);
516 
517  voip::tid_t tid;
518  voip::context_t ctx;
519 
520  Mutex::protect(this);
521  tid = s->tid;
522  ctx = s->context;
523  Mutex::release(this);
524 
525  if(tid < 1)
526  return;
527 
528  voip::send_answer_response(ctx, tid, thread->sevent->response->status_code, NULL);
529 }
530 
531 
533 {
534  assert(thread != NULL);
535  assert(s != NULL);
536 
537  int status = thread->sevent->response->status_code;
538  int tid = -1;
539  voip::body_t body = NULL;
540  voip::msg_t reply = NULL;
542 
543  Mutex::protect(this);
544  if(s == source && target) {
545  tid = target->tid;
546  ctx = target->context;
547  }
548  else if(s == target) {
549  tid = source->tid;
550  ctx = source->context;
551  }
552 
553  osip_message_get_body(thread->sevent->response, 0, &body);
554 
555  switch(s->state) {
556  case session::REFER:
557  if(status == SIP_ACCEPTED) {
558  set(TRANSFER, 'x', "transfer");
559  disconnectLocked();
560  Mutex::release(this);
561  return;
562  }
563  s->state = session::OPEN;
564  break;
565  case session::REINVITE:
566  if(status != SIP_ACCEPTED)
567  s->state = session::OPEN;
568  default:
569  break;
570  }
571  Mutex::release(this);
572  if(tid < 1)
573  return;
574 
575  if(voip::make_answer_response(ctx, tid, status, &reply)) {
576  if(stack::sip_protocol == IPPROTO_UDP)
577  voip::server_requires(reply, "100rel");
578  voip::header(reply, "RSeq", "1");
579  if(body && body->body)
580  voip::attach(reply, SDP_BODY, body->body);
581  voip::send_answer_response(ctx, tid, status, reply);
582  }
583 }
584 
586 {
587  assert(thread != NULL);
588  assert(s != NULL);
589 
590  voip::msg_t ack = NULL;
591  time_t now;
592  voip::did_t did = -1;
593  voip::context_t ctx = NULL;
594 
595  Mutex::protect(this);
596  if(target == NULL) {
597  Mutex::release(this);
598  shell::debug(2, "cannot confirm call %08x:%u from session %08x:%u\n",
599  source->sequence, source->cid, s->sequence, s->cid);
600  return;
601  }
602  switch(state)
603  {
604  case ANSWERED:
605  case JOINED:
606  set(JOINED, 'j', "joined");
607  source->state = target->state = session::OPEN;
608  if(thread->sevent->did > -1)
609  s->did = thread->sevent->did;
610  if(expires) {
611  time(&now);
612  arm((timeout_t)((expires - now) * 1000l));
613  }
614  else
615  arm((timeout_t)DAY_TIMEOUT);
616  case HOLDING:
617  if(s == source) {
618  ctx = target->context;
619  did = target->did;
620  }
621  else if(s == target) {
622  did = source->did;
623  ctx = source->context;
624  }
625  break;
626  default:
627  Mutex::release(this);
628  shell::debug(2, "cannot confirm unanswered call %08x:%u",
629  source->sequence, source->cid);
630  return;
631  }
632  Mutex::release(this);
633  if(voip::make_ack_message(ctx, did, &ack)) {
634  stack::siplog(ack);
635  voip::send_ack_message(ctx, did, ack);
636  }
637  else {
638  shell::debug(2, "confirm failed to send for call %08x:%u",
639  source->sequence, source->cid);
640  }
641 }
642 
644 {
645  assert(thread != NULL);
646 
647  Mutex::protect(this);
648  switch(state) {
649  case INITIAL:
650  if(!s) {
651  set(BUSY, 'b', "busy");
652  disconnectLocked();
653  Mutex::release(this);
654  return;
655  }
656  case FINAL:
657  case HOLDING:
658  case JOINED:
659  case ANSWERED:
660  case FAILED:
661  Mutex::release(this);
662  return;
663  default:
664  break;
665  }
666 
667  if(s && s != source) {
668  if(s->state == session::RING)
669  --ringing;
670  if(s->state != session::BUSY) {
671  ++ringbusy;
672  s->state = session::BUSY;
673  }
674  }
675  else if(!s)
676  ++ringbusy;
677 
678  switch(state) {
679  case INITIAL:
680  case RINGING:
681  case RINGBACK:
682  // we goto busy in this special case, otherwise stack::close handles na
683  if(!ringing && ringbusy && invited == 1 && s != source) {
684  if(forwarding) {
685  forwarding = "busy";
686  if(s)
687  s->state = session::CLOSED;
688  if(s && !s->closed) {
690  s->closed = true;
691  }
692  ringbusy = invited = 0;
693  if(stack::forward(this)) {
694  if(state == RINGING)
695  arm(1000);
696  Mutex::release(this);
697  if(state == RINGING)
698  reply_source(SIP_CALL_IS_BEING_FORWARDED);
699  return;
700  }
701  }
702  set(BUSY, 'b', "busy");
703  disconnectLocked();
704  }
705  default:
706  break;
707  }
708 
709  Mutex::release(this);
710  if(s)
711  stack::close(s);
712  else
713  stack::close(source);
714 }
715 
717 {
718  // if we are in initial state, then send call trying, otherwise
719  // turn-over state and set timer to wait for all invites to become
720  // busy or one or more to start ringing...
721  //
722  if(state == INITIAL) {
723  shell::debug(3, "sip: sending initial ring %d", SIP_RINGING);
724  reply_source(SIP_RINGING);
725  time_t now;
726  time(&now);
727  if(answering)
728  answering -= (unsigned)(now - starting);
729  }
730 
731  Mutex::protect(this);
732  set(TRYING, 't', "trying");
733  arm(4000);
734  Mutex::release(this);
735 }
736 
737 timeout_t stack::call::getTimeout(void)
738 {
739  timeout_t current;
740  Mutex::protect(this);
741  current = timer.get();
742  if(current < 2) {
743  timer = Timer::inf;
744  expired();
745  }
746  Mutex::release(this);
747  return current;
748 }
749 
751 {
752  linked_pointer<segment> sp;
753 
754  switch(state) {
755  case TRANSFER:
756  case HOLDING: // hold-recall timer expired...
757 
758  case RINGING: // re-generate ring event to origination...
759  // also controls call-forward no-answer timing...
760 
761  if(answering == 1 && forwarding) {
762  forwarding = "na";
763  cancelLocked();
764  if(stack::forward(this)) {
765  arm(1000);
766  reply_source(SIP_CALL_IS_BEING_FORWARDED);
767  return;
768  }
769  disconnectLocked();
770  break;
771  }
772  if(answering)
773  --answering;
774  arm(1000);
775  reply_source(SIP_RINGING);
776  return;
777  case REDIRECT: // FIXME: add refer select of next segment if list....
778 
779  case RINGBACK:
780  case BUSY: // invite expired
781  case JOINED: // active call session expired without re-invite
782  case ANSWERED:
783  case REORDER:
784  case TRYING:
785  case FAILED:
786  disconnectLocked();
787  break;
788  case FINAL: // session expired that expects to be recycled.
789  case INITIAL: // never used session recycled.
790  // The call record is garbage collected
791  shell::debug(4, "expiring call %08x:%u\n", source->sequence, source->cid);
792  stack::destroy(this);
793  return;
794  default:
795  break;
796  }
797 }
798 
800 {
801  if(!starting)
802  return NULL;
803 
804  if(!reason)
805  reason = "unknown";
806 
807  if(!ending)
808  time(&ending);
809 
810  if(!joined && target)
811  joined = target->sysident;
812 
813  if(!joined)
814  joined = "n/a";
815 
816  cdr *node = cdr::get();
817  node->type = cdr::STOP;
818  node->starting = starting;
819  node->sequence = source->sequence;
820  node->cid = source->cid;
821  node->duration = (unsigned long)(ending - starting);
822  String::set(node->uuid, sizeof(node->uuid), source->uuid);
823  String::set(node->reason, sizeof(node->reason), reason);
824  String::set(node->ident, sizeof(node->ident), source->sysident);
825  String::set(node->dialed, sizeof(node->dialed), dialed);
826  String::set(node->joined, sizeof(node->joined), joined);
827  String::set(node->display, sizeof(node->display), source->display);
828  if(target)
829  snprintf(node->network, sizeof(node->network), "%s/%s", source->network, target->network);
830  else
831  String::set(node->network, sizeof(node->network), source->network);
832  starting = 0l;
833  return node;
834 }
835 
836 } // end namespace
Structure for SIP Message (REQUEST and RESPONSE).
Definition: osip_message.h:55
static void close(session *s)
Definition: stack.cpp:354
void disarm(void)
Definition: call.cpp:45
static bool forward(stack::call *cr)
Definition: stack.cpp:1411
#define SIP_CALL_IS_BEING_FORWARDED
Definition: osip_const.h:94
void set(state_t state, char id, const char *text)
Definition: call.cpp:221
static cdr * get(void)
Get a free cdr node to fill from the cdr memory pool.
Definition: cdr.cpp:122
void expired(void)
Definition: call.cpp:750
static bool make_answer_response(context_t ctx, tid_t tid, int status, msg_t *msg)
Definition: voip.cpp:587
static void destroy(session *s)
Definition: stack.cpp:431
static void send_ack_message(context_t ctx, did_t did, msg_t msg=NULL)
Definition: voip.cpp:675
int did
unique id for SIP dialogs
Definition: eXosip.h:369
static void notify(void)
Definition: stack.cpp:216
unsigned cid
Internal call sequence identifiers.
Definition: cdr.h:102
Structure for holding Body.
Definition: osip_body.h:48
char sysident[MAX_IDENT_SIZE]
Definition: server.h:267
void failed(thread *thread, session *s)
Definition: call.cpp:294
enum sipwitch::cdr::@0 type
Start or end of call?
void cancelLocked(void)
Definition: call.cpp:57
time_t starting
Time the call was received.
Definition: cdr.h:107
static char * reinvite(stack::session *session, const char *sdp)
Definition: media.cpp:634
unsigned ringbusy
Definition: server.h:355
voip::context_t context
Definition: server.h:255
static bool make_ack_message(context_t ctx, did_t did, msg_t *msg)
Definition: voip.cpp:660
MappedCall * map
Definition: server.h:348
void ring(thread *thread, session *s=NULL)
Definition: call.cpp:264
void closingLocked(session *s)
Definition: call.cpp:185
#define SIP_DECLINE
Definition: osip_const.h:141
static void send_dialog_message(context_t ctx, did_t did, msg_t msg)
Definition: voip.cpp:802
const char * reason
Definition: server.h:343
char reason[16]
Reason the call was terminated.
Definition: cdr.h:97
int tid_t
Definition: voip.h:60
#define SIP_RINGING
Definition: osip_const.h:93
void disconnectLocked(void)
Definition: call.cpp:119
static bool make_dialog_request(context_t ctx, did_t did, const char *method, msg_t *msg)
Definition: voip.cpp:706
session * source
Definition: server.h:345
const char * diverting
Definition: server.h:350
#define SIP_TEMPORARILY_UNAVAILABLE
Definition: osip_const.h:121
#define SIP_OK
Definition: osip_const.h:97
static void server_requires(voip::msg_t msg, const char *txt)
Definition: voip.cpp:918
#define SIP_BUSY_HERE
Definition: osip_const.h:127
const char * forwarding
Definition: server.h:349
enum sipwitch::stack::session::@10 state
timeout_t getTimeout(void)
Definition: call.cpp:737
#define SIP_ACCEPTED
Definition: osip_const.h:98
static stack sip
Definition: server.h:398
char joined[MAX_IDENT_SIZE]
Call destination eventually joined to.
Definition: cdr.h:82
void busy(thread *thread, session *s=NULL)
Definition: call.cpp:643
void trying(thread *thread)
Definition: call.cpp:716
session * target
Definition: server.h:346
void arm(timeout_t timeout)
Definition: call.cpp:39
#define SDP_BODY
Definition: voip.h:151
static timeout_t resetTimeout(void)
Definition: server.h:470
osip_message_t * request
request within current transaction
Definition: eXosip.h:364
char dialed[MAX_IDENT_SIZE]
Destination requested on our switch.
Definition: cdr.h:77
const char * joined
Definition: server.h:344
static void siplog(voip::msg_t msg)
Definition: stack.cpp:331
static void attach(msg_t msg, const char *type, const char *body)
Definition: voip.cpp:941
static void server_supports(voip::msg_t msg, const char *txt)
Definition: voip.cpp:923
char sdp[MAX_SDP_BUFFER]
Definition: server.h:265
unsigned invited
Definition: server.h:353
void message_reply(thread *thread, session *s)
Definition: call.cpp:512
static void release_call(context_t ctx, call_t cid, did_t did)
Definition: voip.cpp:653
unsigned answering
Definition: server.h:351
static void send_answer_response(context_t ctx, tid_t tid, int status, msg_t msg=NULL)
Definition: voip.cpp:601
void bye(thread *thread, session *s)
Definition: call.cpp:231
void confirm(thread *thread, session *s)
Definition: call.cpp:585
char display[MAX_DISPLAY_SIZE]
Display name of calling party.
Definition: cdr.h:87
void * context_t
Definition: voip.h:53
char ident[MAX_IDENT_SIZE]
Ident of calling parting.
Definition: cdr.h:72
void answer(thread *thread, session *s)
Definition: call.cpp:449
voip::event_t sevent
Definition: server.h:587
int did_t
Definition: voip.h:61
static voip::context_t out_context
Definition: service.h:233
long header_expires
Definition: server.h:600
unsigned sequence
Definition: cdr.h:102
void terminateLocked(void)
Definition: call.cpp:50
int status_code
Status Code (SIP answer only)
Definition: osip_message.h:60
registry::mapped * reg
Definition: server.h:251
char * body
buffer containing data
Definition: osip_body.h:49
voip::call_t cid
Definition: server.h:252
void joinLocked(session *s)
Definition: call.cpp:82
void relay(thread *thread, session *s)
Definition: call.cpp:532
Interface class for call detail records.
Definition: cdr.h:56
unsigned unreachable
Definition: server.h:356
int tid
unique id for transactions (to be used for answers)
Definition: eXosip.h:368
unsigned ringing
Definition: server.h:354
static void decUse(mapped *rr, stats::stat_t stat)
Definition: registry.cpp:167
int osip_message_get_body(const osip_message_t *sip, int pos, osip_body_t **dest)
Get one body header.
char * map[96]
Definition: cgiserver.cpp:89
osip_message_t * response
last response within current transaction
Definition: eXosip.h:365
unsigned long duration
Total duration of the call in seconds.
Definition: cdr.h:112
cdr * log(void)
Definition: call.cpp:799
void reinvite(thread *thread, session *s)
Definition: call.cpp:344
void reply_source(int error)
Definition: call.cpp:202
char uuid[48]
A unique identifier for each and every call.
Definition: cdr.h:67
#define DAY_TIMEOUT
Definition: server.h:36
static void header(msg_t msg, const char *key, const char *value)
Definition: voip.cpp:928
#define SIP_BAD_REQUEST
Definition: osip_const.h:104
char network[MAX_NETWORK_SIZE *2]
Subnet interface the caller appeared on.
Definition: cdr.h:92