void pcm_policy_free() { if(PCM_GLOBAL.policy) json_decref(PCM_GLOBAL.policy); PCM_GLOBAL.policy = NULL; }
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 {
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); } } }
/* 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; }
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); }
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; }
void JanssonObjectHandler::OnHandleDestroy(HandleType_t type, void *object) { json_decref((json_t*)object); }
void set( json_t* json ) { if( m_value ) json_decref( m_value ) ; m_value = json ; }
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; }
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; };
~JsonMsg() { if( m_value) json_decref(m_value) ; }
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; }
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; }
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; }
static void json_release_object (void *object) { json_decref (object); }
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; }
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; }
/** * 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; }
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; }
/** * \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); }
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; }
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(); } }
static void janus_sampleevh_event_free(json_t *event) { if(!event || event == &exit_event) return; json_decref(event); }
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; }
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; }
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; }
static void cleanup_json_t_decref (void *ptr) { json_decref (* (json_t **) ptr); }
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; }
/* 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; }
/* * 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; }