Revision 8241c758 plugins/janus_textroom.c

View differences:

plugins/janus_textroom.c
11 11
 * used within the context of any application that needs real-time text
12 12
 * broadcasting (e.g., chatrooms, but not only).
13 13
 *
14
 * The only message that is sent to the plugin through the Janus API is
14
 * The only message that is typically sent to the plugin through the Janus API is
15 15
 * a "setup" message, by which the user initializes the PeerConnection
16
 * itself. Apart from that, all other messages are exchanged directly
17
 * via Data Channels.
16
 * itself. Apart from that, all other messages can be exchanged directly
17
 * via Data Channels. For room management purposes, though, requests like
18
 * "create", "destroy", "list" and "exists" are available through the
19
 * Janus API as well: notice that in this case you'll have to use "request"
20
 * and not "textroom" as the name of the request.
18 21
 *
19 22
 * Each room can also be configured with an HTTP backend to contact for
20 23
 * incoming messages. If configured, messages addressed to that room will
......
358 361
}
359 362
#endif
360 363

  
361
void janus_textroom_handle_incoming_request(janus_plugin_session *handle, char *text, gboolean internal);
364
/* We use this method to handle incoming requests. Since most of the requests 
365
 * will arrive from data channels, but some may also arrive from the regular
366
 * plugin messaging (e.g., room management), we have the ability to pass
367
 * parsed JSON objects instead of strings, which explains why we specify a
368
 * janus_plugin_result pointer as a return value; messages handles via
369
 * datachannels would simply return NULL. Besides, some requests are actually
370
 * originated internally, and don't need any response to be sent to anyone,
371
 * which is what the additional boolean "internal" value is for */
372
janus_plugin_result *janus_textroom_handle_incoming_request(janus_plugin_session *handle,
373
	char *text, json_t *json, gboolean internal);
362 374

  
363 375

  
364 376
/* Plugin implementation */
......
637 649
struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep) {
638 650
	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
639 651
		return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized", NULL);
640
	janus_textroom_message *msg = g_malloc0(sizeof(janus_textroom_message));
641
	msg->handle = handle;
642
	msg->transaction = transaction;
643
	msg->message = message;
644
	msg->jsep = jsep;
645
	g_async_queue_push(messages, msg);
646

  
647
	/* All the requests to this plugin are handled asynchronously */
648
	return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, "I'm taking my time!", NULL);
652

  
653
	/* Pre-parse the message */
654
	int error_code = 0;
655
	char error_cause[512];
656
	json_t *root = message;
657
	json_t *response = NULL;
658

  
659
	if(message == NULL) {
660
		JANUS_LOG(LOG_ERR, "No message??\n");
661
		error_code = JANUS_TEXTROOM_ERROR_NO_MESSAGE;
662
		g_snprintf(error_cause, 512, "%s", "No message??");
663
		goto plugin_response;
664
	}
665

  
666
	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
667
	if(!session) {
668
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
669
		error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
670
		g_snprintf(error_cause, 512, "%s", "session associated with this handle...");
671
		goto plugin_response;
672
	}
673
	if(session->destroyed) {
674
		JANUS_LOG(LOG_ERR, "Session has already been destroyed...\n");
675
		error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
676
		g_snprintf(error_cause, 512, "%s", "Session has already been destroyed...");
677
		goto plugin_response;
678
	}
679
	if(!json_is_object(root)) {
680
		JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
681
		error_code = JANUS_TEXTROOM_ERROR_INVALID_JSON;
682
		g_snprintf(error_cause, 512, "JSON error: not an object");
683
		goto plugin_response;
684
	}
685
	/* Get the request first */
686
	JANUS_VALIDATE_JSON_OBJECT(root, request_parameters,
687
		error_code, error_cause, TRUE,
688
		JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
689
	if(error_code != 0)
690
		goto plugin_response;
691
	json_t *request = json_object_get(root, "request");
692
	/* Some requests (e.g., 'create' and 'destroy') can be handled synchronously */
693
	const char *request_text = json_string_value(request);
694
	if(!strcasecmp(request_text, "list")
695
			|| !strcasecmp(request_text, "exists")
696
			|| !strcasecmp(request_text, "create")
697
			|| !strcasecmp(request_text, "destroy")) {
698
		/* These requests typically only belong to the datachannel
699
		 * messaging, but for admin purposes we might use them on
700
		 * the Janus API as well: add the properties the datachannel
701
		 * processor would expect and handle everything there */
702
		json_object_set_new(root, "textroom", json_string(request_text));
703
		json_object_set_new(root, "transaction", json_string(transaction));
704
		janus_plugin_result *result = janus_textroom_handle_incoming_request(session->handle, NULL, root, FALSE);
705
		if(result == NULL) {
706
			JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
707
			error_code = JANUS_TEXTROOM_ERROR_INVALID_JSON;
708
			g_snprintf(error_cause, 512, "JSON error: not an object");
709
			goto plugin_response;
710
		}
711
		if(root != NULL)
712
			json_decref(root);
713
		if(jsep != NULL)
714
			json_decref(jsep);
715
		g_free(transaction);
716
		return result;
717
	} else if(!strcasecmp(request_text, "setup") || !strcasecmp(request_text, "ack")) {
718
		/* These messages are handled asynchronously */
719
		janus_textroom_message *msg = g_malloc0(sizeof(janus_textroom_message));
720
		msg->handle = handle;
721
		msg->transaction = transaction;
722
		msg->message = root;
723
		msg->jsep = jsep;
724

  
725
		g_async_queue_push(messages, msg);
726

  
727
		return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
728
	} else {
729
		JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text);
730
		error_code = JANUS_TEXTROOM_ERROR_INVALID_REQUEST;
731
		g_snprintf(error_cause, 512, "Unknown request '%s'", request_text);
732
	}
733

  
734
plugin_response:
735
		{
736
			if(error_code == 0 && !response) {
737
				error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
738
				g_snprintf(error_cause, 512, "Invalid response");
739
			}
740
			if(error_code != 0) {
741
				/* Prepare JSON error event */
742
				json_t *event = json_object();
743
				json_object_set_new(event, "textroom", json_string("event"));
744
				json_object_set_new(event, "error_code", json_integer(error_code));
745
				json_object_set_new(event, "error", json_string(error_cause));
746
				response = event;
747
			}
748
			if(root != NULL)
749
				json_decref(root);
750
			if(jsep != NULL)
751
				json_decref(jsep);
752
			g_free(transaction);
753

  
754
			return janus_plugin_result_new(JANUS_PLUGIN_OK, NULL, response);
755
		}
756

  
649 757
}
650 758

  
651 759
void janus_textroom_setup_media(janus_plugin_session *handle) {
......
687 795
	memcpy(text, buf, len);
688 796
	*(text+len) = '\0';
689 797
	JANUS_LOG(LOG_VERB, "Got a DataChannel message (%zu bytes): %s\n", strlen(text), text);
690
	janus_textroom_handle_incoming_request(handle, text, FALSE);
798
	janus_textroom_handle_incoming_request(handle, text, NULL, FALSE);
691 799
}
692 800

  
693 801
/* Helper method to handle incoming messages from the data channel */
694
void janus_textroom_handle_incoming_request(janus_plugin_session *handle, char *text, gboolean internal) {
802
janus_plugin_result *janus_textroom_handle_incoming_request(janus_plugin_session *handle, char *text, json_t *json, gboolean internal) {
695 803
	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
696
	/* Parse JSON */
804
	/* Parse JSON, if needed */
697 805
	json_error_t error;
698
	json_t *root = json_loads(text, 0, &error);
806
	json_t *root = text ? json_loads(text, 0, &error) : json;
699 807
	g_free(text);
700 808
	if(!root) {
701 809
		JANUS_LOG(LOG_ERR, "Error parsing data channel message (JSON error: on line %d: %s)\n", error.line, error.text);
702
		return;
810
		return NULL;
703 811
	}
704 812
	/* Handle request */
705 813
	int error_code = 0;
......
709 817
		JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
710 818
	const char *transaction_text = NULL;
711 819
	if(error_code != 0)
712
		goto error;
820
		goto msg_response;
713 821
	json_t *request = json_object_get(root, "textroom");
714 822
	json_t *transaction = json_object_get(root, "transaction");
715 823
	const char *request_text = json_string_value(request);
716 824
	transaction_text = json_string_value(transaction);
825
	json_t *reply = NULL;
717 826
	if(!strcasecmp(request_text, "message")) {
718 827
		JANUS_VALIDATE_JSON_OBJECT(root, message_parameters,
719 828
			error_code, error_cause, TRUE,
720 829
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
721 830
		if(error_code != 0)
722
			goto error;
831
			goto msg_response;
723 832
		json_t *room = json_object_get(root, "room");
724 833
		guint64 room_id = json_integer_value(room);
725 834
		janus_mutex_lock(&rooms_mutex);
......
729 838
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
730 839
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
731 840
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
732
			goto error;
841
			goto msg_response;
733 842
		}
734 843
		janus_mutex_lock(&textroom->mutex);
735 844
		janus_mutex_unlock(&rooms_mutex);
......
739 848
			JANUS_LOG(LOG_ERR, "Not in room %"SCNu64"\n", room_id);
740 849
			error_code = JANUS_TEXTROOM_ERROR_NOT_IN_ROOM;
741 850
			g_snprintf(error_cause, 512, "Not in room %"SCNu64, room_id);
742
			goto error;
851
			goto msg_response;
743 852
		}
744 853
		json_t *username = json_object_get(root, "to");
745 854
		json_t *usernames = json_object_get(root, "tos");
......
748 857
			JANUS_LOG(LOG_ERR, "Both to and tos array provided\n");
749 858
			error_code = JANUS_TEXTROOM_ERROR_INVALID_ELEMENT;
750 859
			g_snprintf(error_cause, 512, "Both to and tos array provided");
751
			goto error;
860
			goto msg_response;
752 861
		}
753 862
		json_t *text = json_object_get(root, "text");
754 863
		const char *message = json_string_value(text);
......
769 878
		char *msg_text = json_dumps(msg, json_format);
770 879
		json_decref(msg);
771 880
		/* Start preparing the response too */
772
		json_t *reply = json_object();
881
		reply = json_object();
773 882
		json_object_set_new(reply, "textroom", json_string("success"));
774
		json_object_set_new(reply, "transaction", json_string(transaction_text));
775 883
		/* Who should we send this message to? */
776 884
		if(username) {
777 885
			/* A single user */
......
855 963
		json_t *ack = json_object_get(root, "ack");
856 964
		if(!internal && (ack == NULL || json_is_true(ack))) {
857 965
			/* Send response back */
858
			char *reply_text = json_dumps(reply, json_format);
859
			gateway->relay_data(handle, reply_text, strlen(reply_text));
860
			free(reply_text);
966
		} else {
967
			internal = TRUE;
968
			json_decref(reply);
969
			reply = NULL;
861 970
		}
862
		json_decref(reply);
863 971
	} else if(!strcasecmp(request_text, "join")) {
864 972
		JANUS_VALIDATE_JSON_OBJECT(root, join_parameters,
865 973
			error_code, error_cause, TRUE,
866 974
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
867 975
		if(error_code != 0)
868
			goto error;
976
			goto msg_response;
869 977
		json_t *room = json_object_get(root, "room");
870 978
		guint64 room_id = json_integer_value(room);
871 979
		janus_mutex_lock(&rooms_mutex);
......
875 983
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
876 984
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
877 985
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
878
			goto error;
986
			goto msg_response;
879 987
		}
880 988
		janus_mutex_lock(&textroom->mutex);
881 989
		janus_mutex_unlock(&rooms_mutex);
......
886 994
			JANUS_LOG(LOG_ERR, "Already in room %"SCNu64"\n", room_id);
887 995
			error_code = JANUS_TEXTROOM_ERROR_ALREADY_IN_ROOM;
888 996
			g_snprintf(error_cause, 512, "Already in room %"SCNu64, room_id);
889
			goto error;
997
			goto msg_response;
890 998
		}
891 999
		json_t *username = json_object_get(root, "username");
892 1000
		const char *username_text = json_string_value(username);
......
897 1005
			JANUS_LOG(LOG_ERR, "Username already taken\n");
898 1006
			error_code = JANUS_TEXTROOM_ERROR_USERNAME_EXISTS;
899 1007
			g_snprintf(error_cause, 512, "Username already taken");
900
			goto error;
1008
			goto msg_response;
901 1009
		}
902 1010
		json_t *display = json_object_get(root, "display");
903 1011
		const char *display_text = json_string_value(display);
......
948 1056
		janus_mutex_unlock(&textroom->mutex);
949 1057
		if(!internal) {
950 1058
			/* Send response back */
951
			json_t *reply = json_object();
1059
			reply = json_object();
952 1060
			json_object_set_new(reply, "textroom", json_string("success"));
953
			json_object_set_new(reply, "transaction", json_string(transaction_text));
954 1061
			json_object_set_new(reply, "participants", list);
955
			char *reply_text = json_dumps(reply, json_format);
956
			json_decref(reply);
957
			gateway->relay_data(handle, reply_text, strlen(reply_text));
958
			free(reply_text);
959 1062
		}
960 1063
		/* Also notify event handlers */
961 1064
		if(notify_events && gateway->events_is_enabled()) {
......
972 1075
			error_code, error_cause, TRUE,
973 1076
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
974 1077
		if(error_code != 0)
975
			goto error;
1078
			goto msg_response;
976 1079
		json_t *room = json_object_get(root, "room");
977 1080
		guint64 room_id = json_integer_value(room);
978 1081
		janus_mutex_lock(&rooms_mutex);
......
982 1085
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
983 1086
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
984 1087
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
985
			goto error;
1088
			goto msg_response;
986 1089
		}
987 1090
		janus_mutex_lock(&textroom->mutex);
988 1091
		janus_mutex_unlock(&rooms_mutex);
......
994 1097
			JANUS_LOG(LOG_ERR, "Not in room %"SCNu64"\n", room_id);
995 1098
			error_code = JANUS_TEXTROOM_ERROR_NOT_IN_ROOM;
996 1099
			g_snprintf(error_cause, 512, "Not in room %"SCNu64, room_id);
997
			goto error;
1100
			goto msg_response;
998 1101
		}
999 1102
		g_hash_table_remove(session->rooms, &room_id);
1000 1103
		g_hash_table_remove(textroom->participants, participant->username);
......
1039 1142
		janus_mutex_unlock(&textroom->mutex);
1040 1143
		if(!internal) {
1041 1144
			/* Send response back */
1042
			json_t *reply = json_object();
1145
			reply = json_object();
1043 1146
			json_object_set_new(reply, "textroom", json_string("success"));
1044
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1045
			char *reply_text = json_dumps(reply, json_format);
1046
			json_decref(reply);
1047
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1048
			free(reply_text);
1049 1147
		}
1050 1148
	} else if(!strcasecmp(request_text, "list")) {
1051 1149
		/* List all rooms (but private ones) and their details (except for the secret, of course...) */
......
1077 1175
		janus_mutex_unlock(&rooms_mutex);
1078 1176
		if(!internal) {
1079 1177
			/* Send response back */
1080
			json_t *reply = json_object();
1178
			reply = json_object();
1081 1179
			json_object_set_new(reply, "textroom", json_string("success"));
1082
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1083 1180
			json_object_set_new(reply, "list", list);
1084
			char *reply_text = json_dumps(reply, json_format);
1085
			json_decref(reply);
1086
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1087
			free(reply_text);
1088 1181
		}
1089 1182
	} else if(!strcasecmp(request_text, "allowed")) {
1090 1183
		JANUS_LOG(LOG_VERB, "Attempt to edit the list of allowed participants in an existing textroom room\n");
......
1092 1185
			error_code, error_cause, TRUE,
1093 1186
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1094 1187
		if(error_code != 0)
1095
			goto error;
1188
			goto msg_response;
1096 1189
		json_t *action = json_object_get(root, "action");
1097 1190
		json_t *room = json_object_get(root, "room");
1098 1191
		json_t *allowed = json_object_get(root, "allowed");
......
1102 1195
			JANUS_LOG(LOG_ERR, "Unsupported action '%s' (allowed)\n", action_text);
1103 1196
			error_code = JANUS_TEXTROOM_ERROR_INVALID_ELEMENT;
1104 1197
			g_snprintf(error_cause, 512, "Unsupported action '%s' (allowed)", action_text);
1105
			goto error;
1198
			goto msg_response;
1106 1199
		}
1107 1200
		guint64 room_id = json_integer_value(room);
1108 1201
		janus_mutex_lock(&rooms_mutex);
......
1112 1205
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
1113 1206
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
1114 1207
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
1115
			goto error;
1208
			goto msg_response;
1116 1209
		}
1117 1210
		janus_mutex_lock(&textroom->mutex);
1118 1211
		/* A secret may be required for this action */
......
1121 1214
		if(error_code != 0) {
1122 1215
			janus_mutex_unlock(&textroom->mutex);
1123 1216
			janus_mutex_unlock(&rooms_mutex);
1124
			goto error;
1217
			goto msg_response;
1125 1218
		}
1126 1219
		if(!strcasecmp(action_text, "enable")) {
1127 1220
			JANUS_LOG(LOG_VERB, "Enabling the check on allowed authorization tokens for room %"SCNu64"\n", room_id);
......
1150 1243
					g_snprintf(error_cause, 512, "Invalid element in the allowed array (not a string)");
1151 1244
					janus_mutex_unlock(&textroom->mutex);
1152 1245
					janus_mutex_unlock(&rooms_mutex);
1153
					goto error;
1246
					goto msg_response;
1154 1247
				}
1155 1248
				size_t i = 0;
1156 1249
				for(i=0; i<json_array_size(allowed); i++) {
......
1166 1259
		}
1167 1260
		if(!internal) {
1168 1261
			/* Send response back */
1169
			json_t *reply = json_object();
1262
			reply = json_object();
1170 1263
			json_object_set_new(reply, "textroom", json_string("success"));
1171 1264
			json_object_set_new(reply, "room", json_integer(textroom->room_id));
1172 1265
			json_t *list = json_array();
......
1185 1278
			janus_mutex_unlock(&textroom->mutex);
1186 1279
			janus_mutex_unlock(&rooms_mutex);
1187 1280
			JANUS_LOG(LOG_VERB, "TextRoom room allowed list updated\n");
1188
			char *reply_text = json_dumps(reply, json_format);
1189
			json_decref(reply);
1190
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1191
			free(reply_text);
1192 1281
		}
1193 1282
	} else if(!strcasecmp(request_text, "kick")) {
1194 1283
		JANUS_LOG(LOG_VERB, "Attempt to kick a participant from an existing textroom room\n");
......
1196 1285
			error_code, error_cause, TRUE,
1197 1286
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1198 1287
		if(error_code != 0)
1199
			goto error;
1288
			goto msg_response;
1200 1289
		json_t *room = json_object_get(root, "room");
1201 1290
		json_t *username = json_object_get(root, "username");
1202 1291
		guint64 room_id = json_integer_value(room);
......
1207 1296
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
1208 1297
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
1209 1298
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
1210
			goto error;
1299
			goto msg_response;
1211 1300
		}
1212 1301
		janus_mutex_lock(&textroom->mutex);
1213 1302
		/* A secret may be required for this action */
......
1216 1305
		if(error_code != 0) {
1217 1306
			janus_mutex_unlock(&textroom->mutex);
1218 1307
			janus_mutex_unlock(&rooms_mutex);
1219
			goto error;
1308
			goto msg_response;
1220 1309
		}
1221 1310
		const char *user_id = json_string_value(username);
1222 1311
		janus_textroom_participant *participant = g_hash_table_lookup(textroom->participants, user_id);
......
1226 1315
			JANUS_LOG(LOG_ERR, "No such participant %s in room %"SCNu64"\n", user_id, room_id);
1227 1316
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_USER;
1228 1317
			g_snprintf(error_cause, 512, "No such user %s in room %"SCNu64, user_id, room_id);
1229
			goto error;
1318
			goto msg_response;
1230 1319
		}
1231 1320
		/* Notify all participants */
1232 1321
		JANUS_LOG(LOG_VERB, "Notifying all participants about the new kick\n");
......
1270 1359
		janus_mutex_unlock(&rooms_mutex);
1271 1360
		if(!internal) {
1272 1361
			/* Send response back */
1273
			json_t *reply = json_object();
1362
			reply = json_object();
1274 1363
			json_object_set_new(reply, "textbridge", json_string("success"));
1275
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1276
			char *reply_text = json_dumps(reply, json_format);
1277
			json_decref(reply);
1278
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1279
			free(reply_text);
1280 1364
		}
1281 1365
	} else if(!strcasecmp(request_text, "create")) {
1282 1366
		JANUS_VALIDATE_JSON_OBJECT(root, create_parameters,
1283 1367
			error_code, error_cause, TRUE,
1284 1368
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1285 1369
		if(error_code != 0)
1286
			goto error;
1370
			goto msg_response;
1287 1371
		if(admin_key != NULL) {
1288 1372
			/* An admin key was specified: make sure it was provided, and that it's valid */
1289 1373
			JANUS_VALIDATE_JSON_OBJECT(root, adminkey_parameters,
1290 1374
				error_code, error_cause, TRUE,
1291 1375
				JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1292 1376
			if(error_code != 0)
1293
				goto error;
1377
				goto msg_response;
1294 1378
			JANUS_CHECK_SECRET(admin_key, root, "admin_key", error_code, error_cause,
1295 1379
				JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT, JANUS_TEXTROOM_ERROR_UNAUTHORIZED);
1296 1380
			if(error_code != 0)
1297
				goto error;
1381
				goto msg_response;
1298 1382
		}
1299 1383
		json_t *room = json_object_get(root, "room");
1300 1384
		json_t *desc = json_object_get(root, "description");
......
1321 1405
				JANUS_LOG(LOG_ERR, "Invalid element in the allowed array (not a string)\n");
1322 1406
				error_code = JANUS_TEXTROOM_ERROR_INVALID_ELEMENT;
1323 1407
				g_snprintf(error_cause, 512, "Invalid element in the allowed array (not a string)");
1324
				goto error;
1408
				goto msg_response;
1325 1409
			}
1326 1410
		}
1327 1411
		gboolean save = permanent ? json_is_true(permanent) : FALSE;
......
1329 1413
			JANUS_LOG(LOG_ERR, "No configuration file, can't create permanent room\n");
1330 1414
			error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
1331 1415
			g_snprintf(error_cause, 512, "No configuration file, can't create permanent room");
1332
			goto error;
1416
			goto msg_response;
1333 1417
		}
1334 1418
		guint64 room_id = 0;
1335 1419
		room_id = json_integer_value(room);
......
1345 1429
				JANUS_LOG(LOG_ERR, "Room %"SCNu64" already exists!\n", room_id);
1346 1430
				error_code = JANUS_TEXTROOM_ERROR_ROOM_EXISTS;
1347 1431
				g_snprintf(error_cause, 512, "Room %"SCNu64" already exists", room_id);
1348
				goto error;
1432
				goto msg_response;
1349 1433
			}
1350 1434
		}
1351 1435
		/* Create the text room */
......
1440 1524
		janus_mutex_unlock(&rooms_mutex);
1441 1525
		if(!internal) {
1442 1526
			/* Send response back */
1443
			json_t *reply = json_object();
1527
			reply = json_object();
1444 1528
			json_object_set_new(reply, "textroom", json_string("success"));
1445
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1446 1529
			json_object_set_new(reply, "room", json_integer(textroom->room_id));
1447 1530
			json_object_set_new(reply, "permanent", save ? json_true() : json_false());
1448
			char *reply_text = json_dumps(reply, json_format);
1449
			json_decref(reply);
1450
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1451
			free(reply_text);
1452 1531
		}
1453 1532
		/* Also notify event handlers */
1454 1533
		if(notify_events && gateway->events_is_enabled()) {
......
1462 1541
			error_code, error_cause, TRUE,
1463 1542
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1464 1543
		if(error_code != 0)
1465
			goto error;
1544
			goto msg_response;
1466 1545
		json_t *room = json_object_get(root, "room");
1467 1546
		guint64 room_id = json_integer_value(room);
1468 1547
		janus_mutex_lock(&rooms_mutex);
......
1470 1549
		janus_mutex_unlock(&rooms_mutex);
1471 1550
		if(!internal) {
1472 1551
			/* Send response back */
1473
			json_t *reply = json_object();
1552
			reply = json_object();
1474 1553
			json_object_set_new(reply, "textroom", json_string("success"));
1475 1554
			json_object_set_new(reply, "room", json_integer(room_id));
1476 1555
			json_object_set_new(reply, "exists", room_exists ? json_true() : json_false());
1477
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1478
			char *reply_text = json_dumps(reply, json_format);
1479
			json_decref(reply);
1480
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1481
			free(reply_text);
1482 1556
		}
1483 1557
	} else if(!strcasecmp(request_text, "destroy")) {
1484 1558
		JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
1485 1559
			error_code, error_cause, TRUE,
1486 1560
			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
1487 1561
		if(error_code != 0)
1488
			goto error;
1562
			goto msg_response;
1489 1563
		json_t *room = json_object_get(root, "room");
1490 1564
		json_t *permanent = json_object_get(root, "permanent");
1491 1565
		gboolean save = permanent ? json_is_true(permanent) : FALSE;
......
1493 1567
			JANUS_LOG(LOG_ERR, "No configuration file, can't destroy room permanently\n");
1494 1568
			error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
1495 1569
			g_snprintf(error_cause, 512, "No configuration file, can't destroy room permanently");
1496
			goto error;
1570
			goto msg_response;
1497 1571
		}
1498 1572
		guint64 room_id = json_integer_value(room);
1499 1573
		janus_mutex_lock(&rooms_mutex);
......
1503 1577
			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
1504 1578
			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
1505 1579
			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
1506
			goto error;
1580
			goto msg_response;
1507 1581
		}
1508 1582
		janus_mutex_lock(&textroom->mutex);
1509 1583
		/* A secret may be required for this action */
......
1512 1586
		if(error_code != 0) {
1513 1587
			janus_mutex_unlock(&textroom->mutex);
1514 1588
			janus_mutex_unlock(&rooms_mutex);
1515
			goto error;
1589
			goto msg_response;
1516 1590
		}
1517 1591
		/* Remove room */
1518 1592
		g_hash_table_remove(rooms, &room_id);
......
1560 1634
		janus_mutex_unlock(&rooms_mutex);
1561 1635
		if(!internal) {
1562 1636
			/* Send response back */
1563
			json_t *reply = json_object();
1637
			reply = json_object();
1564 1638
			json_object_set_new(reply, "textroom", json_string("success"));
1565
			json_object_set_new(reply, "transaction", json_string(transaction_text));
1566
			char *reply_text = json_dumps(reply, json_format);
1567
			json_decref(reply);
1568
			gateway->relay_data(handle, reply_text, strlen(reply_text));
1569
			free(reply_text);
1570 1639
		}
1571 1640
		/* We'll let the watchdog worry about freeing resources */
1572 1641
		old_rooms = g_list_append(old_rooms, textroom);
......
1581 1650
		JANUS_LOG(LOG_ERR, "Unsupported request %s\n", request_text);
1582 1651
		error_code = JANUS_TEXTROOM_ERROR_INVALID_REQUEST;
1583 1652
		g_snprintf(error_cause, 512, "Unsupported request %s", request_text);
1584
		goto error;
1653
		goto msg_response;
1585 1654
	}
1586 1655

  
1587
	json_decref(root);
1588
	return;
1589

  
1590
error:
1656
msg_response:
1591 1657
		{
1592 1658
			if(!internal) {
1593
				/* Prepare JSON error response */
1594
				json_t *reply = json_object();
1595
				json_object_set_new(reply, "textroom", json_string("error"));
1596
				if(transaction_text)
1659
				if(error_code == 0 && !reply) {
1660
					error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
1661
					g_snprintf(error_cause, 512, "Invalid response");
1662
				}
1663
				if(error_code != 0) {
1664
					/* Prepare JSON error event */
1665
					json_t *event = json_object();
1666
					json_object_set_new(event, "textroom", json_string("error"));
1667
					json_object_set_new(event, "error_code", json_integer(error_code));
1668
					json_object_set_new(event, "error", json_string(error_cause));
1669
					reply = event;
1670
				}
1671
				if(transaction_text && json == NULL)
1597 1672
					json_object_set_new(reply, "transaction", json_string(transaction_text));
1598
				json_object_set_new(reply, "error_code", json_integer(error_code));
1599
				json_object_set_new(reply, "error", json_string(error_cause));
1600
				char *reply_text = json_dumps(reply, json_format);
1601
				json_decref(reply);
1602
				gateway->relay_data(handle, reply_text, strlen(reply_text));
1603
				free(reply_text);
1673
				if(json == NULL) {
1674
					/* Reply via data channels */
1675
					char *reply_text = json_dumps(reply, json_format);
1676
					json_decref(reply);
1677
					gateway->relay_data(handle, reply_text, strlen(reply_text));
1678
					free(reply_text);
1679
				} else {
1680
					/* Reply via Janus API */
1681
					return janus_plugin_result_new(JANUS_PLUGIN_OK, NULL, reply);
1682
				}
1604 1683
			}
1605 1684
			if(root != NULL)
1606 1685
				json_decref(root);
1607 1686
		}
1687
	return NULL;
1608 1688
}
1609 1689

  
1610 1690
void janus_textroom_slow_link(janus_plugin_session *handle, int uplink, int video) {
......
1647 1727
	while(list) {
1648 1728
		guint64 room_id = *((guint64 *)list->data);
1649 1729
		g_snprintf(request, sizeof(request), "{\"textroom\":\"leave\",\"transaction\":\"internal\",\"room\":%"SCNu64"}", room_id);
1650
		janus_textroom_handle_incoming_request(handle, g_strdup(request), TRUE);
1730
		janus_textroom_handle_incoming_request(handle, g_strdup(request), NULL, TRUE);
1651 1731
		list = list->next;
1652 1732
	}
1653 1733
	g_list_free_full(first, (GDestroyNotify)g_free);
......
1709 1789
			goto error;
1710 1790
		json_t *request = json_object_get(root, "request");
1711 1791
		const char *request_text = json_string_value(request);
1792
		do_offer = FALSE;
1712 1793
		if(!strcasecmp(request_text, "setup")) {
1713 1794
			if(!g_atomic_int_compare_and_exchange(&session->setup, 0, 1)) {
1714 1795
				JANUS_LOG(LOG_ERR, "PeerConnection already setup\n");
......
1718 1799
			}
1719 1800
			do_offer = TRUE;
1720 1801
		} else if(!strcasecmp(request_text, "ack")) {
1721
			/* The peer send their answer back: do nothing */
1722
			do_offer = FALSE;
1802
			/* The peer sent their answer back: do nothing */
1723 1803
		} else {
1724 1804
			JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text);
1725 1805
			error_code = JANUS_TEXTROOM_ERROR_INVALID_REQUEST;

Also available in: Unified diff