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 3
[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, "SAVP") || (!strcmp(protocol, "SAVPF") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF))) {
9446
					secure_audio = 1;
9482
					secure_audio = 1;
9447
				} else if (strncmp(protocol, "AVP", 3)) {
9483
				} else if ((!strcmp(protocol, "AVPF") || !strcmp(protocol, "SAVPF")) && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

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

    
   
9485
					continue;

    
   
9486
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9448
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9487
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9449
					continue;
9488
					continue;
9450
				}
9489
				}
9451

    
   
9490

   
9452
				if (has_media_stream(p, SDP_AUDIO)) {
9491
				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 */
9539
				/* Check number of ports offered for stream */
9501
				if (numberofports > 1) {
9540
				if (numberofports > 1) {
9502
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9541
					ast_log(LOG_WARNING, "%d ports offered for video stream, not supported by Asterisk. Will try anyway...\n", numberofports);
9503
				}
9542
				}
9504

    
   
9543

   
9505
				if (!strncmp(protocol, "SAVP", 4)) {
9544
				if (!strcmp(protocol, "SAVP") || (!strcmp(protocol, "SAVPF") && ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF))) {
9506
					secure_video = 1;
9545
					secure_video = 1;
9507
				} else if (strncmp(protocol, "AVP", 3)) {
9546
				} else if ((!strcmp(protocol, "AVPF") || !strcmp(protocol, "SAVPF")) && !ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {

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

    
   
9548
					continue;

    
   
9549
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9508
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9550
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9509
					continue;
9551
					continue;
9510
				}
9552
				}
9511

    
   
9553

   
9512
				if (has_media_stream(p, SDP_VIDEO)) {
9554
				if (has_media_stream(p, SDP_VIDEO)) {
[+20] [20] 1250 lines
[+20] [+] static void set_destination(struct sip_pvt *p, char *uri)
10763

    
   
10805

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

    
   
10808

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

    
   
10811

   
10770
		if (!strncasecmp(trans, "ws", 2)) {
10812
		if (!strncasecmp(trans, "ws", 2)) {
10771
			if (debug)
10813
			if (debug)
10772
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10814
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10773
			return;
10815
			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;
17485
	struct ast_msg *msg;
17444
	int res;
17486
	int res;
17445
	char *from;
17487
	char *from;
17446
	char *to;
17488
	char *to;
17447
	char from_name[50];
17489
	char from_name[50];

    
   
17490
	char stripped[SIPBUFSIZE];
17448

    
   
17491

   
17449
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
17492
	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? */
17493
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
17451
		if (!p->owner) {
17494
		if (!p->owner) {
17452
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
17495
			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));
17639
	res |= ast_msg_set_var(msg, "SIP_RECVADDR", ast_sockaddr_stringify(&p->recv));
17597
	if (!ast_strlen_zero(p->peername)) {
17640
	if (!ast_strlen_zero(p->peername)) {
17598
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17641
		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
17599
	}
17642
	}
17600

    
   
17643

   

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

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

    
   
17646

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

    
   
17649

   
17604
	if (res) {
17650
	if (res) {
17605
		ast_msg_destroy(msg);
17651
		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.
21196
 *  must be locked for this function.
21151
 */
21197
 */
21152
static void check_pendings(struct sip_pvt *p)
21198
static void check_pendings(struct sip_pvt *p)
21153
{
21199
{
21154
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
21200
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {

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

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

    
   
21203
			return;

    
   
21204
		} else if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
21155
		/* if we can't BYE, then this is really a pending CANCEL */
21205
			/* 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;
21206
			p->invitestate = INV_CANCELLED;
21158
			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
21207
			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
21159
			/* If the cancel occurred on an initial invite, cancel the pending BYE */
21208
			/* If the cancel occurred on an initial invite, cancel the pending BYE */
21160
			if (!ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
21209
			if (!ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
21161
				ast_clear_flag(&p->flags[0], SIP_PENDINGBYE);
21210
				ast_clear_flag(&p->flags[0], SIP_PENDINGBYE);
21162
			}
21211
			}
21163
			/* Actually don't destroy us yet, wait for the 487 on our original
21212
			/* 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. */
21213
			   INVITE, but do set an autodestruct just in case we never get it. */
21165
		} else {
21214
		} else {
21166
			/* We have a pending outbound invite, don't send something
21215
			/* We have a pending outbound invite, don't send something
21167
				new in-transaction */
21216
			 * new in-transaction, unless it is a pending reinvite, then
21168
			if (p->pendinginvite)
21217
			 * by the time we are called here, we should probably just hang up. */

    
   
21218
			if (p->pendinginvite && !p->ongoing_reinvite)
21169
				return;
21219
				return;
21170

    
   
21220

   
21171
			if (p->owner) {
21221
			if (p->owner) {
21172
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21222
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21173
			}
21223
			}
[+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 ? */
21462
 	/* Final response, not 200 ? */
21413
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21463
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21414
 		p->invitestate = INV_COMPLETED;
21464
 		p->invitestate = INV_COMPLETED;
21415
	}
21465
	}
21416
 	
21466
 	

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

    
   
21468
		p->ongoing_reinvite = 0;

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

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

    
   
21471
		}

    
   
21472
	}

    
   
21473

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

   
21421
			p->ongoing_reinvite = 0;

   
21422
		}

   
21423
	}
21477
	}
21424

    
   
21478

   
21425
	/* If this is a response to our initial INVITE, we need to set what we can use
21479
	/* If this is a response to our initial INVITE, we need to set what we can use
21426
	 * for this peer.
21480
	 * for this peer.
21427
	 */
21481
	 */
[+20] [20] 4131 lines
[+20] [+] static int block_msg_header(const char *header_name)
25559
		"Contact",
25613
		"Contact",
25560
		"Call-ID",
25614
		"Call-ID",
25561
		"CSeq",
25615
		"CSeq",
25562
		"Allow",
25616
		"Allow",
25563
		"Content-Length",
25617
		"Content-Length",

    
   
25618
		"Request-URI",
25564
	};
25619
	};
25565

    
   
25620

   
25566
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25621
	for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) {
25567
		if (!strcasecmp(header_name, hdr[idx])) {
25622
		if (!strcasecmp(header_name, hdr[idx])) {
25568
			/* Block addition of this header. */
25623
			/* 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

    
   
25641

   
25587
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25642
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
25588
		return -1;
25643
		return -1;
25589
	}
25644
	}
25590

    
   
25645

   

    
   
25646
        for (iter = ast_msg_var_iterator_init(msg);

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

    
   
25648
	     ast_msg_var_unref_current(iter)) {

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

    
   
25650
			ast_string_field_set(pvt, fullcontact, val);

    
   
25651
			ast_msg_var_unref_current(iter);

    
   
25652
			break;

    
   
25653
		}

    
   
25654
	}

    
   
25655
	ast_msg_var_iterator_destroy(iter);

    
   
25656

   
25591
	to_uri = ast_strdupa(to);
25657
	to_uri = ast_strdupa(to);
25592
	to_uri = get_in_brackets(to_uri);
25658
	to_uri = get_in_brackets(to_uri);
25593
	parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL);
25659
	parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL);
25594

    
   
25660

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

    
   
27144

   
27079
	req.socket.fd = sipsock;
27145
	req.socket.fd = sipsock;
27080
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27146
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27081
	req.socket.tcptls_session	= NULL;
27147
	req.socket.tcptls_session	= NULL;
27082
	req.socket.ws_session = NULL;

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

    
   
27149

   
27085
	handle_request_do(&req, &addr);
27150
	handle_request_do(&req, &addr);
27086
	deinit_req(&req);
27151
	deinit_req(&req);
27087

    
   
27152

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