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 1 Diff Revision 4
[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] 1350 lines
[+20] [+] static void *sip_tcp_worker_fn(void *data)
2524
}
2530
}
2525

    
   
2531

   
2526
/*! \brief SIP WebSocket connection handler */
2532
/*! \brief SIP WebSocket connection handler */
2527
static void sip_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
2533
static void sip_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
2528
{
2534
{
2529
	int flags, res;
2535
	int res;
2530

    
   

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

   
2532
		goto end;

   
2533
	}

   
2534

    
   

   
2535
	flags |= O_NONBLOCK;

   
2536

    
   
2536

   
2537
	if (fcntl(ast_websocket_fd(session), F_SETFL, flags) == -1) {
2537
	if (ast_websocket_set_nonblock(session)) {
2538
		goto end;
2538
		goto end;
2539
	}
2539
	}
2540

    
   
2540

   
2541
	while ((res = ast_wait_for_input(ast_websocket_fd(session), -1)) > 0) {
2541
	while ((res = ast_wait_for_input(ast_websocket_fd(session), -1)) > 0) {
2542
		char *payload;
2542
		char *payload;
[+20] [20] 12 lines
[+20] static void sip_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
2555
			if (!(req.data = ast_str_create(payload_len))) {
2555
			if (!(req.data = ast_str_create(payload_len))) {
2556
				goto end;
2556
				goto end;
2557
			}
2557
			}
2558

    
   
2558

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

    
   
2560
				deinit_req(&req);
2560
				goto end;
2561
				goto end;
2561
			}
2562
			}
2562

    
   
2563

   
2563
			req.socket.fd = ast_websocket_fd(session);
2564
			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
			set_socket_transport(&req.socket, ast_websocket_is_secure(session) ? SIP_TRANSPORT_WSS : SIP_TRANSPORT_WS);
[+20] [20] 802 lines
[+20] [+] static int get_transport_str2enum(const char *transport)
3367

    
   
3368

   
3368
	return res;
3369
	return res;
3369
}
3370
}
3370

    
   
3371

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

   
3376
	case SIP_TRANSPORT_TCP:
3377
	if (!transports) {
3377
		return "TCP";
3378
		return "UNKNOWN";
3378
	case SIP_TRANSPORT_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";

   
3390
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP:

   
3391
		return "TCP,UDP";

   
3392
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS:

   
3393
		return "TLS,UDP";

   
3394
	case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS:

   
3395
		return "TLS,TCP";

   
3396
	default:

   
3397
		return transports ?

   
3398
			"TLS,TCP,UDP,WS,WSS" : "UNKNOWN";	

   
3399
	}
3379
	}

    
   
3380

   

    
   
3381
	if (!(buf = ast_threadstorage_get(&sip_transport_str_buf, SIP_TRANSPORT_STR_BUFSIZE))) {

    
   
3382
		return "";

    
   
3383
	}

    
   
3384

   

    
   
3385
	memset(buf, 0, SIP_TRANSPORT_STR_BUFSIZE);

    
   
3386

   

    
   
3387
	if (transports & SIP_TRANSPORT_UDP) {

    
   
3388
		strncat(buf, "UDP,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));

    
   
3389
	}

    
   
3390
	if (transports & SIP_TRANSPORT_TCP) {

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

    
   
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;
3400
}
3409
}
3401

    
   
3410

   
3402
/*! \brief Return transport as string */
3411
/*! \brief Return transport as string */
3403
const char *sip_get_transport(enum sip_transport t)
3412
const char *sip_get_transport(enum sip_transport t)
3404
{
3413
{
[+20] [20] 589 lines
[+20] [+] static int __sip_autodestruct(const void *data)
3994
		if (!p->needdestroy) {
4003
		if (!p->needdestroy) {
3995
			char method_str[31];
4004
			char method_str[31];
3996
			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
4005
			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
3997
			append_history(p, "ReliableXmit", "timeout");
4006
			append_history(p, "ReliableXmit", "timeout");
3998
			if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
4007
			if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
3999
				if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
4008
				if (p->ongoing_reinvite || method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
4000
					pvt_set_needdestroy(p, "autodestruct");
4009
					pvt_set_needdestroy(p, "autodestruct");
4001
				}
4010
				}
4002
			}
4011
			}
4003
			return 10000;
4012
			return 10000;
4004
		} else {
4013
		} else {
[+20] [20] 2462 lines
[+20] [+] const char *hangup_cause2sip(int cause)
6467

    
   
6476

   
6468
	/* Never reached */
6477
	/* Never reached */
6469
	return 0;
6478
	return 0;
6470
}
6479
}
6471

    
   
6480

   

    
   
6481
static int reinvite_timeout(const void *data)

    
   
6482
{

    
   
6483
	struct sip_pvt *dialog = (struct sip_pvt *) data;

    
   
6484
	struct ast_channel *owner = sip_pvt_lock_full(dialog);

    
   
6485
	dialog->reinviteid = -1;

    
   
6486
	check_pendings(dialog);

    
   
6487
	if (owner) {

    
   
6488
		ast_channel_unlock(owner);

    
   
6489
		ast_channel_unref(owner);

    
   
6490
	}

    
   
6491
	ao2_unlock(dialog);

    
   
6492
	dialog_unref(dialog, "unref for reinvite timeout");

    
   
6493
	return 0;

    
   
6494
}

    
   
6495

   
6472
/*! \brief  sip_hangup: Hangup SIP call
6496
/*! \brief  sip_hangup: Hangup SIP call
6473
 * Part of PBX interface, called from ast_hangup */
6497
 * Part of PBX interface, called from ast_hangup */
6474
static int sip_hangup(struct ast_channel *ast)
6498
static int sip_hangup(struct ast_channel *ast)
6475
{
6499
{
6476
	struct sip_pvt *p = ast_channel_tech_pvt(ast);
6500
	struct sip_pvt *p = ast_channel_tech_pvt(ast);
[+20] [20] 113 lines
[+20] static int sip_hangup(struct ast_channel *ast)
6590
		} else {	/* Call is in UP state, send BYE */
6614
		} else {	/* Call is in UP state, send BYE */
6591
			if (p->stimer->st_active == TRUE) {
6615
			if (p->stimer->st_active == TRUE) {
6592
				stop_session_timer(p);
6616
				stop_session_timer(p);
6593
			}
6617
			}
6594

    
   
6618

   
6595
			if (!p->pendinginvite || p->ongoing_reinvite) {
6619
			if (!p->pendinginvite) {
6596
				struct ast_channel *bridge = ast_bridged_channel(oldowner);
6620
				struct ast_channel *bridge = ast_bridged_channel(oldowner);
6597
				char quality_buf[AST_MAX_USER_FIELD], *quality;
6621
				char quality_buf[AST_MAX_USER_FIELD], *quality;
6598

    
   
6622

   
6599
				/* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt
6623
				/* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt
6600
				 * to lock the bridge. This may get hairy...
6624
				 * to lock the bridge. This may get hairy...
[+20] [20] 51 lines
[+20] static int sip_hangup(struct ast_channel *ast)
6652
				/* Note we will need a BYE when this all settles out
6676
				/* Note we will need a BYE when this all settles out
6653
				   but we can't send one while we have "INVITE" outstanding. */
6677
				   but we can't send one while we have "INVITE" outstanding. */
6654
				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
6678
				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
6655
				ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);	
6679
				ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);	
6656
				AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
6680
				AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
6657
				if (sip_cancel_destroy(p))
6681
				if (sip_cancel_destroy(p)) {
6658
					ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
6682
					ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
6659
			}
6683
				}

    
   
6684
				/* If we have an ongoing reinvite, there is a chance that we have gotten a provisional

    
   
6685
				 * response, but something weird has happened and we will never receive a final response.

    
   
6686
				 * So, just in case, check for pending actions after a bit of time to trigger the pending

    
   
6687
				 * bye that we are setting above */

    
   
6688
				if (p->ongoing_reinvite && p->reinviteid < 0) {

    
   
6689
					p->reinviteid = ast_sched_add(sched, 32 * p->timer_t1, reinvite_timeout, dialog_ref(p, "ref for reinvite_timeout"));

    
   
6690
				}

    
   
6691
			}
6660
		}
6692
		}
6661
	}
6693
	}
6662
	if (needdestroy) {
6694
	if (needdestroy) {
6663
		pvt_set_needdestroy(p, "hangup");
6695
		pvt_set_needdestroy(p, "hangup");
6664
	}
6696
	}
[+20] [20] 604 lines
[+20] [+] static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
7269
			ast_aoc_destroy_decoded(decoded);
7301
			ast_aoc_destroy_decoded(decoded);
7270
		}
7302
		}
7271
		break;
7303
		break;
7272
	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 */
7273
		break;
7305
		break;

    
   
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;

    
   
7308
		break;
7274
	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 */
7275
	case -1:
7310
	case -1:
7276
		res = -1;
7311
		res = -1;
7277
		break;
7312
		break;
7278
	default:
7313
	default:
[+20] [20] 785 lines
[+20] [+] struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
8064

    
   
8099

   
8065
	p->socket.fd = -1;
8100
	p->socket.fd = -1;
8066
	p->method = intended_method;
8101
	p->method = intended_method;
8067
	p->initid = -1;
8102
	p->initid = -1;
8068
	p->waitid = -1;
8103
	p->waitid = -1;

    
   
8104
	p->reinviteid = -1;
8069
	p->autokillid = -1;
8105
	p->autokillid = -1;
8070
	p->request_queue_sched_id = -1;
8106
	p->request_queue_sched_id = -1;
8071
	p->provisional_keepalive_sched_id = -1;
8107
	p->provisional_keepalive_sched_id = -1;
8072
	p->t38id = -1;
8108
	p->t38id = -1;
8073
	p->subscribed = NONE;
8109
	p->subscribed = NONE;
[+20] [20] 1366 lines
[+20] [+] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9440
				/* Check number of ports offered for stream */
9476
				/* Check number of ports offered for stream */
9441
				if (numberofports > 1) {
9477
				if (numberofports > 1) {
9442
					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);
9443
				}
9479
				}
9444

    
   
9480

   
9445
				if (!strncmp(protocol, "SAVP", 4)) {
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")) {
9446
					secure_audio = 1;
9488
					secure_audio = 1;
9447
				} else if (strncmp(protocol, "AVP", 3)) {
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")) {
9448
					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);
9449
					continue;
9497
					continue;
9450
				}
9498
				}
9451

    
   
9499

   
9452
				if (has_media_stream(p, SDP_AUDIO)) {
9500
				if (has_media_stream(p, SDP_AUDIO)) {
[+20] [20] 47 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
9500
				/* Check number of ports offered for stream */
9548
				/* Check number of ports offered for stream */
9501
				if (numberofports > 1) {
9549
				if (numberofports > 1) {
9502
					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);
9503
				}
9551
				}
9504

    
   
9552

   
9505
				if (!strncmp(protocol, "SAVP", 4)) {
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")) {
9506
					secure_video = 1;
9560
					secure_video = 1;
9507
				} else if (strncmp(protocol, "AVP", 3)) {
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")) {
9508
					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);
9509
					continue;
9569
					continue;
9510
				}
9570
				}
9511

    
   
9571

   
9512
				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)
9537
				goto process_sdp_cleanup;
9597
				goto process_sdp_cleanup;
9538
			}
9598
			}
9539
		}
9599
		}
9540
		/* Check for 'text' media offer */
9600
		/* Check for 'text' media offer */
9541
		else if (strncmp(m, "text ", 5) == 0) {
9601
		else if (strncmp(m, "text ", 5) == 0) {
9542
			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) ||
9543
			    (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)) {
9544
				codecs = m + len;
9604
				codecs = m + len;
9545
				/* produce zero-port m-line since it may be needed later
9605
				/* produce zero-port m-line since it may be needed later
9546
				 * length is "m=text 0 RTP/AVP " + codecs + "\0" */
9606
				 * length is "m=text 0 RTP/" + protocol + " " + codecs + "\0" */
9547
				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))) {
9548
					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");
9549
					res = -1;
9609
					res = -1;
9550
					goto process_sdp_cleanup;
9610
					goto process_sdp_cleanup;
9551
				}
9611
				}
9552
				/* guaranteed to be exactly the right length */
9612
				/* guaranteed to be exactly the right length */
9553
				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);
9554

    
   
9614

   
9555
				if (x == 0) {
9615
				if (x == 0) {
9556
					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");
9557
					continue;
9617
					continue;
9558
				}
9618
				}
9559

    
   
9619

   
9560
				/* Check number of ports offered for stream */
9620
				/* Check number of ports offered for stream */
9561
				if (numberofports > 1) {
9621
				if (numberofports > 1) {
9562
					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);
9563
				}
9623
				}
9564

    
   
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

   
9565
				if (has_media_stream(p, SDP_TEXT)) {
9636
				if (has_media_stream(p, SDP_TEXT)) {
9566
					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);
9567
					continue;
9638
					continue;
9568
				}
9639
				}
9569

    
   
9640

   
[+20] [20] 1193 lines
[+20] [+] static void set_destination(struct sip_pvt *p, char *uri)
10763

    
   
10834

   
10764
	if (debug)
10835
	if (debug)
10765
		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);
10766

    
   
10837

   
10767
	if ((trans = strcasestr(uri, ";transport="))) {
10838
	if ((trans = strcasestr(uri, ";transport="))) {
10768
		trans += 11;
10839
		trans += strlen(";transport=");
10769

    
   
10840

   
10770
		if (!strncasecmp(trans, "ws", 2)) {
10841
		if (!strncasecmp(trans, "ws", 2)) {
10771
			if (debug)
10842
			if (debug)
10772
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10843
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10773
			return;
10844
			return;
[+20] [20] 6669 lines
[+20] [+] static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
17443
	struct ast_msg *msg;
17514
	struct ast_msg *msg;
17444
	int res;
17515
	int res;
17445
	char *from;
17516
	char *from;
17446
	char *to;
17517
	char *to;
17447
	char from_name[50];
17518
	char from_name[50];

    
   
17519
	char stripped[SIPBUFSIZE];
17448

    
   
17520

   
17449
	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 */
17450
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
17522
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
17451
		if (!p->owner) {
17523
		if (!p->owner) {
17452
			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)
17596
	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));
17597
	if (!ast_strlen_zero(p->peername)) {
17669
	if (!ast_strlen_zero(p->peername)) {
17598
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17670
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17599
	}
17671
	}
17600

    
   
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

   
17601
	res |= ast_msg_set_exten(msg, "%s", p->exten);
17676
	res |= ast_msg_set_exten(msg, "%s", p->exten);
17602
	res |= set_message_vars_from_req(msg, req);
17677
	res |= set_message_vars_from_req(msg, req);
17603

    
   
17678

   
17604
	if (res) {
17679
	if (res) {
17605
		ast_msg_destroy(msg);
17680
		ast_msg_destroy(msg);
[+20] [20] 3544 lines
[+20] [+] static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
21150
 *  must be locked for this function.
21225
 *  must be locked for this function.
21151
 */
21226
 */
21152
static void check_pendings(struct sip_pvt *p)
21227
static void check_pendings(struct sip_pvt *p)
21153
{
21228
{
21154
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
21229
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {

    
   
21230
		if (p->reinviteid > -1) {

    
   
21231
			/* Outstanding p->reinviteid timeout, so wait... */

    
   
21232
			return;

    
   
21233
		} else if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
21155
		/* if we can't BYE, then this is really a pending CANCEL */
21234
			/* if we can't BYE, then this is really a pending CANCEL */
21156
		if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {

   
21157
			p->invitestate = INV_CANCELLED;
21235
			p->invitestate = INV_CANCELLED;
21158
			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
21236
			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
21159
			/* If the cancel occurred on an initial invite, cancel the pending BYE */
21237
			/* If the cancel occurred on an initial invite, cancel the pending BYE */
21160
			if (!ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
21238
			if (!ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
21161
				ast_clear_flag(&p->flags[0], SIP_PENDINGBYE);
21239
				ast_clear_flag(&p->flags[0], SIP_PENDINGBYE);
21162
			}
21240
			}
21163
			/* Actually don't destroy us yet, wait for the 487 on our original
21241
			/* Actually don't destroy us yet, wait for the 487 on our original
21164
			   INVITE, but do set an autodestruct just in case we never get it. */
21242
			   INVITE, but do set an autodestruct just in case we never get it. */
21165
		} else {
21243
		} else {
21166
			/* We have a pending outbound invite, don't send something
21244
			/* We have a pending outbound invite, don't send something
21167
				new in-transaction */
21245
			 * new in-transaction, unless it is a pending reinvite, then
21168
			if (p->pendinginvite)
21246
			 * by the time we are called here, we should probably just hang up. */

    
   
21247
			if (p->pendinginvite && !p->ongoing_reinvite)
21169
				return;
21248
				return;
21170

    
   
21249

   
21171
			if (p->owner) {
21250
			if (p->owner) {
21172
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21251
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21173
			}
21252
			}
[+20] [20] 238 lines
[+20] [+] static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
21412
 	/* Final response, not 200 ? */
21491
 	/* Final response, not 200 ? */
21413
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21492
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21414
 		p->invitestate = INV_COMPLETED;
21493
 		p->invitestate = INV_COMPLETED;
21415
	}
21494
	}
21416
 	
21495
 	

    
   
21496
	if ((resp >= 200 && reinvite)) {

    
   
21497
		p->ongoing_reinvite = 0;

    
   
21498
		if (p->reinviteid > -1) {

    
   
21499
			AST_SCHED_DEL_UNREF(sched, p->reinviteid, dialog_unref(p, "unref dialog for reinvite timeout because of a final response"));

    
   
21500
		}

    
   
21501
	}

    
   
21502

   
21417
	/* Final response, clear out pending invite */
21503
	/* Final response, clear out pending invite */
21418
	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) {
21504
	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) {
21419
		p->pendinginvite = 0;
21505
		p->pendinginvite = 0;
21420
		if (reinvite) {

   
21421
			p->ongoing_reinvite = 0;

   
21422
		}

   
21423
	}
21506
	}
21424

    
   
21507

   
21425
	/* If this is a response to our initial INVITE, we need to set what we can use
21508
	/* If this is a response to our initial INVITE, we need to set what we can use
21426
	 * for this peer.
21509
	 * for this peer.
21427
	 */
21510
	 */
[+20] [20] 4131 lines
[+20] [+] static int block_msg_header(const char *header_name)
25559
		"Contact",
25642
		"Contact",
25560
		"Call-ID",
25643
		"Call-ID",
25561
		"CSeq",
25644
		"CSeq",
25562
		"Allow",
25645
		"Allow",
25563
		"Content-Length",
25646
		"Content-Length",

    
   
25647
		"Request-URI",
25564
	};
25648
	};
25565

    
   
25649

   
25566
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25650
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25567
		if (!strcasecmp(header_name, hdr[idx])) {
25651
		if (!strcasecmp(header_name, hdr[idx])) {
25568
			/* 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)
25586

    
   
25670

   
25587
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25671
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25588
		return -1;
25672
		return -1;
25589
	}
25673
	}
25590

    
   
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

   
25591
	to_uri = ast_strdupa(to);
25686
	to_uri = ast_strdupa(to);
25592
	to_uri = get_in_brackets(to_uri);
25687
	to_uri = get_in_brackets(to_uri);
25593
	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);
25594

    
   
25689

   
25595
	if (ast_strlen_zero(to_host)) {
25690
	if (ast_strlen_zero(to_host)) {
[+20] [20] 1481 lines
[+20] [+] static int sipsock_read(int *id, int fd, short events, void *ignore)
27077
	}
27172
	}
27078

    
   
27173

   
27079
	req.socket.fd = sipsock;
27174
	req.socket.fd = sipsock;
27080
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27175
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27081
	req.socket.tcptls_session	= NULL;
27176
	req.socket.tcptls_session	= NULL;
27082
	req.socket.ws_session = NULL;

   
27083
	req.socket.port = htons(ast_sockaddr_port(&bindaddr));
27177
	req.socket.port = htons(ast_sockaddr_port(&bindaddr));
27084

    
   
27178

   
27085
	handle_request_do(&req, &addr);
27179
	handle_request_do(&req, &addr);
27086
	deinit_req(&req);
27180
	deinit_req(&req);
27087

    
   
27181

   
[+20] [20] 5760 lines
/trunk/channels/sip/sdp_crypto.c
Diff Revision 1 Diff Revision 4
 
/trunk/channels/sip/security_events.c
Diff Revision 1 Diff Revision 4
 
/trunk/channels/sip/include/sip.h
Diff Revision 1 Diff Revision 4
 
/trunk/configs/sip.conf.sample
Diff Revision 1 Diff Revision 4
 
/trunk/include/asterisk/http_websocket.h
Diff Revision 1 Diff Revision 4
 
/trunk/res/res_http_websocket.c
Diff Revision 1 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.