Revision 28df6ac9 plugins/janus_sip.c

View differences:

plugins/janus_sip.c
295 295
	janus_sip_registration_status registration_status;
296 296
} janus_sip_account;
297 297

  
298
typedef struct janus_sip_rtp_context {
299
	/* Needed to fix seq and ts in case of re-INVITEs/UPDATEs that result in a RTP stream */
300
	uint32_t a_last_ssrc, a_last_ts, a_base_ts, a_base_ts_prev,
301
			v_last_ssrc, v_last_ts, v_base_ts, v_base_ts_prev;
302
	uint16_t a_last_seq, a_base_seq, a_base_seq_prev,
303
			v_last_seq, v_base_seq, v_base_seq_prev;
304
} janus_sip_rtp_context;
305

  
306 298
typedef struct janus_sip_media {
307 299
	char *remote_ip;
308 300
	int ready:1;
......
318 310
	srtp_t audio_srtp_in, audio_srtp_out;
319 311
	srtp_policy_t audio_remote_policy, audio_local_policy;
320 312
	int audio_srtp_suite_in, audio_srtp_suite_out;
321
	gboolean audio_send;
322 313
	int has_video:1;
323 314
	int video_rtp_fd, video_rtcp_fd;
324 315
	int local_video_rtp_port, remote_video_rtp_port;
......
329 320
	srtp_t video_srtp_in, video_srtp_out;
330 321
	srtp_policy_t video_remote_policy, video_local_policy;
331 322
	int video_srtp_suite_in, video_srtp_suite_out;
332
	gboolean video_send;
333
	janus_sip_rtp_context context;
334
	int pipefd[2];
335
	gboolean updated;
336 323
} janus_sip_media;
337 324

  
338 325
typedef struct janus_sip_session {
......
343 330
	janus_sip_media media;
344 331
	char *transaction;
345 332
	char *callee;
346
	janus_sdp *sdp;				/* The SDP this user sent */
347 333
	janus_recorder *arc;		/* The Janus recorder instance for this user's audio, if enabled */
348 334
	janus_recorder *arc_peer;	/* The Janus recorder instance for the peer's audio, if enabled */
349 335
	janus_recorder *vrc;		/* The Janus recorder instance for this user's video, if enabled */
......
520 506
/* Sofia callbacks */
521 507
void janus_sip_sofia_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
522 508
/* SDP parsing and manipulation */
523
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed);
509
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer);
524 510
char *janus_sip_sdp_manipulate(janus_sip_session *session, janus_sdp *sdp, gboolean answer);
525 511
/* Media */
526 512
static int janus_sip_allocate_local_ports(janus_sip_session *session);
......
625 611
					    g_free(session->callee);
626 612
					    session->callee = NULL;
627 613
					}
628
					if (session->sdp) {
629
					    janus_sdp_free(session->sdp);
630
					    session->sdp = NULL;
631
					}
632 614
					if (session->transaction) {
633 615
					    g_free(session->transaction);
634 616
					    session->transaction = NULL;
......
884 866
	session->stack = NULL;
885 867
	session->transaction = NULL;
886 868
	session->callee = NULL;
887
	session->sdp = NULL;
888 869
	session->media.remote_ip = NULL;
889 870
	session->media.ready = 0;
890 871
	session->media.autoack = TRUE;
......
904 885
	session->media.audio_pt_name = NULL;
905 886
	session->media.audio_srtp_suite_in = 0;
906 887
	session->media.audio_srtp_suite_out = 0;
907
	session->media.audio_send = TRUE;
908 888
	session->media.has_video = 0;
909 889
	session->media.video_rtp_fd = -1;
910 890
	session->media.video_rtcp_fd= -1;
......
918 898
	session->media.video_pt_name = NULL;
919 899
	session->media.video_srtp_suite_in = 0;
920 900
	session->media.video_srtp_suite_out = 0;
921
	session->media.video_send = TRUE;
922
	/* Initialize the RTP context */
923
	session->media.context.a_last_ssrc = 0;
924
	session->media.context.a_last_ssrc = 0;
925
	session->media.context.a_last_ts = 0;
926
	session->media.context.a_base_ts = 0;
927
	session->media.context.a_base_ts_prev = 0;
928
	session->media.context.v_last_ssrc = 0;
929
	session->media.context.v_last_ts = 0;
930
	session->media.context.v_base_ts = 0;
931
	session->media.context.v_base_ts_prev = 0;
932
	session->media.context.a_last_seq = 0;
933
	session->media.context.a_base_seq = 0;
934
	session->media.context.a_base_seq_prev = 0;
935
	session->media.context.v_last_seq = 0;
936
	session->media.context.v_base_seq = 0;
937
	session->media.context.v_base_seq_prev = 0;
938
	session->media.pipefd[0] = -1;
939
	session->media.pipefd[1] = -1;
940
	session->media.updated = FALSE;
941 901
	janus_mutex_init(&session->rec_mutex);
942 902
	session->destroyed = 0;
943 903
	g_atomic_int_set(&session->hangingup, 0);
......
1067 1027
			return;
1068 1028
		/* Forward to our SIP peer */
1069 1029
		if(video) {
1070
			if(!session->media.video_send) {
1071
				/* Dropping video packet, peer doesn't want to receive it */
1072
				return;
1073
			}
1074 1030
			if(session->media.video_ssrc == 0) {
1075 1031
				rtp_header *header = (rtp_header *)buf;
1076 1032
				session->media.video_ssrc = ntohl(header->ssrc);
......
1101 1057
				}
1102 1058
			}
1103 1059
		} else {
1104
			if(!session->media.audio_send) {
1105
				/* Dropping audio packet, peer doesn't want to receive it */
1106
				return;
1107
			}
1108 1060
			if(session->media.audio_ssrc == 0) {
1109 1061
				rtp_header *header = (rtp_header *)buf;
1110 1062
				session->media.audio_ssrc = ntohl(header->ssrc);
......
1663 1615
				g_snprintf(error_cause, 512, "Missing SDP");
1664 1616
				goto error;
1665 1617
			}
1666
			if(strstr(msg->sdp, "m=application")) {
1667
				JANUS_LOG(LOG_ERR, "The SIP plugin does not support DataChannels\n");
1668
				error_code = JANUS_SIP_ERROR_MISSING_SDP;
1669
				g_snprintf(error_cause, 512, "The SIP plugin does not support DataChannels");
1670
				goto error;
1671
			}
1672 1618
			JANUS_LOG(LOG_VERB, "%s is calling %s\n", session->account.username, uri_text);
1673 1619
			JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
1674 1620
			/* Clean up SRTP stuff from before first, in case it's still needed */
......
1711 1657
				g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1712 1658
				goto error;
1713 1659
			}
1714
			/* Take note of the SDP (may be useful for UPDATEs or re-INVITEs) */
1715
			janus_sdp_free(session->sdp);
1716
			session->sdp = parsed_sdp;
1660
			janus_sdp_free(parsed_sdp);
1717 1661
			JANUS_LOG(LOG_VERB, "Prepared SDP for INVITE:\n%s", sdp);
1718 1662
			/* Prepare the From header */
1719 1663
			char from_hdr[1024];
......
1729 1673
			if(session->stack->s_nh_i == NULL) {
1730 1674
				JANUS_LOG(LOG_WARN, "NUA Handle for INVITE still null??\n");
1731 1675
				g_free(sdp);
1732
				session->sdp = NULL;
1733 1676
				janus_sdp_free(parsed_sdp);
1734 1677
				error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1735 1678
				g_snprintf(error_cause, 512, "Invalid NUA Handle");
......
1846 1789
				g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1847 1790
				goto error;
1848 1791
			}
1792
			janus_sdp_free(parsed_sdp);
1849 1793
			if(session->media.audio_pt > -1) {
1850 1794
				session->media.audio_pt_name = janus_get_codec_from_pt(sdp, session->media.audio_pt);
1851 1795
				JANUS_LOG(LOG_VERB, "Detected audio codec: %d (%s)\n", session->media.audio_pt, session->media.audio_pt_name);
......
1854 1798
				session->media.video_pt_name = janus_get_codec_from_pt(sdp, session->media.video_pt);
1855 1799
				JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
1856 1800
			}
1857
			/* Take note of the SDP (may be useful for UPDATEs or re-INVITEs) */
1858
			janus_sdp_free(session->sdp);
1859
			session->sdp = parsed_sdp;
1860 1801
			JANUS_LOG(LOG_VERB, "Prepared SDP for 200 OK:\n%s", sdp);
1861 1802
			/* Send 200 OK */
1862 1803
			g_atomic_int_set(&session->hangingup, 0);
......
2336 2277
				nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2337 2278
				break;
2338 2279
			}
2339
			gboolean reinvite = FALSE;
2340 2280
			if(session->stack->s_nh_i != NULL) {
2341 2281
				if(session->stack->s_nh_i == nh) {
2342
					/* re-INVITE, we'll check what changed later */
2343
					reinvite = TRUE;
2344
					JANUS_LOG(LOG_VERB, "Got a re-INVITE...\n");
2282
					/* re-INVITE, we don't support those. */
2283
					nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2345 2284
				} else if(session->status >= janus_sip_call_status_inviting) {
2346 2285
					/* Busy with another call */
2347 2286
					JANUS_LOG(LOG_VERB, "\tAlready in a call (busy, status=%s)\n", janus_sip_call_status_string(session->status));
......
2364 2303
					int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, missed_text, NULL, NULL);
2365 2304
					JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
2366 2305
					g_free(missed_text);
2367
					/* Done */
2368
					janus_sdp_free(sdp);
2369
					break;
2370 2306
				}
2371
			}
2372
			if(!reinvite) {
2373
				/* New incoming call */
2374
				session->callee = g_strdup(url_as_string(session->stack->s_home, sip->sip_from->a_url));
2375
				session->status = janus_sip_call_status_invited;
2376
				/* Clean up SRTP stuff from before first, in case it's still needed */
2377
				janus_sip_srtp_cleanup(session);
2378
			}
2379
			/* Parse SDP */
2380
			JANUS_LOG(LOG_VERB, "Someone is %s a call:\n%s",
2381
				reinvite ? "updating" : "inviting us in",
2382
				sip->sip_payload->pl_data);
2383
			gboolean changed = FALSE;
2384
			janus_sip_sdp_process(session, sdp, FALSE, reinvite, &changed);
2385
			if(reinvite) {
2386
				/* No need to involve the browser: we reply ourselves */
2387
				nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2388 2307
				janus_sdp_free(sdp);
2389 2308
				break;
2390 2309
			}
2310
			/* New incoming call */
2311
			session->callee = g_strdup(url_as_string(session->stack->s_home, sip->sip_from->a_url));
2312
			session->status = janus_sip_call_status_invited;
2313
			/* Clean up SRTP stuff from before first, in case it's still needed */
2314
			janus_sip_srtp_cleanup(session);
2315
			/* Parse SDP */
2316
			char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
2317
			JANUS_LOG(LOG_VERB, "Someone is inviting us in a call:\n%s", sip->sip_payload->pl_data);
2318
			janus_sip_sdp_process(session, sdp, FALSE);
2391 2319
			/* Send SDP to the browser */
2392 2320
			json_t *call = json_object();
2393 2321
			json_object_set_new(call, "sip", json_string("event"));
......
2405 2333
			char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
2406 2334
			json_decref(call);
2407 2335
			JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
2408
			int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "offer", sip->sip_payload->pl_data);
2336
			int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "offer", fixed_sdp);
2409 2337
			JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
2410 2338
			g_free(call_text);
2339
			g_free(fixed_sdp);
2411 2340
			janus_sdp_free(sdp);
2412 2341
			/* Send a Ringing back */
2413 2342
			nua_respond(nh, 180, sip_status_phrase(180), TAG_END());
......
2515 2444
			JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sip->sip_payload->pl_data);
2516 2445
			session->status = janus_sip_call_status_incall;
2517 2446
			char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
2518
			janus_sip_sdp_process(session, sdp, TRUE, FALSE, NULL);
2447
			janus_sip_sdp_process(session, sdp, TRUE);
2519 2448
			/* If we asked for SRTP and are not getting it, fail */
2520 2449
			if(session->media.require_srtp && !session->media.has_srtp_remote) {
2521 2450
				JANUS_LOG(LOG_ERR, "\tWe asked for mandatory SRTP but didn't get any in the reply!\n");
......
2625 2554
	}
2626 2555
}
2627 2556

  
2628
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed) {
2557
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer) {
2629 2558
	if(!session || !sdp)
2630 2559
		return;
2631 2560
	/* c= */
2632 2561
	if(sdp->c_addr) {
2633
		if(update && strcmp(sdp->c_addr, session->media.remote_ip)) {
2634
			/* This is an update and an address changed */
2635
			if(changed)
2636
				*changed = TRUE;
2637
		}
2638 2562
		g_free(session->media.remote_ip);
2639 2563
		session->media.remote_ip = g_strdup(sdp->c_addr);
2564
		JANUS_LOG(LOG_VERB, "  >> Media connection:\n");
2565
		JANUS_LOG(LOG_VERB, "       %s\n", session->media.remote_ip);
2640 2566
	}
2567
	JANUS_LOG(LOG_VERB, "  >> Media lines:\n");
2641 2568
	GList *temp = sdp->m_lines;
2642 2569
	while(temp) {
2643 2570
		janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
2644 2571
		session->media.require_srtp = session->media.require_srtp || (m->proto && !strcasecmp(m->proto, "RTP/SAVP"));
2645 2572
		if(m->type == JANUS_SDP_AUDIO) {
2573
			JANUS_LOG(LOG_VERB, "       Audio: %"SCNu16"\n", m->port);
2646 2574
			if(m->port) {
2647
				if(m->port != session->media.remote_audio_rtp_port) {
2648
					/* This is an update and an address changed */
2649
					if(changed)
2650
						*changed = TRUE;
2651
				}
2652 2575
				session->media.has_audio = 1;
2653 2576
				session->media.remote_audio_rtp_port = m->port;
2654 2577
				session->media.remote_audio_rtcp_port = m->port+1;	/* FIXME We're assuming RTCP is on the next port */
2655
				if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2656
					session->media.audio_send = FALSE;
2657
				else
2658
					session->media.audio_send = TRUE;
2659
			} else {
2660
				session->media.audio_send = FALSE;
2661 2578
			}
2662 2579
		} else if(m->type == JANUS_SDP_VIDEO) {
2580
			JANUS_LOG(LOG_VERB, "       Video: %"SCNu16"\n", m->port);
2663 2581
			if(m->port) {
2664
				if(m->port != session->media.remote_video_rtp_port) {
2665
					/* This is an update and an address changed */
2666
					if(changed)
2667
						*changed = TRUE;
2668
				}
2669 2582
				session->media.has_video = 1;
2670 2583
				session->media.remote_video_rtp_port = m->port;
2671 2584
				session->media.remote_video_rtcp_port = m->port+1;	/* FIXME We're assuming RTCP is on the next port */
2672
				if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2673
					session->media.video_send = FALSE;
2674
				else
2675
					session->media.video_send = TRUE;
2676
			} else {
2677
				session->media.video_send = FALSE;
2678 2585
			}
2679 2586
		} else {
2680
			JANUS_LOG(LOG_WARN, "Unsupported media line (not audio/video)\n");
2587
			JANUS_LOG(LOG_WARN, "       Unsupported media line (not audio/video)\n");
2681 2588
			temp = temp->next;
2682 2589
			continue;
2683 2590
		}
2591
		JANUS_LOG(LOG_VERB, "       Media connections:\n");
2684 2592
		if(m->c_addr) {
2685
			if(update && strcmp(m->c_addr, session->media.remote_ip)) {
2686
				/* This is an update and an address changed */
2687
				if(changed)
2688
					*changed = TRUE;
2689
			}
2690 2593
			g_free(session->media.remote_ip);
2691 2594
			session->media.remote_ip = g_strdup(m->c_addr);
2595
			JANUS_LOG(LOG_VERB, "         [%s]\n", session->media.remote_ip);
2692 2596
		}
2693
		if(update) {
2694
			/* FIXME This is a session update, we only accept changes in IP/ports */
2695
			temp = temp->next;
2696
			continue;
2697
		}
2597
		JANUS_LOG(LOG_VERB, "       Media attributes:\n");
2698 2598
		GList *tempA = m->attributes;
2699 2599
		while(tempA) {
2700 2600
			janus_sdp_attribute *a = (janus_sdp_attribute *)tempA->data;
2701 2601
			if(a->name) {
2702
				if(!strcasecmp(a->name, "crypto")) {
2602
				if(!strcasecmp(a->name, "rtpmap")) {
2603
					JANUS_LOG(LOG_VERB, "         RTP Map:     %s\n", a->value);
2604
				} else if(!strcasecmp(a->name, "crypto")) {
2605
					JANUS_LOG(LOG_VERB, "         Crypto:      %s\n", a->value);
2703 2606
					if(m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO) {
2704 2607
						gint32 tag = 0;
2705 2608
						int suite;
......
2744 2647
		}
2745 2648
		temp = temp->next;
2746 2649
	}
2747
	if(changed && *changed) {
2748
		/* Something changed: mark this on the session, so that the thread can update the sockets */
2749
		session->media.updated = TRUE;
2750
		if(session->media.pipefd[1] > 0) {
2751
			int code = 1;
2752
			ssize_t res = 0;
2753
			do {
2754
				res = write(session->media.pipefd[1], &code, sizeof(int));
2755
			} while(res == -1 && errno == EINTR);
2756
		}
2757
	}
2758 2650
}
2759 2651

  
2760 2652
char *janus_sip_sdp_manipulate(janus_sip_session *session, janus_sdp *sdp, gboolean answer) {
......
2840 2732
	session->media.local_video_rtp_port = 0;
2841 2733
	session->media.local_video_rtcp_port = 0;
2842 2734
	session->media.video_ssrc = 0;
2843
	if(session->media.pipefd[0] > 0) {
2844
		close(session->media.pipefd[0]);
2845
		session->media.pipefd[0] = -1;
2846
	}
2847
	if(session->media.pipefd[1] > 0) {
2848
		close(session->media.pipefd[1]);
2849
		session->media.pipefd[1] = -1;
2850
	}
2851 2735
	/* Start */
2852 2736
	int attempts = 100;	/* FIXME Don't retry forever */
2853 2737
	if(session->media.has_audio) {
......
2932 2816
			session->media.local_video_rtcp_port = rtcp_port;
2933 2817
		}
2934 2818
	}
2935
	/* We need this to quickly interrupt the poll when it's time to update a session or wrap up */
2936
	pipe(session->media.pipefd);
2937 2819
	return 0;
2938 2820
}
2939 2821

  
2940
/* Helper method to (re)connect RTP/RTCP sockets */
2941
static void janus_sip_connect_sockets(janus_sip_session *session, struct sockaddr_in *server_addr) {
2942
	if(!session || !server_addr)
2943
		return;
2944

  
2945
	if(session->media.updated) {
2946
		JANUS_LOG(LOG_VERB, "Updating session sockets\n");
2947
	}
2948

  
2949
	/* Connect peers (FIXME This pretty much sucks right now) */
2950
	if(session->media.remote_audio_rtp_port) {
2951
		server_addr->sin_port = htons(session->media.remote_audio_rtp_port);
2952
		if(connect(session->media.audio_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2953
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtp_port);
2954
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2955
		}
2956
	}
2957
	if(session->media.remote_audio_rtcp_port) {
2958
		server_addr->sin_port = htons(session->media.remote_audio_rtcp_port);
2959
		if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2960
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtcp_port);
2961
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2962
		}
2963
	}
2964
	if(session->media.remote_video_rtp_port) {
2965
		server_addr->sin_port = htons(session->media.remote_video_rtp_port);
2966
		if(connect(session->media.video_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2967
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtp_port);
2968
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2969
		}
2970
	}
2971
	if(session->media.remote_video_rtcp_port) {
2972
		server_addr->sin_port = htons(session->media.remote_video_rtcp_port);
2973
		if(connect(session->media.video_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2974
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtcp_port);
2975
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2976
		}
2977
	}
2978

  
2979
}
2980

  
2981 2822
/* Thread to relay RTP/RTCP frames coming from the SIP peer */
2982 2823
static void *janus_sip_relay_thread(void *data) {
2983 2824
	janus_sip_session *session = (janus_sip_session *)data;
......
3000 2841
			server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
3001 2842
		}
3002 2843
	}
3003
	if(have_server_ip)
3004
		janus_sip_connect_sockets(session, &server_addr);
2844

  
2845
	/* Connect peers (FIXME This pretty much sucks right now) */
2846
	if(have_server_ip && session->media.remote_audio_rtp_port) {
2847
		server_addr.sin_port = htons(session->media.remote_audio_rtp_port);
2848
		if(connect(session->media.audio_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
2849
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtp_port);
2850
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2851
		}
2852
	}
2853
	if(have_server_ip && session->media.remote_audio_rtcp_port) {
2854
		server_addr.sin_port = htons(session->media.remote_audio_rtcp_port);
2855
		if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
2856
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtcp_port);
2857
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2858
		}
2859
	}
2860
	if(have_server_ip && session->media.remote_video_rtp_port) {
2861
		server_addr.sin_port = htons(session->media.remote_video_rtp_port);
2862
		if(connect(session->media.video_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
2863
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtp_port);
2864
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2865
		}
2866
	}
2867
	if(have_server_ip && session->media.remote_video_rtcp_port) {
2868
		server_addr.sin_port = htons(session->media.remote_video_rtcp_port);
2869
		if(connect(session->media.video_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
2870
			JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtcp_port);
2871
			JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2872
		}
2873
	}
3005 2874

  
3006 2875
	if(!session->callee) {
3007 2876
		JANUS_LOG(LOG_VERB, "[SIP-%s] Leaving thread, no callee...\n", session->account.username);
......
3013 2882
	struct sockaddr_in remote;
3014 2883
	int resfd = 0, bytes = 0;
3015 2884
	struct pollfd fds[4];
3016
	int pipe_fd = session->media.pipefd[0];
3017 2885
	char buffer[1500];
3018 2886
	memset(buffer, 0, 1500);
3019 2887
	/* Loop */
3020 2888
	int num = 0;
3021 2889
	gboolean goon = TRUE;
3022
	int astep = 0, vstep = 0;
3023
	guint32 ats = 0, vts = 0;
3024 2890
	while(goon && session != NULL && !session->destroyed &&
3025 2891
			session->status > janus_sip_call_status_idle &&
3026 2892
			session->status < janus_sip_call_status_closing) {	/* FIXME We need a per-call watchdog as well */
3027

  
3028
		if(session->media.updated) {
3029
			/* Apparently there was a session update */
3030
			if(have_server_ip)
3031
				janus_sip_connect_sockets(session, &server_addr);
3032
			session->media.updated = FALSE;
3033
		}
3034

  
3035 2893
		/* Prepare poll */
3036 2894
		num = 0;
3037 2895
		if(session->media.audio_rtp_fd != -1) {
......
3058 2916
			fds[num].revents = 0;
3059 2917
			num++;
3060 2918
		}
3061
		if(pipe_fd != -1) {
3062
			fds[num].fd = pipe_fd;
3063
			fds[num].events = POLLIN;
3064
			fds[num].revents = 0;
3065
			num++;
3066
		}
3067 2919
		/* Wait for some data */
3068 2920
		resfd = poll(fds, num, 1000);
3069 2921
		if(resfd < 0) {
......
3085 2937
				JANUS_LOG(LOG_ERR, "[SIP-%s] Error polling: %s...\n", session->account.username,
3086 2938
					fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
3087 2939
				JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3088
				if(session->media.updated)
3089
					break;
3090 2940
				goon = FALSE;	/* Can we assume it's pretty much over, after a POLLERR? */
3091 2941
				/* FIXME Simulate a "hangup" coming from the browser */
3092 2942
				janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
......
3098 2948
				g_async_queue_push(messages, msg);
3099 2949
				break;
3100 2950
			} else if(fds[i].revents & POLLIN) {
3101
				if(pipe_fd != -1 && fds[i].fd == pipe_fd) {
3102
					/* Poll interrupted for a reason, go on */
3103
					int code = 0;
3104
					bytes = read(pipe_fd, &code, sizeof(int));
3105
					break;
3106
				}
3107 2951
				/* Got an RTP/RTCP packet */
3108 2952
				if(session->media.audio_rtp_fd != -1 && fds[i].fd == session->media.audio_rtp_fd) {
3109 2953
					/* Got something audio (RTP) */
3110 2954
					addrlen = sizeof(remote);
3111 2955
					bytes = recvfrom(session->media.audio_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2956
					//~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTP channel...\n", bytes);
2957
					//~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2958
					//~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2959
						//~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
3112 2960
					if(session->media.audio_ssrc_peer == 0) {
3113 2961
						rtp_header *header = (rtp_header *)buffer;
3114 2962
						session->media.audio_ssrc_peer = ntohl(header->ssrc);
......
3128 2976
						}
3129 2977
						bytes = buflen;
3130 2978
					}
3131
					/* Check if the SSRC changed (e.g., after a re-INVITE or UPDATE) */
3132
					rtp_header *header = (rtp_header *)buffer;
3133
					guint32 ssrc = ntohl(header->ssrc);
3134
					guint32 timestamp = ntohl(header->timestamp);
3135
					guint16 seq = ntohs(header->seq_number);
3136
					if(ssrc != session->media.context.a_last_ssrc) {
3137
						JANUS_LOG(LOG_VERB, "Audio SSRC changed (re-INVITE?), %"SCNu32" --> %"SCNu32"\n",
3138
							session->media.context.a_last_ssrc, ssrc);
3139
						session->media.context.a_last_ssrc = ssrc;
3140
						session->media.context.a_base_ts_prev = session->media.context.a_last_ts;
3141
						session->media.context.a_base_ts = timestamp;
3142
						session->media.context.a_base_seq_prev = session->media.context.a_last_seq;
3143
						session->media.context.a_base_seq = seq;
3144
					}
3145
					/* Compute a coherent timestamp and sequence number */
3146
					session->media.context.a_last_ts = (timestamp-session->media.context.a_base_ts)
3147
						+ session->media.context.a_base_ts_prev+(astep ? astep : 960);	/* FIXME */
3148
					session->media.context.a_last_seq = (seq-session->media.context.a_base_seq)+session->media.context.a_base_seq_prev+1;
3149
					/* Update the timestamp and sequence number in the RTP packet, and send it */
3150
					header->timestamp = htonl(session->media.context.a_last_ts);
3151
					header->seq_number = htons(session->media.context.a_last_seq);
3152
					if(ats == 0) {
3153
						ats = timestamp;
3154
					} else if(astep == 0) {
3155
						astep = timestamp-ats;
3156
						if(astep < 0)
3157
							astep = 0;
3158
					}
3159 2979
					/* Save the frame if we're recording */
3160 2980
					janus_recorder_save_frame(session->arc_peer, buffer, bytes);
3161 2981
					/* Relay to browser */
......
3207 3027
						}
3208 3028
						bytes = buflen;
3209 3029
					}
3210
					/* Check if the SSRC changed (e.g., after a re-INVITE or UPDATE) */
3211
					rtp_header *header = (rtp_header *)buffer;
3212
					guint32 ssrc = ntohl(header->ssrc);
3213
					guint32 timestamp = ntohl(header->timestamp);
3214
					guint16 seq = ntohs(header->seq_number);
3215
					if(ssrc != session->media.context.v_last_ssrc) {
3216
						JANUS_LOG(LOG_VERB, "Video SSRC changed (re-INVITE?)\n");
3217
						session->media.context.v_last_ssrc = ssrc;
3218
						session->media.context.v_base_ts_prev = session->media.context.v_last_ts;
3219
						session->media.context.v_base_ts = timestamp;
3220
						session->media.context.v_base_seq_prev = session->media.context.v_last_seq;
3221
						session->media.context.v_base_seq = seq;
3222
					}
3223
					/* Compute a coherent timestamp and sequence number */
3224
					session->media.context.v_last_ts = (timestamp-session->media.context.v_base_ts)
3225
						+ session->media.context.v_base_ts_prev+(vstep ? vstep : 4500);	/* FIXME */
3226
					session->media.context.v_last_seq = (seq-session->media.context.v_base_seq)+session->media.context.v_base_seq_prev+1;
3227
					/* Update the timestamp and sequence number in the RTP packet, and send it */
3228
					header->timestamp = htonl(session->media.context.v_last_ts);
3229
					header->seq_number = htons(session->media.context.v_last_seq);
3230
					if(vts == 0) {
3231
						vts = timestamp;
3232
					} else if(vstep == 0) {
3233
						vstep = timestamp-vts;
3234
						if(vstep < 0)
3235
							vstep = 0;
3236
					}
3237 3030
					/* Save the frame if we're recording */
3238 3031
					janus_recorder_save_frame(session->vrc_peer, buffer, bytes);
3239 3032
					/* Relay to browser */
......
3284 3077
	session->media.local_video_rtp_port = 0;
3285 3078
	session->media.local_video_rtcp_port = 0;
3286 3079
	session->media.video_ssrc = 0;
3287
	if(session->media.pipefd[0] > 0) {
3288
		close(session->media.pipefd[0]);
3289
		session->media.pipefd[0] = -1;
3290
	}
3291
	if(session->media.pipefd[1] > 0) {
3292
		close(session->media.pipefd[1]);
3293
		session->media.pipefd[1] = -1;
3294
	}
3295 3080
	/* Clean up SRTP stuff, if needed */
3296 3081
	janus_sip_srtp_cleanup(session);
3297 3082
	/* Done */
......
3331 3116
	session->stack->s_nua = nua_create(session->stack->s_root,
3332 3117
				janus_sip_sofia_callback,
3333 3118
				session,
3334
				SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE"),
3119
				SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS"),
3335 3120
				NUTAG_M_USERNAME(session->account.username),
3336 3121
				NUTAG_URL(sip_url),
3337 3122
				TAG_IF(session->account.sips, NUTAG_SIPS_URL(sips_url)),

Also available in: Unified diff