RTS API Documentation  1.10.11
switch_msrp.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2011-2017, Seven Du <dujinfang@gmail.com>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Seven Du <dujinfang@gmail.com>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  *
27  *
28  * msrp.c -- MSRP lib
29  *
30  */
31 
32 #include <switch.h>
33 #include <switch_ssl.h>
34 #include <switch_msrp.h>
35 #include <switch_stun.h>
36 
37 #define MSRP_BUFF_SIZE (SWITCH_RTP_MAX_BUF_LEN - 32)
38 #define DEBUG_MSRP 0
39 
40 struct msrp_socket_s {
44  int secure;
45 };
46 
49  SSL *ssl;
50  int secure;
53 };
54 
55 static struct {
56  int running;
57  int debug;
59  // switch_mutex_t *mutex;
60  char *ip;
62 
63  char *cert;
64  char *key;
65  const SSL_METHOD *ssl_method;
66  SSL_CTX *ssl_ctx;
67  int ssl_ready;
68  const SSL_METHOD *ssl_client_method;
69  SSL_CTX *ssl_client_ctx;
70 
73 } globals;
74 
75 typedef struct worker_helper{
76  int debug;
81 
83 {
84  if (!msrp_msg->payload) {
85  switch_malloc(msrp_msg->payload, payload_bytes + 1);
86  } else if (msrp_msg->payload_bytes < payload_bytes + 1) {
87  msrp_msg->payload = realloc(msrp_msg->payload, payload_bytes + 1);
88  }
89 
90  switch_assert(msrp_msg->payload);
91  memcpy(msrp_msg->payload, buf, payload_bytes);
92  *(msrp_msg->payload + payload_bytes) = '\0';
93  msrp_msg->payload_bytes = payload_bytes;
94 }
95 
97 {
98  const char *msrp_h_success_report = switch_msrp_msg_get_header(msrp_msg, MSRP_H_SUCCESS_REPORT);
99  return (msrp_h_success_report && !strcmp(msrp_h_success_report, "yes"));
100 }
101 
102 static void msrp_deinit_ssl(void)
103 {
104  globals.ssl_ready = 0;
105  if (globals.ssl_ctx) {
106  SSL_CTX_free(globals.ssl_ctx);
107  globals.ssl_ctx = NULL;
108  }
109  if (globals.ssl_client_ctx) {
110  SSL_CTX_free(globals.ssl_client_ctx);
111  globals.ssl_client_ctx = NULL;
112  }
113 }
114 
115 static void msrp_init_ssl(void)
116 {
117  const char *err = "";
118 
119  globals.ssl_client_method = SSLv23_client_method();
120  globals.ssl_client_ctx = SSL_CTX_new(globals.ssl_client_method);
121  assert(globals.ssl_client_ctx);
122  SSL_CTX_set_options(globals.ssl_client_ctx, SSL_OP_NO_SSLv2);
123 
124  globals.ssl_method = SSLv23_server_method(); /* create server instance */
125  globals.ssl_ctx = SSL_CTX_new(globals.ssl_method); /* create context */
126  assert(globals.ssl_ctx);
127  globals.ssl_ready = 1;
128 
129  /* Disable SSLv2 */
130  SSL_CTX_set_options(globals.ssl_ctx, SSL_OP_NO_SSLv2);
131  /* Disable SSLv3 */
132  SSL_CTX_set_options(globals.ssl_ctx, SSL_OP_NO_SSLv3);
133  /* Disable TLSv1 */
134  SSL_CTX_set_options(globals.ssl_ctx, SSL_OP_NO_TLSv1);
135  /* Disable Compression CRIME (Compression Ratio Info-leak Made Easy) */
136  SSL_CTX_set_options(globals.ssl_ctx, SSL_OP_NO_COMPRESSION);
137 
138  // /* set the local certificate from CertFile */
139  // if (!zstr(profile->chain)) {
140  // if (switch_file_exists(profile->chain, NULL) != SWITCH_STATUS_SUCCESS) {
141  // err = "SUPPLIED CHAIN FILE NOT FOUND\n";
142  // goto fail;
143  // }
144 
145  // if (!SSL_CTX_use_certificate_chain_file(profile->ssl_ctx, profile->chain)) {
146  // err = "CERT CHAIN FILE ERROR";
147  // goto fail;
148  // }
149  // }
150 
151  if (switch_file_exists(globals.cert, NULL) != SWITCH_STATUS_SUCCESS) {
152  err = "SUPPLIED CERT FILE NOT FOUND\n";
153  goto fail;
154  }
155 
156  if (!SSL_CTX_use_certificate_file(globals.ssl_ctx, globals.cert, SSL_FILETYPE_PEM)) {
157  err = "CERT FILE ERROR";
158  goto fail;
159  }
160 
161  /* set the private key from KeyFile */
162 
164  err = "SUPPLIED KEY FILE NOT FOUND\n";
165  goto fail;
166  }
167 
168  if (!SSL_CTX_use_PrivateKey_file(globals.ssl_ctx, globals.key, SSL_FILETYPE_PEM)) {
169  err = "PRIVATE KEY FILE ERROR";
170  goto fail;
171  }
172 
173  /* verify private key */
174  if ( !SSL_CTX_check_private_key(globals.ssl_ctx) ) {
175  err = "PRIVATE KEY FILE ERROR";
176  goto fail;
177  }
178 
179  SSL_CTX_set_cipher_list(globals.ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH");
180 
181  return;
182 
183  fail:
184  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SSL ERR: %s\n", err);
185  msrp_deinit_ssl();
186 }
187 
188 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip);
189 
191 {
192  char *cf = "msrp.conf";
193  switch_xml_t cfg, xml = NULL, settings, param;
195 
197  globals.key = globals.cert;
198 
201  }
202 
203  if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
204  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Open of %s failed\n", cf);
205  status = SWITCH_STATUS_FALSE;
206  return status;
207  }
208 
209  if ((settings = switch_xml_child(cfg, "settings"))) {
210  for (param = switch_xml_child(settings, "param"); param; param = param->next) {
211  char *var = (char *) switch_xml_attr_soft(param, "name");
212  char *val = (char *) switch_xml_attr_soft(param, "value");
213  if (!strcasecmp(var, "listen-ip")) {
214  set_global_ip(val);
215  } else if (!strcasecmp(var, "listen-port")) {
216  globals.msock.port = atoi(val);
217  } else if (!strcasecmp(var, "listen-ssl-port")) {
218  globals.msock_ssl.port = atoi(val);
219  } else if (!strcasecmp(var, "debug")) {
220  globals.debug = switch_true(val);
221  } else if (!strcasecmp(var, "secure-cert")) {
222  globals.cert = switch_core_strdup(globals.pool, val);
223  } else if (!strcasecmp(var, "secure-key")) {
224  globals.key = switch_core_strdup(globals.pool, val);
225  } else if (!strcasecmp(var, "message-buffer-size") && val) {
226  globals.message_buffer_size = atoi(val);
227  if (globals.message_buffer_size == 0) globals.message_buffer_size = 50;
228  }
229  }
230  }
231 
232  switch_xml_free(xml);
233 
234  return status;
235 }
236 
237 static void *SWITCH_THREAD_FUNC msrp_listener(switch_thread_t *thread, void *obj);
238 
240 {
241  // switch_mutex_lock(globals.sock_mutex);
242  if (*sock) {
244  switch_socket_close(*sock);
245  *sock = NULL;
246  }
247  // switch_mutex_unlock(globals.sock_mutex);
248 }
249 
251 {
252  switch_sockaddr_t *sa;
253  switch_status_t rv;
254 
255  rv = switch_sockaddr_info_get(&sa, ip, SWITCH_UNSPEC, port, 0, pool);
256  if (rv) {
257  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot get information about MSRP listen IP address %s\n", ip);
258  goto sock_fail;
259  }
260 
261  rv = switch_socket_create(sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool);
262  if (rv) goto sock_fail;
263 
265  if (rv) goto sock_fail;
266 
267 #ifdef WIN32
268  /* Enable dual-stack listening on Windows */
269  if (switch_sockaddr_get_family(sa) == AF_INET6) {
271  if (rv) goto sock_fail;
272  }
273 #endif
274 
275  rv = switch_socket_bind(*sock, sa);
276  if (rv) goto sock_fail;
277 
278  rv = switch_socket_listen(*sock, 5);
279  if (rv) goto sock_fail;
280 
281  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Socket up listening on %s:%u\n", ip, port);
282 
283  return SWITCH_STATUS_SUCCESS;
284 
285 sock_fail:
286  return rv;
287 }
288 
290 {
291  return globals.ip;
292 }
293 
295 {
298  switch_threadattr_t *thd_attr = NULL;
299  switch_status_t status;
300 
303  return SWITCH_STATUS_FALSE;
304  }
305 
306  memset(&globals, 0, sizeof(globals));
307  set_global_ip("0.0.0.0");
308  globals.pool = pool;
309  globals.msock.port = (switch_port_t)0;
310  globals.msock_ssl.port = (switch_port_t)0;
311  globals.msock_ssl.secure = 1;
312  globals.message_buffer_size = 50;
313  globals.debug = DEBUG_MSRP;
314 
315  load_config();
316 
317  if (globals.msock.port) {
318  globals.running = 1;
319 
320  status = msock_init(globals.ip, globals.msock.port, &globals.msock.sock, pool);
321 
322  if (status == SWITCH_STATUS_SUCCESS) {
323  switch_threadattr_create(&thd_attr, pool);
324  // switch_threadattr_detach_set(thd_attr, 1);
326  switch_thread_create(&thread, thd_attr, msrp_listener, &globals.msock, pool);
327  globals.msock.thread = thread;
328  }
329  }
330 
331  if (globals.msock_ssl.port) {
332  globals.running = 1;
333 
334  msrp_init_ssl();
335  status = msock_init(globals.ip, globals.msock_ssl.port, &globals.msock_ssl.sock, pool);
336 
337  if (status == SWITCH_STATUS_SUCCESS) {
338  switch_threadattr_create(&thd_attr, pool);
339  // switch_threadattr_detach_set(thd_attr, 1);
341  switch_thread_create(&thread, thd_attr, msrp_listener, &globals.msock_ssl, pool);
342  globals.msock_ssl.thread = thread;
343  }
344  }
345 
346  return SWITCH_STATUS_SUCCESS;
347 }
348 
350 {
353 
354  globals.running = 0;
355 
356  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "destroying thread\n");
357 
358  sock = globals.msock.sock;
359  close_socket(&sock);
360 
361  sock = globals.msock_ssl.sock;
362  close_socket(&sock);
363 
364  if (globals.msock.thread) switch_thread_join(&st, globals.msock.thread);
365  if (globals.msock_ssl.thread) switch_thread_join(&st, globals.msock_ssl.thread);
366  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "destroy thread done\n");
367 
368  globals.msock.thread = NULL;
369  globals.msock_ssl.thread = NULL;
370 
371  msrp_deinit_ssl();
372 
374 
375  return st;
376 }
377 
379 {
381  ms = switch_core_alloc(pool, sizeof(switch_msrp_session_t));
382  switch_assert(ms);
383  ms->pool = pool;
384  ms->secure = secure;
385  ms->local_port = secure ? globals.msock_ssl.port : globals.msock.port;
386  ms->msrp_msg_buffer_size = globals.message_buffer_size;
387  ms->call_id = switch_core_strdup(pool, call_id);
389  return ms;
390 }
391 
393 {
394  int sanity = 500;
395 
396  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying MSRP session %s\n", (*ms)->call_id);
397 
398  switch_mutex_lock((*ms)->mutex);
399 
400  if ((*ms)->csock && (*ms)->csock->sock) {
401  close_socket(&(*ms)->csock->sock);
402  }
403 
404  switch_mutex_unlock((*ms)->mutex);
405 
406  switch_yield(20000);
407 
408  while(sanity-- > 0 && (*ms)->running) {
409  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "waiting MSRP worker %s\n", (*ms)->call_id);
410  switch_yield(20000);
411  }
412 
413  if ((*ms)->send_queue) {
414  switch_msrp_msg_t *msg = NULL;
415 
416  while (switch_queue_trypop((*ms)->send_queue, (void **)&msg) == SWITCH_STATUS_SUCCESS) {
418  }
419  }
420 
421  switch_mutex_destroy((*ms)->mutex);
422  ms = NULL;
423  return SWITCH_STATUS_SUCCESS;
424 }
425 
427 {
429 
430  if (ms->last_msg == NULL) {
431  ms->last_msg = msg;
432  ms->msrp_msg = msg;
433  } else {
434  ms->last_msg->next = msg;
435  ms->last_msg = msg;
436  }
437 
438  ms->msrp_msg_count++;
439 
441 
442  return SWITCH_STATUS_SUCCESS;
443 }
444 
446 {
447  switch_msrp_msg_t *m = NULL;
448 
450 
451  m = ms->msrp_msg;
452 
453  if (m == NULL) {
455  switch_yield(20000);
457  }
458 
459  m = ms->msrp_msg;
460 
461  if (m == NULL) {
463  return NULL;
464  }
465 
466  ms->msrp_msg = ms->msrp_msg->next;
467  ms->msrp_msg_count--;
468 
469  if (ms->msrp_msg == NULL) ms->last_msg = NULL;
470 
472 
473  return m;
474 }
475 
477 {
478  char *code_number_str = switch_mprintf("%d", msrp_msg->code_number);
479  const char *content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE);
480  char method[10];
481  char *result = NULL;
482 
483  switch(msrp_msg->method) {
484  case MSRP_METHOD_SEND: sprintf(method, "SEND"); break;
485  case MSRP_METHOD_AUTH: sprintf(method, "AUTH"); break;
486  case MSRP_METHOD_REPLY: sprintf(method, "REPLY"); break;
487  case MSRP_METHOD_REPORT: sprintf(method, "REPORT"); break;
488  default: sprintf(method, "??%d", msrp_msg->method); break;
489  }
490 
491  result = switch_mprintf("\n=================================\n"
492  "MSRP %s %s%s\r\nFrom: %s\r\nTo: %s\r\nMessage-ID: %s\r\n"
493  "Byte-Range: %" SWITCH_SIZE_T_FMT "-%" SWITCH_SIZE_T_FMT"/%" SWITCH_SIZE_T_FMT "\r\n"
494  "%s%s%s" /* Content-Type */
495  "%s%s%s%s$\r\n"
496  "=================================\n",
497  msrp_msg->transaction_id ? msrp_msg->transaction_id : code_number_str,
498  msrp_msg->transaction_id ? "" : " ",
499  msrp_msg->transaction_id ? method : msrp_msg->code_description,
503  msrp_msg->byte_start,
504  msrp_msg->byte_end,
505  msrp_msg->bytes,
506  content_type ? "Content-Type: " : "",
507  content_type ? content_type : "",
508  content_type ? "\r\n" : "",
509  msrp_msg->payload ? "\r\n" : "",
510  msrp_msg->payload ? msrp_msg->payload : "",
511  msrp_msg->payload ? "\r\n" : "",
512  msrp_msg->delimiter);
513 
514  switch_safe_free(code_number_str)
515 
516  return result;
517 }
518 
520 {
522 
523  if (csock->secure) {
524  switch_ssize_t r;
525  r = SSL_read(csock->ssl, buf, *len);
526  if (r < 0) {
527  int error = SSL_get_error(csock->ssl, r);
528  if (!(SSL_ERROR_SYSCALL == error && errno == 9)) {// socket closed
529  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TLS read error: ret=%" SWITCH_SSIZE_T_FMT " error=%d errno=%d\n", r, error, errno);
530  }
531  *len = 0;
532  } else {
533  *len = r;
534  status = SWITCH_STATUS_SUCCESS;
535  }
536  } else {
537  status = switch_socket_recv(csock->sock, buf, len);
538  }
539 
540  if (globals.debug && status != SWITCH_STATUS_SUCCESS) {
541  char err[1024] = { 0 };
542  switch_strerror(status, err, sizeof(err) - 1);
543  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msrp socket recv status = %d, %s\n", status, err);
544  }
545 
546  return status;
547 }
548 
550 {
551  // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "send: %s\n", buf);
552 
553  if (csock->secure) {
554  *len = SSL_write(csock->ssl, buf, *len);
556  } else {
557  return switch_socket_send(csock->sock, buf, len);
558  }
559 }
560 
561 void dump_buffer(const char *buf, switch_size_t len, int line, int is_send)
562 {
563  int i, j, k = 0;
564  char buff[MSRP_BUFF_SIZE * 2];
565  // return;
566  for(i=0,j=0; i<len; i++) {
567  if (buf[i] == '\0') {
568  buff[j++] = '\\';
569  buff[j++] = '0';
570  } else if(buf[i] == '\r') {
571  buff[j++] = '\\';
572  buff[j++] = 'r';
573  } else if(buf[i] == '\n') {
574  buff[j++] = '\\';
575  buff[j++] = 'n';
576  buff[j++] = '\n';
577  k = 0;
578  }
579  else {
580  buff[j++] = buf[i];
581  }
582  if ((++k) %80 == 0) buff[j++] = '\n';
583  if (j >= MSRP_BUFF_SIZE * 2) break;
584  }
585 
586  buff[j] = '\0';
588  "%d: %s [%" SWITCH_SIZE_T_FMT "] bytes [\n%s]\n", line, is_send? "SEND" : "RECV", len, buff);
589 }
590 
591 char *find_delim(char *buf, int len, const char *delim)
592 {
593  char *p, *q, *s = NULL;
594  char *end;
595 
596  p = buf;
597  q = (char *)delim;
598 
599  if (p == NULL) return NULL;
600  if (q == NULL) return NULL;
601 
602  end = buf + len - strlen(delim);
603 
604  while(p < end && *q) {
605  if (*p == *q) {
606  if (s == NULL) s = p;
607  p++;
608  q++;
609  } else {
610  s = NULL;
611  p++;
612  q = (char *)delim;
613  }
614  if (*q == '\0') return s;
615  }
616  return NULL;
617 }
618 
619 /*
620 MSRP d4c667b2351e958f SEND
621 To-Path: msrp://192.168.0.56:2856/73671a97c9dec690d303;tcp
622 From-Path: msrp://192.168.0.56:2855/2fb5dfec96f3609f7b48;tcp
623 Message-ID: 7b7c9965ffa8533c
624 Byte-Range: 1-0/0
625 -------d4c667b2351e958f$
626 */
627 
628 char* HEADER_NAMES[] = {
629  "MSRP_H_FROM_PATH",
630  "MSRP_H_TO_PATH",
631  "MSRP_H_MESSAGE_ID",
632  "MSRP_H_CONTENT_TYPE",
633  "MSRP_H_SUCCESS_REPORT",
634  "MSRP_H_FAILURE_REPORT",
635  "MSRP_H_STATUS",
636  "MSRP_H_KEEPALIVE",
637 
638  "MSRP_H_TRASACTION_ID",
639  "MSRP_H_DELIMITER",
640  "MSRP_H_CODE_DESCRIPTION",
641 
642  "MSRP_H_UNKNOWN"
643 };
644 
646  if (htype > MSRP_H_UNKNOWN) htype = MSRP_H_UNKNOWN;
647 
648  return HEADER_NAMES[htype];
649 }
650 
652 {
653  switch_status_t status;
654 
655  int ret = 0;
656  char *data;
657  va_list ap;
658 
659  va_start(ap, fmt);
660  ret = switch_vasprintf(&data, fmt, ap);
661  va_end(ap);
662 
663  if (ret == -1) {
664  return SWITCH_STATUS_MEMERR;
665  }
666 
668 
669  switch (htype) {
672  break;
673  case MSRP_H_DELIMITER:
675  break;
678  break;
679  default: break;
680  }
681 
682  return status;
683 }
684 
686  char *v = switch_event_get_header(msrp_msg->headers, switch_msrp_msg_header_name(htype));
687  return v;
688 }
689 
690 static char *msrp_parse_header(char *start, int skip, const char *end, switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, switch_memory_pool_t *pool)
691 {
692  char *p = start + skip;
693  char *q;
694  if (*p && *p == ' ') p++;
695  q = p;
696  while(*q != '\n' && q < end) q++;
697  if (q > p) {
698  if (*(q-1) == '\r') *(q-1) = '\0';
699  *q = '\0';
700  switch_msrp_msg_add_header(msrp_msg, htype, p);
701  return q + 1;
702  }
703  return start;
704 }
705 
707 {
708  char *p = start;
709  char *q;
710  const char *end = start + len;
711 
712  while(p < end) {
713  if (!strncasecmp(p, "MSRP ", 5)) {
714  p += 5;
715  q = p;
716 
717  while(*q && q < end && *q != ' ') q++;
718 
719  if (q > p) {
720  *q = '\0';
722  switch_msrp_msg_add_header(msrp_msg, MSRP_H_DELIMITER, "-------%s", p);
723  msrp_msg->state = MSRP_ST_PARSE_HEADER;
724  }
725 
726  p = q;
727 
728  if (++p >= end) goto done;
729 
730  if (!strncasecmp(p, "SEND", 4)) {
731  msrp_msg->method = MSRP_METHOD_SEND;
732  p += 6; /*skip \r\n*/
733  } else if (!strncasecmp(p, "REPORT", 6)) {
734  msrp_msg->method = MSRP_METHOD_REPORT;
735  p += 8;
736  } else if (!strncasecmp(p, "AUTH", 4)) {
737  msrp_msg->method = MSRP_METHOD_AUTH;
738  p += 6;
739  } else {/* MSRP transaction_id coden_number codede_scription */
740  msrp_msg->method = MSRP_METHOD_REPLY;
741  q = p;
742  while(*q && q < end && *q != ' ') q++;
743  if (q > p) {
744  *q = '\0';
745  msrp_msg->code_number = atoi(p);
746  p = ++q;
747  while(*q && q < end && *q != '\n') q++;
748  if (q > p) {
749  if (*(q-1) == '\r') *(q-1) = '\0';
750  *q = '\0';
752  p = ++q;
753  }
754  }
755  }
756  } else if (!strncasecmp(p, "From-Path:", 10)) {
757  q = msrp_parse_header(p, 10, end, msrp_msg, MSRP_H_FROM_PATH, pool);
758  if (q == p) break; /* incomplete header*/
759  p = q;
760  } else if (!strncasecmp(p, "To-Path:", 8)) {
761  q = msrp_parse_header(p, 8, end, msrp_msg, MSRP_H_TO_PATH, pool);
762  if (q == p) break; /* incomplete header*/
763  p = q;
764  } else if (!strncasecmp(p, "Status:", 7)) {
765  q = msrp_parse_header(p, 7, end, msrp_msg, MSRP_H_STATUS, pool);
766  if (q == p) break; /* incomplete header*/
767  p = q;
768  } else if (!strncasecmp(p, "Keep-Alive:", 11)) {
769  q = msrp_parse_header(p, 11, end, msrp_msg, MSRP_H_KEEPALIVE, pool);
770  if (q == p) break; /* incomplete header*/
771  p = q;
772  } else if (!strncasecmp(p, "Message-ID:", 11)) {
773  q = msrp_parse_header(p, 11, end, msrp_msg, MSRP_H_MESSAGE_ID, pool);
774  if (q == p) break; /* incomplete header*/
775  p = q;
776  } else if (!strncasecmp(p, "Content-Type:", 13)) {
777  q = msrp_parse_header(p, 13, end, msrp_msg, MSRP_H_CONTENT_TYPE, pool);
778  if (q == p) break; /* incomplete header*/
779  p = q;
780  } else if (!strncasecmp(p, "Success-Report:", 15)) {
781  q = msrp_parse_header(p, 15, end, msrp_msg, MSRP_H_SUCCESS_REPORT, pool);
782  if (q == p) break; /* incomplete header*/
783  p = q;
784  } else if (!strncasecmp(p, "Failure-Report:", 15)) {
785  q = msrp_parse_header(p, 15, end, msrp_msg, MSRP_H_FAILURE_REPORT, pool);
786  if (q == p) break; /* incomplete header*/
787  p = q;
788  } else if (!strncasecmp(p, "Byte-Range:", 11)) {
789  p += 11;
790  if (*p && *p == ' ') p++;
791  q = p;
792  while(*q && q < end && *q != '-') q++;
793  if (q > p) {
794  *q = '\0';
795  msrp_msg->byte_start = atoi(p);
796  switch_assert(msrp_msg->byte_start > 0);
797  p = ++q;
798  if (*p && *p == '*') {
799  msrp_msg->range_star = 1;
800  }
801  while(*q && q < end && *q != '/') q++;
802  if (q > p) {
803  *q = '\0';
804  msrp_msg->byte_end = msrp_msg->range_star ? 0 : atoi(p);
805  p = ++q;
806  while(*q && q < end && *q != '\n') q++;
807  if (q > p) {
808  if (*(q-1) == '\r') *(q-1) = '\0';
809  *q = '\0';
810  msrp_msg->bytes = atoi(p);
811 
812  if (!msrp_msg->range_star) {
813  msrp_msg->payload_bytes = msrp_msg->byte_end + 1 - msrp_msg->byte_start;
814  }
815 
816  if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%" SWITCH_SIZE_T_FMT " payload bytes\n", msrp_msg->payload_bytes);
817 
818  /*Fixme sanity check to avoid large byte-range attack*/
819  if (!msrp_msg->range_star && msrp_msg->payload_bytes > msrp_msg->bytes) {
820  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "payload size does't match %" SWITCH_SIZE_T_FMT " != %" SWITCH_SIZE_T_FMT "\n", msrp_msg->payload_bytes, msrp_msg->bytes);
821  msrp_msg->state = MSRP_ST_ERROR;
822  p = ++q;
823  break;
824  }
825  p = ++q;
826  }
827  }
828  }
829  } else if (*p == '\r' && *(p+1) == '\n') {
830  msrp_msg->state = MSRP_ST_WAIT_BODY;
831  p += 2;
832  break;
833  } else if (msrp_msg->delimiter &&
834  !strncasecmp(p, msrp_msg->delimiter, strlen(msrp_msg->delimiter))) {
835  char *x = p + strlen(msrp_msg->delimiter);
836  if (x < end) {
837  if (*x == '$') {
838  p = x + 1;
839  msrp_msg->state = MSRP_ST_DONE;
840  if (*p == '\r') p++;
841  if (*p == '\n') p++;
842  break;
843  } else if(*x == '+') {
844  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unsupported %c\n", *x);
845  if (*p == '\r') p++;
846  if (*p == '\n') p++;
847  break;
848  } else {
849  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unsupported %c\n", *x);
850  msrp_msg->state = MSRP_ST_ERROR; //TODO support # etc.
851  break;
852  }
853  }
854  break;
855  } else {/* unsupported header */
856  q = p;
857  while(*q && q < end && *q != ':') q++;
858  if (q > p) {
859  char *last_p = p;
860  *q = '\0';
861  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unsupported header [%s]\n", p);
862  p = q + 1;
863  q = msrp_parse_header(p, 0, end, msrp_msg, MSRP_H_UNKNOWN, pool);
864  if (q == p) {
865  p = last_p;
866  break; /* incomplete header */
867  }
868  p = q;
869  }
870  }
871  }
872 
873 done:
874  msrp_msg->last_p = p;
875  return msrp_msg;
876 }
877 
879 {
880  char *start;
881 
882  if (!msrp_msg) {
883  msrp_msg = switch_msrp_msg_create();
884  msrp_msg->state = MSRP_ST_WAIT_HEADER;
885  }
886 
887  if (globals.debug) {
888  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "parse state: %d\n", msrp_msg->state);
889  dump_buffer(buf, len, __LINE__, 0);
890  }
891 
892  if (msrp_msg->state == MSRP_ST_WAIT_HEADER) {
893  if ((start = (char *)switch_stristr("MSRP ", buf)) == NULL) {
894  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not an MSRP packet, Skip!\n");
895  return msrp_msg;
896  }
897 
898  msrp_msg = msrp_parse_headers(start, len - (start - buf), msrp_msg, pool);
899 
900  if (msrp_msg->state == MSRP_ST_ERROR) return msrp_msg;
901  if (msrp_msg->state == MSRP_ST_DONE) return msrp_msg;
902 
903  if (msrp_msg->last_p && msrp_msg->last_p < buf + len) {
904  msrp_msg = msrp_parse_buffer(msrp_msg->last_p, len - (msrp_msg->last_p - buf), msrp_msg, pool);
905  }
906  } else if (msrp_msg->state == MSRP_ST_WAIT_BODY) {
907  if(!msrp_msg->range_star && msrp_msg->byte_end == 0) {
908  msrp_msg->state = MSRP_ST_DONE;
909  return msrp_msg;
910  }
911 
912  if (msrp_msg->range_star) { /* the * case */
913  /*hope we can find the delimiter at the end*/
914  int dlen;
915  char *delim_pos = NULL;
916  switch_size_t payload_bytes;
917 
918  switch_assert(msrp_msg->delimiter);
919  dlen = strlen(msrp_msg->delimiter);
920 
921  if (!strncmp(buf + len - dlen - 3, msrp_msg->delimiter, dlen)) { /*bingo*/
922  payload_bytes = len - dlen - 5;
923  switch_msrp_msg_set_payload(msrp_msg, buf, payload_bytes);
924  msrp_msg->byte_end = msrp_msg->byte_start + payload_bytes - 1;
925  msrp_msg->state = MSRP_ST_DONE;
926  msrp_msg->last_p = buf + len;
927  if (msrp_msg->accumulated_bytes) {
928  msrp_msg->accumulated_bytes += payload_bytes;
929  }
930  return msrp_msg;
931  } else if ((delim_pos = find_delim(buf, len, msrp_msg->delimiter))) {
932  if (globals.debug) {
933  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "=======================================delimiter: %s\n", delim_pos);
934  }
935  switch_assert(delim_pos - buf >= 2);
936  payload_bytes = delim_pos - buf - 2;
937  switch_msrp_msg_set_payload(msrp_msg, buf, payload_bytes);
938  msrp_msg->byte_end = msrp_msg->byte_start + msrp_msg->payload_bytes - 1;
939  msrp_msg->state = MSRP_ST_DONE;
940  msrp_msg->last_p = delim_pos + dlen + 3;
941  if (msrp_msg->accumulated_bytes) {
942  msrp_msg->accumulated_bytes += payload_bytes;
943  }
944  return msrp_msg;
945  } else {/* keep waiting*/
946  msrp_msg->last_p = buf;
947  return msrp_msg;
948  }
949  } else if (msrp_msg->payload_bytes == 0) {
950  int dlen = strlen(msrp_msg->delimiter);
951 
952  if (strncasecmp(buf, msrp_msg->delimiter, dlen)) {
953  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error find delimiter\n");
954  msrp_msg->state = MSRP_ST_ERROR;
955  return msrp_msg;
956  }
957 
958  msrp_msg->payload = NULL;
959  msrp_msg->state = MSRP_ST_DONE;
960  msrp_msg->last_p = buf + dlen + 3; /*Fixme: assuming end with $\r\n*/
961 
962  return msrp_msg;
963  } else {
964  int dlen = strlen(msrp_msg->delimiter);
965 
966  if (msrp_msg->payload_bytes > len) {
967  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "payload too large ... %d > %d\n", (int)msrp_msg->payload_bytes, (int)len);
968  msrp_msg->state = MSRP_ST_ERROR; // not supported yet
969  return msrp_msg;
970  }
971 
972  switch_msrp_msg_set_payload(msrp_msg, buf, msrp_msg->payload_bytes);
973  msrp_msg->last_p = buf + msrp_msg->payload_bytes;
974  msrp_msg->state = MSRP_ST_DONE;
975  msrp_msg->last_p = buf + msrp_msg->payload_bytes;
976 
977  if (msrp_msg->payload_bytes <= len - dlen - 5) {
978  msrp_msg->last_p = buf + msrp_msg->payload_bytes + dlen + 5;
979 
980  if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "payload bytes: %" SWITCH_SIZE_T_FMT " len: %d dlen: %d delimiter: %s\n", msrp_msg->payload_bytes, len, dlen, msrp_msg->delimiter);
981 
982  return msrp_msg; /*Fixme: assuming \r\ndelimiter$\r\n present*/
983  }
984 
986  msrp_msg->state = MSRP_ST_ERROR;
987 
988  return msrp_msg;
989  }
990  } else {
991  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error code: %d\n", msrp_msg->state);
992  }
993 
994  return msrp_msg;
995 }
996 
998 {
999  char buf[2048];
1000  switch_size_t len;
1001  sprintf(buf, "MSRP %s 200 OK\r\nTo-Path: %s\r\nFrom-Path: %s\r\n"
1002  "%s$\r\n",
1003  msrp_msg->transaction_id,
1006  msrp_msg->delimiter);
1007  len = strlen(buf);
1008 
1009  return msrp_socket_send(csock, buf, &len);
1010 }
1011 
1013 {
1014  char buf[2048];
1015  switch_size_t len;
1016  sprintf(buf, "MSRP %s REPORT\r\nTo-Path: %s\r\nFrom-Path: %s\r\nMessage-ID: %s\r\n"
1017  "Status: 000 %s\r\nByte-Range: 1-%" SWITCH_SIZE_T_FMT "/%" SWITCH_SIZE_T_FMT
1018  "\r\n%s$\r\n",
1019  msrp_msg->transaction_id,
1023  switch_str_nil(status_code),
1024  msrp_msg->accumulated_bytes ? msrp_msg->accumulated_bytes : msrp_msg->byte_end,
1025  msrp_msg->bytes,
1026  msrp_msg->delimiter);
1027  len = strlen(buf);
1028 
1029  if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "report: %" SWITCH_SIZE_T_FMT " bytes [\n%s]\n", len, buf);
1030 
1031  return msrp_socket_send(csock, buf, &len);
1032 }
1033 
1034 static switch_bool_t msrp_find_uuid(char *uuid, const char *to_path)
1035 {
1036  int len = strlen(to_path);
1037  int i;
1038  int slash_count = 0;
1039  switch_assert(to_path);
1040  for(i=0; i<len; i++){
1041  if (*(to_path + i) == '/') {
1042  if (++slash_count == 3) break;
1043  }
1044  }
1045  if (slash_count < 3) return SWITCH_FALSE;
1046  if (len - i++ < 36) return SWITCH_FALSE;
1047  switch_snprintf(uuid, 37, to_path + i);
1048  return SWITCH_TRUE;
1049 }
1050 
1052 {
1054  switch_msrp_client_socket_t *csock = &helper->csock;
1055  switch_memory_pool_t *pool = helper->pool;
1056  char buf[MSRP_BUFF_SIZE];
1057  char *p;
1058  char *last_p;
1060  switch_status_t status;
1061  switch_msrp_msg_t *msrp_msg = NULL;
1062  char uuid[128] = { 0 };
1063  switch_msrp_session_t *msrp_session = NULL;
1064  int sanity = 10;
1065  SSL *ssl = NULL;
1066  int client_mode = helper->csock.client_mode;
1067 
1068  if (client_mode) {
1069  switch_sockaddr_t *sa = NULL;
1071  const char *remote_ip = NULL;
1072  switch_port_t remote_port = 0;
1073  char *dup = NULL;
1074  char *p = NULL;
1075 
1076  switch_assert(setup_msg);
1077  switch_assert(helper->msrp_session);
1078  msrp_session = helper->msrp_session;
1079  msrp_session->running = 1;
1080 
1081  switch_assert(msrp_session->remote_path);
1082  dup = switch_core_strdup(pool, msrp_session->remote_path);
1083  switch_assert(dup);
1084 
1085  p = (char *)switch_stristr("msrp://", dup);
1086 
1087  if (p) {
1088  p += 7;
1089  } else {
1090  p = (char *)switch_stristr("msrps://", dup);
1091 
1092  if (p) p+= 8;
1093  }
1094 
1095  if (p) {
1096  remote_ip = p;
1097 
1098  p = (char *)switch_stristr(":", p);
1099 
1100  if (p) {
1101  *p++ = '\0';
1102  remote_port = atoi(p);
1103  }
1104  }
1105 
1106  if (!remote_ip || remote_port <= 0) {
1107  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error get remote MSRP ip:port from path: [%s]\n", msrp_session->remote_path);
1108  }
1109 
1110  if (switch_sockaddr_info_get(&sa, remote_ip, SWITCH_UNSPEC, remote_port, 0, pool) != SWITCH_STATUS_SUCCESS) {
1112  goto end;
1113  }
1114 
1116  SOCK_STREAM, SWITCH_PROTO_TCP, pool) != SWITCH_STATUS_SUCCESS) {
1118  goto end;
1119  }
1120 
1123  // switch_socket_opt_set(csock->sock, SWITCH_SO_NONBLOCK, TRUE);
1126  switch_socket_timeout_set(csock->sock, 3000000); // abort connection 3 seconds than forever
1127 
1128  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MSRP %s Connecting to %s\n", msrp_session->call_id, msrp_session->remote_path);
1129 
1130  if ((switch_socket_connect(csock->sock, sa)) != SWITCH_STATUS_SUCCESS) {
1131  char errbuf[512] = {0};
1132  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error: %s\n", switch_strerror(errno, errbuf, sizeof(errbuf)));
1133  goto end;
1134  }
1135 
1136  switch_socket_timeout_set(csock->sock, -1);
1137 
1138  if (msrp_session->secure) {
1139  X509 *cert = NULL;
1141  int ret;
1142 
1143  switch_os_sock_get(&sockdes, csock->sock);
1144  switch_assert(sockdes != SWITCH_SOCK_INVALID);
1145 
1146  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MSRP setup TLS %s\n", msrp_session->call_id);
1147 
1148  ssl = SSL_new(globals.ssl_client_ctx);
1149  assert(ssl);
1150  csock->ssl = ssl;
1151  SSL_set_fd(ssl, sockdes);
1152 
1153  if ((ret = SSL_connect(ssl)) != 1 ) {
1154  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: Could not build a SSL session to: %s error=%d\n", msrp_session->remote_path, SSL_get_error(ssl, ret));
1155  goto end;
1156  }
1157 
1158  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Successfully enabled SSL/TLS session to: %s\n", msrp_session->remote_path);
1159 
1160  cert = SSL_get_peer_certificate(ssl);
1161 
1162  if (cert == NULL) {
1163  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: Could not get a certificate from: %s\n", msrp_session->remote_path);
1164  } else {
1165  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got SSL Cert from %s\n", msrp_session->remote_path);
1166 #if 0
1167  certname = X509_NAME_new();
1168  certname = X509_get_subject_name(cert);
1169 
1170  X509_NAME_print_ex(outbio, certname, 0, 0);
1171  BIO_printf(outbio, "\n");
1172 #endif
1173  }
1174  }
1175 
1176  helper->msrp_session->csock = csock;
1177 
1178  switch_msrp_msg_add_header(setup_msg, MSRP_H_CONTENT_TYPE, "text/plain");
1179 
1180  if (SWITCH_STATUS_SUCCESS != switch_msrp_send(msrp_session, setup_msg)) {
1181  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MSRP initial setup send error!\n");
1182  switch_msrp_msg_destroy(&setup_msg);
1183  goto end;
1184  }
1185 
1186  switch_msrp_msg_destroy(&setup_msg);
1187  } else { // server mode
1189  // switch_socket_opt_set(csock->sock, SWITCH_SO_NONBLOCK, TRUE);
1190 
1191  if (csock->secure) { // tls?
1192  int secure_established = 0;
1193  int sanity = 10;
1195  int code = 0;
1196 
1197  if (globals.ssl_ready != 1) {
1199  goto end;
1200  }
1201 
1202  switch_os_sock_get(&sockdes, csock->sock);
1203  // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "socket: %d\n", sockdes);
1204  switch_assert(sockdes != SWITCH_SOCK_INVALID);
1205 
1206  ssl = SSL_new(globals.ssl_ctx);
1207  assert(ssl);
1208  csock->ssl = ssl;
1209 
1210  SSL_set_fd(ssl, sockdes);
1211 
1212  do {
1213  code = SSL_accept(ssl);
1214 
1215  if (code == 1) {
1216  secure_established = 1;
1217  goto done;
1218  } else if (code == 0) {
1219  goto err;
1220  } else if (code < 0) {
1221  if (code == -1 && SSL_get_error(ssl, code) != SSL_ERROR_WANT_READ) {
1222  goto err;
1223  }
1224  }
1225  } while(sanity--);
1226 
1227  err:
1228  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SSL ERR code=%d error=%d\n", code, SSL_get_error(ssl, code));
1229  goto end;
1230 
1231  done:
1232  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SSL established = %d\n", secure_established);
1233  }
1234 
1235  len = MSRP_BUFF_SIZE;
1236  status = msrp_socket_recv(csock, buf, &len);
1237 
1238  if (helper->debug) {
1239  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "status:%d, len:%" SWITCH_SIZE_T_FMT "\n", status, len);
1240  }
1241 
1242  if (status == SWITCH_STATUS_SUCCESS) {
1243  msrp_msg = msrp_parse_buffer(buf, len, NULL, pool);
1244  switch_assert(msrp_msg);
1245  } else {
1246  goto end;
1247  }
1248 
1249  if (helper->debug) {
1250  char *data = msrp_msg_serialize(msrp_msg);
1251 
1252  if (data) {
1254  free(data);
1255  }
1256  }
1257 
1258  if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_SEND) {
1259  msrp_reply(csock, msrp_msg);
1260  if (msrp_check_success_report(msrp_msg)) {
1261  msrp_report(csock, msrp_msg, "200 OK");
1262  }
1263  } else if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_AUTH) {
1264  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MSRP_METHOD_AUTH\n");
1265  } else {
1266  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse initial message error!\n");
1267  goto end;
1268  }
1269 
1271  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid MSRP to-path!\n");
1272  }
1273 
1274  {
1275  switch_core_session_t *session = NULL;
1276 
1277  while (sanity-- && !(session = switch_core_session_locate(uuid))) {
1278  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "waiting for session\n");
1279  switch_yield(1000000);
1280  }
1281 
1282  if(!session) {
1283  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No such session %s\n", uuid);
1284  goto end;
1285  }
1286 
1287  msrp_session = switch_core_media_get_msrp_session(session);
1288  switch_assert(msrp_session);
1289  msrp_session->csock = csock;
1290  msrp_session->running = 1;
1291 
1293  }
1294  }
1295 
1296  len = MSRP_BUFF_SIZE;
1297  p = buf;
1298  last_p = buf;
1299  if (msrp_msg) switch_msrp_msg_destroy(&msrp_msg);
1300 
1301  while (msrp_socket_recv(csock, p, &len) == SWITCH_STATUS_SUCCESS) {
1302  // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "read bytes: %" SWITCH_SIZE_T_FMT "\n", len);
1303 
1304  if (len == 0) {
1306  continue;
1307  }
1308 
1309  if (helper->debug) dump_buffer(buf, (p - buf) + len, __LINE__, 0);
1310 
1311  again:
1312  msrp_msg = msrp_parse_buffer(last_p, p - last_p + len, msrp_msg, pool);
1313 
1314  switch_assert(msrp_msg);
1315 
1316  if (msrp_msg->state == MSRP_ST_ERROR) {
1317  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "msrp parse error!\n");
1318  goto end;
1319  }
1320 
1321  if (helper->debug) {
1322  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "state:%d, len:%" SWITCH_SIZE_T_FMT " payload_bytes:%" SWITCH_SIZE_T_FMT "\n", msrp_msg->state, len, msrp_msg->payload_bytes);
1323  }
1324 
1325  if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_SEND) {
1326  msrp_reply(csock, msrp_msg);
1327 
1328  if (msrp_check_success_report(msrp_msg)) {
1329  msrp_report(csock, msrp_msg, "200 OK");
1330  }
1331 
1332  last_p = msrp_msg->last_p;
1333  switch_msrp_session_push_msg(msrp_session, msrp_msg);
1334  msrp_msg = NULL;
1335  } else if (msrp_msg->state == MSRP_ST_DONE) { /* throw away */
1336  last_p = msrp_msg->last_p;
1337  switch_msrp_msg_destroy(&msrp_msg);
1338  } else {
1339  last_p = msrp_msg->last_p;
1340  }
1341 
1342  while (msrp_session && msrp_session->running && msrp_session->msrp_msg_count > msrp_session->msrp_msg_buffer_size) {
1343  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s reading too fast, relax...\n", msrp_session->call_id);
1344  switch_yield(100000);
1345  }
1346 
1347  if (p + len > last_p) { // unparsed msg in buffer
1348  p += len;
1349  len = MSRP_BUFF_SIZE - (p - buf);
1350 
1351  if (!msrp_msg) {
1352  int rest_len = p - last_p;
1353 
1354  memmove(buf, last_p, rest_len);
1355  p = buf + rest_len;
1356  len = MSRP_BUFF_SIZE - rest_len;
1357  last_p = buf;
1358 
1359  if (rest_len > 10) { // might have a complete msg in buffer, try parse again
1360  len = 0;
1361  goto again;
1362  }
1363 
1364  continue;
1365  }
1366 
1367  if (p >= buf + MSRP_BUFF_SIZE) {
1368  switch_msrp_msg_t *new_msg;
1369 
1370  if (msrp_msg->state != MSRP_ST_WAIT_BODY || !msrp_msg->range_star) {
1371  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "buffer overflow\n");
1372  /*todo, do a strstr in the whole buffer ?*/
1373  break;
1374  }
1375 
1376  switch_assert(p == buf + MSRP_BUFF_SIZE);
1377 
1378  /* buffer full*/
1379  msrp_msg->payload_bytes = 0;
1380  new_msg = switch_msrp_msg_dup(msrp_msg);
1381  switch_msrp_msg_set_payload(new_msg, last_p, p - last_p);
1382  new_msg->state = MSRP_ST_DONE;
1383  switch_msrp_session_push_msg(msrp_session, new_msg);
1384  new_msg = NULL;
1385 
1386  msrp_msg->accumulated_bytes += (p - last_p);
1387  p = buf;
1388  len = MSRP_BUFF_SIZE;
1389  last_p = buf;
1390  msrp_msg->last_p = buf;
1391  msrp_msg->byte_start = msrp_msg->byte_end = 0;
1392  msrp_msg->payload_bytes = 0;
1393 
1394  if (globals.debug) {
1396  }
1397  }
1398  } else { /* all buffer parsed */
1399  p = buf;
1400  len = MSRP_BUFF_SIZE;
1401  last_p = buf;
1402  }
1403  if (!msrp_session->running) break;
1404  }
1405 
1406 end:
1407 
1408  if (msrp_session) {
1409  switch_mutex_lock(msrp_session->mutex);
1410  close_socket(&csock->sock);
1411  switch_mutex_unlock(msrp_session->mutex);
1412  }
1413 
1414  if (!client_mode) switch_core_destroy_memory_pool(&pool);
1415 
1416  if (ssl) SSL_free(ssl);
1417 
1418  if (msrp_session) msrp_session->running = 0;
1419 
1420  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP worker down %s\n", msrp_session ? msrp_session->call_id : "!");
1421 
1422  return NULL;
1423 }
1424 
1426 {
1428  switch_memory_pool_t *pool = NULL;
1429  switch_threadattr_t *thd_attr = NULL;
1430  switch_socket_t *sock = NULL;
1431 
1432  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP listener start%s\n", msock->secure ? " ssl" : "");
1433 
1436  return NULL;
1437  }
1438 
1440  // switch_socket_opt_set(msock->sock, SWITCH_SO_NONBLOCK, TRUE);
1441 
1442  while (globals.running && switch_socket_accept(&sock, msock->sock, pool) == SWITCH_STATUS_SUCCESS) {
1443  switch_memory_pool_t *worker_pool;
1445 
1446  if (globals.debug > 0) {
1447  switch_sockaddr_t *addr = NULL;
1448  char remote_ip[128];
1449 
1450  /* Get the remote address/port info */
1451  switch_socket_addr_get(&addr, SWITCH_TRUE, sock);
1452 
1453  if (addr) {
1454  switch_get_addr(remote_ip, sizeof(remote_ip), addr);
1455  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Connection Open%s from %s:%d\n", msock->secure ? " SSL" : "", remote_ip, switch_sockaddr_get_port(addr));
1456  } else {
1457  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error get remote addr!\n");
1458  }
1459  }
1460 
1461  if (switch_core_new_memory_pool(&worker_pool) != SWITCH_STATUS_SUCCESS) {
1463  return NULL;
1464  }
1465 
1466  helper = switch_core_alloc(worker_pool, sizeof(worker_helper_t));
1467 
1468  switch_assert(helper != NULL);
1469  helper->pool = worker_pool;
1470  helper->debug = globals.debug;
1471  helper->csock.sock = sock;
1472  helper->csock.secure = msock->secure;
1473 
1474  switch_threadattr_create(&thd_attr, pool);
1475  switch_threadattr_detach_set(thd_attr, 1);
1477  switch_thread_create(&thread, thd_attr, msrp_worker, helper, worker_pool);
1478  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP worker new thread spawned!\n");
1479  }
1480 
1481  if (pool) switch_core_destroy_memory_pool(&pool);
1482 
1483  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP listener down\n");
1484 
1485  return NULL;
1486 }
1487 
1489 {
1492  switch_threadattr_t *thd_attr = NULL;
1493 
1494  helper = switch_core_alloc(msrp_session->pool, sizeof(worker_helper_t));
1495 
1496  switch_assert(helper != NULL);
1497  helper->pool = msrp_session->pool;
1498  helper->debug = globals.debug;
1499  helper->csock.sock = NULL; // client mode
1500  helper->csock.secure = msrp_session->secure;
1501  helper->csock.client_mode = 1;
1502  helper->msrp_session = msrp_session;
1503 
1504  switch_threadattr_create(&thd_attr, helper->pool);
1505  switch_threadattr_detach_set(thd_attr, 1);
1507  switch_thread_create(&thread, thd_attr, msrp_worker, helper, helper->pool);
1508  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP new worker client started! %s\n", msrp_session->call_id);
1509 
1510  return SWITCH_STATUS_SUCCESS;
1511 }
1512 
1513 void random_string(char *buf, uint16_t size)
1514 {
1515  switch_stun_random_string(buf, size, NULL);
1516 }
1517 
1518 #define MSRP_TRANS_ID_LEN 16
1519 static switch_status_t switch_msrp_do_send(switch_msrp_session_t *ms, switch_msrp_msg_t *msrp_msg, const char *file, const char *func, int line)
1520 {
1521  char transaction_id[MSRP_TRANS_ID_LEN + 1] = { 0 };
1522  char buf[MSRP_BUFF_SIZE];
1523  char message_id[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
1524  switch_size_t len;
1525  const char *msrp_h_to_path = switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH);
1526  const char *msrp_h_from_path = switch_msrp_msg_get_header(msrp_msg, MSRP_H_FROM_PATH);
1527  const char *to_path = msrp_h_to_path ? msrp_h_to_path : ms->remote_path;
1528  const char *from_path = msrp_h_from_path ? msrp_h_from_path: ms->local_path;
1529  const char *content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE);
1530 
1531  if (msrp_msg->payload_bytes == 2 && msrp_msg->payload && !strncmp(msrp_msg->payload, "\r\n", 2)) {
1532  // discard \r\n appended in uuid_send_text
1533  return SWITCH_STATUS_SUCCESS;
1534  }
1535 
1536  if (!from_path) {
1537  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_WARNING, "NO FROM PATH\n");
1538  return SWITCH_STATUS_SUCCESS;
1539  }
1540 
1541  if (zstr(content_type)) {
1542  content_type = "text/plain";
1543  }
1544 
1545  random_string(transaction_id, MSRP_TRANS_ID_LEN);
1546  switch_uuid_str(message_id, sizeof(message_id));
1547 
1548  sprintf(buf, "MSRP %s SEND\r\nTo-Path: %s\r\nFrom-Path: %s\r\n"
1549  "Message-ID: %s\r\n"
1550  "Byte-Range: 1-%" SWITCH_SIZE_T_FMT "/%" SWITCH_SIZE_T_FMT "\r\n"
1551  "%s%s%s",
1552  transaction_id,
1553  to_path,
1554  from_path,
1555  message_id,
1556  msrp_msg->payload ? msrp_msg->payload_bytes : 0,
1557  msrp_msg->payload ? msrp_msg->payload_bytes : 0,
1558  msrp_msg->payload ? "Content-Type: " : "",
1559  msrp_msg->payload ? content_type : "",
1560  msrp_msg->payload ? "\r\n\r\n" : "");
1561 
1562  len = strlen(buf);
1563 
1564  if (msrp_msg->payload) {
1565  if (len + msrp_msg->payload_bytes >= MSRP_BUFF_SIZE) {
1566  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_ERROR, "payload too large! %" SWITCH_SIZE_T_FMT "\n", len + msrp_msg->payload_bytes);
1567  return SWITCH_STATUS_FALSE;
1568  }
1569  memcpy(buf + len, msrp_msg->payload, msrp_msg->payload_bytes);
1570  len += msrp_msg->payload_bytes;
1571  sprintf(buf + len, "\r\n");
1572  len += 2;
1573  }
1574 
1575  sprintf(buf + len, "-------%s$\r\n", transaction_id);
1576  len += (10 + strlen(transaction_id));
1577 
1578  if (globals.debug) dump_buffer(buf, len, __LINE__, 1);
1579 
1580  return ms->csock ? msrp_socket_send(ms->csock, buf, &len) : SWITCH_STATUS_FALSE;
1581 }
1582 
1583 SWITCH_DECLARE (switch_status_t) switch_msrp_perform_send(switch_msrp_session_t *ms, switch_msrp_msg_t *msrp_msg, const char *file, const char *func, int line)
1584 {
1585  switch_msrp_msg_t *msg = NULL;
1587 
1588  if (!ms->running) {
1589  if (!ms->send_queue) {
1590  switch_queue_create(&ms->send_queue, 100, ms->pool);
1591  }
1592 
1593  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_WARNING, "MSRP not ready! Buffering one message %" SWITCH_SIZE_T_FMT " bytes\n", msrp_msg->payload_bytes);
1594 
1595  if (globals.debug && msrp_msg->payload) {
1596  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_WARNING, "MSRP not ready! Buffered one message [%s]\n", msrp_msg->payload);
1597  }
1598 
1599  msg = switch_msrp_msg_dup(msrp_msg);
1600 
1601  status = switch_queue_trypush(ms->send_queue, msg);
1602 
1603  if (status != SWITCH_STATUS_SUCCESS) {
1604  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_ERROR, "MSRP queue FULL! Discard one message %" SWITCH_SIZE_T_FMT " bytes\n", msg->payload_bytes);
1606  }
1607 
1608  return status;
1609  }
1610 
1611  if (ms->send_queue) {
1612  while (status == SWITCH_STATUS_SUCCESS && switch_queue_trypop(ms->send_queue, (void **)&msg) == SWITCH_STATUS_SUCCESS) {
1613  status = switch_msrp_do_send(ms, msg, file, func, line);
1614  }
1615 
1617  ms->send_queue = NULL;
1618  }
1619 
1620  status = switch_msrp_do_send(ms, msrp_msg, file, func, line);
1621 
1622  return status;
1623 }
1624 
1626 {
1627  switch_msrp_msg_t *msg = malloc(sizeof(switch_msrp_msg_t));
1628  switch_assert(msg);
1629 
1630  memset(msg, 0, sizeof(switch_msrp_msg_t));
1632  switch_assert(msg->headers);
1633 
1634  return msg;
1635 }
1636 
1638 {
1639  switch_msrp_msg_t *new_msg = malloc(sizeof(switch_msrp_msg_t));
1640  switch_assert(new_msg);
1641  memset(new_msg, 0, sizeof(switch_msrp_msg_t));
1642  switch_event_dup(&new_msg->headers, msg->headers);
1643  switch_assert(new_msg->headers);
1644 
1648  new_msg->state = msg->state;
1649  new_msg->method = msg->method;
1650  new_msg->code_number = msg->code_number;
1651  new_msg->payload_bytes = msg->payload_bytes;
1652 
1653  if (msg->payload_bytes > 0 && msg->payload) {
1654  new_msg->payload = malloc(msg->payload_bytes + 1);
1655  switch_assert(new_msg->payload);
1656  memcpy(new_msg->payload, msg->payload, msg->payload_bytes);
1657  *(new_msg->payload + msg->payload_bytes) = '\0';
1658  }
1659 
1660  return new_msg;
1661 }
1662 
1664 {
1665  switch_msrp_msg_t *msrp_msg = *msg;
1666  if (msrp_msg->headers) {
1667  switch_event_destroy(&msrp_msg->headers);
1668  }
1669 
1670  switch_safe_free(msrp_msg->payload);
1671  *msg = NULL;
1672 }
1673 
1674 /* Experimental */
1675 
1676 SWITCH_STANDARD_APP(msrp_recv_file_function)
1677 {
1678  switch_msrp_session_t *msrp_session = NULL;
1679  switch_msrp_msg_t *msrp_msg = NULL;
1682  switch_file_t *fd;
1683  const char *filename = data;
1684 
1686  switch_channel_answer(channel);
1687 
1688  if (zstr(data)) {
1689  filename = switch_channel_get_variable(channel, "sip_msrp_file_name");
1690 
1691  if (zstr(filename)) {
1692  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No file specified.\n");
1693  return;
1694  }
1695 
1696  filename = switch_core_session_sprintf(session, "%s%s%s", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR, filename);
1697  }
1698 
1699  if (!(msrp_session = switch_core_media_get_msrp_session(session))) {
1700  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not a MSRP session!\n");
1701  return;
1702  }
1703 
1705  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Open File %s\n", filename);
1706  return;
1707  }
1708 
1709  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File [%s] Opened\n", filename);
1710 
1711  while (1) {
1712  if ((msrp_msg = switch_msrp_session_pop_msg(msrp_session)) == NULL) {
1713  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "MSRP message queue size: %d\n", (int)msrp_session->msrp_msg_count);
1714  if (!switch_channel_ready(channel)) break;
1715  continue;
1716  }
1717 
1718  if (msrp_msg->method == MSRP_METHOD_SEND) {
1719  switch_size_t bytes = msrp_msg->payload_bytes;
1720  const char *msg = switch_msrp_msg_get_header(msrp_msg, MSRP_H_MESSAGE_ID);
1721  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s %" SWITCH_SIZE_T_FMT " bytes writing\n", msg, bytes);
1722  switch_file_write(fd, msrp_msg->payload, &bytes);
1724  if (bytes != msrp_msg->payload_bytes) {
1725  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "write failed, bytes lost!\n");
1726  }
1727  }
1728 
1729  switch_safe_free(msrp_msg);
1730  }
1731 
1732  switch_file_close(fd);
1734 
1736 }
1737 
1738 /* Experimental, if it doesn't work, it doesn't */
1739 
1740 SWITCH_STANDARD_APP(msrp_send_file_function)
1741 {
1742  switch_msrp_session_t *msrp_session = NULL;
1743  switch_msrp_msg_t *msrp_msg = NULL;
1746  switch_file_t *fd;
1747  const char *filename = data;
1748  switch_size_t len = 1024;
1749  char buf[1024];
1750  int sanity = 10;
1751 
1752  if (!(msrp_session = switch_core_media_get_msrp_session(session))) {
1753  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not a msrp session!\n");
1754  return;
1755  }
1756 
1758  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Open File %s\n", filename);
1759  return;
1760  }
1761 
1762  msrp_msg = switch_msrp_msg_create();
1763 
1764  switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
1765 
1766  msrp_msg->payload_bytes = switch_file_get_size(fd);
1767  msrp_msg->byte_start = 1;
1768 
1769  while(sanity-- && !msrp_session->running) {
1770  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting MSRP socket ...\n");
1771  switch_yield(1000000);
1772  }
1773 
1774  if (!msrp_session->running) {
1775  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for MSRP socket timedout, exiting...\n");
1776  goto end;
1777  }
1778 
1779  while (switch_file_read(fd, buf, &len) == SWITCH_STATUS_SUCCESS &&
1780  switch_channel_ready(channel) && len > 0) {
1781 
1782  msrp_msg->byte_end = msrp_msg->byte_start + len + 1;
1783  switch_msrp_msg_set_payload(msrp_msg, buf, len);
1784 
1785  /*TODO: send in chunk should ending in + but not $ after delimiter*/
1786  switch_msrp_send(msrp_session, msrp_msg);
1787 
1789 
1790  msrp_msg->byte_start += len;
1791  }
1792 
1793  sanity = 10;
1794 
1795  while(sanity-- && switch_channel_ready(channel)) {
1796  switch_yield(1000000);
1797  }
1798 
1799 end:
1800  switch_file_close(fd);
1801  switch_msrp_msg_destroy(&msrp_msg);
1802  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File [%s] sent, closed!\n", filename);
1803 }
1804 
1805 SWITCH_STANDARD_API(uuid_msrp_send_function)
1806 {
1807  char *mycmd = NULL, *argv[3] = { 0 };
1808  int argc;
1809  switch_core_session_t *msession = NULL;
1810  switch_msrp_session_t *msrp_session = NULL;
1811  switch_msrp_msg_t *msrp_msg = NULL;
1812 
1813  if (zstr(cmd) || !(mycmd = strdup(cmd))) {
1814  goto error;
1815  }
1816 
1817  argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
1818 
1819  if (argc < 2 || !argv[0]) {
1820  goto error;
1821  }
1822 
1823  if (!(msession = switch_core_session_locate(argv[0]))) {
1824  stream->write_function(stream, "-ERR Usage: cannot locate session.\n");
1825  return SWITCH_STATUS_SUCCESS;
1826  }
1827 
1828  if (!(msrp_session = switch_core_media_get_msrp_session(msession))) {
1829  stream->write_function(stream, "-ERR No msrp_session.\n");
1830  switch_core_session_rwunlock(msession);
1831  return SWITCH_STATUS_SUCCESS;
1832  }
1833 
1834  msrp_msg = switch_msrp_msg_create();
1835  switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
1836  switch_msrp_msg_set_payload(msrp_msg, argv[1], strlen(argv[1]));
1837  switch_msrp_send(msrp_session, msrp_msg);
1838  switch_msrp_msg_destroy(&msrp_msg);
1839  stream->write_function(stream, "+OK message sent\n");
1840  switch_core_session_rwunlock(msession);
1841  return SWITCH_STATUS_SUCCESS;
1842 
1843 error:
1844  stream->write_function(stream, "-ERR Usage: uuid_msrp_send <uuid> msg\n");
1845  return SWITCH_STATUS_SUCCESS;
1846 }
1847 
1848 #define MSRP_SYNTAX "debug <on|off>|restart"
1849 SWITCH_STANDARD_API(msrp_api_function)
1850 {
1851  if (zstr(cmd)) {
1852  stream->write_function(stream, "-ERR usage: " MSRP_SYNTAX "\n");
1853  return SWITCH_STATUS_SUCCESS;
1854  }
1855 
1856  if (!strcmp(cmd, "debug on")) {
1857  globals.debug = 1;
1858  stream->write_function(stream, "+OK debug on\n");
1859  } else if(!strcmp(cmd, "debug off")) {
1860  globals.debug = 0;
1861  stream->write_function(stream, "+OK debug off\n");
1862  } else if(!strcmp(cmd, "restart")) {
1864  switch_msrp_init();
1865  }
1866 
1867  return SWITCH_STATUS_SUCCESS;
1868 }
1869 
1871 {
1872  switch_application_interface_t *app_interface;
1873  switch_api_interface_t *api_interface;
1874 
1875  SWITCH_ADD_API(api_interface, "msrp", "MSRP Functions", msrp_api_function, MSRP_SYNTAX);
1876 
1877  SWITCH_ADD_API(api_interface, "uuid_msrp_send", "send msrp text", uuid_msrp_send_function, "<msg>");
1878  SWITCH_ADD_APP(app_interface, "msrp_recv_file", "Recv msrp message to file", "Recv msrp message", msrp_recv_file_function, "<filename>", SAF_SUPPORT_TEXT_ONLY | SAF_SUPPORT_NOMEDIA);
1879  SWITCH_ADD_APP(app_interface, "msrp_send_file", "Send file via msrp", "Send file via msrp", msrp_send_file_function, "<filename>", SAF_SUPPORT_TEXT_ONLY | SAF_SUPPORT_NOMEDIA);
1880 
1881  switch_console_set_complete("add msrp debug on");
1882  switch_console_set_complete("add msrp debug off");
1883  switch_console_set_complete("restart");
1884  switch_console_set_complete("add uuid_msrp_send ::console::list_uuid");
1885 }
1886 
1887 
1888 /* For Emacs:
1889  * Local Variables:
1890  * mode:c
1891  * indent-tabs-mode:t
1892  * tab-width:4
1893  * c-basic-offset:4
1894  * End:
1895  * For VIM:
1896  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1897  */
switch_status_t switch_socket_connect(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:757
switch_status_t switch_console_set_complete(const char *string)
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
#define switch_channel_answer(channel)
Answer a channel (initiate/acknowledge a successful connection)
switch_msrp_msg_t * msrp_msg
Definition: switch_msrp.h:107
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
A module interface to implement an application.
const char * switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr)
returns the value of the requested tag attribute, or "" if not found
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
switch_socket_t * sock
Definition: switch_msrp.c:42
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#define SWITCH_CHANNEL_SESSION_LOG(x)
uint16_t switch_sockaddr_get_port(switch_sockaddr_t *sa)
Definition: switch_apr.c:1001
SWITCH_STANDARD_APP(msrp_recv_file_function)
Definition: switch_msrp.c:1676
#define SWITCH_FOPEN_TRUNCATE
Definition: switch_apr.h:773
#define SWITCH_THREAD_FUNC
switch_status_t switch_file_write(switch_file_t *thefile, const void *buf, switch_size_t *nbytes)
Definition: switch_apr.c:462
switch_status_t switch_mutex_destroy(switch_mutex_t *lock)
Definition: switch_apr.c:303
#define SWITCH_CHANNEL_LOG
#define switch_malloc(ptr, len)
#define SWITCH_SO_IPV6_V6ONLY
Definition: switch_apr.h:1002
static switch_status_t msrp_socket_send(switch_msrp_client_socket_t *csock, char *buf, switch_size_t *len)
Definition: switch_msrp.c:549
switch_status_t msrp_report(switch_msrp_client_socket_t *csock, switch_msrp_msg_t *msrp_msg, char *status_code)
Definition: switch_msrp.c:1012
switch_msrp_msg_t * last_msg
Definition: switch_msrp.h:108
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:742
switch_port_t port
Definition: switch_msrp.c:41
static switch_status_t load_config(void)
Definition: switch_msrp.c:190
switch_size_t byte_start
Definition: switch_msrp.h:80
const char * code_description
Definition: switch_msrp.h:79
#define SWITCH_FOPEN_READ
Definition: switch_apr.h:769
switch_msrp_socket_t msock_ssl
Definition: switch_msrp.c:72
int message_buffer_size
Definition: switch_msrp.c:61
#define SWITCH_PROTO_TCP
Definition: switch_apr.h:1041
switch_size_t msrp_msg_buffer_size
Definition: switch_msrp.h:110
switch_bool_t
Definition: switch_types.h:437
static char * msrp_parse_header(char *start, int skip, const char *end, switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, switch_memory_pool_t *pool)
Definition: switch_msrp.c:690
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
switch_size_t byte_end
Definition: switch_msrp.h:81
#define SWITCH_ADD_APP(app_int, int_name, short_descript, long_descript, funcptr, syntax_string, app_flags)
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
switch_status_t switch_socket_timeout_set(switch_socket_t *sock, switch_interval_time_t t)
Definition: switch_apr.c:941
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
static void *SWITCH_THREAD_FUNC msrp_listener(switch_thread_t *thread, void *obj)
Definition: switch_msrp.c:1425
static switch_bool_t msrp_check_success_report(switch_msrp_msg_t *msrp_msg)
Definition: switch_msrp.c:96
char * find_delim(char *buf, int len, const char *delim)
Definition: switch_msrp.c:591
void switch_msrp_msg_destroy(switch_msrp_msg_t **msg)
Definition: switch_msrp.c:1663
#define fail()
Definition: tone2wav.c:70
#define switch_channel_ready(_channel)
char * last_p
Definition: switch_msrp.h:86
switch_status_t switch_msrp_start_client(switch_msrp_session_t *msrp_session)
Definition: switch_msrp.c:1488
#define SWITCH_SO_TCP_KEEPIDLE
Definition: switch_apr.h:1000
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1264
int32_t switch_sockaddr_get_family(switch_sockaddr_t *sa)
Definition: switch_apr.c:1006
static void close_socket(switch_socket_t **sock)
Definition: switch_msrp.c:239
struct msrp_msg_s * next
Definition: switch_msrp.h:88
switch_size_t bytes
Definition: switch_msrp.h:82
#define SWITCH_FPROT_OS_DEFAULT
Definition: switch_apr.h:726
const char * switch_msrp_msg_get_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype)
Definition: switch_msrp.c:685
#define MSRP_BUFF_SIZE
Definition: switch_msrp.c:37
char * switch_msrp_msg_header_name(switch_msrp_header_type_t htype)
Definition: switch_msrp.c:645
char * HEADER_NAMES[]
Definition: switch_msrp.c:628
switch_socket_t * sock
Definition: switch_msrp.c:48
A representation of an XML tree.
Definition: switch_xml.h:79
const char * delimiter
Definition: switch_msrp.h:77
switch_status_t switch_socket_recv(switch_socket_t *sock, char *buf, switch_size_t *len)
Definition: switch_apr.c:805
static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
Definition: switch_msrp.c:1051
#define DEBUG_MSRP
Definition: switch_msrp.c:38
#define SWITCH_SO_KEEPALIVE
Definition: switch_apr.h:992
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
switch_msrp_session_t * msrp_session
Definition: switch_msrp.c:79
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
#define SWITCH_SOCK_INVALID
switch_msrp_socket_t msock
Definition: switch_msrp.c:71
static switch_bool_t msrp_find_uuid(char *uuid, const char *to_path)
Definition: switch_msrp.c:1034
switch_size_t payload_bytes
Definition: switch_msrp.h:83
#define zstr(x)
Definition: switch_utils.h:314
int cJSON_bool fmt
Definition: switch_cJSON.h:150
switch_status_t switch_socket_addr_get(switch_sockaddr_t **sa, switch_bool_t remote, switch_socket_t *sock)
Definition: switch_apr.c:722
switch_status_t switch_socket_send(switch_socket_t *sock, const char *buf, switch_size_t *len)
Definition: switch_apr.c:762
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_msrp_header_type_t
Definition: switch_msrp.h:50
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
int range_star
Definition: switch_msrp.h:85
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
#define SWITCH_SSIZE_T_FMT
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
switch_status_t switch_socket_accept(switch_socket_t **new_sock, switch_socket_t *sock, switch_memory_pool_t *pool)
Definition: switch_apr.c:752
switch_status_t switch_threadattr_detach_set(switch_threadattr_t *attr, int32_t on)
Definition: switch_apr.c:678
Definition: cJSON.c:68
#define MSRP_TRANS_ID_LEN
Definition: switch_msrp.c:1518
switch_xml_t next
Definition: switch_xml.h:91
switch_byte_t switch_byte_t * buf
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
static switch_msrp_msg_t * msrp_parse_headers(char *start, int len, switch_msrp_msg_t *msrp_msg, switch_memory_pool_t *pool)
Definition: switch_msrp.c:706
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
int running
Definition: switch_msrp.c:56
A module interface to implement an api function.
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
switch_msrp_session_t * switch_msrp_session_new(switch_memory_pool_t *pool, const char *call_id, switch_bool_t secure)
Definition: switch_msrp.c:378
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
SSL_CTX * ssl_ctx
Definition: switch_msrp.c:66
switch_event_t * headers
Definition: switch_msrp.h:75
intptr_t switch_ssize_t
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
static switch_status_t switch_msrp_do_send(switch_msrp_session_t *ms, switch_msrp_msg_t *msrp_msg, const char *file, const char *func, int line)
Definition: switch_msrp.c:1519
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
const char * transaction_id
Definition: switch_msrp.h:76
const char * switch_msrp_listen_ip(void)
Definition: switch_msrp.c:289
void dump_buffer(const char *buf, switch_size_t len, int line, int is_send)
Definition: switch_msrp.c:561
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_status_t switch_socket_listen(switch_socket_t *sock, int32_t backlog)
Definition: switch_apr.c:747
#define MSRP_SYNTAX
Definition: switch_msrp.c:1848
struct switch_msrp_session_s * msrp_session
Definition: switch_msrp.c:52
int switch_os_socket_t
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
switch_status_t switch_socket_opt_set(switch_socket_t *sock, int32_t opt, int32_t on)
Definition: switch_apr.c:907
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
switch_status_t switch_msrp_msg_add_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, char *fmt,...)
Definition: switch_msrp.c:651
static switch_status_t msock_init(char *ip, switch_port_t port, switch_socket_t **sock, switch_memory_pool_t *pool)
Definition: switch_msrp.c:250
switch_memory_pool_t * pool
Definition: switch_msrp.c:77
uintptr_t switch_size_t
static void msrp_deinit_ssl(void)
Definition: switch_msrp.c:102
int switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap)
uint16_t switch_port_t
struct worker_helper worker_helper_t
switch_status_t switch_file_read(switch_file_t *thefile, void *buf, switch_size_t *nbytes)
Definition: switch_apr.c:457
switch_status_t switch_msrp_perform_send(switch_msrp_session_t *ms, switch_msrp_msg_t *msrp_msg, const char *file, const char *func, int line)
Definition: switch_msrp.c:1583
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_msrp_session_destroy(switch_msrp_session_t **ms)
Definition: switch_msrp.c:392
char * switch_strerror(switch_status_t statcode, char *buf, switch_size_t bufsize)
Definition: switch_apr.c:1440
struct fspr_sockaddr_t switch_sockaddr_t
Definition: switch_apr.h:1029
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
switch_status_t switch_os_sock_get(switch_os_socket_t *thesock, switch_socket_t *sock)
Definition: switch_apr.c:712
switch_status_t switch_file_exists(const char *filename, switch_memory_pool_t *pool)
Definition: switch_apr.c:519
char * ip
Definition: switch_msrp.c:60
switch_status_t switch_socket_create(switch_socket_t **new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
Definition: switch_apr.c:727
switch_memory_pool_t * pool
Definition: switch_msrp.h:92
char * cert
Definition: switch_msrp.c:63
switch_memory_pool_t * pool
Definition: switch_msrp.c:58
#define SWITCH_SIZE_T_FMT
switch_status_t
Common return values.
static switch_msrp_msg_t * msrp_parse_buffer(char *buf, int len, switch_msrp_msg_t *msrp_msg, switch_memory_pool_t *pool)
Definition: switch_msrp.c:878
switch_thread_t * thread
Definition: switch_msrp.c:43
char * switch_uuid_str(char *buf, switch_size_t len)
#define SWITCH_SO_TCP_KEEPINTVL
Definition: switch_apr.h:1001
void switch_msrp_msg_set_payload(switch_msrp_msg_t *msrp_msg, const char *buf, switch_size_t payload_bytes)
Definition: switch_msrp.c:82
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
SSL_CTX * ssl_client_ctx
Definition: switch_msrp.c:69
int code_number
Definition: switch_msrp.h:78
switch_msrp_msg_t * switch_msrp_session_pop_msg(switch_msrp_session_t *ms)
Definition: switch_msrp.c:445
switch_status_t switch_socket_close(switch_socket_t *sock)
Definition: switch_apr.c:737
switch_mutex_t * mutex
Definition: switch_msrp.h:109
#define SWITCH_UNSPEC
Definition: switch_apr.h:1022
switch_size_t msrp_msg_count
Definition: switch_msrp.h:111
switch_status_t switch_socket_shutdown(switch_socket_t *sock, switch_shutdown_how_e how)
Definition: switch_apr.c:732
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
Main Library Header.
switch_msrp_client_socket_t csock
Definition: switch_msrp.c:78
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
#define SWITCH_DECLARE(type)
const char * filename
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
struct fspr_file_t switch_file_t
Definition: switch_apr.h:685
switch_status_t msrp_reply(switch_msrp_client_socket_t *csock, switch_msrp_msg_t *msrp_msg)
Definition: switch_msrp.c:997
#define switch_channel_set_flag(_c, _f)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
const SSL_METHOD * ssl_method
Definition: switch_msrp.c:65
switch_status_t switch_msrp_init(void)
Definition: switch_msrp.c:294
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip)
#define SWITCH_ADD_API(api_int, int_name, descript, funcptr, syntax_string)
switch_status_t switch_queue_trypush(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1279
#define SWITCH_SO_REUSEADDR
Definition: switch_apr.h:995
void switch_msrp_load_apis_and_applications(switch_loadable_module_interface_t **module_interface)
Definition: switch_msrp.c:1870
void random_string(char *buf, uint16_t size)
Definition: switch_msrp.c:1513
switch_msrp_msg_t * switch_msrp_msg_create(void)
Definition: switch_msrp.c:1625
switch_status_t switch_queue_term(switch_queue_t *queue)
Definition: switch_apr.c:1274
char * key
Definition: switch_msrp.c:64
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
switch_msrp_session_t * switch_core_media_get_msrp_session(switch_core_session_t *session)
#define SWITCH_SO_TCP_NODELAY
Definition: switch_apr.h:999
char * msrp_msg_serialize(switch_msrp_msg_t *msrp_msg)
Definition: switch_msrp.c:476
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:698
int debug
Definition: switch_msrp.c:57
switch_queue_t * send_queue
Definition: switch_msrp.h:118
struct fspr_pool_t switch_memory_pool_t
switch_status_t switch_file_open(switch_file_t **newf, const char *fname, int32_t flag, switch_fileperms_t perm, switch_memory_pool_t *pool)
Definition: switch_apr.c:411
const char * switch_get_addr(char *buf, switch_size_t len, switch_sockaddr_t *in)
Definition: switch_apr.c:979
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1233
#define TRUE
void switch_event_destroy(switch_event_t **event)
Destroy an event.
SWITCH_STANDARD_API(uuid_msrp_send_function)
Definition: switch_msrp.c:1805
static void msrp_init_ssl(void)
Definition: switch_msrp.c:115
struct fspr_socket_t switch_socket_t
Definition: switch_apr.h:1026
#define SWITCH_FOPEN_CREATE
Definition: switch_apr.h:771
int switch_core_gen_certs(const char *prefix)
int ssl_ready
Definition: switch_msrp.c:67
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_status_t switch_file_close(switch_file_t *thefile)
Definition: switch_apr.c:432
char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the pool ...
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
#define switch_msrp_send(ms, msg)
Definition: switch_msrp.h:141
switch_status_t switch_sockaddr_info_get(switch_sockaddr_t **sa, const char *hostname, int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:839
char * payload
Definition: switch_msrp.h:87
static switch_status_t msrp_socket_recv(switch_msrp_client_socket_t *csock, char *buf, switch_size_t *len)
Definition: switch_msrp.c:519
#define SWITCH_FOPEN_WRITE
Definition: switch_apr.h:770
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
switch_msrp_client_socket_t * csock
Definition: switch_msrp.h:113
switch_size_t accumulated_bytes
Definition: switch_msrp.h:84
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
const SSL_METHOD * ssl_client_method
Definition: switch_msrp.c:68
#define SWITCH_UUID_FORMATTED_LENGTH
Definition: switch_apr.h:545
The abstraction of a loadable module.
static struct @7 globals
switch_msrp_msg_t * switch_msrp_msg_dup(switch_msrp_msg_t *msg)
Definition: switch_msrp.c:1637
switch_status_t switch_msrp_destroy(void)
Definition: switch_msrp.c:349
switch_size_t switch_file_get_size(switch_file_t *thefile)
Definition: switch_apr.c:491
switch_status_t switch_msrp_session_push_msg(switch_msrp_session_t *ms, switch_msrp_msg_t *msg)
Definition: switch_msrp.c:426