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 2
[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
	}
3379
		return "TLS";
3380

   
3380
	case SIP_TRANSPORT_WS:
3381
	if (!(buf = ast_threadstorage_get(&sip_transport_str_buf, SIP_TRANSPORT_STR_BUFSIZE))) {
3381
		return "WS";
3382
		return "";
3382
	case SIP_TRANSPORT_WSS:
3383
	}
3383
		return "WSS";
3384

   
3384
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_WS:
3385
	memset(buf, 0, SIP_TRANSPORT_STR_BUFSIZE);
3385
		return "WS,UDP";
3386

   
3386
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_WSS:
3387
	if (transports & SIP_TRANSPORT_UDP) {
3387
		return "WSS,UDP";
3388
		strncat(buf, "UDP,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3388
	case SIP_TRANSPORT_WS | SIP_TRANSPORT_WSS:
3389
	}
3389
		return "WSS,WS";
3390
	if (transports & SIP_TRANSPORT_TCP) {
3390
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP:
3391
		strncat(buf, "TCP,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3391
		return "TCP,UDP";
3392
	}
3392
	case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS:
3393
	if (transports & SIP_TRANSPORT_TLS) {
3393
		return "TLS,UDP";
3394
		strncat(buf, "TLS,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3394
	case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS:
3395
	}
3395
		return "TLS,TCP";
3396
	if (transports & SIP_TRANSPORT_WS) {
3396
	default:
3397
		strncat(buf, "WS,", SIP_TRANSPORT_STR_BUFSIZE - strlen(buf));
3397
		return transports ?

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

   
3399
	}
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: /* Absorb this since it is irrelevant to SIP. */

    
   
7307
		break;
7274
	case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
7308
	case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
7275
	case -1:
7309
	case -1:
7276
		res = -1;
7310
		res = -1;
7277
		break;
7311
		break;
7278
	default:
7312
	default:
[+20] [20] 785 lines
[+20] [+] struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
8064

    
   
8098

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

    
   
8103
	p->reinviteid = -1;
8069
	p->autokillid = -1;
8104
	p->autokillid = -1;
8070
	p->request_queue_sched_id = -1;
8105
	p->request_queue_sched_id = -1;
8071
	p->provisional_keepalive_sched_id = -1;
8106
	p->provisional_keepalive_sched_id = -1;
8072
	p->t38id = -1;
8107
	p->t38id = -1;
8073
	p->subscribed = NONE;
8108
	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 */
9475
				/* Check number of ports offered for stream */
9441
				if (numberofports > 1) {
9476
				if (numberofports > 1) {
9442
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9477
					ast_log(LOG_WARNING, "%d ports offered for audio media, not supported by Asterisk. Will try anyway...\n", numberofports);
9443
				}
9478
				}
9444

    
   
9479

   
9445
				if (!strncmp(protocol, "SAVP", 4)) {
9480
				if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9446
					secure_audio = 1;
9481
					secure_audio = 1;
9447
				} else if (strncmp(protocol, "AVP", 3)) {
9482
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9448
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9483
					ast_log(LOG_WARNING, "Unknown RTP profile in audio offer: %s\n", m);
9449
					continue;
9484
					continue;
9450
				}
9485
				}
9451

    
   
9486

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

    
   
9539

   
9505
				if (!strncmp(protocol, "SAVP", 4)) {
9540
				if (!strcmp(protocol, "SAVP") || !strcmp(protocol, "SAVPF")) {
9506
					secure_video = 1;
9541
					secure_video = 1;
9507
				} else if (strncmp(protocol, "AVP", 3)) {
9542
				} else if (strcmp(protocol, "AVP") && strcmp(protocol, "AVPF")) {
9508
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9543
					ast_log(LOG_WARNING, "Unknown RTP profile in video offer: %s\n", m);
9509
					continue;
9544
					continue;
9510
				}
9545
				}
9511

    
   
9546

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

    
   
10798

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

    
   
10801

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

    
   
10804

   
10770
		if (!strncasecmp(trans, "ws", 2)) {
10805
		if (!strncasecmp(trans, "ws", 2)) {
10771
			if (debug)
10806
			if (debug)
10772
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10807
				ast_verbose("set_destination: URI is for WebSocket, we can't set destination\n");
10773
			return;
10808
			return;
[+20] [20] 10376 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.
21185
 *  must be locked for this function.
21151
 */
21186
 */
21152
static void check_pendings(struct sip_pvt *p)
21187
static void check_pendings(struct sip_pvt *p)
21153
{
21188
{
21154
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
21189
	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {

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

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

    
   
21192
			return;

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

    
   
21207
			if (p->pendinginvite && !p->ongoing_reinvite)
21169
				return;
21208
				return;
21170

    
   
21209

   
21171
			if (p->owner) {
21210
			if (p->owner) {
21172
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21211
				ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
21173
			}
21212
			}
[+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 ? */
21451
 	/* Final response, not 200 ? */
21413
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21452
 	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) {
21414
 		p->invitestate = INV_COMPLETED;
21453
 		p->invitestate = INV_COMPLETED;
21415
	}
21454
	}
21416
 	
21455
 	

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

    
   
21457
		p->ongoing_reinvite = 0;

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

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

    
   
21460
		}

    
   
21461
	}

    
   
21462

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

   
21421
			p->ongoing_reinvite = 0;

   
21422
		}

   
21423
	}
21466
	}
21424

    
   
21467

   
21425
	/* If this is a response to our initial INVITE, we need to set what we can use
21468
	/* If this is a response to our initial INVITE, we need to set what we can use
21426
	 * for this peer.
21469
	 * for this peer.
21427
	 */
21470
	 */
[+20] [20] 5649 lines
[+20] [+] static int sipsock_read(int *id, int fd, short events, void *ignore)
27077
	}
27120
	}
27078

    
   
27121

   
27079
	req.socket.fd = sipsock;
27122
	req.socket.fd = sipsock;
27080
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27123
	set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
27081
	req.socket.tcptls_session	= NULL;
27124
	req.socket.tcptls_session	= NULL;
27082
	req.socket.ws_session = NULL;

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

    
   
27126

   
27085
	handle_request_do(&req, &addr);
27127
	handle_request_do(&req, &addr);
27086
	deinit_req(&req);
27128
	deinit_req(&req);
27087

    
   
27129

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