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
Revision 369847 New Change
[20] 1163 lines
[+20] [+] static struct ast_subscription_mwi_list {
1164
static void temp_pvt_cleanup(void *);
1164
static void temp_pvt_cleanup(void *);
1165

    
   
1165

   
1166
/*! \brief A per-thread temporary pvt structure */
1166
/*! \brief A per-thread temporary pvt structure */
1167
AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
1167
AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
1168

    
   
1168

   

    
   
1169
/*! \brief A per-thread buffer for transport to string conversion */

    
   
1170
AST_THREADSTORAGE(sip_transport_str_buf);

    
   
1171

   

    
   
1172
/*! \brief Size of the SIP transport buffer */

    
   
1173
#define SIP_TRANSPORT_STR_BUFSIZE 128

    
   
1174

   
1169
/*! \brief Authentication container for realm authentication */
1175
/*! \brief Authentication container for realm authentication */
1170
static struct sip_auth_container *authl = NULL;
1176
static struct sip_auth_container *authl = NULL;
1171
/*! \brief Global authentication container protection while adjusting the references. */
1177
/*! \brief Global authentication container protection while adjusting the references. */
1172
AST_MUTEX_DEFINE_STATIC(authl_lock);
1178
AST_MUTEX_DEFINE_STATIC(authl_lock);
1173

    
   
1179

   
[+20] [20] 1347 lines
[+20] [+] static void *sip_tcp_worker_fn(void *data)
2521
	struct ast_tcptls_session_instance *tcptls_session = data;
2527
	struct ast_tcptls_session_instance *tcptls_session = data;
2522

    
   
2528

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

    
   
2531

   

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

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

    
   
2534
{

    
   
2535
	int res;

    
   
2536

   

    
   
2537
	if (ast_websocket_set_nonblock(session)) {

    
   
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
				deinit_req(&req);

    
   
2561
				goto end;

    
   
2562
			}

    
   
2563

   

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

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

    
   
2566
			req.socket.ws_session = session;

    
   
2567

   

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

    
   
2569
			deinit_req(&req);

    
   
2570

   

    
   
2571
		} else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {

    
   
2572
			break;

    
   
2573
		}

    
   
2574
	}

    
   
2575

   

    
   
2576
end:

    
   
2577
	ast_websocket_unref(session);

    
   
2578
}

    
   
2579

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

    
   
2853

   
2800
			req.socket.tcptls_session = tcptls_session;
2854
			req.socket.tcptls_session = tcptls_session;

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

    
   
2858

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

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

    
   
3363
		res |= SIP_TRANSPORT_WS;

    
   
3364
	}

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

    
   
3366
		res |= SIP_TRANSPORT_WSS;

    
   
3367
	}
3307

    
   
3368

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

    
   
3371

   
3311
/*! \brief Return configuration of transports for a device */
3372
/*! \brief Return configuration of transports for a device */
3312
static inline const char *get_transport_list(unsigned int transports) {
3373
static inline const char *get_transport_list(unsigned int transports)
3313
	switch (transports) {
3374
{
3314
		case SIP_TRANSPORT_UDP:
3375
	char *buf;
3315
			return "UDP";
3376

   
3316
		case SIP_TRANSPORT_TCP:
3377
	if (!transports) {
3317
			return "TCP";
3378
		return "UNKNOWN";
3318
		case SIP_TRANSPORT_TLS:
3379
	}
3319
			return "TLS";
3380

   
3320
		case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP:
3381
	if (!(buf = ast_threadstorage_get(&sip_transport_str_buf, SIP_TRANSPORT_STR_BUFSIZE))) {
3321
			return "TCP,UDP";
3382
		return "";
3322
		case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS:
3383
	}
3323
			return "TLS,UDP";
3384

   
3324
		case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS:
3385
	memset(buf, 0, SIP_TRANSPORT_STR_BUFSIZE);
3325
			return "TLS,TCP";
3386

   
3326
		default:
3387
	if (transports & SIP_TRANSPORT_UDP) {
3327
			return transports ?
3388
		strncat(buf, "UDP,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3328
				"TLS,TCP,UDP" : "UNKNOWN";	
3389
	}

    
   
3390
	if (transports & SIP_TRANSPORT_TCP) {

    
   
3391
		strncat(buf, "TCP,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3329
	}
3392
	}

    
   
3393
	if (transports & SIP_TRANSPORT_TLS) {

    
   
3394
		strncat(buf, "TLS,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));

    
   
3395
	}

    
   
3396
	if (transports & SIP_TRANSPORT_WS) {

    
   
3397
		strncat(buf, "WS,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));

    
   
3398
	}

    
   
3399
	if (transports & SIP_TRANSPORT_WSS) {

    
   
3400
		strncat(buf, "WSS,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));

    
   
3401
	}

    
   
3402

   

    
   
3403
	/* Remove the trailing ',' if present */

    
   
3404
	if (strlen(buf)) {

    
   
3405
		buf[strlen(buf) - 1] = 0;

    
   
3406
	}

    
   
3407

   

    
   
3408
	return buf;
3330
}
3409
}
3331

    
   
3410

   
3332
/*! \brief Return transport as string */
3411
/*! \brief Return transport as string */
3333
const char *sip_get_transport(enum sip_transport t)
3412
const char *sip_get_transport(enum sip_transport t)
3334
{
3413
{
3335
	switch (t) {
3414
	switch (t) {
3336
	case SIP_TRANSPORT_UDP:
3415
	case SIP_TRANSPORT_UDP:
3337
		return "UDP";
3416
		return "UDP";
3338
	case SIP_TRANSPORT_TCP:
3417
	case SIP_TRANSPORT_TCP:
3339
		return "TCP";
3418
		return "TCP";
3340
	case SIP_TRANSPORT_TLS:
3419
	case SIP_TRANSPORT_TLS:
3341
		return "TLS";
3420
		return "TLS";

    
   
3421
	case SIP_TRANSPORT_WS:

    
   
3422
	case SIP_TRANSPORT_WSS:

    
   
3423
		return "WS";
3342
	}
3424
	}
3343

    
   
3425

   
3344
	return "UNKNOWN";
3426
	return "UNKNOWN";
3345
}
3427
}
3346

    
   
3428

   
3347
/*! \brief Return protocol string for srv dns query */
3429
/*! \brief Return protocol string for srv dns query */
3348
static inline const char *get_srv_protocol(enum sip_transport t)
3430
static inline const char *get_srv_protocol(enum sip_transport t)
3349
{
3431
{
3350
	switch (t) {
3432
	switch (t) {
3351
	case SIP_TRANSPORT_UDP:
3433
	case SIP_TRANSPORT_UDP:
3352
		return "udp";
3434
		return "udp";

    
   
3435
	case SIP_TRANSPORT_WS:

    
   
3436
		return "ws";
3353
	case SIP_TRANSPORT_TLS:
3437
	case SIP_TRANSPORT_TLS:
3354
	case SIP_TRANSPORT_TCP:
3438
	case SIP_TRANSPORT_TCP:
3355
		return "tcp";
3439
		return "tcp";

    
   
3440
	case SIP_TRANSPORT_WSS:

    
   
3441
		return "wss";
3356
	}
3442
	}
3357

    
   
3443

   
3358
	return "udp";
3444
	return "udp";
3359
}
3445
}
3360

    
   
3446

   
3361
/*! \brief Return service string for srv dns query */
3447
/*! \brief Return service string for srv dns query */
3362
static inline const char *get_srv_service(enum sip_transport t)
3448
static inline const char *get_srv_service(enum sip_transport t)
3363
{
3449
{
3364
	switch (t) {
3450
	switch (t) {
3365
	case SIP_TRANSPORT_TCP:
3451
	case SIP_TRANSPORT_TCP:
3366
	case SIP_TRANSPORT_UDP:
3452
	case SIP_TRANSPORT_UDP:

    
   
3453
	case SIP_TRANSPORT_WS:
3367
		return "sip";
3454
		return "sip";
3368
	case SIP_TRANSPORT_TLS:
3455
	case SIP_TRANSPORT_TLS:

    
   
3456
	case SIP_TRANSPORT_WSS:
3369
		return "sips";
3457
		return "sips";
3370
	}
3458
	}
3371
	return "sip";
3459
	return "sip";
3372
}
3460
}
3373

    
   
3461

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

    
   
3498

   
3411
	if (p->socket.type == SIP_TRANSPORT_UDP) {
3499
	if (p->socket.type == SIP_TRANSPORT_UDP) {
3412
		res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst);
3500
		res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst);
3413
	} else if (p->socket.tcptls_session) {
3501
	} else if (p->socket.tcptls_session) {
3414
		res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data));
3502
		res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data));

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

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

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

    
   
3506
			res = ast_str_strlen(data);

    
   
3507
		}
3415
	} else {
3508
	} else {
3416
		ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
3509
		ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
3417
		return XMIT_ERROR;
3510
		return XMIT_ERROR;
3418
	}
3511
	}
3419

    
   
3512

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

    
   
4820

   
4728
	if (peer->socket.tcptls_session) {
4821
	if (peer->socket.tcptls_session) {
4729
		ao2_ref(peer->socket.tcptls_session, -1);
4822
		ao2_ref(peer->socket.tcptls_session, -1);
4730
		peer->socket.tcptls_session = NULL;
4823
		peer->socket.tcptls_session = NULL;

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

    
   
4825
		ast_websocket_unref(peer->socket.ws_session);

    
   
4826
		peer->socket.ws_session = NULL;
4731
	}
4827
	}
4732

    
   
4828

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

    
   
4830

   
4735
	ast_string_field_free_memory(peer);
4831
	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)
5390
static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket *from_sock)
5295
{
5391
{
5296
	if (to_sock->tcptls_session) {
5392
	if (to_sock->tcptls_session) {
5297
		ao2_ref(to_sock->tcptls_session, -1);
5393
		ao2_ref(to_sock->tcptls_session, -1);
5298
		to_sock->tcptls_session = NULL;
5394
		to_sock->tcptls_session = NULL;

    
   
5395
	} else if (to_sock->ws_session) {

    
   
5396
		ast_websocket_unref(to_sock->ws_session);

    
   
5397
		to_sock->ws_session = NULL;
5299
	}
5398
	}
5300

    
   
5399

   
5301
	if (from_sock->tcptls_session) {
5400
	if (from_sock->tcptls_session) {
5302
		ao2_ref(from_sock->tcptls_session, +1);
5401
		ao2_ref(from_sock->tcptls_session, +1);

    
   
5402
	} else if (from_sock->ws_session) {

    
   
5403
		ast_websocket_ref(from_sock->ws_session);
5303
	}
5404
	}
5304

    
   
5405

   
5305
	*to_sock = *from_sock;
5406
	*to_sock = *from_sock;
5306
}
5407
}
5307

    
   
5408

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

    
   
6109

   
6009
	if (p->socket.tcptls_session) {
6110
	if (p->socket.tcptls_session) {
6010
		ao2_ref(p->socket.tcptls_session, -1);
6111
		ao2_ref(p->socket.tcptls_session, -1);
6011
		p->socket.tcptls_session = NULL;
6112
		p->socket.tcptls_session = NULL;

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

    
   
6114
		ast_websocket_unref(p->socket.ws_session);

    
   
6115
		p->socket.ws_session = NULL;
6012
	}
6116
	}
6013

    
   
6117

   
6014
	if (p->peerauth) {
6118
	if (p->peerauth) {
6015
		ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
6119
		ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
6016
		p->peerauth = NULL;
6120
		p->peerauth = NULL;
[+20] [20] 3312 lines
[+20] [+] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9329
		int audio = FALSE;
9433
		int audio = FALSE;
9330
		int video = FALSE;
9434
		int video = FALSE;
9331
		int image = FALSE;
9435
		int image = FALSE;
9332
		int text = FALSE;
9436
		int text = FALSE;
9333
		int processed_crypto = FALSE;
9437
		int processed_crypto = FALSE;
9334
		char protocol[5] = {0,};
9438
		char protocol[6] = {0,};
9335
		int x;
9439
		int x;
9336

    
   
9440

   
9337
		numberofports = 0;
9441
		numberofports = 0;
9338
		len = -1;
9442
		len = -1;
9339
		start = next;
9443
		start = next;
[+20] [20] 9 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9349
		AST_LIST_INSERT_TAIL(&p->offered_media, offer, next);
9453
		AST_LIST_INSERT_TAIL(&p->offered_media, offer, next);
9350
		offer->type = SDP_UNKNOWN;
9454
		offer->type = SDP_UNKNOWN;
9351

    
   
9455

   
9352
		/* Check for 'audio' media offer */
9456
		/* Check for 'audio' media offer */
9353
		if (strncmp(m, "audio ", 6) == 0) {
9457
		if (strncmp(m, "audio ", 6) == 0) {
9354
			if ((sscanf(m, "audio %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9458
			if ((sscanf(m, "audio %30u/%30u RTP/%5s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9355
			    (sscanf(m, "audio %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) {
9459
			    (sscanf(m, "audio %30u RTP/%5s %n", &x, protocol, &len) == 2 && len > 0)) {
9356
				codecs = m + len;
9460
				codecs = m + len;
9357
				/* produce zero-port m-line since it may be needed later
9461
				/* produce zero-port m-line since it may be needed later
9358
				 * length is "m=audio 0 RTP/" + protocol + " " + codecs + "\0" */
9462
				 * length is "m=audio 0 RTP/" + protocol + " " + codecs + "\0" */
9359
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9463
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9360
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9464
					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)
9372
				/* Check number of ports offered for stream */
9476
				/* Check number of ports offered for stream */
9373
				if (numberofports > 1) {
9477
				if (numberofports > 1) {
9374
					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);
9375
				}
9479
				}
9376

    
   
9480

   
9377
				if (!strcmp(protocol, "SAVP")) {
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")) {
9378
					secure_audio = 1;
9488
					secure_audio = 1;
9379
				} else if (strcmp(protocol, "AVP")) {
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;

    
   
9495
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9380
					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);
9381
					continue;
9497
					continue;
9382
				}
9498
				}
9383

    
   
9499

   
9384
				if (has_media_stream(p, SDP_AUDIO)) {
9500
				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)
9409
				goto process_sdp_cleanup;
9525
				goto process_sdp_cleanup;
9410
			}
9526
			}
9411
		}
9527
		}
9412
		/* Check for 'video' media offer */
9528
		/* Check for 'video' media offer */
9413
		else if (strncmp(m, "video ", 6) == 0) {
9529
		else if (strncmp(m, "video ", 6) == 0) {
9414
			if ((sscanf(m, "video %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9530
			if ((sscanf(m, "video %30u/%30u RTP/%5s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
9415
			    (sscanf(m, "video %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) {
9531
			    (sscanf(m, "video %30u RTP/%5s %n", &x, protocol, &len) == 2 && len > 0)) {
9416
				codecs = m + len;
9532
				codecs = m + len;
9417
				/* produce zero-port m-line since it may be needed later
9533
				/* produce zero-port m-line since it may be needed later
9418
				 * length is "m=video 0 RTP/" + protocol + " " + codecs + "\0" */
9534
				 * length is "m=video 0 RTP/" + protocol + " " + codecs + "\0" */
9419
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9535
				if (!(offer->decline_m_line = ast_malloc(14 + strlen(protocol) + 1 + strlen(codecs) + 1))) {
9420
					ast_log(LOG_WARNING, "Failed to allocate memory for SDP offer declination\n");
9536
					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)
9432
				/* Check number of ports offered for stream */
9548
				/* Check number of ports offered for stream */
9433
				if (numberofports > 1) {
9549
				if (numberofports > 1) {
9434
					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);
9435
				}
9551
				}
9436

    
   
9552

   
9437
				if (!strcmp(protocol, "SAVP")) {
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")) {
9438
					secure_video = 1;
9560
					secure_video = 1;
9439
				} else if (strcmp(protocol, "AVP")) {
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;

    
   
9567
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9440
					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);
9441
					continue;
9569
					continue;
9442
				}
9570
				}
9443

    
   
9571

   
9444
				if (has_media_stream(p, SDP_VIDEO)) {
9572
				if (has_media_stream(p, SDP_VIDEO)) {
[+20] [20] 24 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9469
				goto process_sdp_cleanup;
9597
				goto process_sdp_cleanup;
9470
			}
9598
			}
9471
		}
9599
		}
9472
		/* Check for 'text' media offer */
9600
		/* Check for 'text' media offer */
9473
		else if (strncmp(m, "text ", 5) == 0) {
9601
		else if (strncmp(m, "text ", 5) == 0) {
9474
			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) ||
9475
			    (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)) {
9476
				codecs = m + len;
9604
				codecs = m + len;
9477
				/* produce zero-port m-line since it may be needed later
9605
				/* produce zero-port m-line since it may be needed later
9478
				 * length is "m=text 0 RTP/AVP " + codecs + "\0" */
9606
				 * length is "m=text 0 RTP/" + protocol + " " + codecs + "\0" */
9479
				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))) {
9480
					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");
9481
					res = -1;
9609
					res = -1;
9482
					goto process_sdp_cleanup;
9610
					goto process_sdp_cleanup;
9483
				}
9611
				}
9484
				/* guaranteed to be exactly the right length */
9612
				/* guaranteed to be exactly the right length */
9485
				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);
9486

    
   
9614

   
9487
				if (x == 0) {
9615
				if (x == 0) {
9488
					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");
9489
					continue;
9617
					continue;
9490
				}
9618
				}
9491

    
   
9619

   
9492
				/* Check number of ports offered for stream */
9620
				/* Check number of ports offered for stream */
9493
				if (numberofports > 1) {
9621
				if (numberofports > 1) {
9494
					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);
9495
				}
9623
				}
9496

    
   
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

   
9497
				if (has_media_stream(p, SDP_TEXT)) {
9636
				if (has_media_stream(p, SDP_TEXT)) {
9498
					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);
9499
					continue;
9638
					continue;
9500
				}
9639
				}
9501

    
   
9640

   
[+20] [20] 1184 lines
[+20] [+] static void add_route(struct sip_request *req, struct sip_route *route)
10686
 *
10825
 *
10687
 * If there's a sips: uri scheme, TLS will be required.
10826
 * If there's a sips: uri scheme, TLS will be required.
10688
 */
10827
 */
10689
static void set_destination(struct sip_pvt *p, char *uri)
10828
static void set_destination(struct sip_pvt *p, char *uri)
10690
{
10829
{
10691
	char *h, *maddr, hostname[256];
10830
	char *trans, *h, *maddr, hostname[256];
10692
	int hn;
10831
	int hn;
10693
	int debug=sip_debug_test_pvt(p);
10832
	int debug=sip_debug_test_pvt(p);
10694
	int tls_on = FALSE;
10833
	int tls_on = FALSE;
10695

    
   
10834

   
10696
	if (debug)
10835
	if (debug)
10697
		ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
10836
		ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
10698

    
   
10837

   

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

    
   
10839
		trans += strlen(";transport=");

    
   
10840

   

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

    
   
10842
			if (debug)

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

    
   
10844
			return;

    
   
10845
		}

    
   
10846
	}

    
   
10847

   
10699
	/* Find and parse hostname */
10848
	/* Find and parse hostname */
10700
	h = strchr(uri, '@');
10849
	h = strchr(uri, '@');
10701
	if (h)
10850
	if (h)
10702
		++h;
10851
		++h;
10703
	else {
10852
	else {
[+20] [20] 1330 lines
[+20] [+] static void get_crypto_attrib(struct sip_pvt *p, struct sip_srtp *srtp, const char **a_crypto)
12034
			ast_log(LOG_WARNING, "No SRTP key management enabled\n");
12183
			ast_log(LOG_WARNING, "No SRTP key management enabled\n");
12035
		}
12184
		}
12036
	}
12185
	}
12037
}
12186
}
12038

    
   
12187

   

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

    
   
12189
{

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

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

    
   
12192
	} else {

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

    
   
12194
	}

    
   
12195
}

    
   
12196

   
12039
/*! \brief Add Session Description Protocol message
12197
/*! \brief Add Session Description Protocol message
12040

    
   
12198

   
12041
    If oldsdp is TRUE, then the SDP version number is not incremented. This mechanism
12199
    If oldsdp is TRUE, then the SDP version number is not incremented. This mechanism
12042
    is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions
12200
    is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions
12043
    without modifying the media session in any way.
12201
    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)
12194
		/* Ok, we need video. Let's add what we need for video and set codecs.
12352
		/* Ok, we need video. Let's add what we need for video and set codecs.
12195
		   Video is handled differently than audio since we can not transcode. */
12353
		   Video is handled differently than audio since we can not transcode. */
12196
		if (needvideo) {
12354
		if (needvideo) {
12197
			get_crypto_attrib(p, p->vsrtp, &v_a_crypto);
12355
			get_crypto_attrib(p, p->vsrtp, &v_a_crypto);
12198
			ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest),
12356
			ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest),
12199
				v_a_crypto ? "SAVP" : "AVP");
12357
				       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12200

    
   
12358

   
12201
			/* Build max bitrate string */
12359
			/* Build max bitrate string */
12202
			if (p->maxcallbitrate)
12360
			if (p->maxcallbitrate)
12203
				snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
12361
				snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
12204
			if (debug) {
12362
			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)
12215
		if (needtext) {
12373
		if (needtext) {
12216
			if (sipdebug_text)
12374
			if (sipdebug_text)
12217
				ast_verbose("Lets set up the text sdp\n");
12375
				ast_verbose("Lets set up the text sdp\n");
12218
			get_crypto_attrib(p, p->tsrtp, &t_a_crypto);
12376
			get_crypto_attrib(p, p->tsrtp, &t_a_crypto);
12219
			ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest),
12377
			ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest),
12220
				t_a_crypto ? "SAVP" : "AVP");
12378
				       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12221
			if (debug) {  /* XXX should I use tdest below ? */
12379
			if (debug) {  /* XXX should I use tdest below ? */
12222
				ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr));
12380
				ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr));
12223
			}
12381
			}
12224

    
   
12382

   
12225
			if (!doing_directmedia) {
12383
			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)
12232
		/* We break with the "recommendation" and send our IP, in order that our
12390
		/* We break with the "recommendation" and send our IP, in order that our
12233
		   peer doesn't have to ast_gethostbyname() us */
12391
		   peer doesn't have to ast_gethostbyname() us */
12234

    
   
12392

   
12235
		get_crypto_attrib(p, p->srtp, &a_crypto);
12393
		get_crypto_attrib(p, p->srtp, &a_crypto);
12236
		ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest),
12394
		ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest),
12237
			a_crypto ? "SAVP" : "AVP");
12395
			       get_sdp_rtp_profile(p, a_crypto ? 1 : 0));
12238

    
   
12396

   
12239
		/* Now, start adding audio codecs. These are added in this order:
12397
		/* Now, start adding audio codecs. These are added in this order:
12240
		   - First what was requested by the calling channel
12398
		   - First what was requested by the calling channel
12241
		   - Then preferences in order from sip.conf device config for this peer/user
12399
		   - Then preferences in order from sip.conf device config for this peer/user
12242
		   - Then other codecs in capabilities, including video
12400
		   - Then other codecs in capabilities, including video
[+20] [20] 2402 lines
[+20] [+] static void set_socket_transport(struct sip_socket *socket, int transport)
14645
		socket->fd = -1;
14803
		socket->fd = -1;
14646
		socket->type = transport;
14804
		socket->type = transport;
14647
		if (socket->tcptls_session) {
14805
		if (socket->tcptls_session) {
14648
			ao2_ref(socket->tcptls_session, -1);
14806
			ao2_ref(socket->tcptls_session, -1);
14649
			socket->tcptls_session = NULL;
14807
			socket->tcptls_session = NULL;

    
   
14808
		} else if (socket->ws_session) {

    
   
14809
			ast_websocket_unref(socket->ws_session);

    
   
14810
			socket->ws_session = NULL;
14650
		}
14811
		}
14651
	}
14812
	}
14652
}
14813
}
14653

    
   
14814

   
14654
/*! \brief Expire registration of SIP peer */
14815
/*! \brief Expire registration of SIP peer */
[+20] [20] 12 lines
[+20] [+] static int expire_register(const void *data)
14667
	set_socket_transport(&peer->socket, peer->default_outbound_transport);
14828
	set_socket_transport(&peer->socket, peer->default_outbound_transport);
14668

    
   
14829

   
14669
	if (peer->socket.tcptls_session) {
14830
	if (peer->socket.tcptls_session) {
14670
		ao2_ref(peer->socket.tcptls_session, -1);
14831
		ao2_ref(peer->socket.tcptls_session, -1);
14671
		peer->socket.tcptls_session = NULL;
14832
		peer->socket.tcptls_session = NULL;

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

    
   
14834
		ast_websocket_unref(peer->socket.ws_session);

    
   
14835
		peer->socket.ws_session = NULL;
14672
	}
14836
	}
14673

    
   
14837

   
14674
	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
14838
	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
14675
	register_peer_exten(peer, FALSE);	/* Remove regexten */
14839
	register_peer_exten(peer, FALSE);	/* Remove regexten */
14676
	ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
14840
	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)
16831
	struct ast_sockaddr tmp = { { 0, } };
16995
	struct ast_sockaddr tmp = { { 0, } };
16832
	uint16_t port;
16996
	uint16_t port;
16833

    
   
16997

   
16834
	ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via));
16998
	ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via));
16835

    
   
16999

   

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

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

    
   
17002
		return;

    
   
17003
	}

    
   
17004

   
16836
	/* Work on the leftmost value of the topmost Via header */
17005
	/* Work on the leftmost value of the topmost Via header */
16837
	c = strchr(via, ',');
17006
	c = strchr(via, ',');
16838
	if (c)
17007
	if (c)
16839
		*c = '\0';
17008
		*c = '\0';
16840

    
   
17009

   
[+20] [20] 4133 lines
[+20] [+] static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
20974
	contact_number = remove_uri_parameters(contact_number);
21143
	contact_number = remove_uri_parameters(contact_number);
20975

    
   
21144

   
20976
	if (p->socket.tcptls_session) {
21145
	if (p->socket.tcptls_session) {
20977
		ao2_ref(p->socket.tcptls_session, -1);
21146
		ao2_ref(p->socket.tcptls_session, -1);
20978
		p->socket.tcptls_session = NULL;
21147
		p->socket.tcptls_session = NULL;

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

    
   
21149
		ast_websocket_unref(p->socket.ws_session);

    
   
21150
		p->socket.ws_session = NULL;
20979
	}
21151
	}
20980

    
   
21152

   
20981
	set_socket_transport(&p->socket, transport);
21153
	set_socket_transport(&p->socket, transport);
20982

    
   
21154

   
20983
	if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
21155
	if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
[+20] [20] 6202 lines
[+20] [+] static int sip_prepare_socket(struct sip_pvt *p)
27186
	if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) &&
27358
	if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) &&
27187
			(s->tcptls_session) &&
27359
			(s->tcptls_session) &&
27188
			(s->tcptls_session->fd != -1)) {
27360
			(s->tcptls_session->fd != -1)) {
27189
		return s->tcptls_session->fd;
27361
		return s->tcptls_session->fd;
27190
	}
27362
	}

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

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

    
   
27365
	}
27191

    
   
27366

   
27192
	/*! \todo Check this... This might be wrong, depending on the proxy configuration
27367
	/*! \todo Check this... This might be wrong, depending on the proxy configuration
27193
		If proxy is in "force" mode its correct.
27368
		If proxy is in "force" mode its correct.
27194
	 */
27369
	 */
27195
	if (p->outboundproxy && p->outboundproxy->transport) {
27370
	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)
29160
				while ((trans = strsep(&val, ","))) {
29335
				while ((trans = strsep(&val, ","))) {
29161
					trans = ast_skip_blanks(trans);
29336
					trans = ast_skip_blanks(trans);
29162

    
   
29337

   
29163
					if (!strncasecmp(trans, "udp", 3)) {
29338
					if (!strncasecmp(trans, "udp", 3)) {
29164
						peer->transports |= SIP_TRANSPORT_UDP;
29339
						peer->transports |= SIP_TRANSPORT_UDP;

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

    
   
29341
						peer->transports |= SIP_TRANSPORT_WSS;

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

    
   
29343
						peer->transports |= SIP_TRANSPORT_WS;
29165
					} else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) {
29344
					} else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) {
29166
						peer->transports |= SIP_TRANSPORT_TCP;
29345
						peer->transports |= SIP_TRANSPORT_TCP;
29167
					} else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) {
29346
					} else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) {
29168
						peer->transports |= SIP_TRANSPORT_TLS;
29347
						peer->transports |= SIP_TRANSPORT_TLS;
29169
					} else if (!strncasecmp(trans, "tcp", 3) || !strncasecmp(trans, "tls", 3)) {
29348
					} 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)
29510
				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP);
29689
				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP);
29511
			} else if (!strcasecmp(v->name, "encryption_taglen")) {
29690
			} else if (!strcasecmp(v->name, "encryption_taglen")) {
29512
				ast_set2_flag(&peer->flags[2], !strcasecmp(v->value, "32"), SIP_PAGE3_SRTP_TAG_32);
29691
				ast_set2_flag(&peer->flags[2], !strcasecmp(v->value, "32"), SIP_PAGE3_SRTP_TAG_32);
29513
			} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
29692
			} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
29514
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
29693
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);

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

    
   
29695
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_USE_AVPF);
29515
			}
29696
			}
29516
		}
29697
		}
29517

    
   
29698

   
29518
		/* These apply to devstate lookups */
29699
		/* These apply to devstate lookups */
29519
		if (realtime && !strcasecmp(v->name, "lastms")) {
29700
		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)
29623
	 * 1. Registration is not present and the socket.type and default transport types are different.
29804
	 * 1. Registration is not present and the socket.type and default transport types are different.
29624
	 * 2. The socket.type is not an acceptable transport type after rebuilding peer.
29805
	 * 2. The socket.type is not an acceptable transport type after rebuilding peer.
29625
	 * 3. The socket.type is not set yet. */
29806
	 * 3. The socket.type is not set yet. */
29626
	if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) ||
29807
	if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) ||
29627
		!(peer->socket.type & peer->transports) || !(peer->socket.type)) {
29808
		!(peer->socket.type & peer->transports) || !(peer->socket.type)) {
29628

    
   

   
29629
		set_socket_transport(&peer->socket, peer->default_outbound_transport);
29809
		set_socket_transport(&peer->socket, peer->default_outbound_transport);
29630
	}
29810
	}
29631

    
   
29811

   
29632
	if (ast_str_strlen(fullcontact)) {
29812
	if (ast_str_strlen(fullcontact)) {
29633
		ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
29813
		ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
[+20] [20] 521 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
30155
					default_transports |= SIP_TRANSPORT_UDP;
30335
					default_transports |= SIP_TRANSPORT_UDP;
30156
				} else if (!strncasecmp(trans, "tcp", 3)) {
30336
				} else if (!strncasecmp(trans, "tcp", 3)) {
30157
					default_transports |= SIP_TRANSPORT_TCP;
30337
					default_transports |= SIP_TRANSPORT_TCP;
30158
				} else if (!strncasecmp(trans, "tls", 3)) {
30338
				} else if (!strncasecmp(trans, "tls", 3)) {
30159
					default_transports |= SIP_TRANSPORT_TLS;
30339
					default_transports |= SIP_TRANSPORT_TLS;

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

    
   
30341
					default_transports |= SIP_TRANSPORT_WSS;

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

    
   
30343
					default_transports |= SIP_TRANSPORT_WS;
30160
				} else {
30344
				} else {
30161
					ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
30345
					ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
30162
				}
30346
				}
30163
				if (default_primary_transport == 0) {
30347
				if (default_primary_transport == 0) {
30164
					default_primary_transport = default_transports;
30348
					default_primary_transport = default_transports;
[+20] [20] 2394 lines
[+20] [+] static int load_module(void)
32559

    
   
32743

   
32560

    
   
32744

   
32561
	sip_register_tests();
32745
	sip_register_tests();
32562
	network_change_event_subscribe();
32746
	network_change_event_subscribe();
32563

    
   
32747

   

    
   
32748
	ast_websocket_add_protocol("sip", sip_websocket_callback);

    
   
32749

   
32564
	return AST_MODULE_LOAD_SUCCESS;
32750
	return AST_MODULE_LOAD_SUCCESS;
32565
}
32751
}
32566

    
   
32752

   
32567
/*! \brief PBX unload module API */
32753
/*! \brief PBX unload module API */
32568
static int unload_module(void)
32754
static int unload_module(void)
32569
{
32755
{
32570
	struct sip_pvt *p;
32756
	struct sip_pvt *p;
32571
	struct sip_threadinfo *th;
32757
	struct sip_threadinfo *th;
32572
	struct ast_context *con;
32758
	struct ast_context *con;
32573
	struct ao2_iterator i;
32759
	struct ao2_iterator i;
32574
	int wait_count;
32760
	int wait_count;
32575

    
   
32761

   

    
   
32762
	ast_websocket_remove_protocol("sip", sip_websocket_callback);

    
   
32763

   
32576
	network_change_event_unsubscribe();
32764
	network_change_event_unsubscribe();
32577

    
   
32765

   
32578
	ast_sched_dump(sched);
32766
	ast_sched_dump(sched);
32579
	
32767
	
32580
	/* First, take us out of the channel type list */
32768
	/* First, take us out of the channel type list */
[+20] [20] 173 lines
/trunk/channels/sip/sdp_crypto.c
Revision 369836 New Change
 
/trunk/channels/sip/security_events.c
Revision 369836 New Change
 
/trunk/channels/sip/include/sip.h
Revision 369836 New Change
 
/trunk/configs/sip.conf.sample
Revision 369836 New Change
 
/trunk/include/asterisk/http_websocket.h
Revision 369836 New Change
 
/trunk/res/res_http_websocket.c
Revision 369836 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...
  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.