Review Board 1.7.16


WebSocket SIP Support

Review Request #2008 - Created July 2, 2012 and submitted

Joshua Colp
websocket-sip
Reviewers
asterisk-dev
Asterisk
These changes add WebSocket transport support to chan_sip and fix some minor issues uncovered in the stack when used with WebSocket as a transport.
Tested using sipml5 javascript SIP stack. Confirmed protocol traffic is correct, that connections are shutdown properly when they should be, that registration works, and that calling works.
/trunk/channels/chan_sip.c
Diff Revision 2 Diff Revision 4
[20] 7300 lines
[+20] [+] static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
7301
			ast_aoc_destroy_decoded(decoded);
7301
			ast_aoc_destroy_decoded(decoded);
7302
		}
7302
		}
7303
		break;
7303
		break;
7304
	case AST_CONTROL_UPDATE_RTP_PEER: /* Absorb this since it is handled by the bridge */
7304
	case AST_CONTROL_UPDATE_RTP_PEER: /* Absorb this since it is handled by the bridge */
7305
		break;
7305
		break;
7306
	case AST_CONTROL_FLASH: /* Absorb this since it is irrelevant to SIP. */
7306
	case AST_CONTROL_FLASH: /* We don't currently handle AST_CONTROL_FLASH here, but it is expected, so we don't need to warn either. */

    
   
7307
		res = -1;
7307
		break;
7308
		break;
7308
	case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
7309
	case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
7309
	case -1:
7310
	case -1:
7310
		res = -1;
7311
		res = -1;
7311
		break;
7312
		break;
[+20] [20] 2163 lines
[+20] [+] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9475
				/* Check number of ports offered for stream */
9476
				/* Check number of ports offered for stream */
9476
				if (numberofports > 1) {
9477
				if (numberofports > 1) {
9477
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9478
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9478
				}
9479
				}
9479

    
   
9480

   
9480
				if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9481
				if (!strcmp(protocol, "SAVPF") && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9482
					ast_log(LOG_WARNING, "Received SAVPF profle in audio offer but AVPF is not enabled: %s\n", m);

    
   
9483
					continue;

    
   
9484
				} else if (!strcmp(protocol, "SAVP") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9485
					ast_log(LOG_WARNING, "Received SAVP profile in audio offer but AVPF is enabled: %s\n", m);

    
   
9486
					continue;

    
   
9487
				} else if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9481
					secure_audio = 1;
9488
					secure_audio = 1;

    
   
9489
				} else if (!strcmp(protocol, "AVPF") && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9490
					ast_log(LOG_WARNING, "Received AVPF profile in audio offer but AVPF is not enabled: %s\n", m);

    
   
9491
					continue;

    
   
9492
				} else if (!strcmp(protocol, "AVP") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9493
					ast_log(LOG_WARNING, "Received AVP profile in audio offer but AVPF is enabled: %s\n", m);

    
   
9494
					continue;
9482
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9495
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9483
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9496
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9484
					continue;
9497
					continue;
9485
				}
9498
				}
9486

    
   
9499

   
[+20] [20] 48 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9535
				/* Check number of ports offered for stream */
9548
				/* Check number of ports offered for stream */
9536
				if (numberofports > 1) {
9549
				if (numberofports > 1) {
9537
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9550
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9538
				}
9551
				}
9539

    
   
9552

   
9540
				if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9553
				if (!strcmp(protocol, "SAVPF") && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9554
					ast_log(LOG_WARNING, "Received SAVPF profle in video offer but AVPF is not enabled: %s\n", m);

    
   
9555
					continue;

    
   
9556
				} else if (!strcmp(protocol, "SAVP") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9557
					ast_log(LOG_WARNING, "Received SAVP profile in video offer but AVPF is enabled: %s\n", m);

    
   
9558
					continue;

    
   
9559
				} else if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9541
					secure_video = 1;
9560
					secure_video = 1;

    
   
9561
				} else if (!strcmp(protocol, "AVPF") && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9562
					ast_log(LOG_WARNING, "Received AVPF profile in video offer but AVPF is not enabled: %s\n", m);

    
   
9563
					continue;

    
   
9564
				} else if (!strcmp(protocol, "AVP") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9565
					ast_log(LOG_WARNING, "Received AVP profile in video offer but AVPF is enabled: %s\n", m);

    
   
9566
					continue;
9542
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9567
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9543
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9568
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9544
					continue;
9569
					continue;
9545
				}
9570
				}
9546

    
   
9571

   
[+20] [20] 25 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9572
				goto process_sdp_cleanup;
9597
				goto process_sdp_cleanup;
9573
			}
9598
			}
9574
		}
9599
		}
9575
		/* Check for 'text' media offer */
9600
		/* Check for 'text' media offer */
9576
		else if (strncmp(m, "text ", 5) == 0) {
9601
		else if (strncmp(m, "text ", 5) == 0) {
9577
			if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
9602
			if ((sscanf(m, "text %30u/%30u RTP/%s %n", &x, &numberofports, protocol, &len) == 2 && len > 0) ||
9578
			    (sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
9603
			    (sscanf(m, "text %30u RTP/%s %n", &x, protocol, &len) == 1 && len > 0)) {
9579
				codecs = m + len;
9604
				codecs = m + len;
9580
				/* produce zero-port m-line since it may be needed later
9605
				/* produce zero-port m-line since it may be needed later
9581
				 * length is "m=text 0 RTP/AVP " + codecs + "\0" */
9606
				 * length is "m=text 0 RTP/" + protocol + " " + codecs + "\0" */
9582
				if (!(offer->decline_m_line = ast_malloc(17 + strlen(codecs) + 1))) {
9607
				if (!(offer->decline_m_line = ast_malloc(13 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9583
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9608
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9584
					res = -1;
9609
					res = -1;
9585
					goto process_sdp_cleanup;
9610
					goto process_sdp_cleanup;
9586
				}
9611
				}
9587
				/* guaranteed to be exactly the right length */
9612
				/* guaranteed to be exactly the right length */
9588
				sprintf(offer->decline_m_line, "m=text 0 RTP/AVP %s", codecs);
9613
				sprintf(offer->decline_m_line, "m=text 0 RTP/%s %s", protocol, codecs);
9589

    
   
9614

   
9590
				if (x == 0) {
9615
				if (x == 0) {
9591
					ast_log(LOG_WARNING, "Ignoring text stream offer because port number is zero\n");
9616
					ast_log(LOG_WARNING, "Ignoring text stream offer because port number is zero\n");
9592
					continue;
9617
					continue;
9593
				}
9618
				}
9594

    
   
9619

   
9595
				/* Check number of ports offered for stream */
9620
				/* Check number of ports offered for stream */
9596
				if (numberofports > 1) {
9621
				if (numberofports > 1) {
9597
					ast_log(LOG_WARNING, "%d ports offered for text stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9622
					ast_log(LOG_WARNING, "%d ports offered for text stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9598
				}
9623
				}
9599

    
   
9624

   

    
   
9625
				if (!strcmp(protocol, "AVPF") && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9626
					ast_log(LOG_WARNING, "Received AVPF profile in text offer but AVPF is not enabled: %s\n", m);

    
   
9627
					continue;

    
   
9628
				} else if (!strcmp(protocol, "AVP") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
9629
					ast_log(LOG_WARNING, "Received AVP profile in text offer but AVPF is enabled: %s\n", m);

    
   
9630
					continue;

    
   
9631
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {

    
   
9632
					ast_log(LOG_WARNING, "Unknown RTP profile in text offer: %s\n", m);

    
   
9633
					continue;

    
   
9634
				}

    
   
9635

   
9600
				if (has_media_stream(p, SDP_TEXT)) {
9636
				if (has_media_stream(p, SDP_TEXT)) {
9601
					ast_log(LOG_WARNING, "Declining non-primary text stream: %s\n", m);
9637
					ast_log(LOG_WARNING, "Declining non-primary text stream: %s\n", m);
9602
					continue;
9638
					continue;
9603
				}
9639
				}
9604

    
   
9640

   
[+20] [20] 7873 lines
[+20] [+] static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
17478
	struct ast_msg *msg;
17514
	struct ast_msg *msg;
17479
	int res;
17515
	int res;
17480
	char *from;
17516
	char *from;
17481
	char *to;
17517
	char *to;
17482
	char from_name[50];
17518
	char from_name[50];

    
   
17519
	char stripped[SIPBUFSIZE];
17483

    
   
17520

   
17484
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
17521
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
17485
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
17522
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
17486
		if (!p->owner) {
17523
		if (!p->owner) {
17487
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
17524
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
[+20] [20] 143 lines
[+20] static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
17631
	res |= ast_msg_set_var(msg, "SIP_RECVADDR", ast_sockaddr_stringify(&p->recv));
17668
	res |= ast_msg_set_var(msg, "SIP_RECVADDR", ast_sockaddr_stringify(&p->recv));
17632
	if (!ast_strlen_zero(p->peername)) {
17669
	if (!ast_strlen_zero(p->peername)) {
17633
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17670
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17634
	}
17671
	}
17635

    
   
17672

   

    
   
17673
	ast_copy_string(stripped, sip_get_header(req, "Contact"), sizeof(stripped));

    
   
17674
	res |= ast_msg_set_var(msg, "SIP_FULLCONTACT", get_in_brackets(stripped));

    
   
17675

   
17636
	res |= ast_msg_set_exten(msg, "%s", p->exten);
17676
	res |= ast_msg_set_exten(msg, "%s", p->exten);
17637
	res |= set_message_vars_from_req(msg, req);
17677
	res |= set_message_vars_from_req(msg, req);
17638

    
   
17678

   
17639
	if (res) {
17679
	if (res) {
17640
		ast_msg_destroy(msg);
17680
		ast_msg_destroy(msg);
[+20] [20] 7961 lines
[+20] [+] static int block_msg_header(const char *header_name)
25602
		"Contact",
25642
		"Contact",
25603
		"Call-ID",
25643
		"Call-ID",
25604
		"CSeq",
25644
		"CSeq",
25605
		"Allow",
25645
		"Allow",
25606
		"Content-Length",
25646
		"Content-Length",

    
   
25647
		"Request-URI",
25607
	};
25648
	};
25608

    
   
25649

   
25609
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25650
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25610
		if (!strcasecmp(header_name, hdr[idx])) {
25651
		if (!strcasecmp(header_name, hdr[idx])) {
25611
			/* Block addition of this header. */
25652
			/* Block addition of this header. */
[+20] [20] 17 lines
[+20] [+] static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from)
25629

    
   
25670

   
25630
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25671
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25631
		return -1;
25672
		return -1;
25632
	}
25673
	}
25633

    
   
25674

   

    
   
25675
        for (iter = ast_msg_var_iterator_init(msg);

    
   
25676
	     ast_msg_var_iterator_next(msg, iter, &var, &val);

    
   
25677
	     ast_msg_var_unref_current(iter)) {

    
   
25678
		if (!strcasecmp(var, "Request-URI")) {

    
   
25679
			ast_string_field_set(pvt, fullcontact, val);

    
   
25680
			ast_msg_var_unref_current(iter);

    
   
25681
			break;

    
   
25682
		}

    
   
25683
	}

    
   
25684
	ast_msg_var_iterator_destroy(iter);

    
   
25685

   
25634
	to_uri = ast_strdupa(to);
25686
	to_uri = ast_strdupa(to);
25635
	to_uri = get_in_brackets(to_uri);
25687
	to_uri = get_in_brackets(to_uri);
25636
	parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL);
25688
	parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL);
25637

    
   
25689

   
25638
	if (ast_strlen_zero(to_host)) {
25690
	if (ast_strlen_zero(to_host)) {
[+20] [20] 7251 lines
/trunk/channels/sip/sdp_crypto.c
Diff Revision 2 Diff Revision 4
 
/trunk/channels/sip/security_events.c
Diff Revision 2 Diff Revision 4
 
/trunk/channels/sip/include/sip.h
Diff Revision 2 Diff Revision 4
 
/trunk/configs/sip.conf.sample
Diff Revision 2 Diff Revision 4
 
/trunk/include/asterisk/http_websocket.h
Diff Revision 2 Diff Revision 4
 
/trunk/res/res_http_websocket.c
Diff Revision 2 Diff Revision 4
 
  1. /trunk/channels/chan_sip.c: Loading...
  2. /trunk/channels/sip/sdp_crypto.c: Loading...
  3. /trunk/channels/sip/security_events.c: Loading...
  4. /trunk/channels/sip/include/sip.h: Loading...
  5. /trunk/configs/sip.conf.sample: Loading...
  6. /trunk/include/asterisk/http_websocket.h: Loading...
  7. /trunk/res/res_http_websocket.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.