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.

Diff revision 1

This is not the most recent revision of the diff. The latest diff is revision 4. See what's changed.

1 2 3 4
1 2 3 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...
/trunk/channels/chan_sip.c
Revision 369517 New Change
[20] 2520 lines
[+20] [+] static void *sip_tcp_worker_fn(void *data)
2521
	struct ast_tcptls_session_instance *tcptls_session = data;
2521
	struct ast_tcptls_session_instance *tcptls_session = data;
2522

    
   
2522

   
2523
	return _sip_tcp_helper_thread(tcptls_session);
2523
	return _sip_tcp_helper_thread(tcptls_session);
2524
}
2524
}
2525

    
   
2525

   

    
   
2526
/*! \brief SIP WebSocket connection handler */

    
   
2527
static void sip_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)

    
   
2528
{

    
   
2529
	int flags, res;

    
   
2530

   

    
   
2531
	if ((flags = fcntl(ast_websocket_fd(session), F_GETFL)) == -1) {

    
   
2532
		goto end;

    
   
2533
	}

    
   
2534

   

    
   
2535
	flags |= O_NONBLOCK;

    
   
2536

   

    
   
2537
	if (fcntl(ast_websocket_fd(session), F_SETFL, flags) == -1) {

    
   
2538
		goto end;

    
   
2539
	}

    
   
2540

   

    
   
2541
	while ((res = ast_wait_for_input(ast_websocket_fd(session), -1)) > 0) {

    
   
2542
		char *payload;

    
   
2543
		uint64_t payload_len;

    
   
2544
		enum ast_websocket_opcode opcode;

    
   
2545
		int fragmented;

    
   
2546

   

    
   
2547
		if (ast_websocket_read(session, &payload, &payload_len, &opcode, &fragmented)) {

    
   
2548
			/* We err on the side of caution and terminate the session if any error occurs */

    
   
2549
			break;

    
   
2550
		}

    
   
2551

   

    
   
2552
		if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {

    
   
2553
			struct sip_request req = { 0, };

    
   
2554

   

    
   
2555
			if (!(req.data = ast_str_create(payload_len))) {

    
   
2556
				goto end;

    
   
2557
			}

    
   
2558

   

    
   
2559
			if (ast_str_set(&req.data, -1, "%s", payload) == AST_DYNSTR_BUILD_FAILED) {

    
   
2560
				goto end;

    
   
2561
			}

    
   
2562

   

    
   
2563
			req.socket.fd = ast_websocket_fd(session);

    
   
2564
			set_socket_transport(&req.socket, ast_websocket_is_secure(session) ? SIP_TRANSPORT_WSS : SIP_TRANSPORT_WS);

    
   
2565
			req.socket.ws_session = session;

    
   
2566

   

    
   
2567
			handle_request_do(&req, ast_websocket_remote_address(session));

    
   
2568
			deinit_req(&req);

    
   
2569

   

    
   
2570
		} else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {

    
   
2571
			break;

    
   
2572
		}

    
   
2573
	}

    
   
2574

   

    
   
2575
end:

    
   
2576
	ast_websocket_unref(session);

    
   
2577
}

    
   
2578

   
2526
/*! \brief Check if the authtimeout has expired.
2579
/*! \brief Check if the authtimeout has expired.
2527
 * \param start the time when the session started
2580
 * \param start the time when the session started
2528
 *
2581
 *
2529
 * \retval 0 the timeout has expired
2582
 * \retval 0 the timeout has expired
2530
 * \retval -1 error
2583
 * \retval -1 error
[+20] [20] 265 lines
[+20] [+] static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_session)
2796
			}
2849
			}
2797
			/*! \todo XXX If there's no Content-Length or if the content-length and what
2850
			/*! \todo XXX If there's no Content-Length or if the content-length and what
2798
					we receive is not the same - we should generate an error */
2851
					we receive is not the same - we should generate an error */
2799

    
   
2852

   
2800
			req.socket.tcptls_session = tcptls_session;
2853
			req.socket.tcptls_session = tcptls_session;

    
   
2854
			req.socket.ws_session = NULL;
2801
			handle_request_do(&req, &tcptls_session->remote_address);
2855
			handle_request_do(&req, &tcptls_session->remote_address);
2802
		}
2856
		}
2803

    
   
2857

   
2804
		if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */
2858
		if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */
2805
			enum sip_tcptls_alert alert;
2859
			enum sip_tcptls_alert alert;
[+20] [20] 496 lines
[+20] [+] static int get_transport_str2enum(const char *transport)
3302
		res |= SIP_TRANSPORT_TCP;
3356
		res |= SIP_TRANSPORT_TCP;
3303
	}
3357
	}
3304
	if (!strcasecmp(transport, "tls")) {
3358
	if (!strcasecmp(transport, "tls")) {
3305
		res |= SIP_TRANSPORT_TLS;
3359
		res |= SIP_TRANSPORT_TLS;
3306
	}
3360
	}

    
   
3361
	if (!strcasecmp(transport, "ws")) {

    
   
3362
		res |= SIP_TRANSPORT_WS;

    
   
3363
	}

    
   
3364
	if (!strcasecmp(transport, "wss")) {

    
   
3365
		res |= SIP_TRANSPORT_WSS;

    
   
3366
	}
3307

    
   
3367

   
3308
	return res;
3368
	return res;
3309
}
3369
}
3310

    
   
3370

   
3311
/*! \brief Return configuration of transports for a device */
3371
/*! \brief Return configuration of transports for a device */
3312
static inline const char *get_transport_list(unsigned int transports) {
3372
static inline const char *get_transport_list(unsigned int transports) {
3313
	switch (transports) {
3373
	switch (transports) {
3314
		case SIP_TRANSPORT_UDP:
3374
	case SIP_TRANSPORT_UDP:
3315
			return "UDP";
3375
		return "UDP";
3316
		case SIP_TRANSPORT_TCP:
3376
	case SIP_TRANSPORT_TCP:
3317
			return "TCP";
3377
		return "TCP";
3318
		case SIP_TRANSPORT_TLS:
3378
	case SIP_TRANSPORT_TLS:
3319
			return "TLS";
3379
		return "TLS";

    
   
3380
	case SIP_TRANSPORT_WS:

    
   
3381
		return "WS";

    
   
3382
	case SIP_TRANSPORT_WSS:

    
   
3383
		return "WSS";

    
   
3384
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_WS:

    
   
3385
		return "WS,UDP";

    
   
3386
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_WSS:

    
   
3387
		return "WSS,UDP";

    
   
3388
	case SIP_TRANSPORT_WS | SIP_TRANSPORT_WSS:

    
   
3389
		return "WSS,WS";
3320
		case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP:
3390
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP:
3321
			return "TCP,UDP";
3391
		return "TCP,UDP";
3322
		case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS:
3392
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS:
3323
			return "TLS,UDP";
3393
		return "TLS,UDP";
3324
		case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS:
3394
	case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS:
3325
			return "TLS,TCP";
3395
		return "TLS,TCP";
3326
		default:
3396
	default:
3327
			return transports ?
3397
		return transports ?
3328
				"TLS,TCP,UDP" : "UNKNOWN";	
3398
			"TLS,TCP,UDP,WS,WSS" : "UNKNOWN";	
3329
	}
3399
	}
3330
}
3400
}
3331

    
   
3401

   
3332
/*! \brief Return transport as string */
3402
/*! \brief Return transport as string */
3333
const char *sip_get_transport(enum sip_transport t)
3403
const char *sip_get_transport(enum sip_transport t)
3334
{
3404
{
3335
	switch (t) {
3405
	switch (t) {
3336
	case SIP_TRANSPORT_UDP:
3406
	case SIP_TRANSPORT_UDP:
3337
		return "UDP";
3407
		return "UDP";
3338
	case SIP_TRANSPORT_TCP:
3408
	case SIP_TRANSPORT_TCP:
3339
		return "TCP";
3409
		return "TCP";
3340
	case SIP_TRANSPORT_TLS:
3410
	case SIP_TRANSPORT_TLS:
3341
		return "TLS";
3411
		return "TLS";

    
   
3412
	case SIP_TRANSPORT_WS:

    
   
3413
	case SIP_TRANSPORT_WSS:

    
   
3414
		return "WS";
3342
	}
3415
	}
3343

    
   
3416

   
3344
	return "UNKNOWN";
3417
	return "UNKNOWN";
3345
}
3418
}
3346

    
   
3419

   
3347
/*! \brief Return protocol string for srv dns query */
3420
/*! \brief Return protocol string for srv dns query */
3348
static inline const char *get_srv_protocol(enum sip_transport t)
3421
static inline const char *get_srv_protocol(enum sip_transport t)
3349
{
3422
{
3350
	switch (t) {
3423
	switch (t) {
3351
	case SIP_TRANSPORT_UDP:
3424
	case SIP_TRANSPORT_UDP:
3352
		return "udp";
3425
		return "udp";

    
   
3426
	case SIP_TRANSPORT_WS:

    
   
3427
		return "ws";
3353
	case SIP_TRANSPORT_TLS:
3428
	case SIP_TRANSPORT_TLS:
3354
	case SIP_TRANSPORT_TCP:
3429
	case SIP_TRANSPORT_TCP:
3355
		return "tcp";
3430
		return "tcp";

    
   
3431
	case SIP_TRANSPORT_WSS:

    
   
3432
		return "wss";
3356
	}
3433
	}
3357

    
   
3434

   
3358
	return "udp";
3435
	return "udp";
3359
}
3436
}
3360

    
   
3437

   
3361
/*! \brief Return service string for srv dns query */
3438
/*! \brief Return service string for srv dns query */
3362
static inline const char *get_srv_service(enum sip_transport t)
3439
static inline const char *get_srv_service(enum sip_transport t)
3363
{
3440
{
3364
	switch (t) {
3441
	switch (t) {
3365
	case SIP_TRANSPORT_TCP:
3442
	case SIP_TRANSPORT_TCP:
3366
	case SIP_TRANSPORT_UDP:
3443
	case SIP_TRANSPORT_UDP:

    
   
3444
	case SIP_TRANSPORT_WS:
3367
		return "sip";
3445
		return "sip";
3368
	case SIP_TRANSPORT_TLS:
3446
	case SIP_TRANSPORT_TLS:

    
   
3447
	case SIP_TRANSPORT_WSS:
3369
		return "sips";
3448
		return "sips";
3370
	}
3449
	}
3371
	return "sip";
3450
	return "sip";
3372
}
3451
}
3373

    
   
3452

   
[+20] [20] 36 lines
[+20] [+] static int __sip_xmit(struct sip_pvt *p, struct ast_str *data)
3410

    
   
3489

   
3411
	if (p->socket.type == SIP_TRANSPORT_UDP) {
3490
	if (p->socket.type == SIP_TRANSPORT_UDP) {
3412
		res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst);
3491
		res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst);
3413
	} else if (p->socket.tcptls_session) {
3492
	} else if (p->socket.tcptls_session) {
3414
		res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data));
3493
		res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data));

    
   
3494
	} else if (p->socket.ws_session) {

    
   
3495
		if (!(res = ast_websocket_write(p->socket.ws_session, AST_WEBSOCKET_OPCODE_TEXT, data->str, ast_str_strlen(data)))) {

    
   
3496
			/* The WebSocket API just returns 0 on success and -1 on failure, while this code expects the payload length to be returned */

    
   
3497
			res = ast_str_strlen(data);

    
   
3498
		}
3415
	} else {
3499
	} else {
3416
		ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
3500
		ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
3417
		return XMIT_ERROR;
3501
		return XMIT_ERROR;
3418
	}
3502
	}
3419

    
   
3503

   
[+20] [20] 1306 lines
[+20] [+] static void sip_destroy_peer(struct sip_peer *peer)
4726
	}
4810
	}
4727

    
   
4811

   
4728
	if (peer->socket.tcptls_session) {
4812
	if (peer->socket.tcptls_session) {
4729
		ao2_ref(peer->socket.tcptls_session, -1);
4813
		ao2_ref(peer->socket.tcptls_session, -1);
4730
		peer->socket.tcptls_session = NULL;
4814
		peer->socket.tcptls_session = NULL;

    
   
4815
	} else if (peer->socket.ws_session) {

    
   
4816
		ast_websocket_unref(peer->socket.ws_session);

    
   
4817
		peer->socket.ws_session = NULL;
4731
	}
4818
	}
4732

    
   
4819

   
4733
	ast_cc_config_params_destroy(peer->cc_params);
4820
	ast_cc_config_params_destroy(peer->cc_params);
4734

    
   
4821

   
4735
	ast_string_field_free_memory(peer);
4822
	ast_string_field_free_memory(peer);
[+20] [20] 558 lines
[+20] [+] static void set_t38_capabilities(struct sip_pvt *p)
5294
static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket *from_sock)
5381
static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket *from_sock)
5295
{
5382
{
5296
	if (to_sock->tcptls_session) {
5383
	if (to_sock->tcptls_session) {
5297
		ao2_ref(to_sock->tcptls_session, -1);
5384
		ao2_ref(to_sock->tcptls_session, -1);
5298
		to_sock->tcptls_session = NULL;
5385
		to_sock->tcptls_session = NULL;

    
   
5386
	} else if (to_sock->ws_session) {

    
   
5387
		ast_websocket_unref(to_sock->ws_session);

    
   
5388
		to_sock->ws_session = NULL;
5299
	}
5389
	}
5300

    
   
5390

   
5301
	if (from_sock->tcptls_session) {
5391
	if (from_sock->tcptls_session) {
5302
		ao2_ref(from_sock->tcptls_session, +1);
5392
		ao2_ref(from_sock->tcptls_session, +1);

    
   
5393
	} else if (from_sock->ws_session) {

    
   
5394
		ast_websocket_ref(from_sock->ws_session);
5303
	}
5395
	}
5304

    
   
5396

   
5305
	*to_sock = *from_sock;
5397
	*to_sock = *from_sock;
5306
}
5398
}
5307

    
   
5399

   
[+20] [20] 699 lines
[+20] [+] void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
6007
	}
6099
	}
6008

    
   
6100

   
6009
	if (p->socket.tcptls_session) {
6101
	if (p->socket.tcptls_session) {
6010
		ao2_ref(p->socket.tcptls_session, -1);
6102
		ao2_ref(p->socket.tcptls_session, -1);
6011
		p->socket.tcptls_session = NULL;
6103
		p->socket.tcptls_session = NULL;

    
   
6104
	} else if (p->socket.ws_session) {

    
   
6105
		ast_websocket_unref(p->socket.ws_session);

    
   
6106
		p->socket.ws_session = NULL;
6012
	}
6107
	}
6013

    
   
6108

   
6014
	if (p->peerauth) {
6109
	if (p->peerauth) {
6015
		ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
6110
		ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
6016
		p->peerauth = NULL;
6111
		p->peerauth = NULL;
[+20] [20] 3285 lines
[+20] [+] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9302
		int audio = FALSE;
9397
		int audio = FALSE;
9303
		int video = FALSE;
9398
		int video = FALSE;
9304
		int image = FALSE;
9399
		int image = FALSE;
9305
		int text = FALSE;
9400
		int text = FALSE;
9306
		int processed_crypto = FALSE;
9401
		int processed_crypto = FALSE;
9307
		char protocol[5] = {0,};
9402
		char protocol[6] = {0,};
9308
		int x;
9403
		int x;
9309

    
   
9404

   
9310
		numberofports = 0;
9405
		numberofports = 0;
9311
		len = -1;
9406
		len = -1;
9312
		start = next;
9407
		start = next;
[+20] [20] 9 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9322
		AST_LIST_INSERT_TAIL(&p->offered_media, offer, next);
9417
		AST_LIST_INSERT_TAIL(&p->offered_media, offer, next);
9323
		offer->type = SDP_UNKNOWN;
9418
		offer->type = SDP_UNKNOWN;
9324

    
   
9419

   
9325
		/* Check for 'audio' media offer */
9420
		/* Check for 'audio' media offer */
9326
		if (strncmp(m, "audio ", 6) == 0) {
9421
		if (strncmp(m, "audio ", 6) == 0) {
9327
			if ((sscanf(m, "audio %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9422
			if ((sscanf(m, "audio %30u/%30u RTP/%5s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9328
			    (sscanf(m, "audio %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) {
9423
			    (sscanf(m, "audio %30u RTP/%5s %n", &x, protocol, &len) == 2 && len > 0)) {
9329
				codecs = m + len;
9424
				codecs = m + len;
9330
				/* produce zero-port m-line since it may be needed later
9425
				/* produce zero-port m-line since it may be needed later
9331
				 * length is "m=audio 0 RTP/" + protocol + " " + codecs + "\0" */
9426
				 * length is "m=audio 0 RTP/" + protocol + " " + codecs + "\0" */
9332
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9427
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9333
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9428
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
[+20] [20] 11 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9345
				/* Check number of ports offered for stream */
9440
				/* Check number of ports offered for stream */
9346
				if (numberofports > 1) {
9441
				if (numberofports > 1) {
9347
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9442
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9348
				}
9443
				}
9349

    
   
9444

   
9350
				if (!strcmp(protocol, "SAVP")) {
9445
				if (!strncmp(protocol, "SAVP", 4)) {
9351
					secure_audio = 1;
9446
					secure_audio = 1;
9352
				} else if (strcmp(protocol, "AVP")) {
9447
				} else if (strncmp(protocol, "AVP", 3)) {
9353
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9448
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9354
					continue;
9449
					continue;
9355
				}
9450
				}
9356

    
   
9451

   
9357
				if (has_media_stream(p, SDP_AUDIO)) {
9452
				if (has_media_stream(p, SDP_AUDIO)) {
[+20] [20] 24 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9382
				goto process_sdp_cleanup;
9477
				goto process_sdp_cleanup;
9383
			}
9478
			}
9384
		}
9479
		}
9385
		/* Check for 'video' media offer */
9480
		/* Check for 'video' media offer */
9386
		else if (strncmp(m, "video ", 6) == 0) {
9481
		else if (strncmp(m, "video ", 6) == 0) {
9387
			if ((sscanf(m, "video %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9482
			if ((sscanf(m, "video %30u/%30u RTP/%5s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9388
			    (sscanf(m, "video %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) {
9483
			    (sscanf(m, "video %30u RTP/%5s %n", &x, protocol, &len) == 2 && len > 0)) {
9389
				codecs = m + len;
9484
				codecs = m + len;
9390
				/* produce zero-port m-line since it may be needed later
9485
				/* produce zero-port m-line since it may be needed later
9391
				 * length is "m=video 0 RTP/" + protocol + " " + codecs + "\0" */
9486
				 * length is "m=video 0 RTP/" + protocol + " " + codecs + "\0" */
9392
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9487
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9393
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9488
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
[+20] [20] 11 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9405
				/* Check number of ports offered for stream */
9500
				/* Check number of ports offered for stream */
9406
				if (numberofports > 1) {
9501
				if (numberofports > 1) {
9407
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9502
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9408
				}
9503
				}
9409

    
   
9504

   
9410
				if (!strcmp(protocol, "SAVP")) {
9505
				if (!strncmp(protocol, "SAVP", 4)) {
9411
					secure_video = 1;
9506
					secure_video = 1;
9412
				} else if (strcmp(protocol, "AVP")) {
9507
				} else if (strncmp(protocol, "AVP", 3)) {
9413
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9508
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9414
					continue;
9509
					continue;
9415
				}
9510
				}
9416

    
   
9511

   
9417
				if (has_media_stream(p, SDP_VIDEO)) {
9512
				if (has_media_stream(p, SDP_VIDEO)) {
[+20] [20] 1241 lines
[+20] [+] static void add_route(struct sip_request *req, struct sip_route *route)
10659
 *
10754
 *
10660
 * If there's a sips: uri scheme, TLS will be required.
10755
 * If there's a sips: uri scheme, TLS will be required.
10661
 */
10756
 */
10662
static void set_destination(struct sip_pvt *p, char *uri)
10757
static void set_destination(struct sip_pvt *p, char *uri)
10663
{
10758
{
10664
	char *h, *maddr, hostname[256];
10759
	char *trans, *h, *maddr, hostname[256];
10665
	int hn;
10760
	int hn;
10666
	int debug=sip_debug_test_pvt(p);
10761
	int debug=sip_debug_test_pvt(p);
10667
	int tls_on = FALSE;
10762
	int tls_on = FALSE;
10668

    
   
10763

   
10669
	if (debug)
10764
	if (debug)
10670
		ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
10765
		ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
10671

    
   
10766

   

    
   
10767
	if ((trans = strcasestr(uri, ";transport="))) {

    
   
10768
		trans += 11;

    
   
10769

   

    
   
10770
		if (!strncasecmp(trans, "ws", 2)) {

    
   
10771
			if (debug)

    
   
10772
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");

    
   
10773
			return;

    
   
10774
		}

    
   
10775
	}

    
   
10776

   
10672
	/* Find and parse hostname */
10777
	/* Find and parse hostname */
10673
	h = strchr(uri, '@');
10778
	h = strchr(uri, '@');
10674
	if (h)
10779
	if (h)
10675
		++h;
10780
		++h;
10676
	else {
10781
	else {
[+20] [20] 1330 lines
[+20] [+] static void get_crypto_attrib(struct sip_pvt *p, struct sip_srtp *srtp, const char **a_crypto)
12007
			ast_log(LOG_WARNING, "No SRTP key management enabled\n");
12112
			ast_log(LOG_WARNING, "No SRTP key management enabled\n");
12008
		}
12113
		}
12009
	}
12114
	}
12010
}
12115
}
12011

    
   
12116

   

    
   
12117
static char *get_sdp_rtp_profile(const struct sip_pvt *p, unsigned int secure)

    
   
12118
{

    
   
12119
	if (ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

    
   
12120
		return secure ? "SAVPF" : "AVPF";

    
   
12121
	} else {

    
   
12122
		return secure ? "SAVP" : "AVP";

    
   
12123
	}

    
   
12124
}

    
   
12125

   
12012
/*! \brief Add Session Description Protocol message
12126
/*! \brief Add Session Description Protocol message
12013

    
   
12127

   
12014
    If oldsdp is TRUE, then the SDP version number is not incremented. This mechanism
12128
    If oldsdp is TRUE, then the SDP version number is not incremented. This mechanism
12015
    is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions
12129
    is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions
12016
    without modifying the media session in any way.
12130
    without modifying the media session in any way.
[+20] [20] 150 lines
[+20] [+] static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
12167
		/* Ok, we need video. Let's add what we need for video and set codecs.
12281
		/* Ok, we need video. Let's add what we need for video and set codecs.
12168
		   Video is handled differently than audio since we can not transcode. */
12282
		   Video is handled differently than audio since we can not transcode. */
12169
		if (needvideo) {
12283
		if (needvideo) {
12170
			get_crypto_attrib(p, p->vsrtp, &v_a_crypto);
12284
			get_crypto_attrib(p, p->vsrtp, &v_a_crypto);
12171
			ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest),
12285
			ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest),
12172
				v_a_crypto ? "SAVP" : "AVP");
12286
				       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12173

    
   
12287

   
12174
			/* Build max bitrate string */
12288
			/* Build max bitrate string */
12175
			if (p->maxcallbitrate)
12289
			if (p->maxcallbitrate)
12176
				snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
12290
				snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
12177
			if (debug) {
12291
			if (debug) {
[+20] [20] 10 lines
[+20] static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
12188
		if (needtext) {
12302
		if (needtext) {
12189
			if (sipdebug_text)
12303
			if (sipdebug_text)
12190
				ast_verbose("Lets set up the text sdp\n");
12304
				ast_verbose("Lets set up the text sdp\n");
12191
			get_crypto_attrib(p, p->tsrtp, &t_a_crypto);
12305
			get_crypto_attrib(p, p->tsrtp, &t_a_crypto);
12192
			ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest),
12306
			ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest),
12193
				t_a_crypto ? "SAVP" : "AVP");
12307
				       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12194
			if (debug) {  /* XXX should I use tdest below ? */
12308
			if (debug) {  /* XXX should I use tdest below ? */
12195
				ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr));
12309
				ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr));
12196
			}
12310
			}
12197

    
   
12311

   
12198
			if (!doing_directmedia) {
12312
			if (!doing_directmedia) {
[+20] [20] 6 lines
[+20] static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
12205
		/* We break with the "recommendation" and send our IP, in order that our
12319
		/* We break with the "recommendation" and send our IP, in order that our
12206
		   peer doesn't have to ast_gethostbyname() us */
12320
		   peer doesn't have to ast_gethostbyname() us */
12207

    
   
12321

   
12208
		get_crypto_attrib(p, p->srtp, &a_crypto);
12322
		get_crypto_attrib(p, p->srtp, &a_crypto);
12209
		ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest),
12323
		ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest),
12210
			a_crypto ? "SAVP" : "AVP");
12324
			       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12211

    
   
12325

   
12212
		/* Now, start adding audio codecs. These are added in this order:
12326
		/* Now, start adding audio codecs. These are added in this order:
12213
		   - First what was requested by the calling channel
12327
		   - First what was requested by the calling channel
12214
		   - Then preferences in order from sip.conf device config for this peer/user
12328
		   - Then preferences in order from sip.conf device config for this peer/user
12215
		   - Then other codecs in capabilities, including video
12329
		   - Then other codecs in capabilities, including video
[+20] [20] 2402 lines
[+20] [+] static void set_socket_transport(struct sip_socket *socket, int transport)
14618
		socket->fd = -1;
14732
		socket->fd = -1;
14619
		socket->type = transport;
14733
		socket->type = transport;
14620
		if (socket->tcptls_session) {
14734
		if (socket->tcptls_session) {
14621
			ao2_ref(socket->tcptls_session, -1);
14735
			ao2_ref(socket->tcptls_session, -1);
14622
			socket->tcptls_session = NULL;
14736
			socket->tcptls_session = NULL;

    
   
14737
		} else if (socket->ws_session) {

    
   
14738
			ast_websocket_unref(socket->ws_session);

    
   
14739
			socket->ws_session = NULL;
14623
		}
14740
		}
14624
	}
14741
	}
14625
}
14742
}
14626

    
   
14743

   
14627
/*! \brief Expire registration of SIP peer */
14744
/*! \brief Expire registration of SIP peer */
[+20] [20] 12 lines
[+20] [+] static int expire_register(const void *data)
14640
	set_socket_transport(&peer->socket, peer->default_outbound_transport);
14757
	set_socket_transport(&peer->socket, peer->default_outbound_transport);
14641

    
   
14758

   
14642
	if (peer->socket.tcptls_session) {
14759
	if (peer->socket.tcptls_session) {
14643
		ao2_ref(peer->socket.tcptls_session, -1);
14760
		ao2_ref(peer->socket.tcptls_session, -1);
14644
		peer->socket.tcptls_session = NULL;
14761
		peer->socket.tcptls_session = NULL;

    
   
14762
	} else if (peer->socket.ws_session) {

    
   
14763
		ast_websocket_unref(peer->socket.ws_session);

    
   
14764
		peer->socket.ws_session = NULL;
14645
	}
14765
	}
14646

    
   
14766

   
14647
	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
14767
	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
14648
	register_peer_exten(peer, FALSE);	/* Remove regexten */
14768
	register_peer_exten(peer, FALSE);	/* Remove regexten */
14649
	ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
14769
	ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
[+20] [20] 2154 lines
[+20] [+] static void check_via(struct sip_pvt *p, struct sip_request *req)
16804
	struct ast_sockaddr tmp = { { 0, } };
16924
	struct ast_sockaddr tmp = { { 0, } };
16805
	uint16_t port;
16925
	uint16_t port;
16806

    
   
16926

   
16807
	ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via));
16927
	ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via));
16808

    
   
16928

   

    
   
16929
	/* If this is via WebSocket we don't use the Via header contents at all */

    
   
16930
	if (!strncasecmp(via, "SIP/2.0/WS", 10)) {

    
   
16931
		return;

    
   
16932
	}

    
   
16933

   
16809
	/* Work on the leftmost value of the topmost Via header */
16934
	/* Work on the leftmost value of the topmost Via header */
16810
	c = strchr(via, ',');
16935
	c = strchr(via, ',');
16811
	if (c)
16936
	if (c)
16812
		*c = '\0';
16937
		*c = '\0';
16813

    
   
16938

   
[+20] [20] 4129 lines
[+20] [+] static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
20943
	contact_number = remove_uri_parameters(contact_number);
21068
	contact_number = remove_uri_parameters(contact_number);
20944

    
   
21069

   
20945
	if (p->socket.tcptls_session) {
21070
	if (p->socket.tcptls_session) {
20946
		ao2_ref(p->socket.tcptls_session, -1);
21071
		ao2_ref(p->socket.tcptls_session, -1);
20947
		p->socket.tcptls_session = NULL;
21072
		p->socket.tcptls_session = NULL;

    
   
21073
	} else if (p->socket.ws_session) {

    
   
21074
		ast_websocket_unref(p->socket.ws_session);

    
   
21075
		p->socket.ws_session = NULL;
20948
	}
21076
	}
20949

    
   
21077

   
20950
	set_socket_transport(&p->socket, transport);
21078
	set_socket_transport(&p->socket, transport);
20951

    
   
21079

   
20952
	if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
21080
	if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
[+20] [20] 5996 lines
[+20] [+] static int sipsock_read(int *id, int fd, short events, void *ignore)
26949
	}
27077
	}
26950

    
   
27078

   
26951
	req.socket.fd = sipsock;
27079
	req.socket.fd = sipsock;
26952
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27080
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
26953
	req.socket.tcptls_session	= NULL;
27081
	req.socket.tcptls_session	= NULL;

    
   
27082
	req.socket.ws_session = NULL;
26954
	req.socket.port = htons(ast_sockaddr_port(&bindaddr));
27083
	req.socket.port = htons(ast_sockaddr_port(&bindaddr));
26955

    
   
27084

   
26956
	handle_request_do(&req, &addr);
27085
	handle_request_do(&req, &addr);
26957
	deinit_req(&req);
27086
	deinit_req(&req);
26958

    
   
27087

   
[+20] [20] 176 lines
[+20] [+] static int sip_prepare_socket(struct sip_pvt *p)
27135
	if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) &&
27264
	if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) &&
27136
			(s->tcptls_session) &&
27265
			(s->tcptls_session) &&
27137
			(s->tcptls_session->fd != -1)) {
27266
			(s->tcptls_session->fd != -1)) {
27138
		return s->tcptls_session->fd;
27267
		return s->tcptls_session->fd;
27139
	}
27268
	}

    
   
27269
	if ((s->type & (SIP_TRANSPORT_WS | SIP_TRANSPORT_WSS))) {

    
   
27270
		return s->ws_session ? ast_websocket_fd(s->ws_session) : -1;

    
   
27271
	}
27140

    
   
27272

   
27141
	/*! \todo Check this... This might be wrong, depending on the proxy configuration
27273
	/*! \todo Check this... This might be wrong, depending on the proxy configuration
27142
		If proxy is in "force" mode its correct.
27274
		If proxy is in "force" mode its correct.
27143
	 */
27275
	 */
27144
	if (p->outboundproxy && p->outboundproxy->transport) {
27276
	if (p->outboundproxy && p->outboundproxy->transport) {
[+20] [20] 1964 lines
[+20] [+] static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
29109
				while ((trans = strsep(&val, ","))) {
29241
				while ((trans = strsep(&val, ","))) {
29110
					trans = ast_skip_blanks(trans);
29242
					trans = ast_skip_blanks(trans);
29111

    
   
29243

   
29112
					if (!strncasecmp(trans, "udp", 3)) {
29244
					if (!strncasecmp(trans, "udp", 3)) {
29113
						peer->transports |= SIP_TRANSPORT_UDP;
29245
						peer->transports |= SIP_TRANSPORT_UDP;

    
   
29246
					} else if (!strncasecmp(trans, "wss", 3)) {

    
   
29247
						peer->transports |= SIP_TRANSPORT_WSS;

    
   
29248
					} else if (!strncasecmp(trans, "ws", 2)) {

    
   
29249
						peer->transports |= SIP_TRANSPORT_WS;
29114
					} else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) {
29250
					} else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) {
29115
						peer->transports |= SIP_TRANSPORT_TCP;
29251
						peer->transports |= SIP_TRANSPORT_TCP;
29116
					} else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) {
29252
					} else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) {
29117
						peer->transports |= SIP_TRANSPORT_TLS;
29253
						peer->transports |= SIP_TRANSPORT_TLS;
29118
					} else if (!strncasecmp(trans, "tcp", 3) || !strncasecmp(trans, "tls", 3)) {
29254
					} else if (!strncasecmp(trans, "tcp", 3) || !strncasecmp(trans, "tls", 3)) {
[+20] [20] 340 lines
[+20] static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
29459
				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP);
29595
				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP);
29460
			} else if (!strcasecmp(v->name, "encryption_taglen")) {
29596
			} else if (!strcasecmp(v->name, "encryption_taglen")) {
29461
				ast_set2_flag(&peer->flags[2], !strcasecmp(v->value, "32"), SIP_PAGE3_SRTP_TAG_32);
29597
				ast_set2_flag(&peer->flags[2], !strcasecmp(v->value, "32"), SIP_PAGE3_SRTP_TAG_32);
29462
			} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
29598
			} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
29463
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
29599
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);

    
   
29600
			} else if (!strcasecmp(v->name, "avpf")) {

    
   
29601
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_USE_AVPF);
29464
			}
29602
			}
29465
		}
29603
		}
29466

    
   
29604

   
29467
		/* These apply to devstate lookups */
29605
		/* These apply to devstate lookups */
29468
		if (realtime && !strcasecmp(v->name, "lastms")) {
29606
		if (realtime && !strcasecmp(v->name, "lastms")) {
[+20] [20] 103 lines
[+20] static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
29572
	 * 1. Registration is not present and the socket.type and default transport types are different.
29710
	 * 1. Registration is not present and the socket.type and default transport types are different.
29573
	 * 2. The socket.type is not an acceptable transport type after rebuilding peer.
29711
	 * 2. The socket.type is not an acceptable transport type after rebuilding peer.
29574
	 * 3. The socket.type is not set yet. */
29712
	 * 3. The socket.type is not set yet. */
29575
	if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) ||
29713
	if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) ||
29576
		!(peer->socket.type & peer->transports) || !(peer->socket.type)) {
29714
		!(peer->socket.type & peer->transports) || !(peer->socket.type)) {
29577

    
   

   
29578
		set_socket_transport(&peer->socket, peer->default_outbound_transport);
29715
		set_socket_transport(&peer->socket, peer->default_outbound_transport);
29579
	}
29716
	}
29580

    
   
29717

   
29581
	if (ast_str_strlen(fullcontact)) {
29718
	if (ast_str_strlen(fullcontact)) {
29582
		ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
29719
		ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
[+20] [20] 521 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
30104
					default_transports |= SIP_TRANSPORT_UDP;
30241
					default_transports |= SIP_TRANSPORT_UDP;
30105
				} else if (!strncasecmp(trans, "tcp", 3)) {
30242
				} else if (!strncasecmp(trans, "tcp", 3)) {
30106
					default_transports |= SIP_TRANSPORT_TCP;
30243
					default_transports |= SIP_TRANSPORT_TCP;
30107
				} else if (!strncasecmp(trans, "tls", 3)) {
30244
				} else if (!strncasecmp(trans, "tls", 3)) {
30108
					default_transports |= SIP_TRANSPORT_TLS;
30245
					default_transports |= SIP_TRANSPORT_TLS;

    
   
30246
				} else if (!strncasecmp(trans, "wss", 3)) {

    
   
30247
					default_transports |= SIP_TRANSPORT_WSS;

    
   
30248
				} else if (!strncasecmp(trans, "ws", 2)) {

    
   
30249
					default_transports |= SIP_TRANSPORT_WS;
30109
				} else {
30250
				} else {
30110
					ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
30251
					ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
30111
				}
30252
				}
30112
				if (default_primary_transport == 0) {
30253
				if (default_primary_transport == 0) {
30113
					default_primary_transport = default_transports;
30254
					default_primary_transport = default_transports;
[+20] [20] 2394 lines
[+20] [+] static int load_module(void)
32508

    
   
32649

   
32509

    
   
32650

   
32510
	sip_register_tests();
32651
	sip_register_tests();
32511
	network_change_event_subscribe();
32652
	network_change_event_subscribe();
32512

    
   
32653

   

    
   
32654
	ast_websocket_add_protocol("sip", sip_websocket_callback);

    
   
32655

   
32513
	return AST_MODULE_LOAD_SUCCESS;
32656
	return AST_MODULE_LOAD_SUCCESS;
32514
}
32657
}
32515

    
   
32658

   
32516
/*! \brief PBX unload module API */
32659
/*! \brief PBX unload module API */
32517
static int unload_module(void)
32660
static int unload_module(void)
32518
{
32661
{
32519
	struct sip_pvt *p;
32662
	struct sip_pvt *p;
32520
	struct sip_threadinfo *th;
32663
	struct sip_threadinfo *th;
32521
	struct ast_context *con;
32664
	struct ast_context *con;
32522
	struct ao2_iterator i;
32665
	struct ao2_iterator i;
32523
	int wait_count;
32666
	int wait_count;
32524

    
   
32667

   

    
   
32668
	ast_websocket_remove_protocol("sip", sip_websocket_callback);

    
   
32669

   
32525
	network_change_event_unsubscribe();
32670
	network_change_event_unsubscribe();
32526

    
   
32671

   
32527
	ast_sched_dump(sched);
32672
	ast_sched_dump(sched);
32528
	
32673
	
32529
	/* First, take us out of the channel type list */
32674
	/* First, take us out of the channel type list */
[+20] [20] 173 lines
/trunk/channels/sip/sdp_crypto.c
Revision 369516 New Change
 
/trunk/channels/sip/security_events.c
Revision 369516 New Change
 
/trunk/channels/sip/include/sip.h
Revision 369516 New Change
 
/trunk/configs/sip.conf.sample
Revision 369516 New Change
 
  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...

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.