Revision 78955474

View differences:

plugins/janus_audiobridge.c
500 500
	gpointer participant;
501 501
	gboolean started;
502 502
	gboolean stopping;
503
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
503
	gboolean hangingup;
504
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
504 505
} janus_audiobridge_session;
505 506
static GHashTable *sessions;
506 507
static GList *old_sessions;
......
876 877
	JANUS_LOG(LOG_VERB, "Removing AudioBridge session...\n");
877 878
	janus_mutex_lock(&sessions_mutex);
878 879
	if(!session->destroyed) {
879
		session->destroyed = janus_get_monotonic_time();
880 880
		g_hash_table_remove(sessions, handle);
881 881
		janus_audiobridge_hangup_media(handle);
882
		session->destroyed = janus_get_monotonic_time();
882 883
		/* Cleaning up and removing the session is done in a lazy way */
883 884
		old_sessions = g_list_append(old_sessions, session);
884 885
	}
......
1532 1533
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1533 1534
		return;
1534 1535
	}
1535
	if(session->destroyed || !session->participant)
1536
	session->started = FALSE;
1537
	if(session->destroyed || !session->participant || session->hangingup)
1536 1538
		return;
1539
	session->hangingup = TRUE;
1537 1540
	/* Get rid of participant */
1538 1541
	janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
1539 1542
	janus_audiobridge_room *audiobridge = participant->room;
......
1562 1565
	}
1563 1566
	/* Free the participant resources */
1564 1567
	janus_mutex_lock(&participant->qmutex);
1565
	session->started = FALSE;
1566 1568
	participant->active = FALSE;
1567 1569
	participant->muted = TRUE;
1568 1570
	if(participant->display)
......
1593 1595
	if(audiobridge != NULL) {
1594 1596
		janus_mutex_unlock(&audiobridge->mutex);
1595 1597
	}
1598
	/* Done */
1599
	session->hangingup = FALSE;
1596 1600
}
1597 1601

  
1598 1602
/* Thread to handle incoming messages */
plugins/janus_echotest.c
177 177
	gboolean video_active;
178 178
	uint64_t bitrate;
179 179
	guint16 slowlink_count;
180
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
180
	gboolean hangingup;
181
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
181 182
} janus_echotest_session;
182 183
static GHashTable *sessions;
183 184
static GList *old_sessions;
......
588 589
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
589 590
		return;
590 591
	}
591
	if(session->destroyed)
592
	if(session->destroyed || session->hangingup)
592 593
		return;
594
	session->hangingup = TRUE;
593 595
	/* Send an event to the browser and tell it's over */
594 596
	json_t *event = json_object();
595 597
	json_object_set_new(event, "echotest", json_string("event"));
......
604 606
	session->audio_active = TRUE;
605 607
	session->video_active = TRUE;
606 608
	session->bitrate = 0;
609
	/* Done */
610
	session->hangingup = FALSE;
607 611
}
608 612

  
609 613
/* Thread to handle incoming messages */
plugins/janus_recordplay.c
383 383
	guint video_keyframe_interval; /* keyframe request interval (ms) */
384 384
	guint64 video_keyframe_request_last; /* timestamp of last keyframe request sent */
385 385
	gint video_fir_seq;
386
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
386
	gboolean hangingup;
387
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
387 388
} janus_recordplay_session;
388 389
static GHashTable *sessions;
389 390
static GList *old_sessions;
......
1040 1041
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1041 1042
		return;
1042 1043
	}
1043
	if(session->destroyed)
1044
		return;
1045 1044
	session->active = FALSE;
1046
	if(!session->recorder)
1045
	if(session->destroyed || !session->recorder || session->hangingup)
1047 1046
		return;
1047
	session->hangingup = TRUE;
1048 1048

  
1049 1049
	/* Send an event to the browser and tell it's over */
1050 1050
	json_t *event = json_object();
......
1065 1065
	msg->sdp_type = NULL;
1066 1066
	msg->sdp = NULL;
1067 1067
	g_async_queue_push(messages, msg);
1068
	/* Done */
1069
	session->hangingup = FALSE;
1068 1070
}
1069 1071

  
1070 1072
/* Thread to handle incoming messages */
......
1622 1624

  
1623 1625
	/* Pre-parse */
1624 1626
	JANUS_LOG(LOG_VERB, "Pre-parsing file %s to generate ordered index...\n", source);
1627
	gboolean parsed_header = FALSE;
1625 1628
	int bytes = 0;
1626 1629
	long offset = 0;
1627 1630
	uint16_t len = 0, count = 0;
......
1638 1641
			fclose(file);
1639 1642
			return NULL;
1640 1643
		}
1641
		offset += 8;
1642
		bytes = fread(&len, sizeof(uint16_t), 1, file);
1643
		len = ntohs(len);
1644
		offset += 2;
1645
		if(len == 5) {
1646
			/* This is the main header */
1647
			bytes = fread(prebuffer, sizeof(char), 5, file);
1648
			if(prebuffer[0] == 'v') {
1649
				JANUS_LOG(LOG_VERB, "This is a video recording, assuming VP8\n");
1650
			} else if(prebuffer[0] == 'a') {
1651
				JANUS_LOG(LOG_VERB, "This is an audio recording, assuming Opus\n");
1652
			} else {
1653
				JANUS_LOG(LOG_ERR, "Unsupported recording media type...\n");
1654
				fclose(file);
1655
				return NULL;
1644
		if(prebuffer[1] == 'E') {
1645
			/* Either the old .mjr format header ('MEETECHO' header followed by 'audio' or 'video'), or a frame */
1646
			offset += 8;
1647
			bytes = fread(&len, sizeof(uint16_t), 1, file);
1648
			len = ntohs(len);
1649
			offset += 2;
1650
			if(len == 5 && !parsed_header) {
1651
				/* This is the main header */
1652
				parsed_header = TRUE;
1653
				JANUS_LOG(LOG_VERB, "Old .mjr header format\n");
1654
				bytes = fread(prebuffer, sizeof(char), 5, file);
1655
				if(prebuffer[0] == 'v') {
1656
					JANUS_LOG(LOG_INFO, "This is a video recording, assuming VP8\n");
1657
				} else if(prebuffer[0] == 'a') {
1658
					JANUS_LOG(LOG_INFO, "This is an audio recording, assuming Opus\n");
1659
				} else {
1660
					JANUS_LOG(LOG_WARN, "Unsupported recording media type...\n");
1661
					fclose(file);
1662
					return NULL;
1663
				}
1664
				offset += len;
1665
				continue;
1666
			} else if(len < 12) {
1667
				/* Not RTP, skip */
1668
				JANUS_LOG(LOG_VERB, "Skipping packet (not RTP?)\n");
1669
				offset += len;
1670
				continue;
1656 1671
			}
1657
			offset += len;
1658
			continue;
1659
		} else if(len < 12) {
1660
			/* Not RTP, skip */
1661
			JANUS_LOG(LOG_VERB, "Skipping packet (not RTP?)\n");
1662
			offset += len;
1663
			continue;
1672
		} else if(prebuffer[1] == 'J') {
1673
			/* New .mjr format, the header may contain useful info */
1674
			offset += 8;
1675
			bytes = fread(&len, sizeof(uint16_t), 1, file);
1676
			len = ntohs(len);
1677
			offset += 2;
1678
			if(len > 0 && !parsed_header) {
1679
				/* This is the info header */
1680
				JANUS_LOG(LOG_VERB, "New .mjr header format\n");
1681
				bytes = fread(prebuffer, sizeof(char), len, file);
1682
				parsed_header = TRUE;
1683
				prebuffer[len] = '\0';
1684
				json_error_t error;
1685
				json_t *info = json_loads(prebuffer, 0, &error);
1686
				if(!info) {
1687
					JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text);
1688
					JANUS_LOG(LOG_WARN, "Error parsing info header...\n");
1689
					fclose(file);
1690
					return NULL;
1691
				}
1692
				/* Is it audio or video? */
1693
				json_t *type = json_object_get(info, "t");
1694
				if(!type || !json_is_string(type)) {
1695
					JANUS_LOG(LOG_WARN, "Missing/invalid recording type in info header...\n");
1696
					fclose(file);
1697
					return NULL;
1698
				}
1699
				const char *t = json_string_value(type);
1700
				int video = 0;
1701
				gint64 c_time = 0, w_time = 0;
1702
				if(!strcasecmp(t, "v")) {
1703
					video = 1;
1704
				} else if(!strcasecmp(t, "a")) {
1705
					video = 0;
1706
				} else {
1707
					JANUS_LOG(LOG_WARN, "Unsupported recording type '%s' in info header...\n", t);
1708
					fclose(file);
1709
					return NULL;
1710
				}
1711
				/* What codec was used? */
1712
				json_t *codec = json_object_get(info, "c");
1713
				if(!codec || !json_is_string(codec)) {
1714
					JANUS_LOG(LOG_WARN, "Missing recording codec in info header...\n");
1715
					fclose(file);
1716
					return NULL;
1717
				}
1718
				const char *c = json_string_value(codec);
1719
				if(video && strcasecmp(c, "vp8")) {
1720
					JANUS_LOG(LOG_WARN, "The post-processor only suupports VP8 video for now (was '%s')...\n", c);
1721
					fclose(file);
1722
					return NULL;
1723
				} else if(!video && strcasecmp(c, "opus")) {
1724
					JANUS_LOG(LOG_WARN, "The post-processor only suupports Opus audio for now (was '%s')...\n", c);
1725
					fclose(file);
1726
					return NULL;
1727
				}
1728
				/* When was the file created? */
1729
				json_t *created = json_object_get(info, "s");
1730
				if(!created || !json_is_integer(created)) {
1731
					JANUS_LOG(LOG_WARN, "Missing recording created time in info header...\n");
1732
					fclose(file);
1733
					return NULL;
1734
				}
1735
				c_time = json_integer_value(created);
1736
				/* When was the first frame written? */
1737
				json_t *written = json_object_get(info, "u");
1738
				if(!written || !json_is_integer(written)) {
1739
					JANUS_LOG(LOG_WARN, "Missing recording written time in info header...\n");
1740
					fclose(file);
1741
					return NULL;
1742
				}
1743
				w_time = json_integer_value(created);
1744
				/* Summary */
1745
				JANUS_LOG(LOG_VERB, "This is %s recording:\n", video ? "a video" : "an audio");
1746
				JANUS_LOG(LOG_VERB, "  -- Codec:   %s\n", c);
1747
				JANUS_LOG(LOG_VERB, "  -- Created: %"SCNi64"\n", c_time);
1748
				JANUS_LOG(LOG_VERB, "  -- Written: %"SCNi64"\n", w_time);
1749
			}
1750
		} else {
1751
			JANUS_LOG(LOG_ERR, "Invalid header...\n");
1752
			fclose(file);
1753
			return NULL;
1664 1754
		}
1665 1755
		/* Only read RTP header */
1666 1756
		bytes = fread(prebuffer, sizeof(char), 16, file);
......
1699 1789
		len = ntohs(len);
1700 1790
		JANUS_LOG(LOG_HUGE, "  -- Length: %"SCNu16"\n", len);
1701 1791
		offset += 2;
1702
		if(len < 12) {
1792
		if(prebuffer[1] == 'J' || len < 12) {
1703 1793
			/* Not RTP, skip */
1704 1794
			JANUS_LOG(LOG_HUGE, "  -- Not RTP, skipping\n");
1705 1795
			offset += len;
plugins/janus_sip.c
272 272
	janus_sip_media media;
273 273
	char *transaction;
274 274
	char *callee;
275
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
275
	gboolean hangingup;
276
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
276 277
	janus_mutex mutex;
277 278
} janus_sip_session;
278 279
static GHashTable *sessions;
......
656 657
	}
657 658
	janus_mutex_lock(&sessions_mutex);
658 659
	if(!session->destroyed) {
659
		session->destroyed = janus_get_monotonic_time();
660 660
		g_hash_table_remove(sessions, handle);
661 661
		janus_sip_hangup_media(handle);
662
		session->destroyed = janus_get_monotonic_time();
662 663
		JANUS_LOG(LOG_VERB, "Destroying SIP session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
663 664
		/* Shutdown the NUA */
664 665
		nua_shutdown(session->stack->s_nua);
......
797 798
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
798 799
		return;
799 800
	}
800
	if(session->destroyed)
801
	if(session->destroyed || session->hangingup)
801 802
		return;
803
	session->hangingup = TRUE;
802 804
	if(!(session->status == janus_sip_call_status_inviting ||
803 805
		 session->status == janus_sip_call_status_invited ||
804 806
		 session->status == janus_sip_call_status_incall))
......
811 813
	msg->sdp_type = NULL;
812 814
	msg->sdp = NULL;
813 815
	g_async_queue_push(messages, msg);
816
	/* Done */
817
	session->hangingup = FALSE;
814 818
}
815 819

  
816 820
/* Thread to handle incoming messages */
plugins/janus_streaming.c
318 318
	gboolean paused;
319 319
	janus_streaming_context context;
320 320
	gboolean stopping;
321
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
321
	gboolean hangingup;
322
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
322 323
} janus_streaming_session;
323 324
static GHashTable *sessions;
324 325
static GList *old_sessions;
......
1934 1935
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1935 1936
		return;
1936 1937
	}
1937
	if(session->destroyed)
1938
	if(session->destroyed || session->hangingup)
1938 1939
		return;
1940
	session->hangingup = TRUE;
1939 1941
	/* FIXME Simulate a "stop" coming from the browser */
1940 1942
	janus_streaming_message *msg = calloc(1, sizeof(janus_streaming_message));
1941
	if(msg == NULL) {
1942
		JANUS_LOG(LOG_FATAL, "Memory error!\n");
1943
		return;
1944
	}
1945 1943
	msg->handle = handle;
1946 1944
	msg->message = json_loads("{\"request\":\"stop\"}", 0, NULL);
1947 1945
	msg->transaction = NULL;
1948 1946
	msg->sdp_type = NULL;
1949 1947
	msg->sdp = NULL;
1950 1948
	g_async_queue_push(messages, msg);
1949
	/* Done */
1950
	session->hangingup = FALSE;
1951 1951
}
1952 1952

  
1953 1953
/* Thread to handle incoming messages */
plugins/janus_videocall.c
334 334
	uint64_t bitrate;
335 335
	guint16 slowlink_count;
336 336
	struct janus_videocall_session *peer;
337
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
337
	gboolean hangingup;
338
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
338 339
} janus_videocall_session;
339 340
static GHashTable *sessions;
340 341
static GList *old_sessions;
......
536 537
	}
537 538
	janus_mutex_lock(&sessions_mutex);
538 539
	if(!session->destroyed) {
539
		session->destroyed = janus_get_monotonic_time();
540 540
		JANUS_LOG(LOG_VERB, "Removing VideoCall user %s session...\n", session->username ? session->username : "'unknown'");
541 541
		janus_videocall_hangup_media(handle);
542
		session->destroyed = janus_get_monotonic_time();
542 543
		if(session->username != NULL) {
543 544
			int res = g_hash_table_remove(sessions, (gpointer)session->username);
544 545
			JANUS_LOG(LOG_VERB, "  -- Removed: %d\n", res);
......
760 761
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
761 762
		return;
762 763
	}
763
	if(session->destroyed)
764
	if(session->destroyed || session->hangingup)
764 765
		return;
765
	janus_mutex_lock(&sessions_mutex);
766
	session->hangingup = TRUE;
766 767
	if(session->peer) {
767 768
		/* Send event to our peer too */
768 769
		json_t *call = json_object();
......
784 785
	session->audio_active = TRUE;
785 786
	session->video_active = TRUE;
786 787
	session->bitrate = 0;
787
	janus_mutex_unlock(&sessions_mutex);
788
	/* Done */
789
	session->hangingup = FALSE;
788 790
}
789 791

  
790 792
/* Thread to handle incoming messages */
plugins/janus_videoroom.c
246 246
	uint16_t fir_freq;			/* Regular FIR frequency (0=disabled) */
247 247
	gboolean record;			/* Whether the feeds from publishers in this room should be recorded */
248 248
	char *rec_dir;				/* Where to save the recordings of this room, if enabled */
249
	guint64 destroyed;			/* Value to flag the room for destruction, done lazily */
249
	gint64 destroyed;			/* Value to flag the room for destruction, done lazily */
250 250
	GHashTable *participants;	/* Map of potential publishers (we get listeners from them) */
251 251
	janus_mutex participants_mutex;/* Mutex to protect room properties */
252 252
} janus_videoroom;
......
261 261
	gpointer participant;
262 262
	gboolean started;
263 263
	gboolean stopping;
264
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
264
	gboolean hangingup;
265
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
265 266
} janus_videoroom_session;
266 267
static GHashTable *sessions;
267 268
static GList *old_sessions;
......
778 779
	/* Cleaning up and removing the session is done in a lazy way */
779 780
	janus_mutex_lock(&sessions_mutex);
780 781
	if(!session->destroyed) {
781
		session->destroyed = janus_get_monotonic_time();
782 782
		/* Any related WebRTC PeerConnection is not available anymore either */
783 783
		janus_videoroom_hangup_media(handle);
784
		session->destroyed = janus_get_monotonic_time();
784 785
		old_sessions = g_list_append(old_sessions, session);
785 786
		if(session->participant_type == janus_videoroom_p_type_publisher) {
786 787
			/* Get rid of publisher */
......
1929 1930
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1930 1931
		return;
1931 1932
	}
1932
	if(session->destroyed)
1933
		return;
1934 1933
	session->started = FALSE;
1934
	if(session->destroyed || session->hangingup)
1935
		return;
1936
	session->hangingup = TRUE;
1935 1937
	/* Send an event to the browser and tell the PeerConnection is over */
1936 1938
	if(session->participant_type == janus_videoroom_p_type_publisher) {
1937 1939
		/* This publisher just 'unpublished' */
......
2027 2029
		}
2028 2030
		/* TODO Should we close the handle as well? */
2029 2031
	}
2032
	/* Done */
2033
	session->hangingup = FALSE;
2030 2034
}
2031 2035

  
2032 2036
/* Thread to handle incoming messages */
plugins/janus_voicemail.c
216 216
	int seq;
217 217
	gboolean started;
218 218
	gboolean stopping;
219
	guint64 destroyed;	/* Time at which this session was marked as destroyed */
219
	gboolean hangingup;
220
	gint64 destroyed;	/* Time at which this session was marked as destroyed */
220 221
} janus_voicemail_session;
221 222
static GHashTable *sessions;
222 223
static GList *old_sessions;
......
477 478
	}
478 479
	janus_mutex_lock(&sessions_mutex);
479 480
	if(!session->destroyed) {
480
		session->destroyed = janus_get_monotonic_time();
481 481
		JANUS_LOG(LOG_VERB, "Removing VoiceMail session...\n");
482 482
		g_hash_table_remove(sessions, handle);
483 483
		janus_voicemail_hangup_media(handle);
484
		session->destroyed = janus_get_monotonic_time();
484 485
		/* Cleaning up and removing the session is done in a lazy way */
485 486
		old_sessions = g_list_append(old_sessions, session);
486 487
	}
......
609 610
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
610 611
		return;
611 612
	}
612
	if(session->destroyed)
613
		return;
614 613
	session->started = FALSE;
614
	if(session->destroyed || session->hangingup)
615
		return;
616
	session->hangingup = TRUE;
615 617
	/* Close and reset stuff */
616 618
	if(session->file)
617 619
		fclose(session->file);
......
619 621
	if(session->stream)
620 622
		ogg_stream_destroy(session->stream);
621 623
	session->stream = NULL;
624
	/* Done */
625
	session->hangingup = FALSE;
622 626
}
623 627

  
624 628
/* Thread to handle incoming messages */

Also available in: Unified diff