void pcm_policy_free()
{
	if(PCM_GLOBAL.policy) json_decref(PCM_GLOBAL.policy);
	PCM_GLOBAL.policy = NULL;
}
예제 #2
0
int
udf_cask_smd_accept_fn(char *module, as_smd_item_list_t *items, void *udata, uint32_t accept_opt)
{
	if (accept_opt & AS_SMD_ACCEPT_OPT_CREATE) {
		cf_debug(AS_UDF, "(doing nothing in UDF accept cb for module creation)");
		return 0;
	}

	cf_debug(AS_UDF, "UDF CASK accept fn : n items %zu", items->num_items);

	// For each item in the list, see if the current version
	// is different from the curretly stored version
	// and if the new item is new, write to the storage directory
	for (int i = 0; i < items->num_items ; i++) {

		as_smd_item_t *item = items->item[i];

		if (item->action == AS_SMD_ACTION_SET) {

			json_error_t json_err;
			json_t *item_obj = json_loads(item->value, 0 /*flags*/, &json_err);

			/*item->key is name */
			json_t *content64_obj = json_object_get(item_obj, "content64");
			const char *content64_str = json_string_value(content64_obj);

			// base 64 decode it
			uint32_t encoded_len = strlen(content64_str);
			uint32_t decoded_len = cf_b64_decoded_buf_size(encoded_len) + 1;
			char *content_str = cf_malloc(decoded_len);

			if (! cf_b64_validate_and_decode(content64_str, encoded_len, (uint8_t*)content_str, &decoded_len)) {
				cf_info(AS_UDF, "invalid script on accept, will not register %s", item->key);
				cf_free(content_str);
				json_decref(content64_obj);
				json_decref(item_obj);
				continue;
			}

			content_str[decoded_len] = 0;

			cf_debug(AS_UDF, "pushing to %s, %d bytes [%s]", item->key, decoded_len, content_str);
			mod_lua_wrlock(&mod_lua);

			// content_gen is actually a hash. Not sure if it's filled out or what.
			unsigned char       content_gen[256]    = {0};
			int e = file_write(item->key, (uint8_t *) content_str, decoded_len, content_gen);
			cf_free(content_str);
			json_decref(content64_obj);
			json_decref(item_obj);
			if ( e ) {
				mod_lua_unlock(&mod_lua);
				cf_info(AS_UDF, "invalid script on accept, will not register %s", item->key);
				continue;
			}
			// Update the cache
			as_module_event ame = {
				.type           = AS_MODULE_EVENT_FILE_ADD,
				.data.filename  = item->key
			};
			as_module_update(&mod_lua, &ame);
			mod_lua_unlock(&mod_lua);
		}
		else if (item->action == AS_SMD_ACTION_DELETE) {
			cf_debug(AS_UDF, "received DELETE SMD action %d key %s", item->action, item->key);

			mod_lua_wrlock(&mod_lua);
			file_remove(item->key);

			// fixes potential cache issues
			as_module_event e = {
				.type           = AS_MODULE_EVENT_FILE_REMOVE,
				.data.filename  = item->key
			};
			as_module_update(&mod_lua, &e);

			mod_lua_unlock(&mod_lua);

		}
		else {
예제 #3
0
void janus_videocall_slow_link(janus_plugin_session *handle, int uplink, int video) {
	/* The core is informing us that our peer got or sent too many NACKs, are we pushing media too hard? */
	if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
		return;
	janus_videocall_session *session = (janus_videocall_session *)handle->plugin_handle;	
	if(!session) {
		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
		return;
	}
	if(session->destroyed)
		return;
	session->slowlink_count++;
	if(uplink && !video && !session->audio_active) {
		/* We're not relaying audio and the peer is expecting it, so NACKs are normal */
		JANUS_LOG(LOG_VERB, "Getting a lot of NACKs (slow uplink) for audio, but that's expected, a configure disabled the audio forwarding\n");
	} else if(uplink && video && !session->video_active) {
		/* We're not relaying video and the peer is expecting it, so NACKs are normal */
		JANUS_LOG(LOG_VERB, "Getting a lot of NACKs (slow uplink) for video, but that's expected, a configure disabled the video forwarding\n");
	} else {
		/* Slow uplink or downlink, maybe we set the bitrate cap too high? */
		if(video) {
			/* Halve the bitrate, but don't go too low... */
			if(!uplink) {
				/* Downlink issue, user has trouble sending, halve this user's bitrate cap */
				session->bitrate = session->bitrate > 0 ? session->bitrate : 512*1024;
				session->bitrate = session->bitrate/2;
				if(session->bitrate < 64*1024)
					session->bitrate = 64*1024;
			} else {
				/* Uplink issue, user has trouble receiving, halve this user's peer's bitrate cap */
				if(session->peer == NULL || session->peer->handle == NULL)
					return;	/* Nothing to do */
				session->peer->bitrate = session->peer->bitrate > 0 ? session->peer->bitrate : 512*1024;
				session->peer->bitrate = session->peer->bitrate/2;
				if(session->peer->bitrate < 64*1024)
					session->peer->bitrate = 64*1024;
			}
			JANUS_LOG(LOG_WARN, "Getting a lot of NACKs (slow %s) for %s, forcing a lower REMB: %"SCNu64"\n",
				uplink ? "uplink" : "downlink", video ? "video" : "audio", uplink ? session->peer->bitrate : session->bitrate);
			/* ... and send a new REMB back */
			char rtcpbuf[200];
			memset(rtcpbuf, 0, 200);
			/* FIXME First put a RR (fake)... */
			int rrlen = 32;
			rtcp_rr *rr = (rtcp_rr *)&rtcpbuf;
			rr->header.version = 2;
			rr->header.type = RTCP_RR;
			rr->header.rc = 1;
			rr->header.length = htons((rrlen/4)-1);
			/* ... then put a SDES... */
			int sdeslen = janus_rtcp_sdes((char *)(&rtcpbuf)+rrlen, 200-rrlen, "janusvideo", 10);
			if(sdeslen > 0) {
				/* ... and then finally a REMB */
				janus_rtcp_remb((char *)(&rtcpbuf)+rrlen+sdeslen, 24, uplink ? session->peer->bitrate : session->bitrate);
				gateway->relay_rtcp(uplink ? session->peer->handle : handle, 1, rtcpbuf, rrlen+sdeslen+24);
			}
			/* As a last thing, notify the affected user about this */
			json_t *event = json_object();
			json_object_set_new(event, "videocall", json_string("event"));
			json_t *result = json_object();
			json_object_set_new(result, "status", json_string("slow_link"));
			json_object_set_new(result, "bitrate", json_integer(uplink ? session->peer->bitrate : session->bitrate));
			json_object_set_new(event, "result", result);
			char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
			json_decref(event);
			json_decref(result);
			event = NULL;
			gateway->push_event(uplink ? session->peer->handle : handle, &janus_videocall_plugin, NULL, event_text, NULL, NULL);
			g_free(event_text);
		}
	}
}
예제 #4
0
/* Thread to handle incoming events */
static void *janus_sampleevh_handler(void *data) {
	JANUS_LOG(LOG_VERB, "Joining SampleEventHandler handler thread\n");
	json_t *event = NULL, *output = NULL;
	char *event_text = NULL;
	int count = 0, max = group_events ? 100 : 1;
	int retransmit = 0;
	while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
		if(!retransmit) {
			event = g_async_queue_pop(events);
			if(event == NULL)
				continue;
			if(event == &exit_event)
				break;
			count = 0;
			output = NULL;

			while(TRUE) {
				/* Handle event: just for fun, let's see how long it took for us to take care of this */
				json_t *created = json_object_get(event, "timestamp");
				if(created && json_is_integer(created)) {
					gint64 then = json_integer_value(created);
					gint64 now = janus_get_monotonic_time();
					JANUS_LOG(LOG_DBG, "Handled event after %"SCNu64" us\n", now-then);
				}

				/* Let's check what kind of event this is: we don't really do anything
				 * with it in this plugin, it's just to show how you can handle
				 * different types of events in an event handler. */
				int type = json_integer_value(json_object_get(event, "type"));
				switch(type) {
					case JANUS_EVENT_TYPE_SESSION:
						/* This is a session related event. The only info that is
						 * required is a name for the event itself: a "created"
						 * event may also contain transport info, in the form of
						 * the transport module that originated the session
						 * (e.g., "janus.transport.http") and an internal unique
						 * ID for the transport instance (which may be associated
						 * to a connection or anything else within the specifics
						 * of the transport module itself). Here's an example of
						 * a new session being created:
							{
							   "type": 1,
							   "timestamp": 3583879627,
							   "session_id": 2004798115,
							   "event": {
								  "name": "created"
							   },
							   "transport": {
							      "transport": "janus.transport.http",
							      "id": "0x7fcb100008c0"
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_HANDLE:
						/* This is a handle related event. The only info that is provided
						 * are the name for the event itself and the package name of the
						 * plugin this handle refers to (e.g., "janus.plugin.echotest").
						 * Here's an example of a new handled being attached in a session
						 * to the EchoTest plugin:
							{
							   "type": 2,
							   "timestamp": 3570304977,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "name": "attached",
								  "plugin: "janus.plugin.echotest"
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_JSEP:
						/* This is a JSEP/SDP related event. It provides information
						 * about an ongoing WebRTC negotiation, and so tells you
						 * about the SDP being sent/received, and who's sending it
						 * ("local" means Janus, "remote" means the user). Here's an
						 * example, where the user originated an offer towards Janus:
							{
							   "type": 8,
							   "timestamp": 3570400208,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "owner": "remote",
								  "jsep": {
									 "type": "offer",
									 "sdp": "v=0[..]\r\n"
								  }
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_WEBRTC:
						/* This is a WebRTC related event, and so the content of
						 * the event may vary quite a bit. In fact, you may be notified
						 * about ICE or DTLS states, or when a WebRTC PeerConnection
						 * goes up or down. Here are some examples, in no particular order:
							{
							   "type": 16,
							   "timestamp": 3570416659,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "ice": "connecting",
								  "stream_id": 1,
								  "component_id": 1
							   }
							}
						 *
							{
							   "type": 16,
							   "timestamp": 3570637554,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "selected-pair": "[..]",
								  "stream_id": 1,
								  "component_id": 1
							   }
							}
						 *
							{
							   "type": 16,
							   "timestamp": 3570656112,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "dtls": "connected",
								  "stream_id": 1,
								  "component_id": 1
							   }
							}
						 *
							{
							   "type": 16,
							   "timestamp": 3570657237,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "connection": "webrtcup"
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_MEDIA:
						/* This is a media related event. This can contain different
						 * information about the health of a media session, or about
						 * what's going on in general (e.g., when Janus started/stopped
						 * receiving media of a certain type, or (TODO) when some media related
						 * statistics are available). Here's an example of Janus getting
						 * video from the peer for the first time, or after a second
						 * of no video at all (which would have triggered a "receiving": false):
							{
							   "type": 32,
							   "timestamp": 3571078797,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "media": "video",
								  "receiving": "true"
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_PLUGIN:
						/* This is a plugin related event. Since each plugin may
						 * provide info in a very custom way, the format of this event
						 * is in general very dynamic. You'll always find, though,
						 * an "event" object containing the package name of the
						 * plugin (e.g., "janus.plugin.echotest") and a "data"
						 * object that contains whatever the plugin decided to
						 * notify you about, that will always vary from plugin to
						 * plugin. Besides, notice that "session_id" and "handle_id"
						 * may or may not be present: when they are, you'll know
						 * the event has been triggered within the context of a
						 * specific handle session with the plugin; when they're
						 * not, the plugin sent an event out of context of a
						 * specific session it is handling. Here's an example:
							{
							   "type": 64,
							   "timestamp": 3570336031,
							   "session_id": 2004798115,
							   "handle_id": 3708519405,
							   "event": {
								  "plugin": "janus.plugin.echotest",
								  "data": {
									 "audio_active": "true",
									 "video_active": "true",
									 "bitrate": 0
								  }
							   }
							}
						*/
						break;
					case JANUS_EVENT_TYPE_TRANSPORT:
						/* This is a transport related event (TODO). The syntax of
						 * the common format (transport specific data aside) is
						 * exactly the same as that of the plugin related events
						 * above, with a "transport" property instead of "plugin"
						 * to contain the transport package name. */
						break;
					case JANUS_EVENT_TYPE_CORE:
						/* This is a core related event. This can contain different
						 * information about the health of the Janus instance, or
						 * more generically on some events in the Janus life cycle
						 * (e.g., when it's just been started or when a shutdown
						 * has been requested). Considering the heterogeneous nature
						 * of the information being reported, the content is always
						 * a JSON object (event). Core events are the only ones
						 * missing a session_id. Here's an example:
							{
							   "type": 256,
							   "timestamp": 28381185382,
							   "event": {
								  "status": "started"
							   }
							}
						*/
						break;
					default:
						JANUS_LOG(LOG_WARN, "Unknown type of event '%d'\n", type);
						break;
				}
				if(!group_events) {
					/* We're done here, we just need a single event */
					output = event;
					break;
				}
				/* If we got here, we're grouping */
				if(output == NULL)
					output = json_array();
				json_array_append_new(output, event);
				/* Never group more than a maximum number of events, though, or we might stay here forever */
				count++;
				if(count == max)
					break;
				event = g_async_queue_try_pop(events);
				if(event == NULL || event == &exit_event)
					break;
			}

			/* Since this a simple plugin, it does the same for all events: so just convert to string... */
			event_text = json_dumps(output, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
		}
		/* Whether we just prepared the event or this is a retransmission, send it via HTTP POST */
		CURLcode res;
		struct curl_slist *headers = NULL;
		CURL *curl = curl_easy_init();
		if(curl == NULL) {
			JANUS_LOG(LOG_ERR, "Error initializing CURL context\n");
			goto done;
		}
		curl_easy_setopt(curl, CURLOPT_URL, backend);
		headers = curl_slist_append(headers, "Accept: application/json");
		headers = curl_slist_append(headers, "Content-Type: application/json");
		headers = curl_slist_append(headers, "charsets: utf-8");
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, event_text);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, janus_sampleehv_write_data);
		/* Any credentials? */
		if(backend_user != NULL && backend_pwd != NULL) {
			curl_easy_setopt(curl, CURLOPT_USERNAME, backend_user);
			curl_easy_setopt(curl, CURLOPT_PASSWORD, backend_pwd);
		}
		/* Don't wait forever (let's say, 10 seconds) */
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
		/* Send the request */
		res = curl_easy_perform(curl);
		if(res != CURLE_OK) {
			JANUS_LOG(LOG_ERR, "Couldn't relay event to the backend: %s\n", curl_easy_strerror(res));
			if(max_retransmissions > 0) {
				/* Retransmissions enabled, let's try again */
				if(retransmit == max_retransmissions) {
					retransmit = 0;
					JANUS_LOG(LOG_WARN, "Maximum number of retransmissions reached (%d), event lost...\n", max_retransmissions);
				} else {
					int next = retransmissions_backoff * (pow(2, retransmit));
					JANUS_LOG(LOG_WARN, "Retransmitting event in %d ms...\n", next);
					g_usleep(next*1000);
					retransmit++;
				}
			} else {
				JANUS_LOG(LOG_WARN, "Retransmissions disabled, event lost...\n");
			}
		} else {
			JANUS_LOG(LOG_DBG, "Event sent!\n");
			retransmit = 0;
		}
done:
		/* Cleanup */
		if(curl)
			curl_easy_cleanup(curl);
		if(headers)
			curl_slist_free_all(headers);
		if(!retransmit)
			g_free(event_text);

		/* Done, let's unref the event */
		json_decref(output);
		output = NULL;
	}
	JANUS_LOG(LOG_VERB, "Leaving SampleEventHandler handler thread\n");
	return NULL;
}
예제 #5
0
static void run_tests()
{
    json_t *j, *j2;
    int i1, i2, i3;
    json_int_t I1;
    int rv;
    size_t z;
    double f;
    char *s;

    json_error_t error;

    /*
     * Simple, valid json_pack cases
     */

    /* true */
    rv = json_unpack(json_true(), "b", &i1);
    if(rv || !i1)
        fail("json_unpack boolean failed");

    /* false */
    rv = json_unpack(json_false(), "b", &i1);
    if(rv || i1)
        fail("json_unpack boolean failed");

    /* null */
    if(json_unpack(json_null(), "n"))
        fail("json_unpack null failed");

    /* integer */
    j = json_integer(42);
    rv = json_unpack(j, "i", &i1);
    if(rv || i1 != 42)
        fail("json_unpack integer failed");
    json_decref(j);

    /* json_int_t */
    j = json_integer(5555555);
    rv = json_unpack(j, "I", &I1);
    if(rv || I1 != 5555555)
        fail("json_unpack json_int_t failed");
    json_decref(j);

    /* real */
    j = json_real(1.7);
    rv = json_unpack(j, "f", &f);
    if(rv || f != 1.7)
        fail("json_unpack real failed");
    json_decref(j);

    /* number */
    j = json_integer(12345);
    rv = json_unpack(j, "F", &f);
    if(rv || f != 12345.0)
        fail("json_unpack (real or) integer failed");
    json_decref(j);

    j = json_real(1.7);
    rv = json_unpack(j, "F", &f);
    if(rv || f != 1.7)
        fail("json_unpack real (or integer) failed");
    json_decref(j);

    /* string */
    j = json_string("foo");
    rv = json_unpack(j, "s", &s);
    if(rv || strcmp(s, "foo"))
        fail("json_unpack string failed");
    json_decref(j);

    /* string with length (size_t) */
    j = json_string("foo");
    rv = json_unpack(j, "s%", &s, &z);
    if(rv || strcmp(s, "foo") || z != 3)
        fail("json_unpack string with length (size_t) failed");
    json_decref(j);

    /* empty object */
    j = json_object();
    if(json_unpack(j, "{}"))
        fail("json_unpack empty object failed");
    json_decref(j);

    /* empty list */
    j = json_array();
    if(json_unpack(j, "[]"))
        fail("json_unpack empty list failed");
    json_decref(j);

    /* non-incref'd object */
    j = json_object();
    rv = json_unpack(j, "o", &j2);
    if(rv || j2 != j || j->refcount != 1)
        fail("json_unpack object failed");
    json_decref(j);

    /* incref'd object */
    j = json_object();
    rv = json_unpack(j, "O", &j2);
    if(rv || j2 != j || j->refcount != 2)
        fail("json_unpack object failed");
    json_decref(j);
    json_decref(j);

    /* simple object */
    j = json_pack("{s:i}", "foo", 42);
    rv = json_unpack(j, "{s:i}", "foo", &i1);
    if(rv || i1 != 42)
        fail("json_unpack simple object failed");
    json_decref(j);

    /* simple array */
    j = json_pack("[iii]", 1, 2, 3);
    rv = json_unpack(j, "[i,i,i]", &i1, &i2, &i3);
    if(rv || i1 != 1 || i2 != 2 || i3 != 3)
        fail("json_unpack simple array failed");
    json_decref(j);

    /* object with many items & strict checking */
    j = json_pack("{s:i, s:i, s:i}", "a", 1, "b", 2, "c", 3);
    rv = json_unpack(j, "{s:i, s:i, s:i}", "a", &i1, "b", &i2, "c", &i3);
    if(rv || i1 != 1 || i2 != 2 || i3 != 3)
        fail("json_unpack object with many items failed");
    json_decref(j);

    /*
     * Invalid cases
     */

    j = json_integer(42);
    if(!json_unpack_ex(j, &error, 0, "z"))
        fail("json_unpack succeeded with invalid format character");
    check_error("Unexpected format character 'z'", "<format>", 1, 1, 1);

    if(!json_unpack_ex(NULL, &error, 0, "[i]"))
        fail("json_unpack succeeded with NULL root");
    check_error("NULL root value", "<root>", -1, -1, 0);
    json_decref(j);

    /* mismatched open/close array/object */
    j = json_pack("[]");
    if(!json_unpack_ex(j, &error, 0, "[}"))
        fail("json_unpack failed to catch mismatched ']'");
    check_error("Unexpected format character '}'", "<format>", 1, 2, 2);
    json_decref(j);

    j = json_pack("{}");
    if(!json_unpack_ex(j, &error, 0, "{]"))
        fail("json_unpack failed to catch mismatched '}'");
    check_error("Expected format 's', got ']'", "<format>", 1, 2, 2);
    json_decref(j);

    /* missing close array */
    j = json_pack("[]");
    if(!json_unpack_ex(j, &error, 0, "["))
        fail("json_unpack failed to catch missing ']'");
    check_error("Unexpected end of format string", "<format>", 1, 2, 2);
    json_decref(j);

    /* missing close object */
    j = json_pack("{}");
    if(!json_unpack_ex(j, &error, 0, "{"))
        fail("json_unpack failed to catch missing '}'");
    check_error("Unexpected end of format string", "<format>", 1, 2, 2);
    json_decref(j);

    /* garbage after format string */
    j = json_pack("[i]", 42);
    if(!json_unpack_ex(j, &error, 0, "[i]a", &i1))
        fail("json_unpack failed to catch garbage after format string");
    check_error("Garbage after format string", "<format>", 1, 4, 4);
    json_decref(j);

    j = json_integer(12345);
    if(!json_unpack_ex(j, &error, 0, "ia", &i1))
        fail("json_unpack failed to catch garbage after format string");
    check_error("Garbage after format string", "<format>", 1, 2, 2);
    json_decref(j);

    /* NULL format string */
    j = json_pack("[]");
    if(!json_unpack_ex(j, &error, 0, NULL))
        fail("json_unpack failed to catch null format string");
    check_error("NULL or empty format string", "<format>", -1, -1, 0);
    json_decref(j);

    /* NULL string pointer */
    j = json_string("foobie");
    if(!json_unpack_ex(j, &error, 0, "s", NULL))
        fail("json_unpack failed to catch null string pointer");
    check_error("NULL string argument", "<args>", 1, 1, 1);
    json_decref(j);

    /* invalid types */
    j = json_integer(42);
    j2 = json_string("foo");
    if(!json_unpack_ex(j, &error, 0, "s"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected string, got integer", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j, &error, 0, "n"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected null, got integer", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j, &error, 0, "b"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected true or false, got integer", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j2, &error, 0, "i"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected integer, got string", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j2, &error, 0, "I"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected integer, got string", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j, &error, 0, "f"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected real, got integer", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j2, &error, 0, "F"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected real or integer, got string", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j, &error, 0, "[i]"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected array, got integer", "<validation>", 1, 1, 1);

    if(!json_unpack_ex(j, &error, 0, "{si}", "foo"))
        fail("json_unpack failed to catch invalid type");
    check_error("Expected object, got integer", "<validation>", 1, 1, 1);

    json_decref(j);
    json_decref(j2);

    /* Array index out of range */
    j = json_pack("[i]", 1);
    if(!json_unpack_ex(j, &error, 0, "[ii]", &i1, &i2))
        fail("json_unpack failed to catch index out of array bounds");
    check_error("Array index 1 out of range", "<validation>", 1, 3, 3);
    json_decref(j);

    /* NULL object key */
    j = json_pack("{si}", "foo", 42);
    if(!json_unpack_ex(j, &error, 0, "{si}", NULL, &i1))
        fail("json_unpack failed to catch null string pointer");
    check_error("NULL object key", "<args>", 1, 2, 2);
    json_decref(j);

    /* Object key not found */
    j = json_pack("{si}", "foo", 42);
    if(!json_unpack_ex(j, &error, 0, "{si}", "baz", &i1))
        fail("json_unpack failed to catch null string pointer");
    check_error("Object item not found: baz", "<validation>", 1, 3, 3);
    json_decref(j);

    /*
     * Strict validation
     */

    j = json_pack("[iii]", 1, 2, 3);
    rv = json_unpack(j, "[iii!]", &i1, &i2, &i3);
    if(rv || i1 != 1 || i2 != 2 || i3 != 3)
        fail("json_unpack array with strict validation failed");
    json_decref(j);

    j = json_pack("[iii]", 1, 2, 3);
    if(!json_unpack_ex(j, &error, 0, "[ii!]", &i1, &i2))
        fail("json_unpack array with strict validation failed");
    check_error("1 array item(s) left unpacked", "<validation>", 1, 5, 5);
    json_decref(j);

    /* Like above, but with JSON_STRICT instead of '!' format */
    j = json_pack("[iii]", 1, 2, 3);
    if(!json_unpack_ex(j, &error, JSON_STRICT, "[ii]", &i1, &i2))
        fail("json_unpack array with strict validation failed");
    check_error("1 array item(s) left unpacked", "<validation>", 1, 4, 4);
    json_decref(j);

    j = json_pack("{s:s, s:i}", "foo", "bar", "baz", 42);
    rv = json_unpack(j, "{sssi!}", "foo", &s, "baz", &i1);
    if(rv || strcmp(s, "bar") != 0 || i1 != 42)
        fail("json_unpack object with strict validation failed");
    json_decref(j);

    /* Unpack the same item twice */
    j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
    if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
        fail("json_unpack object with strict validation failed");
    {
        const char *possible_errors[] = {
            "2 object item(s) left unpacked: baz, quux",
            "2 object item(s) left unpacked: quux, baz"
        };
        check_errors(possible_errors, 2, "<validation>", 1, 10, 10);
    }
    json_decref(j);

    j = json_pack("[i,{s:i,s:n},[i,i]]", 1, "foo", 2, "bar", 3, 4);
    if(json_unpack_ex(j, NULL, JSON_STRICT | JSON_VALIDATE_ONLY,
                      "[i{sisn}[ii]]", "foo", "bar"))
        fail("json_unpack complex value with strict validation failed");
    json_decref(j);

    /* ! and * must be last */
    j = json_pack("[ii]", 1, 2);
    if(!json_unpack_ex(j, &error, 0, "[i!i]", &i1, &i2))
        fail("json_unpack failed to catch ! in the middle of an array");
    check_error("Expected ']' after '!', got 'i'", "<format>", 1, 4, 4);

    if(!json_unpack_ex(j, &error, 0, "[i*i]", &i1, &i2))
        fail("json_unpack failed to catch * in the middle of an array");
    check_error("Expected ']' after '*', got 'i'", "<format>", 1, 4, 4);
    json_decref(j);

    j = json_pack("{sssi}", "foo", "bar", "baz", 42);
    if(!json_unpack_ex(j, &error, 0, "{ss!si}", "foo", &s, "baz", &i1))
        fail("json_unpack failed to catch ! in the middle of an object");
    check_error("Expected '}' after '!', got 's'", "<format>", 1, 5, 5);

    if(!json_unpack_ex(j, &error, 0, "{ss*si}", "foo", &s, "baz", &i1))
        fail("json_unpack failed to catch ! in the middle of an object");
    check_error("Expected '}' after '*', got 's'", "<format>", 1, 5, 5);
    json_decref(j);

    /* Error in nested object */
    j = json_pack("{s{snsn}}", "foo", "bar", "baz");
    if(!json_unpack_ex(j, &error, 0, "{s{sn!}}", "foo", "bar"))
        fail("json_unpack nested object with strict validation failed");
    check_error("1 object item(s) left unpacked: baz", "<validation>", 1, 7, 7);
    json_decref(j);

    /* Error in nested array */
    j = json_pack("[[ii]]", 1, 2);
    if(!json_unpack_ex(j, &error, 0, "[[i!]]", &i1))
        fail("json_unpack nested array with strict validation failed");
    check_error("1 array item(s) left unpacked", "<validation>", 1, 5, 5);
    json_decref(j);

    /* Optional values */
    j = json_object();
    i1 = 0;
    if(json_unpack(j, "{s?i}", "foo", &i1))
        fail("json_unpack failed for optional key");
    if(i1 != 0)
        fail("json_unpack unpacked an optional key");
    json_decref(j);

    i1 = 0;
    j = json_pack("{si}", "foo", 42);
    if(json_unpack(j, "{s?i}", "foo", &i1))
        fail("json_unpack failed for an optional value");
    if(i1 != 42)
        fail("json_unpack failed to unpack an optional value");
    json_decref(j);

    j = json_object();
    i1 = i2 = i3 = 0;
    if(json_unpack(j, "{s?[ii]s?{s{si}}}",
                   "foo", &i1, &i2,
                   "bar", "baz", "quux", &i3))
        fail("json_unpack failed for complex optional values");
    if(i1 != 0 || i2 != 0 || i3 != 0)
        fail("json_unpack unexpectedly unpacked something");
    json_decref(j);

    j = json_pack("{s{si}}", "foo", "bar", 42);
    if(json_unpack(j, "{s?{s?i}}", "foo", "bar", &i1))
        fail("json_unpack failed for complex optional values");
    if(i1 != 42)
        fail("json_unpack failed to unpack");
    json_decref(j);

    /* Combine ? and ! */
    j = json_pack("{si}", "foo", 42);
    i1 = i2 = 0;
    if(json_unpack(j, "{sis?i!}", "foo", &i1, "bar", &i2))
        fail("json_unpack failed for optional values with strict mode");
    if(i1 != 42)
        fail("json_unpack failed to unpack");
    if(i2 != 0)
        fail("json_unpack failed to unpack");
    json_decref(j);

    /* But don't compensate a missing key with an optional one. */
    j = json_pack("{sisi}", "foo", 42, "baz", 43);
    i1 = i2 = i3 = 0;
    if(!json_unpack_ex(j, &error, 0, "{sis?i!}", "foo", &i1, "bar", &i2))
        fail("json_unpack failed for optional values with strict mode and compensation");
    check_error("1 object item(s) left unpacked: baz", "<validation>", 1, 8, 8);
    json_decref(j);
}
예제 #6
0
int
callback_obsapi(struct libwebsocket_context *context,
            struct libwebsocket *wsi,
            enum libwebsocket_callback_reasons reason,
                           void *user, void *in, size_t len)
{
    int n;
    OBSAPIMessageHandler **userp = (OBSAPIMessageHandler**)user;
    OBSAPIMessageHandler *messageHandler = *(userp);

    switch (reason) {

    case LWS_CALLBACK_ESTABLISHED:
        fprintf(stderr, "callback_obsapi: "
                         "LWS_CALLBACK_ESTABLISHED\n");

        /* initiate handler */
        *userp = new OBSAPIMessageHandler(wsi);

        break;

    case LWS_CALLBACK_SERVER_WRITEABLE:
        if(!messageHandler->messagesToSend.empty())
        {
            json_t *message = messageHandler->messagesToSend.front();
            messageHandler->messagesToSend.pop_front();

            char *messageText = json_dumps(message, 0);
            
            if(messageText != NULL)
            {
                int sendLength = strlen(messageText);
                
                /* copy json text into memory buffer properly framed for libwebsockets */
                char* messageBuf = (char*) malloc(LWS_SEND_BUFFER_PRE_PADDING + sendLength + LWS_SEND_BUFFER_POST_PADDING);
                memcpy(messageBuf + LWS_SEND_BUFFER_PRE_PADDING, messageText, sendLength);
                

                n = libwebsocket_write(wsi, (unsigned char *)
                   messageBuf + LWS_SEND_BUFFER_PRE_PADDING,
                   sendLength, LWS_WRITE_TEXT);
                if (n < 0) {
                    fprintf(stderr, "ERROR writing to socket");
                }
                free(messageBuf);
            }
            free((void *)messageText);
            json_decref(message);

            libwebsocket_callback_on_writable(context, wsi);
        }
        break;

    case LWS_CALLBACK_BROADCAST:
        /* should get called with update messages */
		if(!getRemoteConfig()->useAuth || messageHandler->authenticated)
        {
            n = libwebsocket_write(wsi,(unsigned char *) in, len, LWS_WRITE_TEXT);
            if (n < 0)
                fprintf(stderr, "update write failed\n");
        }
        break;

    case LWS_CALLBACK_RECEIVE:
        if(messageHandler->HandleReceivedMessage(in, len))
        {
            libwebsocket_callback_on_writable(context, wsi);
        }
        break;
    
    case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
        /* you could return non-zero here and kill the connection */
        break;

    case LWS_CALLBACK_CLOSED:
        /* free user data */
        delete(*userp);
        break;
    default:
        break;
    }

    return 0;
}
예제 #7
0
void JanssonObjectHandler::OnHandleDestroy(HandleType_t type, void *object) {
	json_decref((json_t*)object);
}
예제 #8
0
		void set( json_t* json ) {
			if( m_value ) json_decref( m_value ) ;
			m_value = json ;
		}
예제 #9
0
int main(int argc, char* argv[])
{
	// parse command line
	const char* config_file = NULL;
	const char* zlog_config_file = NULL;
	if (argc == 2) 
	{
		config_file = argv[1];
	}
	else if (argc == 3)
	{
		config_file = argv[1];
		zlog_config_file = argv[2];	
	}
	else 
	{
		fprintf(stderr, "usage: raptor <application_config> [zlog_config]\n");
		return -1;
	}

	// zlog init
    int ret = dzlog_init(zlog_config_file, "raptor");
    if (ret) 
    {
        fprintf(stderr, "zlog init failed\n");
        return -1;
    }

    // load config file
    json_t* json_root = NULL;
	json_error_t error;

	dzlog_info("load config file: %s", config_file);

	json_root = json_load_file(config_file, 0, &error);
	if (!json_root) 
	{
		dzlog_error("load config file failed: %s", error.text);
		goto to_exit;
	}

	// create mysql proxy 
	RaptorProxy rp;
	
	json_t* json_raptor_server = json_object_get(json_root, "raptor_proxy");
	if (!json_is_object(json_raptor_server)) 
	{
		dzlog_error("get 'raptor_proxy' config item failed");
		goto to_exit;
	}

	json_t* json_raptor_server_address = json_object_get(json_raptor_server, "address");
	if (!json_is_string(json_raptor_server_address))
	{
		dzlog_error("get 'raptor_proxy:address' config item failed");
		goto to_exit;
	}
	rp.address = json_string_value(json_raptor_server_address);

	json_t* json_raptor_server_workers = json_object_get(json_raptor_server, "workers");
	if (!json_is_integer(json_raptor_server_workers))
	{
		dzlog_error("get 'raptor_proxy:workers' config item failed");
		goto to_exit;
	}
	rp.workers = json_integer_value(json_raptor_server_workers);

	if (raptor_proxy_init(&rp) != 0)
	{
		dzlog_error("create raptor proxy failed");
		goto to_exit;
	}
	/*
	json_t* json_raptor_server = json_object_get(json_root, "raptor_server");
	json_t* json_raptor_server_address = json_object_get(json_raptor_server, "address");
	printf("%s\n", json_string_value(json_raptor_server_address));
	*/
to_exit:
	if (raptor_proxy_finit(&rp) != 0)
		dzlog_error("destroy raptor proxy failed");
	if (!json_root) 
		json_decref(json_root);
	dzlog_info("raptor exit!");
    zlog_fini();
	return 0;
}
예제 #10
0
int sqlite3_open(const char* filename, /* Database filename (UTF-8) */
                 sqlite3** ppDb        /* OUT: SQLite db handle */
)
{
    MYSQL* con = mysql_init(NULL);
    
    const char* host = NULL;
    const char* user = NULL;
    const char* pass = NULL;
    const char* db = NULL;
    
    if (con == NULL)
    {
        fprintf(stderr, "sqlite3_open() -> mysql_init() failed\n");
        return 0;
    }
    
    FILE* fh = fopen(filename, "r");
    if (fh)
    {
        json_t* root = json_loadf(fh, JSON_DECODE_ANY, NULL);
        if (root)
        {
            // We got JSON
            host = json_string_value(json_object_get(root, "host"));
            user = json_string_value(json_object_get(root, "user"));
            pass = json_string_value(json_object_get(root, "pass"));
            db   = json_string_value(json_object_get(root, "db"));
            
            if (mysql_real_connect(con, host, user, pass, NULL, 0, NULL, 0) == NULL)
            {
                finish_with_error(con);
                *ppDb = NULL;
            }
            else
            {
                if (mysql_select_db(con, db) != 0)
                {
                    char* sql;
                    int len = asprintf(&sql, "CREATE DATABASE %s", db);
                    mysql_real_query(con, sql, len);
                    free(sql);
                }
                
                if (mysql_select_db(con, db) != 0) {
                    finish_with_error(con);
                    *ppDb = NULL;
                }
                else {
                    *ppDb = (sqlite3*)con;
                }
            }
            
            // Cleanup
            json_decref(root);
        }
        fclose(fh);
    }
    
    return 0;
};
예제 #11
0
		~JsonMsg() {
			if( m_value) json_decref(m_value) ;
		}
예제 #12
0
파일: load.c 프로젝트: hidd3ncod3s/hipara
static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
{
    json_t *object = json_object();
    if(!object)
        return NULL;

    lex_scan(lex, error);
    if(lex->token == '}')
        return object;

    while(1) {
        char *key;
        size_t len;
        json_t *value;

        if(lex->token != TOKEN_STRING) {
            error_set(error, lex, "string or '}' expected");
            goto error;
        }

        key = lex_steal_string(lex, &len);
        if(!key)
            return NULL;
        if (memchr(key, '\0', len)) {
            jsonp_free(key);
            error_set(error, lex, "NUL byte in object key not supported");
            goto error;
        }

        if(flags & JSON_REJECT_DUPLICATES) {
            if(json_object_get(object, key)) {
                jsonp_free(key);
                error_set(error, lex, "duplicate object key");
                goto error;
            }
        }

        lex_scan(lex, error);
        if(lex->token != ':') {
            jsonp_free(key);
            error_set(error, lex, "':' expected");
            goto error;
        }

        lex_scan(lex, error);
        value = parse_value(lex, flags, error);
        if(!value) {
            jsonp_free(key);
            goto error;
        }

        if(json_object_set_nocheck(object, key, value)) {
            jsonp_free(key);
            json_decref(value);
            goto error;
        }

        json_decref(value);
        jsonp_free(key);

        lex_scan(lex, error);
        if(lex->token != ',')
            break;

        lex_scan(lex, error);
    }

    if(lex->token != '}') {
        error_set(error, lex, "'}' expected");
        goto error;
    }

    return object;

error:
    json_decref(object);
    return NULL;
}
예제 #13
0
static char *request(const char *url)
{
	CURL *curl;
	CURLcode status;
	char *data;
	long code;

	curl = curl_easy_init();
	data = (char *)malloc(BUFFER_SIZE);
	if (!curl || !data) {
		return NULL;
	}

	struct write_result write_result = {
		.data = data,
		.pos = 0
	};

	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);

	status = curl_easy_perform(curl);
	if (status != 0) {
		fprintf(stderr, "error: unable to request data from %s:\n", url);
		fprintf(stderr, "%s\n", curl_easy_strerror(status));
		return NULL;
	}

	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
	if (code != 200) {
		fprintf(stderr, "error: server responded with code %ld\n", code);
		return NULL;
	}

	curl_easy_cleanup(curl);
	curl_global_cleanup();

	data[write_result.pos] = '\0';

	return data;
}

int a = 0, h = 0, n = 0;

int handle(const char *url)
{
	char *data;
	int count = 0;

	data = request(url);
	if (data) {
		json_t *root;
		json_error_t error;

		root = json_loads(data, 0, &error);
		free(data);

		if (root) {
			json_t *faction, *auctions;

			faction = json_object_get(root, "alliance");
			auctions = json_object_get(faction, "auctions");
			a = json_array_size(auctions);

			faction = json_object_get(root, "horde");
			auctions = json_object_get(faction, "auctions");
			h = json_array_size(auctions);

			faction = json_object_get(root, "neutral");
			auctions = json_object_get(faction, "auctions");
			n = json_array_size(auctions);
		} else {
			fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
			return -1;
		}

		json_decref(root);
	}

	return count;
}
예제 #14
0
int main(int argc, char **argv)
{
	if (argc < 4) {
		fprintf(stderr, "error: not enough arguments\n" "usage: aucc eu|us realm a|h|n|e\n");
	} else {
		int proceed = 0;

		if (!strncmp(argv[1], "eu", 2) || !strncmp(argv[1], "us", 2)) {
			proceed = 1;
		}
		if (!strncmp(argv[3], "a", 1) || !strncmp(argv[3], "h", 1) || !strncmp(argv[3], "n", 1) || !strncmp(argv[3], "e", 1)) {
			proceed = 1;
		}

		if (proceed) {
			char url[URL_SIZE];
			char *data;

			snprintf(url, URL_SIZE, "http://%s.battle.net/api/wow/auction/data/%s", argv[1], argv[2]);

			data = request(url);
			if (data) {
				json_t *root;
				json_error_t error;

				root = json_loads(data, 0, &error);
				free(data);

				if (root) {
					json_t *files, *file, *urld;

					const char *auction_data_url;

					files = json_object_get(root, "files");
					file = json_array_get(files, 0);
					urld = json_object_get(file, "url");
					auction_data_url = json_string_value(urld);

					int result = handle(auction_data_url);

					if (result == -1) {
						return 1;
					} else {
						int count = 0;

						switch (argv[3][0]) {
						case 'a':
							count = a;
							break;
						case 'h':
							count = h;
							break;
						case 'n':
							count = n;
							break;
						case 'e':
							count = a + h + n;
							break;
						}
						printf("%d auctions found.\n", count);
					}
				} else {
					fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
					return 1;
				}

				json_decref(root);
			} else {
				fprintf(stderr, "error: unable to get data, probably wrong realm name\n");
				return 1;
			}
		}
	}

	return 0;
}
예제 #15
0
static void
json_release_object (void *object)
{
  json_decref (object);
}
예제 #16
0
static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p)
{
    JsonSshLogThread *aft = (JsonSshLogThread *)thread_data;
    MemBuffer *buffer = (MemBuffer *)aft->buffer;
    OutputSshCtx *ssh_ctx = aft->sshlog_ctx;

    if (unlikely(p->flow == NULL)) {
        return 0;
    }

    /* check if we have SSH state or not */
    FLOWLOCK_WRLOCK(p->flow);
    uint16_t proto = FlowGetAppProtocol(p->flow);
    if (proto != ALPROTO_SSH)
        goto end;

    SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
    if (unlikely(ssh_state == NULL)) {
        goto end;
    }

    if (ssh_state->cli_hdr.software_version == NULL || ssh_state->srv_hdr.software_version == NULL)
        goto end;

    json_t *js = CreateJSONHeader((Packet *)p, 1, "ssh");//TODO
    if (unlikely(js == NULL))
        goto end;

    json_t *tjs = json_object();
    if (tjs == NULL) {
        free(js);
        goto end;
    }

    /* reset */
    MemBufferReset(buffer);

    json_t *cjs = json_object();
    if (cjs != NULL) {
        json_object_set_new(cjs, "proto_version",
                json_string((char *)ssh_state->cli_hdr.proto_version));

        json_object_set_new(cjs, "software_version",
                json_string((char *)ssh_state->cli_hdr.software_version));
    }
    json_object_set_new(tjs, "client", cjs);

    json_t *sjs = json_object();
    if (sjs != NULL) {
        json_object_set_new(sjs, "proto_version",
                json_string((char *)ssh_state->srv_hdr.proto_version));

        json_object_set_new(sjs, "software_version",
                json_string((char *)ssh_state->srv_hdr.software_version));
    }
    json_object_set_new(tjs, "server", sjs);

    json_object_set_new(js, "ssh", tjs);

    OutputJSONBuffer(js, ssh_ctx->file_ctx, buffer);
    json_object_clear(js);
    json_decref(js);

    /* we only log the state once */
    ssh_state->cli_hdr.flags |= SSH_FLAG_STATE_LOGGED;
end:
    FLOWLOCK_UNLOCK(p->flow);
    return 0;
}
예제 #17
0
파일: auth.c 프로젝트: clockfort/bingehack4
int
auth_user(char *authbuf, const char *peername, int *is_reg, int *reconnect_id)
{
    json_error_t err;
    json_t *obj, *cmd, *name, *pass, *email, *reconn;
    const char *namestr, *passstr, *emailstr;
    int userid = 0;

    obj = json_loads(authbuf, 0, &err);
    if (!obj)
        return 0;

    /* try 1: is it an auth command? */
    *is_reg = 0;
    cmd = json_object_get(obj, "auth");
    if (!cmd) {
        /* try 2: register? */
        *is_reg = 1;
        cmd = json_object_get(obj, "register");
    }
    if (!cmd)   /* not a recognized command */
        goto err;

    name = json_object_get(cmd, "username");
    pass = json_object_get(cmd, "password");
    email = json_object_get(cmd, "email");      /* is null for auth */
    reconn = json_object_get(cmd, "reconnect");

    if (!name || !pass)
        goto err;

    namestr = json_string_value(name);
    passstr = json_string_value(pass);

    if (!namestr || !passstr || strlen(namestr) < 3 || strlen(passstr) < 3 ||
        !is_valid_username(namestr))
        goto err;

    *reconnect_id = 0;
    if (!*is_reg) {
        if (reconn && json_is_integer(reconn))
            *reconnect_id = json_integer_value(reconn);

        /* authenticate against a user database */
        userid = db_auth_user(namestr, passstr);
        if (userid > 0)
            log_msg("%s has logged in as \"%s\" (userid %d)", peername, namestr,
                    userid);
        else if (userid < 0)
            log_msg("%s has failed to log in as \"%s\" (userid %d)", peername,
                    namestr, -userid);
    } else {
        /* register a new user */
        emailstr = email ? json_string_value(email) : "";
        if (strlen(emailstr) > 100)
            goto err;

        userid = db_register_user(namestr, passstr, emailstr);
        if (userid) {
            char savedir[1024];

            snprintf(savedir, 1024, "%s/save/%s", settings.workdir, namestr);
            mkdir(savedir, 0700);
            log_msg("%s has registered as \"%s\" (userid: %d)", peername,
                    namestr, userid);
        }
    }

    json_decref(obj);
    return userid;

err:
    json_decref(obj);
    return 0;
}
예제 #18
0
파일: json_helper.c 프로젝트: GNUnet/gnunet
/**
 * Variable size object (in network byte order, encoded using
 * Crockford Base32hex encoding).
 *
 * @param name name of the JSON field
 * @param[out] obj pointer where to write the data, will be allocated
 * @param[out] size where to store the number of bytes allocated for @a obj
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_varsize (const char *name,
                          void **obj,
                          size_t *size)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_variable_data,
    .cleaner = &clean_variable_data,
    .cls = NULL,
    .field = name,
    .ptr = obj,
    .ptr_size = 0,
    .size_ptr = size
  };
  *obj = NULL;
  *size = 0;
  return ret;
}


/**
 * Parse given JSON object to string.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_string (void *cls,
              json_t *root,
              struct GNUNET_JSON_Specification *spec)
{
  const char *str;

  str = json_string_value (root);
  if (NULL == str)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  *(const char **) spec->ptr = str;
  return GNUNET_OK;
}


/**
 * The expected field stores a string.
 *
 * @param name name of the JSON field
 * @param strptr where to store a pointer to the field
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_string (const char *name,
                         const char **strptr)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_string,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = strptr,
    .ptr_size = 0,
    .size_ptr = NULL
  };
  *strptr = NULL;
  return ret;
}


/**
 * Parse given JSON object to a JSON object. (Yes, trivial.)
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_object (void *cls,
              json_t *root,
              struct GNUNET_JSON_Specification *spec)
{
  if (! (json_is_object (root) || json_is_array (root)) )
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  json_incref (root);
  *(json_t **) spec->ptr = root;
  return GNUNET_OK;
}


/**
 * Cleanup data left from parsing JSON object.
 *
 * @param cls closure, NULL
 * @param[out] spec where to free the data
 */
static void
clean_object (void *cls,
              struct GNUNET_JSON_Specification *spec)
{
  json_t **ptr = (json_t **) spec->ptr;

  if (NULL != *ptr)
  {
    json_decref (*ptr);
    *ptr = NULL;
  }
}


/**
 * JSON object.
 *
 * @param name name of the JSON field
 * @param[out] jsonp where to store the JSON found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_json (const char *name,
                       json_t **jsonp)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_object,
    .cleaner = &clean_object,
    .cls = NULL,
    .field = name,
    .ptr = jsonp,
    .ptr_size = 0,
    .size_ptr = NULL
  };
  *jsonp = NULL;
  return ret;
}


/**
 * Parse given JSON object to a uint8_t.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_u8 (void *cls,
          json_t *root,
          struct GNUNET_JSON_Specification *spec)
{
  json_int_t val;
  uint8_t *up = spec->ptr;

  if (! json_is_integer (root))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  val = json_integer_value (root);
  if ( (0 > val) || (val > UINT8_MAX) )
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  *up = (uint8_t) val;
  return GNUNET_OK;
}


/**
 * 8-bit integer.
 *
 * @param name name of the JSON field
 * @param[out] u8 where to store the integer found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_uint8 (const char *name,
                        uint8_t *u8)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_u8,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = u8,
    .ptr_size = sizeof (uint8_t),
    .size_ptr = NULL
  };
  return ret;
}


/**
 * Parse given JSON object to a uint16_t.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_u16 (void *cls,
           json_t *root,
           struct GNUNET_JSON_Specification *spec)
{
  json_int_t val;
  uint16_t *up = spec->ptr;

  if (! json_is_integer (root))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  val = json_integer_value (root);
  if ( (0 > val) || (val > UINT16_MAX) )
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  *up = (uint16_t) val;
  return GNUNET_OK;
}


/**
 * 16-bit integer.
 *
 * @param name name of the JSON field
 * @param[out] u16 where to store the integer found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_uint16 (const char *name,
                         uint16_t *u16)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_u16,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = u16,
    .ptr_size = sizeof (uint16_t),
    .size_ptr = NULL
  };
  return ret;
}


/**
 * Parse given JSON object to a uint32_t.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_u32 (void *cls,
           json_t *root,
           struct GNUNET_JSON_Specification *spec)
{
  json_int_t val;
  uint32_t *up = spec->ptr;

  if (! json_is_integer (root))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  val = json_integer_value (root);
  if ( (0 > val) || (val > UINT32_MAX) )
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  *up = (uint32_t) val;
  return GNUNET_OK;
}


/**
 * 32-bit integer.
 *
 * @param name name of the JSON field
 * @param[out] u32 where to store the integer found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_uint32 (const char *name,
                         uint32_t *u32)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_u32,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = u32,
    .ptr_size = sizeof (uint32_t),
    .size_ptr = NULL
  };
  return ret;
}


/**
 * Parse given JSON object to a uint8_t.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_u64 (void *cls,
           json_t *root,
           struct GNUNET_JSON_Specification *spec)
{
  json_int_t val;
  uint64_t *up = spec->ptr;

  if (! json_is_integer (root))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  val = json_integer_value (root);
  *up = (uint64_t) val;
  return GNUNET_OK;
}


/**
 * 64-bit integer.
 *
 * @param name name of the JSON field
 * @param[out] u64 where to store the integer found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_uint64 (const char *name,
                         uint64_t *u64)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_u64,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = u64,
    .ptr_size = sizeof (uint64_t),
    .size_ptr = NULL
  };
  return ret;
}


/* ************ GNUnet-specific parser specifications ******************* */

/**
 * Parse given JSON object to absolute time.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_abs_time (void *cls,
                json_t *root,
                struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_TIME_Absolute *abs = spec->ptr;
  const char *val;
  unsigned long long int tval;

  val = json_string_value (root);
  if (NULL == val)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  if ( (0 == strcasecmp (val,
                         "/forever/")) ||
       (0 == strcasecmp (val,
                         "/end of time/")) ||
       (0 == strcasecmp (val,
                         "/never/")) )
  {
    *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
    return GNUNET_OK;
  }
  if (1 != sscanf (val,
                   "/Date(%llu)/",
                   &tval))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
  abs->abs_value_us = tval * 1000LL * 1000LL;
  if ( (abs->abs_value_us) / 1000LL / 1000LL != tval)
  {
    /* Integer overflow */
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  return GNUNET_OK;
}


/**
 * Absolute time.
 *
 * @param name name of the JSON field
 * @param[out] at where to store the absolute time found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_absolute_time (const char *name,
                                struct GNUNET_TIME_Absolute *at)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_abs_time,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = at,
    .ptr_size = sizeof (uint64_t),
    .size_ptr = NULL
  };
  return ret;
}


/**
 * Parse given JSON object to relative time.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_rel_time (void *cls,
                json_t *root,
                struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_TIME_Relative *rel = spec->ptr;
  const char *val;
  unsigned long long int tval;

  val = json_string_value (root);
  if (NULL == val)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  if ( (0 == strcasecmp (val,
                         "/forever/")) )
  {
    *rel = GNUNET_TIME_UNIT_FOREVER_REL;
    return GNUNET_OK;
  }
  if (1 != sscanf (val,
                   "/Delay(%llu)/",
                   &tval))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Relative */
  rel->rel_value_us = tval * 1000LL * 1000LL;
  if ( (rel->rel_value_us) / 1000LL / 1000LL != tval)
  {
    /* Integer overflow */
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  return GNUNET_OK;
}


/**
 * Relative time.
 *
 * @param name name of the JSON field
 * @param[out] rt where to store the relative time found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_relative_time (const char *name,
                                struct GNUNET_TIME_Relative *rt)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_rel_time,
    .cleaner = NULL,
    .cls = NULL,
    .field = name,
    .ptr = rt,
    .ptr_size = sizeof (uint64_t),
    .size_ptr = NULL
  };
  return ret;
}


/**
 * Parse given JSON object to RSA public key.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_rsa_public_key (void *cls,
                      json_t *root,
                      struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
  const char *enc;
  char *buf;
  size_t len;
  size_t buf_len;

  if (NULL == (enc = json_string_value (root)))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  len = strlen (enc);
  buf_len =  (len * 5) / 8;
  buf = GNUNET_malloc (buf_len);
  if (GNUNET_OK !=
      GNUNET_STRINGS_string_to_data (enc,
                                     len,
                                     buf,
                                     buf_len))
  {
    GNUNET_break_op (0);
    GNUNET_free (buf);
    return GNUNET_SYSERR;
  }
  if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
                                                          buf_len)))
  {
    GNUNET_break_op (0);
    GNUNET_free (buf);
    return GNUNET_SYSERR;
  }
  GNUNET_free (buf);
  return GNUNET_OK;
}


/**
 * Cleanup data left from parsing RSA public key.
 *
 * @param cls closure, NULL
 * @param[out] spec where to free the data
 */
static void
clean_rsa_public_key (void *cls,
                      struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;

  if (NULL != *pk)
  {
    GNUNET_CRYPTO_rsa_public_key_free (*pk);
    *pk = NULL;
  }
}


/**
 * Specification for parsing an RSA public key.
 *
 * @param name name of the JSON field
 * @param pk where to store the RSA key found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_rsa_public_key (const char *name,
                                 struct GNUNET_CRYPTO_RsaPublicKey **pk)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_rsa_public_key,
    .cleaner = &clean_rsa_public_key,
    .cls = NULL,
    .field = name,
    .ptr = pk,
    .ptr_size = 0,
    .size_ptr = NULL
  };
  *pk = NULL;
  return ret;
}


/**
 * Parse given JSON object to RSA signature.
 *
 * @param cls closure, NULL
 * @param root the json object representing data
 * @param[out] spec where to write the data
 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
 */
static int
parse_rsa_signature (void *cls,
                     json_t *root,
                     struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
  size_t size;
  const char *str;
  int res;
  void *buf;

  str = json_string_value (root);
  if (NULL == str)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  size = (strlen (str) * 5) / 8;
  buf = GNUNET_malloc (size);
  res = GNUNET_STRINGS_string_to_data (str,
                                       strlen (str),
                                       buf,
                                       size);
  if (GNUNET_OK != res)
  {
    GNUNET_free (buf);
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
                                                          size)))
  {
    GNUNET_break_op (0);
    GNUNET_free (buf);
    return GNUNET_SYSERR;
  }
  GNUNET_free (buf);
  return GNUNET_OK;
}


/**
 * Cleanup data left from parsing RSA signature.
 *
 * @param cls closure, NULL
 * @param[out] spec where to free the data
 */
static void
clean_rsa_signature (void *cls,
                     struct GNUNET_JSON_Specification *spec)
{
  struct GNUNET_CRYPTO_RsaSignature  **sig = spec->ptr;

  if (NULL != *sig)
  {
    GNUNET_CRYPTO_rsa_signature_free (*sig);
    *sig = NULL;
  }
}


/**
 * Specification for parsing an RSA signature.
 *
 * @param name name of the JSON field
 * @param sig where to store the RSA signature found under @a name
 */
struct GNUNET_JSON_Specification
GNUNET_JSON_spec_rsa_signature (const char *name,
                                struct GNUNET_CRYPTO_RsaSignature **sig)
{
  struct GNUNET_JSON_Specification ret = {
    .parser = &parse_rsa_signature,
    .cleaner = &clean_rsa_signature,
    .cls = NULL,
    .field = name,
    .ptr = sig,
    .ptr_size = 0,
    .size_ptr = NULL
  };
  *sig = NULL;
  return ret;
}
예제 #19
0
DWORD STDCALL MainWebSocketThread(LPVOID lpUnused)
{
    struct libwebsocket_context *context;
    const char *interface = NULL;
    unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1024 +
                          LWS_SEND_BUFFER_POST_PADDING];

    context = libwebsocket_create_context(port, interface, protocols,
                libwebsocket_internal_extensions,
                NULL, NULL, NULL, -1, -1, 0, NULL);
    
    unsigned int oldus = 0;
    int n = 0;

    buf[LWS_SEND_BUFFER_PRE_PADDING] = 'x';

    //json_set_alloc_funcs(malloc, free);
    while (n >= 0 && running) 
    {
        struct timeval tv;

        gettimeofday(&tv, NULL);

        /*
         * Send out all recieved update broadcasts.
         */

        json_t* message = NULL;
        while((message = triggerHandler->popUpdate()) != NULL)
        {
            char *messageText = json_dumps(message, 0);
            
            if(messageText != NULL)
            {
                int sendLength = strlen(messageText);
                
                /* copy json text into memory buffer properly framed for libwebsockets */
                char* messageBuf = (char*) malloc(LWS_SEND_BUFFER_PRE_PADDING + sendLength + LWS_SEND_BUFFER_POST_PADDING);
                memcpy(messageBuf + LWS_SEND_BUFFER_PRE_PADDING, messageText, sendLength);
                

                n = libwebsockets_broadcast(&protocols[PROTOCOL_OBS_API],
                    (unsigned char *) messageBuf + LWS_SEND_BUFFER_PRE_PADDING, sendLength);
                if (n < 0) {
                    fprintf(stderr, "ERROR writing to socket");
                }
                free(messageBuf);
                free((void *)messageText);
            }
            json_decref(message);
        }

        /*
         * This example server does not fork or create a thread for
         * websocket service, it all runs in this single loop.  So,
         * we have to give the websockets an opportunity to service
         * "manually".
         *
         * If no socket is needing service, the call below returns
         * immediately and quickly.  Negative return means we are
         * in process of closing
         */
        n = libwebsocket_service(context, 50);
    }
    
    libwebsocket_context_destroy(context);

    return 0;
}
예제 #20
0
/**
 *  \internal
 *  \brief Write meta data on a single line json record
 */
static void FileWriteJsonRecord(JsonFileLogThread *aft, const Packet *p, const File *ff)
{
    MemBuffer *buffer = (MemBuffer *)aft->buffer;
    json_t *js = CreateJSONHeader((Packet *)p, 0, "fileinfo"); //TODO const
    json_t *hjs = NULL;
    if (unlikely(js == NULL))
        return;

    /* reset */
    MemBufferReset(buffer);

    switch (p->flow->alproto) {
        case ALPROTO_HTTP:
            hjs = JsonHttpAddMetadata(p->flow, ff->txid);
            if (hjs)
                json_object_set_new(js, "http", hjs);
            break;
        case ALPROTO_SMTP:
            hjs = JsonSMTPAddMetadata(p->flow, ff->txid);
            if (hjs)
                json_object_set_new(js, "smtp", hjs);
            hjs = JsonEmailAddMetadata(p->flow, ff->txid);
            if (hjs)
                json_object_set_new(js, "email", hjs);
            break;
    }

    json_object_set_new(js, "app_proto",
            json_string(AppProtoToString(p->flow->alproto)));

    json_t *fjs = json_object();
    if (unlikely(fjs == NULL)) {
        json_decref(js);
        return;
    }

    char *s = BytesToString(ff->name, ff->name_len);
    json_object_set_new(fjs, "filename", json_string(s));
    if (s != NULL)
        SCFree(s);
    if (ff->magic)
        json_object_set_new(fjs, "magic", json_string((char *)ff->magic));
    switch (ff->state) {
        case FILE_STATE_CLOSED:
            json_object_set_new(fjs, "state", json_string("CLOSED"));
#ifdef HAVE_NSS
            if (ff->flags & FILE_MD5) {
                size_t x;
                int i;
                char s[256];
                for (i = 0, x = 0; x < sizeof(ff->md5); x++) {
                    i += snprintf(&s[i], 255-i, "%02x", ff->md5[x]);
                }
                json_object_set_new(fjs, "md5", json_string(s));
            }
#endif
            break;
        case FILE_STATE_TRUNCATED:
            json_object_set_new(fjs, "state", json_string("TRUNCATED"));
            break;
        case FILE_STATE_ERROR:
            json_object_set_new(fjs, "state", json_string("ERROR"));
            break;
        default:
            json_object_set_new(fjs, "state", json_string("UNKNOWN"));
            break;
    }
    json_object_set_new(fjs, "stored",
                        (ff->flags & FILE_STORED) ? json_true() : json_false());
    if (ff->flags & FILE_STORED) {
        json_object_set_new(fjs, "file_id", json_integer(ff->file_id));
    }
    json_object_set_new(fjs, "size", json_integer(ff->size));
    json_object_set_new(fjs, "tx_id", json_integer(ff->txid));

    /* originally just 'file', but due to bug 1127 naming it fileinfo */
    json_object_set_new(js, "fileinfo", fjs);
    OutputJSONBuffer(js, aft->filelog_ctx->file_ctx, buffer);
    json_object_del(js, "fileinfo");

    switch (p->flow->alproto) {
        case ALPROTO_HTTP:
            json_object_del(js, "http");
            break;
        case ALPROTO_SMTP:
            json_object_del(js, "smtp");
            json_object_del(js, "email");
            break;
    }

    json_object_clear(js);
    json_decref(js);
}
예제 #21
0
static char *request(const char *url)
{
    CURL *curl;
    CURLcode status;
    char *data;
    long code;

    curl = curl_easy_init();
    data = malloc(BUFFER_SIZE);
    if(!curl || !data)
        return NULL;

    struct write_result write_result = {
        .data = data,
        .pos = 0
    };

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);

    status = curl_easy_perform(curl);
    if(status != 0)
    {
        fprintf(stderr, "error: unable to request data from %s:\n", url);
        fprintf(stderr, "%s\n", curl_easy_strerror(status));
        return NULL;
    }

    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
    if(code != 200)
    {
        fprintf(stderr, "error: server responded with code %ld\n", code);
        return NULL;
    }

    curl_easy_cleanup(curl);
    curl_global_cleanup();

    /* zero-terminate the result */
    data[write_result.pos] = '\0';

    return data;
}

int main(int argc, char *argv[])
{
    size_t i;
    char *text;
    char url[URL_SIZE];

    json_t *root;
    json_error_t error;
    json_t *commits;

    if(argc != 3)
    {
        fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
        fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
        return 2;
    }

    snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);

    text = request(url);
    if(!text)
        return 1;

    root = json_loads(text, 0, &error);
    free(text);

    if(!root)
    {
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
        return 1;
    }

    commits = json_object_get(root, "commits");
    if(!json_is_array(commits))
    {
        fprintf(stderr, "error: commits is not an array\n");
        return 1;
    }

    for(i = 0; i < json_array_size(commits); i++)
    {
        json_t *commit, *id, *message;
        const char *message_text;

        commit = json_array_get(commits, i);
        if(!json_is_object(commit))
        {
            fprintf(stderr, "error: commit %d is not an object\n", i + 1);
            return 1;
        }

        id = json_object_get(commit, "id");
        if(!json_is_string(id))
        {
            fprintf(stderr, "error: commit %d: id is not a string\n", i + 1);
            return 1;
        }

        message = json_object_get(commit, "message");
        if(!json_is_string(message))
        {
            fprintf(stderr, "error: commit %d: message is not a string\n", i + 1);
            return 1;
        }

        message_text = json_string_value(message);
        printf("%.8s %.*s\n",
               json_string_value(id),
               newline_offset(message_text),
               message_text);
    }

    json_decref(root);
    return 0;
}
예제 #22
0
static void parse_arg (int key, char *arg)
{
	int v, i;

	switch(key) {
	case 'a':
		for (i = 0; i < ARRAY_SIZE(algo_names); i++) {
			if (algo_names[i] &&
			    !strcmp(arg, algo_names[i])) {
				opt_algo = i;
				break;
			}
		}
		if (i == ARRAY_SIZE(algo_names))
			show_usage();
		break;
	case 'c': {
		json_error_t err;
		if (opt_config)
			json_decref(opt_config);
		opt_config = json_load_file(arg, &err);
		if (!json_is_object(opt_config)) {
			fprintf(stderr, "JSON decode of %s failed\n", arg);
			show_usage();
		}
		break;
	}
	case 'l':
		if (opt_log) free(opt_log);
		opt_log = strdup(arg);
		break;
	case 'q':
		opt_quiet = true;
		break;
	case 'D':
		opt_debug = true;
		break;
	case 'P':
		opt_protocol = true;
		break;
	case 'r':
		v = atoi(arg);
		if (v < -1 || v > 9999)	/* sanity check */
			show_usage();

		opt_retries = v;
		break;
	case 'R':
		v = atoi(arg);
		if (v < 1 || v > 9999)	/* sanity check */
			show_usage();

		opt_fail_pause = v;
		break;
	case 's':
		v = atoi(arg);
		if (v < 1 || v > 9999)	/* sanity check */
			show_usage();

		opt_scantime = v;
		break;
	case 't':
		v = atoi(arg);
		if (v < 1 || v > 9999)	/* sanity check */
			show_usage();

		opt_n_threads = v;
		break;
	case 1001:			/* --url */
		if (strncmp(arg, "http://", 7) &&
		    strncmp(arg, "https://", 8))
			show_usage();

		if (rpc_url) free(rpc_url);
		rpc_url = strdup(arg);
		break;
	case 1002:			/* --userpass */
		if (!strchr(arg, ':'))
			show_usage();

		if (userpass) free(userpass);
		userpass = strdup(arg);
		break;
	case 1003:			/* --randomize */
		opt_randomize = true;
		break;
	default:
		show_usage();
	}
}
예제 #23
0
static void janus_sampleevh_event_free(json_t *event) {
	if(!event || event == &exit_event)
		return;
	json_decref(event);
}
예제 #24
0
static bool load_cached_shader_binary(opengl::ShaderProgram* program, SCP_string hash) {
	if (!do_shader_caching()) {
		return false;
	}

	auto base_filename = SCP_string("ogl_shader-") + hash;

	auto metadata = base_filename + ".json";
	auto binary = base_filename + ".bin";

	auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
	if (!metadata_fp) {
		nprintf(("ShaderCache", "Metadata file does not exist.\n"));
		return false;
	}

	auto size = cfilelength(metadata_fp);
	SCP_string metadata_content;
	metadata_content.resize((size_t) size);
	cfread(&metadata_content[0], 1, size, metadata_fp);

	cfclose(metadata_fp);

	auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr);
	if (!metadata_root) {
		mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n"));
		return false;
	}

	json_int_t format;
	if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) {
		mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n"));
		return false;
	}
	auto binary_format = (GLenum) format;
	json_decref(metadata_root);

	auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
	if (!binary_fp) {
		nprintf(("ShaderCache", "Binary file does not exist.\n"));
		return false;
	}
	
	GR_DEBUG_SCOPE("Loading cached shader");
	
	SCP_vector<uint8_t> buffer;
	int length = cfilelength(binary_fp);
	buffer.resize((size_t) length);
	cfread(&buffer[0], 1, length, binary_fp);

	cfclose(binary_fp);

	// Load the data!
	glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size());

	// Check the status...
	GLint status;
	glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status);

	return status == GL_TRUE;
}
예제 #25
0
int udf_cask_info_put(char *name, char * params, cf_dyn_buf * out) {

	cf_debug(AS_INFO, "UDF CASK INFO PUT");

	int					rc 					= 0;
	char                filename[128]       = {0};
	int                 filename_len        = sizeof(filename);
	// Content_len from the client and its expected size
	char                content_len[32]     = {0};
	int 		        clen		        = sizeof(content_len);
	// Udf content from the client and its expected length
	char	 		    *udf_content        = NULL;
	int 		        udf_content_len    = 0;
	// Udf type from the client and its expected size
	char 		         type[8]            = {0};
	int 		         type_len 	        = sizeof(type);

	// get (required) script filename
	char *tmp_char;

	if ( as_info_parameter_get(params, "filename", filename, &filename_len)
			|| !(tmp_char = strchr(filename, '.'))               // No extension in filename
			|| tmp_char == filename                              // '.' at the begining of filename
			|| strlen (tmp_char) <= 1) {                         // '.' in filename, but no extnsion e.g. "abc."
		cf_info(AS_INFO, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
		return 0;
	}

	if ( as_info_parameter_get(params, "content-len", content_len, &(clen)) ) {
		cf_info(AS_INFO, "invalid or missing content-len");
		cf_dyn_buf_append_string(out, "error=invalid_content_len");
		return 0;
	}

	if ( as_info_parameter_get(params, "udf-type", type, &type_len) ) {
		// Replace with DEFAULT IS LUA
		strcpy(type, as_udf_type_name[0]);
	}

	// check type field
	if (-1 == udf_type_getid(type)) {
		cf_info(AS_INFO, "invalid or missing udf-type : %s not valid", type);
		cf_dyn_buf_append_string(out, "error=invalid_udf_type");
		return 0;
	}

	// get b64 encoded script
	udf_content_len = atoi(content_len) + 1;
	udf_content = (char *) cf_malloc(udf_content_len);

	if ( udf_content == NULL ) {
		cf_info(AS_UDF, "internal allocation error");
		cf_dyn_buf_append_string(out, "error=internal_error");
		// As memory is not allocated.
		// It should not continue.
		return 0;
	}

	// cf_info(AS_UDF, "content_len = %s", content_len);
	// cf_info(AS_UDF, "udf_content_len = %d", udf_content_len);


	// get (required) script content - base64 encoded here.
	if ( as_info_parameter_get(params, "content", udf_content, &(udf_content_len)) ) {
		cf_info(AS_UDF, "invalid content");
		cf_dyn_buf_append_string(out, "error=invalid_content");
		cf_free(udf_content);
		return 0;
	}

	// base 64 decode it
	uint32_t encoded_len = strlen(udf_content);
	uint32_t decoded_len = cf_b64_decoded_buf_size(encoded_len) + 1;
	
	// Don't allow UDF file size > 1MB 
	if ( decoded_len > MAX_UDF_CONTENT_LENGTH) {
		cf_info(AS_INFO, "lua file size:%d > 1MB", decoded_len);
		cf_dyn_buf_append_string(out, "error=invalid_udf_content_len, lua file size > 1MB");
		return 0;
	}

	char * decoded_str = cf_malloc(decoded_len);

	if ( ! cf_b64_validate_and_decode(udf_content, encoded_len, (uint8_t*)decoded_str, &decoded_len) ) {
		cf_info(AS_UDF, "invalid base64 content %s", filename);
		cf_dyn_buf_append_string(out, "error=invalid_base64_content");
		cf_free(decoded_str);
		return 0;
	}

	decoded_str[decoded_len] = '\0';

	as_module_error err;
	rc = as_module_validate(&mod_lua, NULL, filename, decoded_str, decoded_len, &err);

	cf_free(decoded_str);
	decoded_str = NULL;
	decoded_len = 0;

	if ( rc ) {
		cf_warning(AS_UDF, "udf-put: compile error: [%s:%d] %s", err.file, err.line, err.message);
		cf_dyn_buf_append_string(out, "error=compile_error");
		cf_dyn_buf_append_string(out, ";file=");
		cf_dyn_buf_append_string(out, err.file);
		cf_dyn_buf_append_string(out, ";line=");
		cf_dyn_buf_append_uint32(out, err.line);

		uint32_t message_len = strlen(err.message);
		uint32_t enc_message_len = cf_b64_encoded_len(message_len);
		char enc_message[enc_message_len];

		cf_b64_encode((const uint8_t*)err.message, message_len, enc_message);

		cf_dyn_buf_append_string(out, ";message=");
		cf_dyn_buf_append_buf(out, (uint8_t *)enc_message, enc_message_len);

		cf_free(udf_content);
		return 0;
	}

	// Create an empty JSON object
	json_t *udf_obj = 0;
	if (!(udf_obj = json_object())) {
		cf_warning(AS_UDF, "failed to create JSON array for receiving UDF");
		if (udf_content) cf_free(udf_content);
		return -1;
	}
	int e = 0;
	e += json_object_set_new(udf_obj, "content64", json_string(udf_content));
	e += json_object_set_new(udf_obj, "type", json_string(type));
	e += json_object_set_new(udf_obj, "name", json_string(filename));
	if (e) {
		cf_warning(AS_UDF, "could not encode UDF object, error %d", e);
		json_decref(udf_obj);
		if (udf_content) cf_free(udf_content);
		return(-1);
	}
	// make it into a string, yet another buffer copy
	char *udf_obj_str = json_dumps(udf_obj, 0/*flags*/);
	json_decref(udf_obj);
	udf_obj = 0;

	cf_debug(AS_UDF, "created json object %s", udf_obj_str);

	// how do I know whether to call create or add?
	e = as_smd_set_metadata(udf_smd_module_name, filename, udf_obj_str);
	if (e) {
		cf_warning(AS_UDF, "could not add UDF metadata, error %d", e);
		cf_free(udf_obj_str);
		if (udf_content) cf_free(udf_content);
		return(-1);
	}

	cf_info(AS_UDF, "UDF module '%s' (%s/%s) registered", filename, g_config.mod_lua.user_path, filename);

	// free the metadata
	cf_free(udf_obj_str);
	udf_obj_str = 0;

	if (udf_content) cf_free(udf_content);

	return 0;
}
예제 #26
0
파일: bser.c 프로젝트: relrod/watchman
static json_t *bunser_object(const char *buf, const char *end,
                             int *used, json_error_t *jerr)
{
    int needed;
    int total = 0;
    json_int_t i, nelems;
    json_t *objval;
    char keybuf[128];

    total = 1;
    buf++;

    if (!bunser_int(buf, end - buf, &needed, &nelems)) {
        *used = needed + total;
        snprintf(jerr->text, sizeof(jerr->text),
                 "invalid object property count encoding");
        return NULL;
    }

    total += needed;
    buf += needed;

    objval = json_object();
    for (i = 0; i < nelems; i++) {
        const char *start;
        json_int_t slen;
        json_t *item;

        // Read key
        if (!bunser_string(buf, end - buf, &needed, &start, &slen)) {
            *used = total + needed;
            json_decref(objval);
            snprintf(jerr->text, sizeof(jerr->text),
                     "invalid string for object key");
            return NULL;
        }
        total += needed;
        buf += needed;

        // Saves us allocating a string when the library is going to
        // do that anyway
        if ((uint16_t)slen > sizeof(keybuf) - 1) {
            json_decref(objval);
            snprintf(jerr->text, sizeof(jerr->text),
                     "object key is too long");
            return NULL;
        }
        memcpy(keybuf, start, slen);
        keybuf[slen] = '\0';

        // Read value
        item = bunser(buf, end, &needed, jerr);
        total += needed;
        buf += needed;

        if (!item) {
            json_decref(objval);
            *used = total;
            return NULL;
        }

        if (json_object_set_new_nocheck(objval, keybuf, item)) {
            json_decref(item);
            json_decref(objval);
            *used = total;
            snprintf(jerr->text, sizeof(jerr->text),
                     "failed to add object property");
            return NULL;
        }
    }

    *used = total;
    return objval;
}
예제 #27
0
static void
cleanup_json_t_decref (void *ptr)
{
  json_decref (* (json_t **) ptr);
}
예제 #28
0
파일: soft_crypto.c 프로젝트: memre/jose-c
int
jose_soft_verify(const char *jwt, jwa_t alg, jose_context_t *ctx)
{

  assert (jwt);
  assert (ctx);
  int rc = -1;

  if (alg == HS256)
    {
      uint8_t *key;
      size_t k_len;

      assert (ctx->key_container[HS256].key);
      key = ctx->key_container[HS256].key;
      k_len = ctx->key_container[HS256].k_len;

      rc = hs256_soft_verify (jwt, key, k_len);

    }
  else if (alg == ES256)
    {
      assert (ctx->key_container[ES256].key);

      json_t *jwk = (json_t *)ctx->key_container[ES256].key;

      if (!json_is_object (jwk))
        goto OUT;

      rc = es256_soft_verify (jwt, jwk);

    }
  else if (alg == NONE)
    {
      /* check to see if alg is really set to none */
      json_t *h, *c;
      rc = jwt_decode (jwt, &h, &c);
      if (rc == 0)
        {
          const char *field = "alg";
          json_t *alg_type = json_object_get(h, field);
          if (alg_type)
            {
              rc = strncmp (json_string_value (alg_type), "none", strlen("none"));
            }
          else
            rc = -2;

          json_decref (h);
          json_decref (c);
        }
      else
        {
          syslog (LOG_DEBUG, "JOSEC: Falied to decoded JWT");
        }

    }

 OUT:
  return rc;

}
예제 #29
0
/* Thread to handle incoming messages */
static void *janus_videocall_handler(void *data) {
	JANUS_LOG(LOG_VERB, "Joining VideoCall handler thread\n");
	janus_videocall_message *msg = NULL;
	int error_code = 0;
	char *error_cause = calloc(512, sizeof(char));
	if(error_cause == NULL) {
		JANUS_LOG(LOG_FATAL, "Memory error!\n");
		return NULL;
	}
	json_t *root = NULL;
	while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
		if(!messages || (msg = g_async_queue_try_pop(messages)) == NULL) {
			usleep(50000);
			continue;
		}
		janus_videocall_session *session = (janus_videocall_session *)msg->handle->plugin_handle;	
		if(!session) {
			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
			janus_videocall_message_free(msg);
			continue;
		}
		if(session->destroyed) {
			janus_videocall_message_free(msg);
			continue;
		}
		/* Handle request */
		error_code = 0;
		root = NULL;
		JANUS_LOG(LOG_VERB, "Handling message: %s\n", msg->message);
		if(msg->message == NULL) {
			JANUS_LOG(LOG_ERR, "No message??\n");
			error_code = JANUS_VIDEOCALL_ERROR_NO_MESSAGE;
			g_snprintf(error_cause, 512, "%s", "No message??");
			goto error;
		}
		json_error_t error;
		root = json_loads(msg->message, 0, &error);
		if(!root) {
			JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text);
			error_code = JANUS_VIDEOCALL_ERROR_INVALID_JSON;
			g_snprintf(error_cause, 512, "JSON error: on line %d: %s", error.line, error.text);
			goto error;
		}
		if(!json_is_object(root)) {
			JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
			error_code = JANUS_VIDEOCALL_ERROR_INVALID_JSON;
			g_snprintf(error_cause, 512, "JSON error: not an object");
			goto error;
		}
		json_t *request = json_object_get(root, "request");
		if(!request) {
			JANUS_LOG(LOG_ERR, "Missing element (request)\n");
			error_code = JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT;
			g_snprintf(error_cause, 512, "Missing element (request)");
			goto error;
		}
		if(!json_is_string(request)) {
			JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
			error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
			g_snprintf(error_cause, 512, "Invalid element (request should be a string)");
			goto error;
		}
		const char *request_text = json_string_value(request);
		json_t *result = NULL;
		char *sdp_type = NULL, *sdp = NULL;
		if(!strcasecmp(request_text, "list")) {
			result = json_object();
			json_t *list = json_array();
			JANUS_LOG(LOG_VERB, "Request for the list of peers\n");
			/* Return a list of all available mountpoints */
			janus_mutex_lock(&sessions_mutex);
			GHashTableIter iter;
			gpointer value;
			g_hash_table_iter_init(&iter, sessions);
			while (g_hash_table_iter_next(&iter, NULL, &value)) {
				janus_videocall_session *user = value;
				if(user != NULL && user->username != NULL)
					json_array_append_new(list, json_string(user->username));
			}
			json_object_set_new(result, "list", list);
			janus_mutex_unlock(&sessions_mutex);
		} else if(!strcasecmp(request_text, "register")) {
			/* Map this handle to a username */
			if(session->username != NULL) {
				JANUS_LOG(LOG_ERR, "Already registered (%s)\n", session->username);
				error_code = JANUS_VIDEOCALL_ERROR_ALREADY_REGISTERED;
				g_snprintf(error_cause, 512, "Already registered (%s)", session->username);
				goto error;
			}
			json_t *username = json_object_get(root, "username");
			if(!username) {
				JANUS_LOG(LOG_ERR, "Missing element (username)\n");
				error_code = JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT;
				g_snprintf(error_cause, 512, "Missing element (username)");
				goto error;
			}
			if(!json_is_string(username)) {
				JANUS_LOG(LOG_ERR, "Invalid element (username should be a string)\n");
				error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
				g_snprintf(error_cause, 512, "Invalid element (username should be a string)");
				goto error;
			}
			const char *username_text = json_string_value(username);
			janus_mutex_lock(&sessions_mutex);
			if(g_hash_table_lookup(sessions, username_text) != NULL) {
				janus_mutex_unlock(&sessions_mutex);
				JANUS_LOG(LOG_ERR, "Username '%s' already taken\n", username_text);
				error_code = JANUS_VIDEOCALL_ERROR_USERNAME_TAKEN;
				g_snprintf(error_cause, 512, "Username '%s' already taken", username_text);
				goto error;
			}
			janus_mutex_unlock(&sessions_mutex);
			session->username = g_strdup(username_text);
			if(session->username == NULL) {
				JANUS_LOG(LOG_FATAL, "Memory error!\n");
				error_code = JANUS_VIDEOCALL_ERROR_UNKNOWN_ERROR;
				g_snprintf(error_cause, 512, "Memory error");
				goto error;
			}
			janus_mutex_lock(&sessions_mutex);
			g_hash_table_insert(sessions, (gpointer)session->username, session);
			janus_mutex_unlock(&sessions_mutex);
			result = json_object();
			json_object_set_new(result, "event", json_string("registered"));
			json_object_set_new(result, "username", json_string(username_text));
		} else if(!strcasecmp(request_text, "call")) {
			/* Call another peer */
			if(session->username == NULL) {
				JANUS_LOG(LOG_ERR, "Register a username first\n");
				error_code = JANUS_VIDEOCALL_ERROR_REGISTER_FIRST;
				g_snprintf(error_cause, 512, "Register a username first");
				goto error;
			}
			if(session->peer != NULL) {
				JANUS_LOG(LOG_ERR, "Already in a call\n");
				error_code = JANUS_VIDEOCALL_ERROR_ALREADY_IN_CALL;
				g_snprintf(error_cause, 512, "Already in a call");
				goto error;
			}
			json_t *username = json_object_get(root, "username");
			if(!username) {
				JANUS_LOG(LOG_ERR, "Missing element (username)\n");
				error_code = JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT;
				g_snprintf(error_cause, 512, "Missing element (username)");
				goto error;
			}
			if(!json_is_string(username)) {
				JANUS_LOG(LOG_ERR, "Invalid element (username should be a string)\n");
				error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
				g_snprintf(error_cause, 512, "Invalid element (username should be a string)");
				goto error;
			}
			const char *username_text = json_string_value(username);
			if(!strcmp(username_text, session->username)) {
				JANUS_LOG(LOG_ERR, "You can't call yourself... use the EchoTest for that\n");
				error_code = JANUS_VIDEOCALL_ERROR_USE_ECHO_TEST;
				g_snprintf(error_cause, 512, "You can't call yourself... use the EchoTest for that");
				goto error;
			}
			janus_mutex_lock(&sessions_mutex);
			janus_videocall_session *peer = g_hash_table_lookup(sessions, username_text);
			if(peer == NULL || peer->destroyed) {
				janus_mutex_unlock(&sessions_mutex);
				JANUS_LOG(LOG_ERR, "Username '%s' doesn't exist\n", username_text);
				error_code = JANUS_VIDEOCALL_ERROR_NO_SUCH_USERNAME;
				g_snprintf(error_cause, 512, "Username '%s' doesn't exist", username_text);
				goto error;
			}
			if(peer->peer != NULL) {
				janus_mutex_unlock(&sessions_mutex);
				JANUS_LOG(LOG_VERB, "%s is busy\n", username_text);
				result = json_object();
				json_object_set_new(result, "event", json_string("hangup"));
				json_object_set_new(result, "username", json_string(session->username));
				json_object_set_new(result, "reason", json_string("User busy"));
			} else {
				janus_mutex_unlock(&sessions_mutex);
				/* Any SDP to handle? if not, something's wrong */
				if(!msg->sdp) {
					JANUS_LOG(LOG_ERR, "Missing SDP\n");
					error_code = JANUS_VIDEOCALL_ERROR_MISSING_SDP;
					g_snprintf(error_cause, 512, "Missing SDP");
					goto error;
				}
				janus_mutex_lock(&sessions_mutex);
				session->peer = peer;
				peer->peer = session;
				janus_mutex_unlock(&sessions_mutex);
				JANUS_LOG(LOG_VERB, "%s is calling %s\n", session->username, session->peer->username);
				JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
				/* Send SDP to our peer */
				json_t *call = json_object();
				json_object_set_new(call, "videocall", json_string("event"));
				json_t *calling = json_object();
				json_object_set_new(calling, "event", json_string("incomingcall"));
				json_object_set_new(calling, "username", json_string(session->username));
				json_object_set_new(call, "result", calling);
				char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
				json_decref(call);
				JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
				int ret = gateway->push_event(peer->handle, &janus_videocall_plugin, NULL, call_text, msg->sdp_type, msg->sdp);
				JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
				g_free(call_text);
				/* Send an ack back */
				result = json_object();
				json_object_set_new(result, "event", json_string("calling"));
			}
		} else if(!strcasecmp(request_text, "accept")) {
			/* Accept a call from another peer */
			if(session->peer == NULL) {
				JANUS_LOG(LOG_ERR, "No incoming call to accept\n");
				error_code = JANUS_VIDEOCALL_ERROR_NO_CALL;
				g_snprintf(error_cause, 512, "No incoming call to accept");
				goto error;
			}
			/* Any SDP to handle? if not, something's wrong */
			if(!msg->sdp) {
				JANUS_LOG(LOG_ERR, "Missing SDP\n");
				error_code = JANUS_VIDEOCALL_ERROR_MISSING_SDP;
				g_snprintf(error_cause, 512, "Missing SDP");
				goto error;
			}
			JANUS_LOG(LOG_VERB, "%s is accepting a call from %s\n", session->username, session->peer->username);
			JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
			/* Send SDP to our peer */
			json_t *call = json_object();
			json_object_set_new(call, "videocall", json_string("event"));
			json_t *calling = json_object();
			json_object_set_new(calling, "event", json_string("accepted"));
			json_object_set_new(calling, "username", json_string(session->username));
			json_object_set_new(call, "result", calling);
			char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
			json_decref(call);
			JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
			int ret = gateway->push_event(session->peer->handle, &janus_videocall_plugin, NULL, call_text, msg->sdp_type, msg->sdp);
			JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
			g_free(call_text);
			/* Send an ack back */
			result = json_object();
			json_object_set_new(result, "event", json_string("accepted"));
		} else if(!strcasecmp(request_text, "set")) {
			/* Update the local configuration (audio/video mute/unmute, or bitrate cap) */
			json_t *audio = json_object_get(root, "audio");
			if(audio && !json_is_boolean(audio)) {
				JANUS_LOG(LOG_ERR, "Invalid element (audio should be a boolean)\n");
				error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
				g_snprintf(error_cause, 512, "Invalid value (audio should be a boolean)");
				goto error;
			}
			json_t *video = json_object_get(root, "video");
			if(video && !json_is_boolean(video)) {
				JANUS_LOG(LOG_ERR, "Invalid element (video should be a boolean)\n");
				error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
				g_snprintf(error_cause, 512, "Invalid value (video should be a boolean)");
				goto error;
			}
			json_t *bitrate = json_object_get(root, "bitrate");
			if(bitrate && !json_is_integer(bitrate)) {
				JANUS_LOG(LOG_ERR, "Invalid element (bitrate should be an integer)\n");
				error_code = JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT;
				g_snprintf(error_cause, 512, "Invalid value (bitrate should be an integer)");
				goto error;
			}
			if(audio) {
				session->audio_active = json_is_true(audio);
				JANUS_LOG(LOG_VERB, "Setting audio property: %s\n", session->audio_active ? "true" : "false");
			}
			if(video) {
				if(!session->video_active && json_is_true(video)) {
					/* Send a PLI */
					JANUS_LOG(LOG_VERB, "Just (re-)enabled video, sending a PLI to recover it\n");
					char buf[12];
					memset(buf, 0, 12);
					janus_rtcp_pli((char *)&buf, 12);
					gateway->relay_rtcp(session->handle, 1, buf, 12);
				}
				session->video_active = json_is_true(video);
				JANUS_LOG(LOG_VERB, "Setting video property: %s\n", session->video_active ? "true" : "false");
			}
			if(bitrate) {
				session->bitrate = json_integer_value(bitrate);
				JANUS_LOG(LOG_VERB, "Setting video bitrate: %"SCNu64"\n", session->bitrate);
				if(session->bitrate > 0) {
					/* FIXME Generate a new REMB (especially useful for Firefox, which doesn't send any we can cap later) */
					char buf[24];
					memset(buf, 0, 24);
					janus_rtcp_remb((char *)&buf, 24, session->bitrate);
					JANUS_LOG(LOG_VERB, "Sending REMB\n");
					gateway->relay_rtcp(session->handle, 1, buf, 24);
					/* FIXME How should we handle a subsequent "no limit" bitrate? */
				}
			}
			/* Send an ack back */
			result = json_object();
			json_object_set_new(result, "event", json_string("set"));
		} else if(!strcasecmp(request_text, "hangup")) {
			/* Hangup an ongoing call or reject an incoming one */
			janus_mutex_lock(&sessions_mutex);
			janus_videocall_session *peer = session->peer;
			if(peer == NULL) {
				JANUS_LOG(LOG_WARN, "No call to hangup\n");
			} else {
				JANUS_LOG(LOG_VERB, "%s is hanging up the call with %s\n", session->username, peer->username);
				session->peer = NULL;
				peer->peer = NULL;
			}
			janus_mutex_unlock(&sessions_mutex);
			/* Notify the success as an hangup message */
			result = json_object();
			json_object_set_new(result, "event", json_string("hangup"));
			json_object_set_new(result, "username", json_string(session->username));
			json_object_set_new(result, "reason", json_string("We did the hangup"));
			if(peer != NULL) {
				/* Send event to our peer too */
				json_t *call = json_object();
				json_object_set_new(call, "videocall", json_string("event"));
				json_t *calling = json_object();
				json_object_set_new(calling, "event", json_string("hangup"));
				json_object_set_new(calling, "username", json_string(session->username));
				json_object_set_new(calling, "reason", json_string("Remote hangup"));
				json_object_set_new(call, "result", calling);
				char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
				json_decref(call);
				JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
				int ret = gateway->push_event(peer->handle, &janus_videocall_plugin, NULL, call_text, NULL, NULL);
				JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
				g_free(call_text);
			}
		} else {
			JANUS_LOG(LOG_ERR, "Unknown request (%s)\n", request_text);
			error_code = JANUS_VIDEOCALL_ERROR_INVALID_REQUEST;
			g_snprintf(error_cause, 512, "Unknown request (%s)", request_text);
			goto error;
		}

		json_decref(root);
		/* Prepare JSON event */
		json_t *event = json_object();
		json_object_set_new(event, "videocall", json_string("event"));
		if(result != NULL)
			json_object_set_new(event, "result", result);
		char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
		json_decref(event);
		JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
		int ret = gateway->push_event(msg->handle, &janus_videocall_plugin, msg->transaction, event_text, sdp_type, sdp);
		JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
		g_free(event_text);
		if(sdp)
			g_free(sdp);
		janus_videocall_message_free(msg);
		continue;
		
error:
		{
			if(root != NULL)
				json_decref(root);
			/* Prepare JSON error event */
			json_t *event = json_object();
			json_object_set_new(event, "videocall", json_string("event"));
			json_object_set_new(event, "error_code", json_integer(error_code));
			json_object_set_new(event, "error", json_string(error_cause));
			char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
			json_decref(event);
			JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
			int ret = gateway->push_event(msg->handle, &janus_videocall_plugin, msg->transaction, event_text, NULL, NULL);
			JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
			g_free(event_text);
			janus_videocall_message_free(msg);
		}
	}
	g_free(error_cause);
	JANUS_LOG(LOG_VERB, "Leaving VideoCall handler thread\n");
	return NULL;
}
예제 #30
0
/*
 * main routine: handle OAuth 2.0 authentication/authorization
 */
int oidc_oauth_check_userid(request_rec *r, oidc_cfg *c) {

	/* check if this is a sub-request or an initial request */
	if (!ap_is_initial_req(r)) {

		if (r->main != NULL)
			r->user = r->main->user;
		else if (r->prev != NULL)
			r->user = r->prev->user;

		if (r->user != NULL) {

			/* this is a sub-request and we have a session */
			oidc_debug(r,
					"recycling user '%s' from initial request for sub-request",
					r->user);

			return OK;
		}

		/* check if this is a request for the public (encryption) keys */
	} else if ((c->redirect_uri != NULL)
			&& (oidc_util_request_matches_url(r, c->redirect_uri))) {

		if (oidc_util_request_has_parameter(r, "jwks")) {

			return oidc_handle_jwks(r, c);

		}

	}

	/* we don't have a session yet */

	/* get the bearer access token from the Authorization header */
	const char *access_token = NULL;
	if (oidc_oauth_get_bearer_token(r, &access_token) == FALSE)
		return HTTP_UNAUTHORIZED;

	/* validate the obtained access token against the OAuth AS validation endpoint */
	json_t *token = NULL;
	char *s_token = NULL;

	/* check if an introspection endpoint is set */
	if (c->oauth.introspection_endpoint_url != NULL) {
		/* we'll validate the token remotely */
		if (oidc_oauth_resolve_access_token(r, c, access_token, &token,
				&s_token) == FALSE)
			return HTTP_UNAUTHORIZED;
	} else {
		/* no introspection endpoint is set, assume the token is a JWT and validate it locally */
		if (oidc_oauth_validate_jwt_access_token(r, c, access_token, &token,
				&s_token) == FALSE)
			return HTTP_UNAUTHORIZED;
	}

	/* check that we've got something back */
	if (token == NULL) {
		oidc_error(r, "could not resolve claims (token == NULL)");
		return HTTP_UNAUTHORIZED;
	}

	/* store the parsed token (cq. the claims from the response) in the request state so it can be accessed by the authz routines */
	oidc_request_state_set(r, OIDC_CLAIMS_SESSION_KEY, (const char *) s_token);

	/* set the REMOTE_USER variable */
	if (oidc_oauth_set_remote_user(r, c, token) == FALSE) {
		oidc_error(r,
				"remote user could not be set, aborting with HTTP_UNAUTHORIZED");
		return HTTP_UNAUTHORIZED;
	}

	/* get a handle to the director config */
	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
			&auth_openidc_module);

	/* set the user authentication HTTP header if set and required */
	if ((r->user != NULL) && (dir_cfg->authn_header != NULL)) {
		oidc_debug(r, "setting authn header (%s) to: %s", dir_cfg->authn_header,
				r->user);
		apr_table_set(r->headers_in, dir_cfg->authn_header, r->user);
	}

	/* set the resolved claims in the HTTP headers for the target application */
	oidc_util_set_app_infos(r, token, c->claim_prefix, c->claim_delimiter,
			dir_cfg->pass_info_in_headers, dir_cfg->pass_info_in_env_vars);

	/* set the access_token in the app headers */
	if (access_token != NULL) {
		oidc_util_set_app_info(r, "access_token", access_token,
				OIDC_DEFAULT_HEADER_PREFIX, dir_cfg->pass_info_in_headers,
				dir_cfg->pass_info_in_env_vars);
	}

	/* free JSON resources */
	json_decref(token);

	return OK;
}