Revision 887df302

View differences:

janus.c
79 79
/* API secrets */
80 80
static char *api_secret = NULL, *admin_api_secret = NULL;
81 81

  
82
/* JSON parameters */
83
static int janus_process_error_string(janus_request *request, uint64_t session_id, const char *transaction, gint error, gchar *error_string);
84

  
85
static struct janus_json_parameter incoming_request_parameters[] = {
86
	{"transaction", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
87
	{"janus", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
88
	{"id", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}
89
};
90
static struct janus_json_parameter attach_parameters[] = {
91
	{"plugin", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
92
};
93
static struct janus_json_parameter jsep_parameters[] = {
94
	{"type", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
95
	{"trickle", JANUS_JSON_BOOL, 0},
96
	{"sdp", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
97
};
82 98

  
83 99
/* Admin/Monitor helpers */
84 100
json_t *janus_admin_stream_summary(janus_ice_stream *stream);
......
501 517
		JANUS_LOG(LOG_ERR, "Missing request or payload to process, giving up...\n");
502 518
		return ret;
503 519
	}
520
	int error_code = 0;
521
	char error_cause[100];
504 522
	json_t *root = request->message;
505 523
	/* Ok, let's start with the ids */
506 524
	guint64 session_id = 0, handle_id = 0;
......
512 530
		handle_id = json_integer_value(h);
513 531

  
514 532
	/* Get transaction and message request */
515
	json_t *transaction = json_object_get(root, "transaction");
516
	if(!transaction) {
517
		ret = janus_process_error(request, session_id, NULL, JANUS_ERROR_MISSING_MANDATORY_ELEMENT, "Missing mandatory element (transaction)");
518
		goto jsondone;
519
	}
520
	if(!json_is_string(transaction)) {
521
		ret = janus_process_error(request, session_id, NULL, JANUS_ERROR_INVALID_ELEMENT_TYPE, "Invalid element type (transaction should be a string)");
533
	JANUS_VALIDATE_JSON_OBJECT(root, incoming_request_parameters,
534
		error_code, error_cause, FALSE,
535
		JANUS_ERROR_MISSING_MANDATORY_ELEMENT, JANUS_ERROR_INVALID_ELEMENT_TYPE);
536
	if(error_code != 0) {
537
		ret = janus_process_error_string(request, session_id, NULL, error_code, error_cause);
522 538
		goto jsondone;
523 539
	}
540
	json_t *transaction = json_object_get(root, "transaction");
524 541
	const gchar *transaction_text = json_string_value(transaction);
525 542
	json_t *message = json_object_get(root, "janus");
526
	if(!message) {
527
		ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_MISSING_MANDATORY_ELEMENT, "Missing mandatory element (janus)");
528
		goto jsondone;
529
	}
530
	if(!json_is_string(message)) {
531
		ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "Invalid element type (janus should be a string)");
532
		goto jsondone;
533
	}
534 543
	const gchar *message_text = json_string_value(message);
535 544
	
536 545
	if(session_id == 0 && handle_id == 0) {
......
582 591
		json_t *id = json_object_get(root, "id");
583 592
		if(id != NULL) {
584 593
			/* The application provided the session ID to use */
585
			if(!json_is_integer(id) || json_integer_value(id) < 0) {
586
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "Invalid element type (id should be a positive integer)");
587
				goto jsondone;
588
			}
589 594
			session_id = json_integer_value(id);
590 595
			if(session_id > 0 && janus_session_find(session_id) != NULL) {
591 596
				/* Session ID already taken */
......
689 694
			ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_REQUEST_PATH, "Unhandled request '%s' at this path", message_text);
690 695
			goto jsondone;
691 696
		}
692
		json_t *plugin = json_object_get(root, "plugin");
693
		if(!plugin) {
694
			ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_MISSING_MANDATORY_ELEMENT, "Missing mandatory element (plugin)");
695
			goto jsondone;
696
		}
697
		if(!json_is_string(plugin)) {
698
			ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "Invalid element type (plugin should be a string)");
697
		JANUS_VALIDATE_JSON_OBJECT(root, attach_parameters,
698
			error_code, error_cause, FALSE,
699
			JANUS_ERROR_MISSING_MANDATORY_ELEMENT, JANUS_ERROR_INVALID_ELEMENT_TYPE);
700
		if(error_code != 0) {
701
			ret = janus_process_error_string(request, session_id, NULL, error_code, error_cause);
699 702
			goto jsondone;
700 703
		}
704
		json_t *plugin = json_object_get(root, "plugin");
701 705
		const gchar *plugin_text = json_string_value(plugin);
702 706
		janus_plugin *plugin_t = janus_plugin_find(plugin_text);
703 707
		if(plugin_t == NULL) {
......
848 852
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_JSON_OBJECT, "Invalid jsep object");
849 853
				goto jsondone;
850 854
			}
851
			json_t *type = json_object_get(jsep, "type");
852
			if(!type) {
853
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_MISSING_MANDATORY_ELEMENT, "JSEP error: missing mandatory element (type)");
854
				goto jsondone;
855
			}
856
			if(!json_is_string(type)) {
857
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "JSEP error: invalid element type (type should be a string)");
855
			JANUS_VALIDATE_JSON_OBJECT_FORMAT("JSEP error: missing mandatory element (%s)",
856
				"JSEP error: invalid element type (%s should be %s)",
857
				jsep, jsep_parameters, error_code, error_cause, FALSE,
858
				JANUS_ERROR_MISSING_MANDATORY_ELEMENT, JANUS_ERROR_INVALID_ELEMENT_TYPE);
859
			if(error_code != 0) {
860
				ret = janus_process_error_string(request, session_id, transaction_text, error_code, error_cause);
858 861
				goto jsondone;
859 862
			}
863
			json_t *type = json_object_get(jsep, "type");
860 864
			jsep_type = g_strdup(json_string_value(type));
861 865
			type = NULL;
862 866
			gboolean do_trickle = TRUE;
863 867
			json_t *jsep_trickle = json_object_get(jsep, "trickle");
864
			if(jsep_trickle && !json_is_boolean(jsep_trickle)) {
865
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "JSEP error: invalid element type (trickle should be a boolean)");
866
				goto jsondone;
867
			}
868 868
			do_trickle = jsep_trickle ? json_is_true(jsep_trickle) : TRUE;
869 869
			/* Are we still cleaning up from a previous media session? */
870 870
			if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_CLEANING)) {
......
899 899
				goto jsondone;
900 900
			}
901 901
			json_t *sdp = json_object_get(jsep, "sdp");
902
			if(!sdp) {
903
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_MISSING_MANDATORY_ELEMENT, "JSEP error: missing mandatory element (sdp)");
904
				g_free(jsep_type);
905
				janus_flags_clear(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_PROCESSING_OFFER);
906
				janus_mutex_unlock(&handle->mutex);
907
				goto jsondone;
908
			}
909
			if(!json_is_string(sdp)) {
910
				ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_ELEMENT_TYPE, "JSEP error: invalid element type (sdp should be a string)");
911
				g_free(jsep_type);
912
				janus_flags_clear(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_PROCESSING_OFFER);
913
				janus_mutex_unlock(&handle->mutex);
914
				goto jsondone;
915
			}
916 902
			jsep_sdp = (char *)json_string_value(sdp);
917 903
			JANUS_LOG(LOG_VERB, "[%"SCNu64"] Remote SDP:\n%s", handle->handle_id, jsep_sdp);
918 904
			/* Is this valid SDP? */
......
2166 2152
	return request->transport->send_message(request->instance, request->request_id, request->admin, payload);
2167 2153
}
2168 2154

  
2169
int janus_process_error(janus_request *request, uint64_t session_id, const char *transaction, gint error, const char *format, ...)
2155
static int janus_process_error_string(janus_request *request, uint64_t session_id, const char *transaction, gint error, gchar *error_string)
2170 2156
{
2171 2157
	if(!request)
2172 2158
		return -1;
2173
	gchar *error_string = NULL;
2174
	gchar error_buf[512];
2175
	if(format == NULL) {
2176
		/* No error string provided, use the default one */
2177
		error_string = (gchar *)janus_get_api_error(error);
2178
	} else {
2179
		/* This callback has variable arguments (error string) */
2180
		va_list ap;
2181
		va_start(ap, format);
2182
		g_vsnprintf(error_buf, sizeof(error_buf), format, ap);
2183
		va_end(ap);
2184
		error_string = error_buf;
2185
	}
2186 2159
	/* Done preparing error */
2187 2160
	JANUS_LOG(LOG_VERB, "[%s] Returning %s API error %d (%s)\n", transaction, request->admin ? "admin" : "Janus", error, error_string);
2188 2161
	/* Prepare JSON error */
......
2200 2173
	return request->transport->send_message(request->instance, request->request_id, request->admin, reply);
2201 2174
}
2202 2175

  
2176
int janus_process_error(janus_request *request, uint64_t session_id, const char *transaction, gint error, const char *format, ...)
2177
{
2178
	if(!request)
2179
		return -1;
2180
	gchar *error_string = NULL;
2181
	gchar error_buf[512];
2182
	if(format == NULL) {
2183
		/* No error string provided, use the default one */
2184
		error_string = (gchar *)janus_get_api_error(error);
2185
	} else {
2186
		/* This callback has variable arguments (error string) */
2187
		va_list ap;
2188
		va_start(ap, format);
2189
		g_vsnprintf(error_buf, sizeof(error_buf), format, ap);
2190
		va_end(ap);
2191
		error_string = error_buf;
2192
	}
2193
	return janus_process_error_string(request, session_id, transaction, error, error_string);
2194
}
2203 2195

  
2204 2196
/* Admin/monitor helpers */
2205 2197
json_t *janus_admin_stream_summary(janus_ice_stream *stream) {
plugins/janus_videoroom.c
195 195
	return &janus_videoroom_plugin;
196 196
}
197 197

  
198
/* Parameter validation */
199
static struct janus_json_parameter request_parameters[] = {
200
	{"request", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
201
};
202
static struct janus_json_parameter create_parameters[] = {
203
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
204
	{"description", JSON_STRING, 0},
205
	{"is_private", JANUS_JSON_BOOL, 0},
206
	{"secrect", JSON_STRING, 0},
207
	{"pin", JSON_STRING, 0},
208
	{"bitrate", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
209
	{"fir_freq", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
210
	{"publishers", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
211
	{"audiocodec", JSON_STRING, 0},
212
	{"videocodec", JSON_STRING, 0},
213
	{"record", JANUS_JSON_BOOL, 0},
214
	{"rec_dir", JSON_STRING, 0},
215
	{"permanent", JANUS_JSON_BOOL, 0}
216
};
217
static struct janus_json_parameter room_parameters[] = {
218
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE}
219
};
220
static struct janus_json_parameter destroy_parameters[] = {
221
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
222
	{"permanent", JANUS_JSON_BOOL, 0}
223
};
224
static struct janus_json_parameter join_parameters[] = {
225
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
226
	{"ptype", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
227
	{"audio", JANUS_JSON_BOOL, 0},
228
	{"video", JANUS_JSON_BOOL, 0},
229
	{"bitrate", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
230
	{"record", JANUS_JSON_BOOL, 0},
231
	{"filename", JSON_STRING, 0}
232
};
233
static struct janus_json_parameter publish_parameters[] = {
234
	{"audio", JANUS_JSON_BOOL, 0},
235
	{"video", JANUS_JSON_BOOL, 0},
236
	{"bitrate", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
237
	{"record", JANUS_JSON_BOOL, 0},
238
	{"filename", JSON_STRING, 0}
239
};
240
static struct janus_json_parameter rtp_forward_parameters[] = {
241
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
242
	{"publisher_id", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
243
	{"vid_port", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
244
	{"au_port", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
245
	{"host", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
246
};
247
static struct janus_json_parameter stop_rtp_forward_parameters[] = {
248
	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
249
	{"publisher_id", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
250
	{"stream_id", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE}
251
};
252
static struct janus_json_parameter secret_parameters[] = {
253
	{"secret", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
254
};
255
static struct janus_json_parameter pin_parameters[] = {
256
	{"pin", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
257
};
258
static struct janus_json_parameter publisher_parameters[] = {
259
	{"id", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
260
	{"display", JSON_STRING, 0}
261
};
262
static struct janus_json_parameter configure_parameters[] = {
263
	{"audio", JANUS_JSON_BOOL, 0},
264
	{"video", JANUS_JSON_BOOL, 0},
265
	{"data", JANUS_JSON_BOOL, 0}
266
};
267
static struct janus_json_parameter listener_parameters[] = {
268
	{"feed", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
269
	{"audio", JANUS_JSON_BOOL, 0},
270
	{"video", JANUS_JSON_BOOL, 0},
271
	{"data", JANUS_JSON_BOOL, 0}
272
};
273
static struct janus_json_parameter feeds_parameters[] = {
274
	{"feeds", JSON_ARRAY, JANUS_JSON_PARAM_NONEMPTY}
275
};
198 276

  
199 277
/* Static configuration instance */
200 278
static janus_config *config = NULL;
......
1101 1179
		goto error;
1102 1180
	}
1103 1181
	/* Get the request first */
1104
	json_t *request = json_object_get(root, "request");
1105
	if(!request) {
1106
		JANUS_LOG(LOG_ERR, "Missing element (request)\n");
1107
		error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1108
		g_snprintf(error_cause, 512, "Missing element (request)");
1109
		goto error;
1110
	}
1111
	if(!json_is_string(request)) {
1112
		JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
1113
		error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1114
		g_snprintf(error_cause, 512, "Invalid element (request should be a string)");
1182
	JANUS_VALIDATE_JSON_OBJECT(root, request_parameters,
1183
		error_code, error_cause, TRUE,
1184
		JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1185
	if(error_code != 0)
1115 1186
		goto error;
1116
	}
1187
	json_t *request = json_object_get(root, "request");
1117 1188
	/* Some requests ('create', 'destroy', 'exists', 'list') can be handled synchronously */
1118 1189
	const char *request_text = json_string_value(request);
1119 1190
	if(!strcasecmp(request_text, "create")) {
1120 1191
		/* Create a new videoroom */
1121 1192
		JANUS_LOG(LOG_VERB, "Creating a new videoroom\n");
1122
		json_t *desc = json_object_get(root, "description");
1123
		if(desc && !json_is_string(desc)) {
1124
			JANUS_LOG(LOG_ERR, "Invalid element (description should be a string)\n");
1125
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1126
			g_snprintf(error_cause, 512, "Invalid element (description should be a string)");
1193
		JANUS_VALIDATE_JSON_OBJECT(root, create_parameters,
1194
			error_code, error_cause, TRUE,
1195
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1196
		if(error_code != 0)
1127 1197
			goto error;
1128
		}
1198
		json_t *desc = json_object_get(root, "description");
1129 1199
		json_t *is_private = json_object_get(root, "is_private");
1130
		if(is_private && !json_is_boolean(is_private)) {
1131
			JANUS_LOG(LOG_ERR, "Invalid element (is_private should be a boolean)\n");
1132
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1133
			g_snprintf(error_cause, 512, "Invalid value (is_private should be a boolean)");
1134
			goto error;
1135
		}
1136 1200
		json_t *secret = json_object_get(root, "secret");
1137
		if(secret && !json_is_string(secret)) {
1138
			JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
1139
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1140
			g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
1141
			goto error;
1142
		}
1143 1201
		json_t *pin = json_object_get(root, "pin");
1144
		if(pin && !json_is_string(pin)) {
1145
			JANUS_LOG(LOG_ERR, "Invalid element (pin should be a string)\n");
1146
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1147
			g_snprintf(error_cause, 512, "Invalid element (pin should be a string)");
1148
			goto error;
1149
		}
1150 1202
		json_t *bitrate = json_object_get(root, "bitrate");
1151
		if(bitrate && (!json_is_integer(bitrate) || json_integer_value(bitrate) < 0)) {
1152
			JANUS_LOG(LOG_ERR, "Invalid element (bitrate should be a positive integer)\n");
1153
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1154
			g_snprintf(error_cause, 512, "Invalid element (bitrate should be a positive integer)");
1155
			goto error;
1156
		}
1157 1203
		json_t *fir_freq = json_object_get(root, "fir_freq");
1158
		if(fir_freq && (!json_is_integer(fir_freq) || json_integer_value(fir_freq) < 0)) {
1159
			JANUS_LOG(LOG_ERR, "Invalid element (fir_freq should be a positive integer)\n");
1160
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1161
			g_snprintf(error_cause, 512, "Invalid element (fir_freq should be a positive integer)");
1162
			goto error;
1163
		}
1164 1204
		json_t *publishers = json_object_get(root, "publishers");
1165
		if(publishers && (!json_is_integer(publishers) || json_integer_value(publishers) < 0)) {
1166
			JANUS_LOG(LOG_ERR, "Invalid element (publishers should be a positive integer)\n");
1167
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1168
			g_snprintf(error_cause, 512, "Invalid element (publishers should be a positive integer)");
1169
			goto error;
1170
		}
1171 1205
		json_t *audiocodec = json_object_get(root, "audiocodec");
1172 1206
		if(audiocodec) {
1173
			if(!json_is_string(audiocodec)) {
1174
				JANUS_LOG(LOG_ERR, "Invalid element (audiocodec should be a string)\n");
1175
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1176
				g_snprintf(error_cause, 512, "Invalid element (audiocodec should be a string)");
1177
				goto error;
1178
			}
1179 1207
			const char *audiocodec_value = json_string_value(audiocodec);
1180 1208
			if(!strcasecmp(audiocodec_value, "opus") && !strcasecmp(audiocodec_value, "isac32") && !strcasecmp(audiocodec_value, "isac16") && !strcasecmp(audiocodec_value, "pcmu") && !strcasecmp(audiocodec_value, "pcma")) {
1181 1209
				JANUS_LOG(LOG_ERR, "Invalid element (audiocodec can only be opus, isac32, isac16, pcmu, or pcma)\n");
......
1186 1214
		}
1187 1215
		json_t *videocodec = json_object_get(root, "videocodec");
1188 1216
		if(videocodec) {
1189
			if(!json_is_string(videocodec)) {
1190
				JANUS_LOG(LOG_ERR, "Invalid element (videocodec should be a string)\n");
1191
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1192
				g_snprintf(error_cause, 512, "Invalid element (videocodec should be a string)");
1193
				goto error;
1194
			}
1195 1217
			const char *videocodec_value = json_string_value(videocodec);
1196 1218
			if(!strcasecmp(videocodec_value, "vp8") && !strcasecmp(videocodec_value, "vp9") && !strcasecmp(videocodec_value, "h264")) {
1197 1219
				JANUS_LOG(LOG_ERR, "Invalid element (videocodec can only be vp8, vp9 or h264)\n");
......
1201 1223
			}
1202 1224
		}
1203 1225
		json_t *record = json_object_get(root, "record");
1204
		if(record && !json_is_boolean(record)) {
1205
			JANUS_LOG(LOG_ERR, "Invalid element (record should be a boolean)\n");
1206
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1207
			g_snprintf(error_cause, 512, "Invalid element (record should be a boolean)");
1208
			goto error;
1209
		}
1210 1226
		json_t *rec_dir = json_object_get(root, "rec_dir");
1211
		if(rec_dir && !json_is_string(rec_dir)) {
1212
			JANUS_LOG(LOG_ERR, "Invalid element (rec_dir should be a string)\n");
1213
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1214
			g_snprintf(error_cause, 512, "Invalid element (rec_dir should be a string)");
1215
			goto error;
1216
		}
1217 1227
		json_t *permanent = json_object_get(root, "permanent");
1218
		if(permanent && !json_is_boolean(permanent)) {
1219
			JANUS_LOG(LOG_ERR, "Invalid element (permanent should be a boolean)\n");
1220
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1221
			g_snprintf(error_cause, 512, "Invalid value (permanent should be a boolean)");
1222
			goto error;
1223
		}
1224 1228
		gboolean save = permanent ? json_is_true(permanent) : FALSE;
1225 1229
		if(save && config == NULL) {
1226 1230
			JANUS_LOG(LOG_ERR, "No configuration file, can't create permanent room\n");
......
1230 1234
		}
1231 1235
		guint64 room_id = 0;
1232 1236
		json_t *room = json_object_get(root, "room");
1233
		if(room && (!json_is_integer(room) || json_integer_value(room) < 0)) {
1234
			JANUS_LOG(LOG_ERR, "Invalid element (room should be a positive integer)\n");
1235
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1236
			g_snprintf(error_cause, 512, "Invalid element (room should be a positive integer)");
1237
			goto error;
1238
		} else {
1237
		if(room) {
1239 1238
			room_id = json_integer_value(room);
1240 1239
			if(room_id == 0) {
1241 1240
				JANUS_LOG(LOG_WARN, "Desired room ID is 0, which is not allowed... picking random ID instead\n");
......
1410 1409
		goto plugin_response;
1411 1410
	} else if(!strcasecmp(request_text, "destroy")) {
1412 1411
		JANUS_LOG(LOG_VERB, "Attempt to destroy an existing videoroom room\n");
1413
		json_t *room = json_object_get(root, "room");
1414
		if(!room) {
1415
			JANUS_LOG(LOG_ERR, "Missing element (room)\n");
1416
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1417
			g_snprintf(error_cause, 512, "Missing element (room)");
1418
			goto error;
1419
		}
1420
		if(!json_is_integer(room) || json_integer_value(room) < 0) {
1421
			JANUS_LOG(LOG_ERR, "Invalid element (room should be a positive integer)\n");
1422
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1423
			g_snprintf(error_cause, 512, "Invalid element (room should be a positive integer)");
1412
		JANUS_VALIDATE_JSON_OBJECT(root, destroy_parameters,
1413
			error_code, error_cause, TRUE,
1414
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1415
		if(error_code != 0)
1424 1416
			goto error;
1425
		}
1417
		json_t *room = json_object_get(root, "room");
1426 1418
		json_t *permanent = json_object_get(root, "permanent");
1427
		if(permanent && !json_is_boolean(permanent)) {
1428
			JANUS_LOG(LOG_ERR, "Invalid element (permanent should be a boolean)\n");
1429
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1430
			g_snprintf(error_cause, 512, "Invalid value (permanent should be a boolean)");
1431
			goto error;
1432
		}
1433 1419
		gboolean save = permanent ? json_is_true(permanent) : FALSE;
1434 1420
		if(save && config == NULL) {
1435 1421
			JANUS_LOG(LOG_ERR, "No configuration file, can't destroy room permanently\n");
......
1457 1443
		}
1458 1444
		if(videoroom->room_secret) {
1459 1445
			/* A secret is required for this action */
1460
			json_t *secret = json_object_get(root, "secret");
1461
			if(!secret) {
1446
			JANUS_VALIDATE_JSON_OBJECT(root, secret_parameters,
1447
				error_code, error_cause, TRUE,
1448
				JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1449
			if(error_code != 0) {
1462 1450
				janus_mutex_unlock(&rooms_mutex);
1463
				JANUS_LOG(LOG_ERR, "Missing element (secret)\n");
1464
				error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1465
				g_snprintf(error_cause, 512, "Missing element (secret)");
1466
				goto error;
1467
			}
1468
			if(!json_is_string(secret)) {
1469
				janus_mutex_unlock(&rooms_mutex);
1470
				JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
1471
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1472
				g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
1473 1451
				goto error;
1474 1452
			}
1453
			json_t *secret = json_object_get(root, "secret");
1475 1454
			if(!janus_strcmp_const_time(videoroom->room_secret, json_string_value(secret))) {
1476 1455
				janus_mutex_unlock(&rooms_mutex);
1477 1456
				JANUS_LOG(LOG_ERR, "Unauthorized (wrong secret)\n");
......
1564 1543
		json_object_set_new(response, "list", list);
1565 1544
		goto plugin_response;
1566 1545
	} else if(!strcasecmp(request_text, "rtp_forward")) {
1567
		json_t *room = json_object_get(root, "room");
1568
		if(!room) {
1569
			JANUS_LOG(LOG_ERR, "Missing element (room)\n");
1570
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1571
			g_snprintf(error_cause, 512, "Missing element (room)");
1546
		JANUS_VALIDATE_JSON_OBJECT(root, rtp_forward_parameters,
1547
			error_code, error_cause, TRUE,
1548
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1549
		if(error_code != 0)
1572 1550
			goto error;
1573
		}
1574
		if(!json_is_integer(room) || json_integer_value(room) < 0 ) {
1575
			JANUS_LOG(LOG_ERR, "Invalid element (room should be a positive integer)\n");
1576
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1577
			g_snprintf(error_cause, 512, "Invalid element (room should be a positive integer)");
1578
			goto error;
1579
		}
1551
		json_t *room = json_object_get(root, "room");
1580 1552
		json_t *pub_id = json_object_get(root, "publisher_id");
1581
		if(!pub_id) {
1582
			JANUS_LOG(LOG_ERR, "Missing element (publisher_id)\n");
1583
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1584
			g_snprintf(error_cause, 512, "Missing element (publisher_id)");
1585
			goto error;
1586
		}
1587
		if(!json_is_integer(pub_id) || json_integer_value(pub_id) < 0) {
1588
			JANUS_LOG(LOG_ERR, "Invalid element (publisher_id should be a postive integer)\n");
1589
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1590
			g_snprintf(error_cause, 512, "Invalid element (publisher_id should be a positive integer)");
1591
			goto error;
1592
		}
1593 1553
		int video_port = -1;
1594 1554
		int audio_port = -1;
1595 1555
		json_t *vid_port = json_object_get(root, "video_port");
1596
		if(vid_port && (!json_is_integer(vid_port) || json_integer_value(vid_port) < 0)) {
1597
			JANUS_LOG(LOG_ERR, "Invalid element (video_port should be a positive integer)\n");
1598
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1599
			g_snprintf(error_cause, 512, "Invalid element (video_port should be a positive integer)");
1600
			goto error;
1601
		}
1602 1556
		if(vid_port) {
1603 1557
			video_port = json_integer_value(vid_port);
1604 1558
		}
1605 1559
		json_t *au_port = json_object_get(root, "audio_port");
1606
		if(au_port && (!json_is_integer(au_port) || json_integer_value(au_port) <0)) {
1607
			JANUS_LOG(LOG_ERR, "Invalid element (audio_port should be a positive integer)\n");
1608
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1609
			g_snprintf(error_cause, 512, "Invalid element (audio_port should be a positive integer)");
1610
			goto error;
1611
		}
1612 1560
		if(au_port) {
1613 1561
			audio_port = json_integer_value(au_port);
1614 1562
		}
1615 1563
		json_t *json_host = json_object_get(root, "host");
1616
		if(!json_host) {
1617
			JANUS_LOG(LOG_ERR, "Missing element (host)\n");
1618
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1619
			g_snprintf(error_cause, 512, "Missing element (host)");
1620
			goto error;
1621
		}
1622
		if(!json_is_string(json_host)) {
1623
			JANUS_LOG(LOG_ERR, "Invalid element (host should be a string)\n");
1624
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1625
			g_snprintf(error_cause, 512, "Invalid element (host should be a string)");
1626
			goto error;
1627
		}
1628 1564
		
1629 1565
		guint64 room_id = json_integer_value(room);
1630 1566
		guint64 publisher_id = json_integer_value(pub_id);
......
1647 1583
		}
1648 1584
		if(videoroom->room_secret) {
1649 1585
			/* A secret is required for this action */
1650
			json_t *secret = json_object_get(root, "secret");
1651
			if(!secret) {
1586
			JANUS_VALIDATE_JSON_OBJECT(root, secret_parameters,
1587
				error_code, error_cause, TRUE,
1588
				JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1589
			if(error_code != 0) {
1652 1590
				janus_mutex_unlock(&rooms_mutex);
1653
				JANUS_LOG(LOG_ERR, "Missing element (secret)\n");
1654
				error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1655
				g_snprintf(error_cause, 512, "Missing element (secret)");
1656
				goto error;
1657
			}
1658
			if(!json_is_string(secret)) {
1659
				janus_mutex_unlock(&rooms_mutex);
1660
				JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
1661
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1662
				g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
1663 1591
				goto error;
1664 1592
			}
1593
			json_t *secret = json_object_get(root, "secret");
1665 1594
			if(!janus_strcmp_const_time(videoroom->room_secret, json_string_value(secret))) {
1666 1595
				janus_mutex_unlock(&rooms_mutex);
1667 1596
				JANUS_LOG(LOG_ERR, "Unauthorized (wrong secret)\n");
......
1728 1657
		json_object_set_new(response, "videoroom", json_string("rtp_forward"));
1729 1658
		goto plugin_response;
1730 1659
	} else if(!strcasecmp(request_text, "stop_rtp_forward")) {
1731
		json_t *room = json_object_get(root, "room");
1732
		if(!room) {
1733
			JANUS_LOG(LOG_ERR, "Missing element (room)\n");
1734
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1735
			g_snprintf(error_cause, 512, "Missing element (room)");
1660
		JANUS_VALIDATE_JSON_OBJECT(root, stop_rtp_forward_parameters,
1661
			error_code, error_cause, TRUE,
1662
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1663
		if(error_code != 0)
1736 1664
			goto error;
1737
		}
1738
		if(!json_is_integer(room) || json_integer_value(room) < 0) {
1739
			JANUS_LOG(LOG_ERR, "Invalid element (room should be a positive integer)\n");
1740
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1741
			g_snprintf(error_cause, 512, "Invalid element (room should be a positive integer)");
1742
			goto error;
1743
		}
1665
		json_t *room = json_object_get(root, "room");
1744 1666
		json_t *pub_id = json_object_get(root, "publisher_id");
1745
		if(!pub_id) {
1746
			JANUS_LOG(LOG_ERR, "Missing element (publisher_id)\n");
1747
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1748
			g_snprintf(error_cause, 512, "Missing element (publisher_id)");
1749
			goto error;
1750
		}
1751
		if(!json_is_integer(pub_id) || json_integer_value(pub_id) < 0) {
1752
			JANUS_LOG(LOG_ERR, "Invalid element (publisher_id should be a positive integer)\n");
1753
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1754
			g_snprintf(error_cause, 512, "Invalid element (publisher_id should be a positive integer)");
1755
			goto error;
1756
		}
1757 1667
		json_t *id = json_object_get(root, "stream_id");
1758
		if(!id) {
1759
			JANUS_LOG(LOG_ERR, "Missing element (stream_id)\n");
1760
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1761
			g_snprintf(error_cause, 512, "Missing element (stream_id)");
1762
			goto error;
1763
		}
1764
		if(!json_is_integer(id) || json_integer_value(id) < 0) {
1765
			JANUS_LOG(LOG_ERR, "Invalid element (stream_id should be a positive integer)\n");
1766
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1767
			g_snprintf(error_cause, 512, "Invalid element (stream_id should be a positive integer)");
1768
			goto error;
1769
		}
1770 1668

  
1771 1669
		guint64 room_id = json_integer_value(room);
1772 1670
		guint64 publisher_id = json_integer_value(pub_id);
......
1789 1687
		}
1790 1688
		if(videoroom->room_secret) {
1791 1689
			/* A secret is required for this action */
1792
			json_t *secret = json_object_get(root, "secret");
1793
			if(!secret) {
1690
			JANUS_VALIDATE_JSON_OBJECT(root, secret_parameters,
1691
				error_code, error_cause, TRUE,
1692
				JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1693
			if(error_code != 0) {
1794 1694
				janus_mutex_unlock(&rooms_mutex);
1795
				JANUS_LOG(LOG_ERR, "Missing element (secret)\n");
1796
				error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1797
				g_snprintf(error_cause, 512, "Missing element (secret)");
1798
				goto error;
1799
			}
1800
			if(!json_is_string(secret)) {
1801
				janus_mutex_unlock(&rooms_mutex);
1802
				JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
1803
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
1804
				g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
1805 1695
				goto error;
1806 1696
			}
1697
			json_t *secret = json_object_get(root, "secret");
1807 1698
			if(!janus_strcmp_const_time(videoroom->room_secret, json_string_value(secret))) {
1808 1699
				janus_mutex_unlock(&rooms_mutex);
1809 1700
				JANUS_LOG(LOG_ERR, "Unauthorized (wrong secret)\n");
......
1842 1733
		goto plugin_response;
1843 1734
	} else if(!strcasecmp(request_text, "exists")) {
1844 1735
		/* Check whether a given room exists or not, returns true/false */	
1845
		json_t *room = json_object_get(root, "room");
1846
		if(!room || !json_is_integer(room) || json_integer_value(room) < 0) {
1847
			JANUS_LOG(LOG_ERR, "Invalid request, room number must be included in request and must be a positive integer\n");
1848
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1849
			g_snprintf(error_cause, 512, "Missing element (room)");
1736
		JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
1737
			error_code, error_cause, TRUE,
1738
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1739
		if(error_code != 0)
1850 1740
			goto error;
1851
		}
1741
		json_t *room = json_object_get(root, "room");
1852 1742
		guint64 room_id = json_integer_value(room);
1853 1743
		janus_mutex_lock(&rooms_mutex);
1854 1744
		gboolean room_exists = g_hash_table_contains(rooms, GUINT_TO_POINTER(room_id));
......
1860 1750
		goto plugin_response;
1861 1751
	} else if(!strcasecmp(request_text, "listparticipants")) {
1862 1752
		/* List all participants in a room, specifying whether they're publishers or just attendees */	
1863
		json_t *room = json_object_get(root, "room");
1864
		if(!room || !json_is_integer(room) || json_integer_value(room) < 0) {
1865
			JANUS_LOG(LOG_ERR, "Invalid request, room number must be included in request and must be a positive integer\n");
1866
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
1867
			g_snprintf(error_cause, 512, "Missing element (room)");
1753
		JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
1754
			error_code, error_cause, TRUE,
1755
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
1756
		if(error_code != 0)
1868 1757
			goto error;
1869
		}
1758
		json_t *room = json_object_get(root, "room");
1870 1759
		guint64 room_id = json_integer_value(room);
1871 1760
		janus_mutex_lock(&rooms_mutex);
1872 1761
		janus_videoroom *videoroom = g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id));
......
2367 2256
	JANUS_LOG(LOG_VERB, "Joining VideoRoom handler thread\n");
2368 2257
	janus_videoroom_message *msg = NULL;
2369 2258
	int error_code = 0;
2370
	char *error_cause = g_malloc0(512);
2371
	if(error_cause == NULL) {
2372
		JANUS_LOG(LOG_FATAL, "Memory error!\n");
2373
		return NULL;
2374
	}
2259
	char error_cause[512];
2375 2260
	json_t *root = NULL;
2376 2261
	while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
2377 2262
		msg = g_async_queue_pop(messages);
......
2409 2294
		}
2410 2295
		root = msg->message;
2411 2296
		/* Get the request first */
2412
		json_t *request = json_object_get(root, "request");
2413
		if(!request) {
2414
			JANUS_LOG(LOG_ERR, "Missing element (request)\n");
2415
			error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
2416
			g_snprintf(error_cause, 512, "Missing element (request)");
2417
			goto error;
2418
		}
2419
		if(!json_is_string(request)) {
2420
			JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
2421
			error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2422
			g_snprintf(error_cause, 512, "Invalid element (request should be a string)");
2297
		JANUS_VALIDATE_JSON_OBJECT(root, request_parameters,
2298
			error_code, error_cause, TRUE,
2299
			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2300
		if(error_code != 0)
2423 2301
			goto error;
2424
		}
2302
		json_t *request = json_object_get(root, "request");
2425 2303
		const char *request_text = json_string_value(request);
2426 2304
		json_t *event = NULL;
2427 2305
		/* 'create' and 'destroy' are handled synchronously: what kind of participant is this session referring to? */
......
2434 2312
				g_snprintf(error_cause, 512, "Invalid request on unconfigured participant");
2435 2313
				goto error;
2436 2314
			}
2437
			json_t *room = json_object_get(root, "room");
2438
			if(!room) {
2439
				JANUS_LOG(LOG_ERR, "Missing element (room)\n");
2440
				g_snprintf(error_cause, 512, "Missing element (room)");
2441
				goto error;
2442
			}
2443
			if(!json_is_integer(room) || json_integer_value(room) < 0) {
2444
				JANUS_LOG(LOG_ERR, "Invalid element (room should be a positive integer)\n");
2445
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2446
				g_snprintf(error_cause, 512, "Invalid element (room should be a positive integer)");
2315
			JANUS_VALIDATE_JSON_OBJECT(root, join_parameters,
2316
				error_code, error_cause, TRUE,
2317
				JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2318
			if(error_code != 0)
2447 2319
				goto error;
2448
			}
2320
			json_t *room = json_object_get(root, "room");
2449 2321
			guint64 room_id = json_integer_value(room);
2450 2322
			janus_mutex_lock(&rooms_mutex);
2451 2323
			janus_videoroom *videoroom = g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id));
......
2465 2337
			}
2466 2338
			if(videoroom->room_pin) {
2467 2339
				/* A pin is required to join this room */
2468
				json_t *pin = json_object_get(root, "pin");
2469
				if(!pin) {
2340
				JANUS_VALIDATE_JSON_OBJECT(root, pin_parameters,
2341
					error_code, error_cause, TRUE,
2342
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2343
				if(error_code != 0) {
2470 2344
					janus_mutex_unlock(&rooms_mutex);
2471
					JANUS_LOG(LOG_ERR, "Missing element (pin)\n");
2472
					error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
2473
					g_snprintf(error_cause, 512, "Missing element (pin)");
2474
					goto error;
2475
				}
2476
				if(!json_is_string(pin)) {
2477
					janus_mutex_unlock(&rooms_mutex);
2478
					JANUS_LOG(LOG_ERR, "Invalid element (pin should be a string)\n");
2479
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2480
					g_snprintf(error_cause, 512, "Invalid element (pin should be a string)");
2481 2345
					goto error;
2482 2346
				}
2347
				json_t *pin = json_object_get(root, "pin");
2483 2348
				if(!janus_strcmp_const_time(videoroom->room_pin, json_string_value(pin))) {
2484 2349
					janus_mutex_unlock(&rooms_mutex);
2485 2350
					JANUS_LOG(LOG_ERR, "Unauthorized (wrong pin)\n");
......
2490 2355
			}
2491 2356
			janus_mutex_unlock(&rooms_mutex);
2492 2357
			json_t *ptype = json_object_get(root, "ptype");
2493
			if(!ptype) {
2494
				JANUS_LOG(LOG_ERR, "Missing element (ptype)\n");
2495
				error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
2496
				g_snprintf(error_cause, 512, "Missing element (ptype)");
2497
				goto error;
2498
			}
2499
			if(!json_is_string(ptype)) {
2500
				JANUS_LOG(LOG_ERR, "Invalid element (ptype should be a string)\n");
2501
				error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2502
				g_snprintf(error_cause, 512, "Invalid element (ptype should be a string)");
2503
				goto error;
2504
			}
2505 2358
			const char *ptype_text = json_string_value(ptype);
2506 2359
			if(!strcasecmp(ptype_text, "publisher")) {
2507 2360
				JANUS_LOG(LOG_VERB, "Configuring new publisher\n");
2508
				json_t *display = json_object_get(root, "display");
2509
				if(display && !json_is_string(display)) {
2510
					JANUS_LOG(LOG_ERR, "Invalid element (display should be a string)\n");
2511
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2512
					g_snprintf(error_cause, 512, "Invalid element (display should be a string)");
2361
				JANUS_VALIDATE_JSON_OBJECT(root, publisher_parameters,
2362
					error_code, error_cause, TRUE,
2363
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2364
				if(error_code != 0)
2513 2365
					goto error;
2514
				}
2366
				json_t *display = json_object_get(root, "display");
2515 2367
				const char *display_text = display ? json_string_value(display) : NULL;
2516 2368
				guint64 user_id = 0;
2517 2369
				json_t *id = json_object_get(root, "id");
2518 2370
				if(id) {
2519
					if(!json_is_integer(id) || json_integer_value(id) < 0) {
2520
						JANUS_LOG(LOG_ERR, "Invalid element (id should be a positive integer)\n");
2521
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2522
						g_snprintf(error_cause, 512, "Invalid element (id should be a positive integer)");
2523
						goto error;
2524
					}
2525 2371
					user_id = json_integer_value(id);
2526 2372
					janus_mutex_lock(&videoroom->participants_mutex);
2527 2373
					if(g_hash_table_lookup(videoroom->participants, GUINT_TO_POINTER(user_id)) != NULL) {
......
2550 2396
				json_t *audio = NULL, *video = NULL, *bitrate = NULL, *record = NULL, *recfile = NULL;
2551 2397
				if(!strcasecmp(request_text, "joinandconfigure")) {
2552 2398
					/* Also configure (or publish a new feed) audio/video/bitrate for this new publisher */
2399
					/* join_parameters were validated earlier. */
2553 2400
					audio = json_object_get(root, "audio");
2554
					if(audio && !json_is_boolean(audio)) {
2555
						JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
2556
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2557
						g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
2558
						goto error;
2559
					}
2560 2401
					video = json_object_get(root, "video");
2561
					if(video && !json_is_boolean(video)) {
2562
						JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
2563
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2564
						g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
2565
						goto error;
2566
					}
2567 2402
					bitrate = json_object_get(root, "bitrate");
2568
					if(bitrate && (!json_is_integer(bitrate) || json_integer_value(bitrate) < 0)) {
2569
						JANUS_LOG(LOG_ERR, "Invalid element (bitrate should be a positive integer)\n");
2570
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2571
						g_snprintf(error_cause, 512, "Invalid value (bitrate should be a positive integer)");
2572
						goto error;
2573
					}
2574 2403
					record = json_object_get(root, "record");
2575
					if(record && !json_is_boolean(record)) {
2576
						JANUS_LOG(LOG_ERR, "Invalid element (record should be a boolean)\n");
2577
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2578
						g_snprintf(error_cause, 512, "Invalid value (record should be a boolean)");
2579
						goto error;
2580
					}
2581 2404
					recfile = json_object_get(root, "filename");
2582
					if(recfile && !json_is_string(recfile)) {
2583
						JANUS_LOG(LOG_ERR, "Invalid element (filename should be a string)\n");
2584
						error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2585
						g_snprintf(error_cause, 512, "Invalid value (filename should be a string)");
2586
						goto error;
2587
					}
2588 2405
				}
2589 2406
				janus_videoroom_participant *publisher = g_malloc0(sizeof(janus_videoroom_participant));
2590 2407
				if(publisher == NULL) {
......
2709 2526
			} else if(!strcasecmp(ptype_text, "listener")) {
2710 2527
				JANUS_LOG(LOG_VERB, "Configuring new listener\n");
2711 2528
				/* This is a new listener */
2712
				json_t *feed = json_object_get(root, "feed");
2713
				if(!feed) {
2714
					JANUS_LOG(LOG_ERR, "Missing element (feed)\n");
2715
					error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
2716
					g_snprintf(error_cause, 512, "Missing element (feed)");
2529
				JANUS_VALIDATE_JSON_OBJECT(root, listener_parameters,
2530
					error_code, error_cause, TRUE,
2531
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2532
				if(error_code != 0)
2717 2533
					goto error;
2718
				}
2719
				if(!json_is_integer(feed) || json_integer_value(feed) < 0) {
2720
					JANUS_LOG(LOG_ERR, "Invalid element (feed should be a positive integer)\n");
2721
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2722
					g_snprintf(error_cause, 512, "Invalid element (feed should be a positive integer)");
2723
					goto error;
2724
				}
2534
				json_t *feed = json_object_get(root, "feed");
2725 2535
				guint64 feed_id = json_integer_value(feed);
2726 2536
				json_t *audio = json_object_get(root, "audio");
2727
				if(audio && !json_is_boolean(audio)) {
2728
					JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
2729
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2730
					g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
2731
					goto error;
2732
				}
2733 2537
				json_t *video = json_object_get(root, "video");
2734
				if(video && !json_is_boolean(video)) {
2735
					JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
2736
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2737
					g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
2738
					goto error;
2739
				}
2740 2538
				json_t *data = json_object_get(root, "data");
2741
				if(data && !json_is_boolean(data)) {
2742
					JANUS_LOG(LOG_ERR, "Invalid element (data should be a boolean)\n");
2743
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2744
					g_snprintf(error_cause, 512, "Invalid value (data should be a boolean)");
2745
					goto error;
2746
				}
2747 2539
				janus_mutex_lock(&videoroom->participants_mutex);
2748 2540
				janus_videoroom_participant *publisher = g_hash_table_lookup(videoroom->participants, GUINT_TO_POINTER(feed_id));
2749 2541
				janus_mutex_unlock(&videoroom->participants_mutex);
......
2824 2616
				JANUS_LOG(LOG_INFO, "Configuring new Multiplexed listener\n");
2825 2617
				/* Any feed we want to attach to already? */
2826 2618
				GList *list = NULL;
2827
				json_t *feeds = json_object_get(root, "feeds");
2828
				if(feeds && !json_is_array(feeds)) {
2829
					JANUS_LOG(LOG_ERR, "Invalid element (feeds should be an array)\n");
2830
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2831
					g_snprintf(error_cause, 512, "Invalid element (feeds should be an array)");
2619
				JANUS_VALIDATE_JSON_OBJECT(root, feeds_parameters,
2620
					error_code, error_cause, TRUE,
2621
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2622
				if(error_code != 0)
2832 2623
					goto error;
2833
				}
2624
				json_t *feeds = json_object_get(root, "feeds");
2834 2625
				if(feeds && json_array_size(feeds) > 0) {
2835 2626
					unsigned int i = 0;
2836 2627
					int problem = 0;
......
2936 2727
					goto error;
2937 2728
				}
2938 2729
				/* Configure (or publish a new feed) audio/video/bitrate for this publisher */
2939
				json_t *audio = json_object_get(root, "audio");
2940
				if(audio && !json_is_boolean(audio)) {
2941
					JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
2942
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2943
					g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
2730
				JANUS_VALIDATE_JSON_OBJECT(root, publish_parameters,
2731
					error_code, error_cause, TRUE,
2732
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2733
				if(error_code != 0)
2944 2734
					goto error;
2945
				}
2735
				json_t *audio = json_object_get(root, "audio");
2946 2736
				json_t *video = json_object_get(root, "video");
2947
				if(video && !json_is_boolean(video)) {
2948
					JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
2949
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2950
					g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
2951
					goto error;
2952
				}
2953 2737
				json_t *bitrate = json_object_get(root, "bitrate");
2954
				if(bitrate && (!json_is_integer(bitrate) || json_integer_value(bitrate) < 0)) {
2955
					JANUS_LOG(LOG_ERR, "Invalid element (bitrate should be a positive integer)\n");
2956
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2957
					g_snprintf(error_cause, 512, "Invalid value (bitrate should be a positive integer)");
2958
					goto error;
2959
				}
2960 2738
				json_t *record = json_object_get(root, "record");
2961
				if(record && !json_is_boolean(record)) {
2962
					JANUS_LOG(LOG_ERR, "Invalid element (record should be a boolean)\n");
2963
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2964
					g_snprintf(error_cause, 512, "Invalid value (record should be a boolean)");
2965
					goto error;
2966
				}
2967 2739
				json_t *recfile = json_object_get(root, "filename");
2968
				if(recfile && !json_is_string(recfile)) {
2969
					JANUS_LOG(LOG_ERR, "Invalid element (filename should be a string)\n");
2970
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
2971
					g_snprintf(error_cause, 512, "Invalid value (filename should be a string)");
2972
					goto error;
2973
				}
2974 2740
				if(audio) {
2975 2741
					participant->audio_active = json_is_true(audio);
2976 2742
					JANUS_LOG(LOG_VERB, "Setting audio property: %s (room %"SCNu64", user %"SCNu64")\n", participant->audio_active ? "true" : "false", participant->room->room_id, participant->user_id);
......
3164 2930
					gateway->relay_rtcp(publisher->session->handle, 1, buf, 12);
3165 2931
				}
3166 2932
			} else if(!strcasecmp(request_text, "configure")) {
3167
				json_t *audio = json_object_get(root, "audio");
3168
				if(audio && !json_is_boolean(audio)) {
3169
					JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
3170
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3171
					g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
2933
				JANUS_VALIDATE_JSON_OBJECT(root, configure_parameters,
2934
					error_code, error_cause, TRUE,
2935
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2936
				if(error_code != 0)
3172 2937
					goto error;
3173
				}
2938
				json_t *audio = json_object_get(root, "audio");
3174 2939
				json_t *video = json_object_get(root, "video");
3175
				if(video && !json_is_boolean(video)) {
3176
					JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
3177
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3178
					g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
3179
					goto error;
3180
				}
3181 2940
				json_t *data = json_object_get(root, "data");
3182
				if(data && !json_is_boolean(data)) {
3183
					JANUS_LOG(LOG_ERR, "Invalid element (data should be a boolean)\n");
3184
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3185
					g_snprintf(error_cause, 512, "Invalid value (data should be a boolean)");
3186
					goto error;
3187
				}
3188 2941
				/* Update the audio/video/data flags, if set */
3189 2942
				janus_videoroom_participant *publisher = listener->feed;
3190 2943
				if(publisher) {
......
3208 2961
				json_object_set_new(event, "paused", json_string("ok"));
3209 2962
			} else if(!strcasecmp(request_text, "switch")) {
3210 2963
				/* This listener wants to switch to a different publisher */
3211
				json_t *feed = json_object_get(root, "feed");
3212
				if(!feed) {
3213
					JANUS_LOG(LOG_ERR, "Missing element (feed)\n");
3214
					error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
3215
					g_snprintf(error_cause, 512, "Missing element (feed)");
2964
				JANUS_VALIDATE_JSON_OBJECT(root, listener_parameters,
2965
					error_code, error_cause, TRUE,
2966
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
2967
				if(error_code != 0)
3216 2968
					goto error;
3217
				}
3218
				if(!json_is_integer(feed) || json_integer_value(feed) < 0) {
3219
					JANUS_LOG(LOG_ERR, "Invalid element (feed should be a positive integer)\n");
3220
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3221
					g_snprintf(error_cause, 512, "Invalid element (feed should be a positive integer)");
3222
					goto error;
3223
				}
2969
				json_t *feed = json_object_get(root, "feed");
3224 2970
				guint64 feed_id = json_integer_value(feed);
3225 2971
				json_t *audio = json_object_get(root, "audio");
3226
				if(audio && !json_is_boolean(audio)) {
3227
					JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
3228
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3229
					g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
3230
					goto error;
3231
				}
3232 2972
				json_t *video = json_object_get(root, "video");
3233
				if(video && !json_is_boolean(video)) {
3234
					JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
3235
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3236
					g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
3237
					goto error;
3238
				}
3239 2973
				json_t *data = json_object_get(root, "data");
3240
				if(data && !json_is_boolean(data)) {
3241
					JANUS_LOG(LOG_ERR, "Invalid element (data should be a boolean)\n");
3242
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3243
					g_snprintf(error_cause, 512, "Invalid value (data should be a boolean)");
3244
					goto error;
3245
				}
3246 2974
				if(!listener->room) {
3247 2975
					JANUS_LOG(LOG_ERR, "Room Destroyed \n");
3248 2976
					error_code = JANUS_VIDEOROOM_ERROR_NO_SUCH_ROOM;
......
3344 3072
			} else if(!strcasecmp(request_text, "add")) {
3345 3073
				/* Add new streams to subscribe to */
3346 3074
				GList *list = NULL;
3347
				json_t *feeds = json_object_get(root, "feeds");
3348
				if(!feeds) {
3349
					JANUS_LOG(LOG_ERR, "Missing element (feeds)\n");
3350
					error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
3351
					g_snprintf(error_cause, 512, "Missing element (feeds)");
3075
				JANUS_VALIDATE_JSON_OBJECT(root, feeds_parameters,
3076
					error_code, error_cause, TRUE,
3077
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
3078
				if(error_code != 0)
3352 3079
					goto error;
3353
				}
3354
				if(!json_is_array(feeds) || json_array_size(feeds) == 0) {
3355
					JANUS_LOG(LOG_ERR, "Invalid element (feeds should be a non-empty array)\n");
3356
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3357
					g_snprintf(error_cause, 512, "Invalid element (feeds should be a non-empty array)");
3358
					goto error;
3359
				}
3080
				json_t *feeds = json_object_get(root, "feeds");
3360 3081
				unsigned int i = 0;
3361 3082
				int problem = 0;
3362 3083
				if(!listener->room) {
......
3415 3136
			} else if(!strcasecmp(request_text, "remove")) {
3416 3137
				/* Remove subscribed streams */
3417 3138
				GList *list = NULL;
3418
				json_t *feeds = json_object_get(root, "feeds");
3419
				if(!feeds) {
3420
					JANUS_LOG(LOG_ERR, "Missing element (feeds)\n");
3421
					error_code = JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT;
3422
					g_snprintf(error_cause, 512, "Missing element (feeds)");
3423
					goto error;
3424
				}
3425
				if(!json_is_array(feeds) || json_array_size(feeds) == 0) {
3426
					JANUS_LOG(LOG_ERR, "Invalid element (feeds should be a non-empty array)\n");
3427
					error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
3428
					g_snprintf(error_cause, 512, "Invalid element (feeds should be a non-empty array)");
3139
				JANUS_VALIDATE_JSON_OBJECT(root, feeds_parameters,
3140
					error_code, error_cause, TRUE,
3141
					JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
3142
				if(error_code != 0)
3429 3143
					goto error;
3430
				}
3144
				json_t *feeds = json_object_get(root, "feeds");
3431 3145
				unsigned int i = 0;
3432 3146
				int error = 0;
3433 3147
				for(i=0; i<json_array_size(feeds); i++) {
......
4082 3796
			janus_videoroom_message_free(msg);
4083 3797
		}
4084 3798
	}
4085
	g_free(error_cause);
4086 3799
	JANUS_LOG(LOG_VERB, "Leaving VideoRoom handler thread\n");
4087 3800
	return NULL;
4088 3801
}
utils.c
558 558
	g_free(pidfile);
559 559
	return 0;
560 560
}
561

  
562
void janus_get_json_type_name(int jtype, unsigned int flags, char *type_name) {
563
	/* Longest possible combination is "a non-empty boolean" plus one for null char */
564
	gsize req_size = 20;
565
	/* Don't allow for both "positive" and "non-empty" because that needlessly increases the size. */
566
	if((flags & JANUS_JSON_PARAM_POSITIVE) != 0) {
567
		g_strlcpy(type_name, "a positive ", req_size);
568
	}
569
	else if((flags & JANUS_JSON_PARAM_NONEMPTY) != 0) {
570
		g_strlcpy(type_name, "a non-empty ", req_size);
571
	}
572
	else if(jtype == JSON_INTEGER || jtype == JSON_ARRAY || jtype == JSON_OBJECT) {
573
		g_strlcpy(type_name, "an ", req_size);
574
	}
575
	else {
576
		g_strlcpy(type_name, "a ", req_size);
577
	}
578
	switch(jtype) {
579
		case JSON_TRUE:
580
			g_strlcat(type_name, "boolean", req_size);
581
			break;
582
		case JSON_INTEGER:
583
			g_strlcat(type_name, "integer", req_size);
584
			break;
585
		case JSON_REAL:
586
			g_strlcat(type_name, "real", req_size);
587
			break;
588
		case JSON_STRING:
589
			g_strlcat(type_name, "string", req_size);
590
			break;
591
		case JSON_ARRAY:
592
			g_strlcat(type_name, "array", req_size);
593
			break;
594
		case JSON_OBJECT:
595
			g_strlcat(type_name, "object", req_size);
596
			break;
597
		default:
598
			break;
599
	}
600
}
601

  
602
gboolean janus_json_is_valid(json_t *val, json_type jtype, unsigned int flags) {
603
	gboolean is_valid = (json_typeof(val) == jtype || (jtype == JSON_TRUE && json_typeof(val) == JSON_FALSE));
604
	if(!is_valid)
605
		return FALSE;
606
	if((flags & JANUS_JSON_PARAM_POSITIVE) != 0) {
607
		switch(jtype) {
608
			case JSON_INTEGER:
609
				is_valid = (json_integer_value(val) >= 0);
610
				break;
611
			case JSON_REAL:
612
				is_valid = (json_real_value(val) >= 0);
613
				break;
614
			default:
615
				break;
616
		}
617
	}
618
	else if((flags & JANUS_JSON_PARAM_NONEMPTY) != 0) {
619
		switch(jtype) {
620
			case JSON_STRING:
621
				is_valid = (json_string_length(val) > 0);
622
				break;
623
			case JSON_ARRAY:
624
				is_valid = (json_array_size(val) > 0);
625
				break;
626
			default:
627
				break;
628
		}
629
	}
630
	return is_valid;
631
}
utils.h
15 15
#include <stdint.h>
16 16
#include <glib.h>
17 17
#include <netinet/in.h>
18
#include <jansson.h>
19

  
20
/* Use JANUS_JSON_BOOL instead of the non-existing JSON_BOOLEAN */
21
#define JANUS_JSON_BOOL JSON_TRUE
22
#define JANUS_JSON_PARAM_REQUIRED 1
23
#define JANUS_JSON_PARAM_POSITIVE 2
24
#define JANUS_JSON_PARAM_NONEMPTY 4
25

  
26
struct janus_json_parameter {
27
	const gchar *name;
28
	json_type jtype;
29
	unsigned int flags;
30
};
18 31

  
19 32
/*! \brief Helper to retrieve the system monotonic time, as Glib's
20 33
 * g_get_monotonic_time may not be available (only since 2.28)
......
139 152
/*! \brief Unlock and remove a previously created PID file
140 153
 * @returns 0 if successful, a negative integer otherwise */
141 154
int janus_pidfile_remove(void);
155

  
156
/*! \brief Creates a string describing the JSON type and constraint
157
 * @param jtype The JSON type, e.g., JSON_STRING
158
 * @param flags Indicates constraints for the described type
159
 * @param[out] The type description, e.g., "a positive integer"; required size is 19 characters
160
 * @returns 0 if successful, a negative integer otherwise */
161
void janus_get_json_type_name(int jtype, unsigned int flags, char *type_name);
162

  
163
/*! \brief Checks whether the JSON value matches the type and constraint
164
 * @param val The JSON value to be checked
165
 * @param jtype The JSON type, e.g., JSON_STRING
166
 * @param flags Indicates constraints for the described type
167
 * @returns TRUE if the value is valid */
168
gboolean janus_json_is_valid(json_t *val, json_type jtype, unsigned int flags);
169

  
170
/*! \brief Validates the JSON object against the description of its parameters
171
 * @param missing_format printf format to indicate a missing required parameter; needs one %s for the parameter name
172
 * @param invalid_format printf format to indicate an invalid parameter; needs two %s for parameter name and type description from janus_get_json_type_name
173
 * @param obj The JSON object to be validated
174
 * @param params Array of struct janus_json_parameter to describe the parameters; the array has to be a global or stack variable to make sizeof work
175
 * @param[out] error_code int to return error code
176
 * @param[out] error_cause Array of char or NULL to return the error descriptions; the array has to be a global or stack variable to make sizeof work; the required size is the length of the format string plus the length of the longest parameter name plus 19 for the type description
177
 * @param log_error If TRUE, log any error with JANUS_LOG(LOG_ERR)
178
 * @param missing_code The code to be returned in error_code if a parameter is missing
179
 * @param invalid_code The code to be returned in error_code if a parameter is invalid */
180
#define JANUS_VALIDATE_JSON_OBJECT_FORMAT(missing_format, invalid_format, obj, params, error_code, error_cause, log_error, missing_code, invalid_code) \
181
	do { \
182
		error_code = 0; \
183
		unsigned int i; \
184
		for(i = 0; i < sizeof(params) / sizeof(struct janus_json_parameter); i++) { \
185
			json_t *val = json_object_get(obj, params[i].name); \
186
			if(!val) { \
187
				if((params[i].flags & JANUS_JSON_PARAM_REQUIRED) != 0) {	\
188
					error_code = (missing_code); \
189
					if(log_error) \
190
						JANUS_LOG(LOG_ERR, missing_format "\n", params[i].name); \
191
					if(error_cause != NULL) \
192
						g_snprintf(error_cause, sizeof(error_cause), missing_format, params[i].name); \
193
					break; \
194
				} \
195
				continue; \
196
			} \
197
			if(!janus_json_is_valid(val, params[i].jtype, params[i].flags)) { \
198
				error_code = (invalid_code); \
199
				char type_name[20]; \
200
				janus_get_json_type_name(params[i].jtype, params[i].flags, type_name); \
201
				if(log_error) \
202
					JANUS_LOG(LOG_ERR, invalid_format "\n", params[i].name, type_name); \
203
				if(error_cause != NULL) \
204
					g_snprintf(error_cause, sizeof(error_cause), invalid_format, params[i].name, type_name); \
205
				break; \
206
			} \
207
		} \
208
	} while(0)
209

  
210
/*! \brief Validates the JSON object against the description of its parameters
211
 * @param obj The JSON object to be validated
212
 * @param params Array of struct janus_json_parameter to describe the parameters; the array has to be a global or stack variable to make sizeof work
213
 * @param[out] error_code int to return error code
214
 * @param[out] error_cause Array of char or NULL to return the error descriptions; the array has to be a global or stack variable to make sizeof work; the required size is the length of the longest parameter name plus 54 for the format string and type description
215
 * @param log_error If TRUE, log any error with JANUS_LOG(LOG_ERR)
216
 * @param missing_code The code to be returned in error_code if a parameter is missing
217
 * @param invalid_code The code to be returned in error_code if a parameter is invalid */
218
#define JANUS_VALIDATE_JSON_OBJECT(obj, params, error_code, error_cause, log_error, missing_code, invalid_code) \
219
	JANUS_VALIDATE_JSON_OBJECT_FORMAT("Missing mandatory element (%s)", "Invalid element type (%s should be %s)", obj, params, error_code, error_cause, log_error, missing_code, invalid_code)
220

  
142 221
#endif

Also available in: Unified diff