int main(int argc, char **argv) { // header information std::cout << "Blackbird Bitcoin Arbitrage\nVersion 0.0.2" << std::endl; std::cout << "DISCLAIMER: USE THE SOFTWARE AT YOUR OWN RISK.\n" << std::endl; // read the config file (config.json) json_error_t error; json_t *root = json_load_file("config.json", 0, &error); if (!root) { std::cout << "ERROR: config.json incorrect (" << error.text << ")\n" << std::endl; return 1; } // get config variables int gapSec = json_integer_value(json_object_get(root, "GapSec")); unsigned debugMaxIteration = json_integer_value(json_object_get(root, "DebugMaxIteration")); bool useFullCash = json_boolean_value(json_object_get(root, "UseFullCash")); double untouchedCash = json_real_value(json_object_get(root, "UntouchedCash")); double cashForTesting = json_real_value(json_object_get(root, "CashForTesting")); if (!useFullCash && cashForTesting < 15.0) { std::cout << "ERROR: Minimum test cash is $15.00.\n" << std::endl; return 1; } // function arrays getQuoteType getQuote[] = {Bitfinex::getQuote, OkCoin::getQuote, Bitstamp::getQuote, Kraken::getQuote}; getAvailType getAvail[] = {Bitfinex::getAvail, OkCoin::getAvail, Bitstamp::getAvail, Kraken::getAvail}; sendOrderType sendOrder[] = {Bitfinex::sendOrder, OkCoin::sendOrder, Bitstamp::sendOrder}; isOrderCompleteType isOrderComplete[] = {Bitfinex::isOrderComplete, OkCoin::isOrderComplete, Bitstamp::isOrderComplete}; getActivePosType getActivePos[] = {Bitfinex::getActivePos, OkCoin::getActivePos, Bitstamp::getActivePos, Kraken::getActivePos}; getLimitPriceType getLimitPrice[] = {Bitfinex::getLimitPrice, OkCoin::getLimitPrice, Bitstamp::getLimitPrice, Kraken::getLimitPrice}; // thousand separator std::locale mylocale(""); std::cout.imbue(mylocale); // print precision of two digits std::cout.precision(2); std::cout << std::fixed; // create a parameters structure Parameters params(root); params.addExchange("Bitfinex", 0.0020, true); params.addExchange("OKCoin", 0.0020, false); params.addExchange("Bitstamp", 0.0025, false); params.addExchange("Kraken", 0.0025, true); // CSV file std::string csvFileName; csvFileName = "result_" + printDateTimeFileName() + ".csv"; std::ofstream csvFile; csvFile.open(csvFileName.c_str(), std::ofstream::trunc); // CSV header csvFile << "TRADE_ID,EXCHANGE_LONG,EXHANGE_SHORT,ENTRY_TIME,EXIT_TIME,DURATION,TOTAL_EXPOSURE,BALANCE_BEFORE,BALANCE_AFTER,RETURN\n"; csvFile.flush(); // time structure time_t rawtime; rawtime = time(NULL); struct tm * timeinfo; timeinfo = localtime(&rawtime); bool inMarket = false; int resultId = 0; Result res; res.clear(); // Vector of Bitcoin std::vector<Bitcoin*> btcVec; // create Bitcoin objects for (unsigned i = 0; i < params.nbExch(); ++i) { btcVec.push_back(new Bitcoin(i, params.exchName[i], params.fees[i], params.hasShort[i])); } // cURL CURL* curl; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); std::cout << "[ Targets ]" << std::endl; std::cout << " Spread to enter: " << params.spreadEntry * 100.0 << "%" << std::endl; std::cout << " Spread to exit: " << params.spreadExit * 100.0 << "%" << std::endl; std::cout << std::endl; // store current balances std::cout << "[ Current balances ]" << std::endl; std::vector<double> balanceUsd; std::vector<double> balanceBtc; for (unsigned i = 0; i < params.nbExch(); ++i) { balanceUsd.push_back(getAvail[i](curl, params, "usd")); balanceBtc.push_back(getAvail[i](curl, params, "btc")); } // vectors that contains balances after a completed trade std::vector<double> newBalUsd(params.nbExch(), 0.0); std::vector<double> newBalBtc(params.nbExch(), 0.0); for (unsigned i = 0; i < params.nbExch(); ++i) { std::cout << " " << params.exchName[i] << ":\t"; std::cout << balanceUsd[i] << " USD\t" << std::setprecision(6) << balanceBtc[i] << std::setprecision(2) << " BTC" << std::endl; } std::cout << std::endl; std::cout << "[ Cash exposure ]" << std::endl; if (useFullCash) { std::cout << " FULL cash used!" << std::endl; } else { std::cout << " TEST cash used\n Value: $" << cashForTesting << std::endl; } std::cout << std::endl; // wait the next gapSec seconds before starting time(&rawtime); timeinfo = localtime(&rawtime); while ((int)timeinfo->tm_sec % gapSec != 0) { sleep(0.01); time(&rawtime); timeinfo = localtime(&rawtime); } // main loop if (!params.verbose) { std::cout << "Running..." << std::endl; } unsigned currIteration = 0; bool stillRunning = true; while (stillRunning) { time_t currTime = mktime(timeinfo); time(&rawtime); // check if we are already too late if (difftime(rawtime, currTime) > 0) { std::cout << "WARNING: " << difftime(rawtime, currTime) << " second(s) too late at " << printDateTime(currTime) << std::endl; unsigned skip = (unsigned)ceil(difftime(rawtime, currTime) / gapSec); for (unsigned i = 0; i < skip; ++i) { // std::cout << " Skipped iteration " << printDateTime(currTime) << std::endl; for (unsigned e = 0; e < params.nbExch(); ++e) { btcVec[e]->addData(currTime, btcVec[e]->getLastBid(), btcVec[e]->getLastAsk(), 0.0); } // go to next iteration timeinfo->tm_sec = timeinfo->tm_sec + gapSec; currTime = mktime(timeinfo); } std::cout << std::endl; } // wait for the next iteration while (difftime(rawtime, currTime) != 0) { sleep(0.01); time(&rawtime); } if (params.verbose) { if (!inMarket) { std::cout << "[ " << printDateTime(currTime) << " ]" << std::endl; } else { std::cout << "[ " << printDateTime(currTime) << " IN MARKET: Long " << res.exchNameLong << " / Short " << res.exchNameShort << " ]" << std::endl; } } // download the exchanges prices for (unsigned e = 0; e < params.nbExch(); ++e) { double bid = getQuote[e](curl, true); double ask = getQuote[e](curl, false); // add previous price if bid or ask is 0.0 if (bid == 0.0) { bid = btcVec[e]->getLastBid(); std::cout << " WARNING: " << params.exchName[e] << " bid is null, use previous one" << std::endl; } if (ask == 0.0) { ask = btcVec[e]->getLastAsk(); std::cout << " WARNING: " << params.exchName[e] << " ask is null, use previous one" << std::endl; } if (params.verbose) { std::cout << " " << params.exchName[e] << ": \t" << bid << " / " << ask << std::endl; } btcVec[e]->addData(currTime, bid, ask, 0.0); curl_easy_reset(curl); } // load data terminated if (params.verbose) { std::cout << " ----------------------------" << std::endl; } // compute entry point if (!inMarket) { for (unsigned i = 0; i < params.nbExch(); ++i) { for (unsigned j = 0; j < params.nbExch(); ++j) { if (i != j) { if (checkEntry(btcVec[i], btcVec[j], res, params)) { // entry opportunity found // compute exposure res.exposure = std::min(balanceUsd[res.idExchLong], balanceUsd[res.idExchShort]); if (res.exposure == 0.0) { std::cout << " WARNING: Opportunity found but no cash available. Trade canceled." << std::endl; break; } if (useFullCash == false && res.exposure <= cashForTesting) { std::cout << " WARNING: Opportunity found but no enough cash. Need more than TEST cash (min. $" << cashForTesting << "). Trade canceled." << std::endl; break; } if (useFullCash) { // leave untouchedCash res.exposure -= untouchedCash * res.exposure; } else { // use test money res.exposure = cashForTesting; } // check volumes double volumeLong = res.exposure / btcVec[res.idExchLong]->getLastAsk(); double volumeShort = res.exposure / btcVec[res.idExchShort]->getLastBid(); double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, false); double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, true); if (limPriceLong - res.priceLongIn > 0.30 || res.priceShortIn - limPriceShort > 0.30) { std::cout << " WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl; break; } inMarket = true; resultId++; // update result res.id = resultId; res.entryTime = currTime; res.printEntry(); res.maxSpread[res.idExchLong][res.idExchShort] = -1.0; res.minSpread[res.idExchLong][res.idExchShort] = 1.0; int longOrderId = 0; int shortOrderId = 0; // send Long order longOrderId = sendOrder[res.idExchLong](curl, params, "buy", volumeLong, btcVec[res.idExchLong]->getLastAsk()); // send Short order shortOrderId = sendOrder[res.idExchShort](curl, params, "sell", volumeShort, btcVec[res.idExchShort]->getLastBid()); // wait for the orders to be filled sleep(3.0); std::cout << "Waiting for the two orders to be filled..." << std::endl; while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) { sleep(3.0); } std::cout << "Done" << std::endl; longOrderId = 0; shortOrderId = 0; break; } } } if (inMarket) { break; } } if (params.verbose) { std::cout << std::endl; } } // in market, looking to exit else if (inMarket) { if (checkExit(btcVec[res.idExchLong], btcVec[res.idExchShort], res, params, currTime)) { // exit opportunity found // check current exposure std::vector<double> btcUsed; for (unsigned i = 0; i < params.nbExch(); ++i) { btcUsed.push_back(getActivePos[i](curl, params)); } // check volumes double volumeLong = btcUsed[res.idExchLong]; double volumeShort = btcUsed[res.idExchShort]; double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, true); double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, false); if (res.priceLongOut - limPriceLong > 0.30 || limPriceShort - res.priceShortOut > 0.30) { std::cout << " WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl; } else { res.exitTime = currTime; res.printExit(); // send orders int longOrderId = 0; int shortOrderId = 0; std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchLong] << ": " << volumeLong << std::setprecision(2) << std::endl; std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchShort] << ": " << volumeShort << std::setprecision(2) << std::endl; std::cout << std::endl; // Close Long longOrderId = sendOrder[res.idExchLong](curl, params, "sell", fabs(btcUsed[res.idExchLong]), btcVec[res.idExchLong]->getLastBid()); // Close Short shortOrderId = sendOrder[res.idExchShort](curl, params, "buy", fabs(btcUsed[res.idExchShort]), btcVec[res.idExchShort]->getLastAsk()); // wait for the orders to be filled sleep(3.0); std::cout << "Waiting for the two orders to be filled..." << std::endl; while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) { sleep(3.0); } std::cout << "Done\n" << std::endl; longOrderId = 0; shortOrderId = 0; // market exited inMarket = false; // new balances for (unsigned i = 0; i < params.nbExch(); ++i) { newBalUsd[i] = getAvail[i](curl, params, "usd"); newBalBtc[i] = getAvail[i](curl, params, "btc"); } for (unsigned i = 0; i < params.nbExch(); ++i) { std::cout << "New balance on " << params.exchName[i] << ": \t"; std::cout << newBalUsd[i] << " USD (perf $" << newBalUsd[i] - balanceUsd[i] << "), "; std::cout << std::setprecision(6) << newBalBtc[i] << std::setprecision(2) << " BTC" << std::endl; } std::cout << std::endl; // update res with total balance res.befBalUsd = std::accumulate(balanceUsd.begin(), balanceUsd.end(), 0.0); res.aftBalUsd = std::accumulate(newBalUsd.begin(), newBalUsd.end(), 0.0); // update current balances with new values for (unsigned i = 0; i < params.nbExch(); ++i) { balanceUsd[i] = newBalUsd[i]; balanceBtc[i] = newBalBtc[i]; } // display performance std::cout << "ACTUAL PERFORMANCE: " << "$" << res.aftBalUsd - res.befBalUsd << " (" << res.totPerf() * 100.0 << "%)\n" << std::endl; // new csv line with result csvFile << res.id << "," << res.exchNameLong << "," << res.exchNameShort << "," << printDateTimeCsv(res.entryTime) << "," << printDateTimeCsv(res.exitTime); csvFile << "," << res.getLength() << "," << res.exposure * 2.0 << "," << res.befBalUsd << "," << res.aftBalUsd << "," << res.totPerf() << "\n"; csvFile.flush(); // send email if (params.sendEmail) { sendEmail(res, params); std::cout << "Email sent" << std::endl; } // delete result information res.clear(); // if "stop_after_exit" file exists then return std::ifstream infile("stop_after_exit"); if (infile.good()) { std::cout << "Exit after last trade (file stop_after_exit found)" << std::endl; stillRunning = false; } } } if (params.verbose) { std::cout << std::endl; } } // activities for this iteration terminated timeinfo->tm_sec = timeinfo->tm_sec + gapSec; currIteration++; if (currIteration >= debugMaxIteration) { std::cout << "Max iteration reached (" << debugMaxIteration << ")" <<std::endl; stillRunning = false; } } // delete Bitcoin objects for (unsigned i = 0; i < params.nbExch(); ++i) { delete(btcVec[i]); } json_decref(root); // close cURL curl_easy_cleanup(curl); curl_global_cleanup(); // close csv file csvFile.close(); return 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; }
/** * 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; }
static void handle_request(int sock) { char *buf = NULL; size_t len; json_t *req = NULL, *ret = NULL, *arg; json_error_t json_error; int req_id, err_code = -1; ret = json_object(); if(ret == NULL) goto end; if(recv_full(sock, &len, sizeof(len)) == -1) { log_error_errno(); goto end; } buf = (char *)malloc(len + 1); if(buf == NULL) { log_error_errno(); goto end; } if(recv_full(sock, buf, len) == -1) { log_error_errno(); goto end; } buf[len] = '\0'; enable_listening_fd(sock); req = json_loads(buf, 0, &json_error); if(req == NULL) { log_error(LOG_COLOR_ERROR, "%d: %s", sock, json_error.text); goto end; } if(!json_is_object(req)) goto invalid_request; arg = json_object_get(req, "req_id"); if(arg == NULL || !json_is_integer(arg)) goto invalid_request; req_id = json_integer_value(arg); if(req_id < 0 || req_id >= sizeof(g_req_handler) / sizeof(*g_req_handler)) goto invalid_request; arg = json_object_get(req, "arg"); if(arg == NULL || !json_is_object(arg)) goto invalid_request; err_code = g_req_handler[req_id](arg, ret); end: send_response(sock, err_code, ret); if(req) json_decref(req); if(buf) free(buf); if(ret) json_decref(ret); return; invalid_request: log_error(LOG_COLOR_ERROR, "%d: Invalid request", sock); goto end; }
janus_turnrest_response *janus_turnrest_request(void) { janus_mutex_lock(&api_mutex); if(api_server == NULL) { janus_mutex_unlock(&api_mutex); return NULL; } /* Prepare the request URI */ char query_string[512]; g_snprintf(query_string, 512, "service=turn"); if(api_key != NULL) { char buffer[256]; g_snprintf(buffer, 256, "&api=%s", api_key); g_strlcat(query_string, buffer, 512); } char request_uri[1024]; g_snprintf(request_uri, 1024, "%s?%s", api_server, query_string); JANUS_LOG(LOG_VERB, "Sending request: %s\n", request_uri); janus_mutex_unlock(&api_mutex); /* Prepare the libcurl context */ CURLcode res; CURL *curl = curl_easy_init(); if(curl == NULL) { JANUS_LOG(LOG_ERR, "libcurl error\n"); return NULL; } curl_easy_setopt(curl, CURLOPT_URL, request_uri); curl_easy_setopt(curl, CURLOPT_POST, 1); /* FIXME Some servers don't like a POST with no data */ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query_string); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); /* FIXME Max 10 seconds */ /* For getting data, we use an helper struct and the libcurl callback */ janus_turnrest_buffer data; data.buffer = malloc(1); data.size = 0; curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, janus_turnrest_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data); curl_easy_setopt(curl, CURLOPT_USERAGENT, "Janus/1.0"); /* Send the request */ res = curl_easy_perform(curl); if(res != CURLE_OK) { JANUS_LOG(LOG_ERR, "Couldn't send the request: %s\n", curl_easy_strerror(res)); free(data.buffer); curl_easy_cleanup(curl); return NULL; } /* Cleanup the libcurl context */ curl_easy_cleanup(curl); /* Process the response */ JANUS_LOG(LOG_VERB, "Got %zu bytes from the TURN REST API server\n", data.size); JANUS_LOG(LOG_VERB, "%s\n", data.buffer); json_error_t error; json_t *root = json_loads(data.buffer, 0, &error); if(!root) { JANUS_LOG(LOG_ERR, "Couldn't parse response: error on line %d: %s", error.line, error.text); free(data.buffer); return NULL; } free(data.buffer); json_t *username = json_object_get(root, "username"); if(!username) { JANUS_LOG(LOG_ERR, "Invalid response: missing username\n"); return NULL; } if(!json_is_string(username)) { JANUS_LOG(LOG_ERR, "Invalid response: username should be a string\n"); return NULL; } json_t *password = json_object_get(root, "password"); if(!password) { JANUS_LOG(LOG_ERR, "Invalid response: missing password\n"); return NULL; } if(!json_is_string(password)) { JANUS_LOG(LOG_ERR, "Invalid response: password should be a string\n"); return NULL; } json_t *ttl = json_object_get(root, "ttl"); if(ttl && !json_is_integer(ttl)) { JANUS_LOG(LOG_ERR, "Invalid response: ttl should be an integer\n"); return NULL; } json_t *uris = json_object_get(root, "uris"); if(!uris) { JANUS_LOG(LOG_ERR, "Invalid response: missing uris\n"); return NULL; } if(!json_is_array(uris) || json_array_size(uris) == 0) { JANUS_LOG(LOG_ERR, "Invalid response: uris should be a non-empty array\n"); return NULL; } /* Turn the response into a janus_turnrest_response object we can use */ janus_turnrest_response *response = calloc(1, sizeof(janus_turnrest_response)); response->username = g_strdup(json_string_value(username)); response->password = g_strdup(json_string_value(password)); response->ttl = ttl ? json_integer_value(ttl) : 0; response->servers = NULL; size_t i = 0; for(i=0; i<json_array_size(uris); i++) { json_t *uri = json_array_get(uris, i); if(uri == NULL || !json_is_string(uri)) { JANUS_LOG(LOG_WARN, "Skipping invalid TURN URI (not a string)...\n"); continue; } const char *turn_uri = json_string_value(uri); if(strstr(turn_uri, "turn:") != turn_uri && strstr(turn_uri, "turns:") != turn_uri) { JANUS_LOG(LOG_WARN, "Skipping invalid TURN URI '%s' (not a TURN URI)...\n", turn_uri); continue; } janus_turnrest_instance *instance = calloc(1, sizeof(janus_turnrest_instance)); instance->transport = NICE_RELAY_TYPE_TURN_UDP; if(strstr(turn_uri, "turns:") == turn_uri) instance->transport = NICE_RELAY_TYPE_TURN_TLS; else if(strstr(turn_uri, "transport=tcp") == turn_uri) instance->transport = NICE_RELAY_TYPE_TURN_TCP; gchar **parts = NULL; if(strstr(turn_uri, "?") != NULL) { parts = g_strsplit(turn_uri, "?", -1); turn_uri = parts[0]; } gchar **uri_parts = g_strsplit(turn_uri, ":", -1); /* Resolve the TURN URI address */ struct hostent *he = gethostbyname(uri_parts[1]); if(he == NULL) { JANUS_LOG(LOG_WARN, "Skipping invalid TURN URI '%s' (could not resolve the address)...\n", uri_parts[1]); g_strfreev(uri_parts); continue; } struct in_addr **addr_list = (struct in_addr **)he->h_addr_list; if(addr_list[0] == NULL) { JANUS_LOG(LOG_WARN, "Skipping invalid TURN URI '%s' (could not resolve the address)...\n", uri_parts[1]); g_strfreev(uri_parts); continue; } instance->server = g_strdup(inet_ntoa(*addr_list[0])); if(uri_parts[2] == NULL) { /* No port? USe 3478 by default */ instance->port = 3478; } else { instance->port = atoi(uri_parts[2]); } g_strfreev(uri_parts); g_strfreev(parts); /* Add the server to the list */ response->servers = g_list_append(response->servers, instance); } if(response->servers == NULL) { JANUS_LOG(LOG_ERR, "Couldn't find any valid TURN URI in the response...\n"); janus_turnrest_response_destroy(response); return NULL; } /* Done */ return response; }
/* return error */ int DEFAULT_CC lib_mod_connect(struct mod *mod) { int error; int len; int i; int index; int use_uds; struct stream *s; char con_port[256]; int retry = 0; int send_error = 0; int rc = 0; unsigned int nbytes; char pidfile[128]; char ip[16]; char cookie[33]; char sessionid[128]; char sessiontoken[128]; struct passwd pwd; struct passwd *pwdresult; char pwdbuffer[16384]; char message[256]; char reply[256]; int sock; struct sockaddr_in server; json_t *request; json_t *response; json_t *display; json_error_t js_error; mod->server_msg(mod, "GoPCNX started connection", 0); sock = socket(AF_INET , SOCK_STREAM , 0); if (sock == -1) { mod->server_msg(mod, "Socket creation failed", 0); return 1; } server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons(9999); if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) { mod->server_msg(mod, "Server connection failed", 0); return 1; } request = json_object(); json_object_set(request, "username", json_string(mod->username)); json_object_set(request, "password", json_string(mod->password)); json_object_set(request, "ip", json_string("127.0.0.1")); json_object_set(request, "link", json_string("lan")); display = json_object(); json_object_set(display, "width", json_integer(mod->width)); json_object_set(display, "height", json_integer(mod->height)); json_object_set(request, "display", display); json_decref(display); g_snprintf(message, sizeof(message)-1, "%s\n", json_dumps(request, 0)); json_decref(request); if (send(sock, message, strlen(message), 0) < 0) { mod->server_msg(mod, "Server request failed", 0); return 1; } if (recv(sock, reply, sizeof(reply), 0) < 0) { mod->server_msg(mod, "Server reply failed", 0); return 1; } response = json_loads(reply, 0, &js_error); if (response == NULL) { mod->server_msg(mod, "Decoding response failed", 0); return 1; } else { json_t *nxsession = json_object_get(response, "session"); json_t *err = json_object_get(response, "err"); int resume = json_is_true(json_object_get(response, "resume")); if (err) { mod->server_msg(mod, json_string_value(err), 0); return 1; } else if (resume) { resize_nxproxy(mod); } else { char sessionstash[512]; const char *cookie = json_string_value(json_object_get(nxsession, "cookie")); const char *host = json_string_value(json_object_get(nxsession, "host")); json_int_t port = json_integer_value(json_object_get(nxsession, "port")); getpwnam_r(mod->username, &pwd, pwdbuffer, sizeof(pwdbuffer), &pwdresult); if (pwdresult == NULL) { mod->server_msg(mod, "Uid lookup failed", 0); return 1; } if (!start_nxproxy(mod, cookie, (int)port)) { mod->server_msg(mod, "nxproxy failed to start", 0); return 1; } json_decref(nxsession); } } json_decref(response); LIB_DEBUG(mod, "in lib_mod_connect"); /* clear screen */ mod->server_begin_update(mod); mod->server_set_fgcolor(mod, 0); mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); mod->server_end_update(mod); mod->server_msg(mod, "started connecting", 0); /* only support 8, 15, 16, and 24 bpp connections from rdp client */ if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24) { mod->server_msg(mod, "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } if (g_strcmp(mod->ip, "") == 0) { mod->server_msg(mod, "error - no ip set", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } make_stream(s); g_snprintf(con_port, 255, "%s", mod->port); use_uds = 0; if (con_port[0] == '/') { use_uds = 1; } mod->sck_closed = 0; i = 0; RECONNECT: while (1) { if (use_uds) { mod->sck = g_tcp_local_socket(); } else { mod->sck = g_tcp_socket(); g_tcp_set_non_blocking(mod->sck); g_tcp_set_no_delay(mod->sck); } /* mod->server_msg(mod, "connecting...", 0); */ if (use_uds) { error = g_tcp_local_connect(mod->sck, con_port); } else { error = g_tcp_connect(mod->sck, mod->ip, con_port); } if (error == -1) { if (g_tcp_last_error_would_block(mod->sck)) { error = 0; index = 0; while (!g_tcp_can_send(mod->sck, 100)) { index++; if ((index >= 30) || mod->server_is_term(mod)) { mod->server_msg(mod, "connect timeout", 0); error = 1; break; } } } else { /* mod->server_msg(mod, "connect error", 0); */ } } if (error == 0) { break; } g_tcp_close(mod->sck); mod->sck = 0; i++; if (i >= 20) { mod->server_msg(mod, "connection problem, giving up", 0); break; } g_sleep(500); } if (error == 0) { if (use_uds) { lib_mod_log_peer(mod); } } if (error == 0) { /* send version message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 301); out_uint32_le(s, 0); out_uint32_le(s, 0); out_uint32_le(s, 0); out_uint32_le(s, 1); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } if (error == 0) { /* send screen size message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 300); out_uint32_le(s, mod->width); out_uint32_le(s, mod->height); out_uint32_le(s, mod->bpp); out_uint32_le(s, 0); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } if (error == 0) { /* send invalidate message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 200); /* x and y */ i = 0; out_uint32_le(s, i); /* width and height */ i = ((mod->width & 0xffff) << 16) | mod->height; out_uint32_le(s, i); out_uint32_le(s, 0); out_uint32_le(s, 0); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); send_error = lib_send(mod, s->data, len); } if (send_error) { if (retry < 50) { g_tcp_close(mod->sck); mod->server_msg(mod, "Doing a retry", 0); retry++; g_sleep(1000); goto RECONNECT; } error = send_error; } free_stream(s); if (error != 0) { mod->server_msg(mod, "some problem", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } else { mod->server_msg(mod, "connected ok", 0); mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0); } LIB_DEBUG(mod, "out lib_mod_connect"); return 0; }
int handle_response(json_t* response) { int retval = 0; jsonrpc_request_t* req = NULL; json_t* return_obj = NULL; json_t* internal = NULL; char* freeme = NULL; /* check if json object */ if(!json_is_object(response)){ WARN("jsonrpc response is not an object\n"); return -1; } /* check version */ json_t* version = json_object_get(response, "jsonrpc"); if(!version) { WARN("jsonrpc response does not have a version.\n"); retval = -1; goto end; } const char* version_s = json_string_value(version); if(!version_s){ WARN("jsonrpc response version is not a string.\n"); retval = -1; goto end; } if (strlen(version_s) != (sizeof(JSONRPC_VERSION)-1) || strncmp(version_s, JSONRPC_VERSION, sizeof(JSONRPC_VERSION)-1) != 0) { WARN("jsonrpc response version is not %s. version: %s\n", JSONRPC_VERSION, version_s); retval = -1; goto end; } /* check for an id */ json_t* _id = json_object_get(response, "id"); if(!_id) { WARN("jsonrpc response does not have an id.\n"); retval = -1; goto end; } int id = json_integer_value(_id); if (!(req = pop_request(id))) { /* don't fail the server for an unrecognized id */ retval = 0; goto end; } return_obj = json_object(); json_t* error = json_object_get(response, "error"); // if the error value is null, we don't care bool _error = error && (json_typeof(error) != JSON_NULL); json_t* result = json_object_get(response, "result"); if(_error) { json_object_set(return_obj, "error", error); } if(result) { json_object_set(return_obj, "result", result); } if ((!result && !_error) || (result && _error)) { WARN("bad response\n"); internal = internal_error(JRPC_ERR_BAD_RESP, req->payload); json_object_update(return_obj, internal); if(internal) json_decref(internal); } pv_value_t val; if(jsontoval(&val, &freeme, return_obj)<0) { fail_request( JRPC_ERR_TO_VAL, req, "Failed to convert response json to pv\n"); retval = -1; goto end; } char* error_s = NULL; if(send_to_script(&val, req->cmd)>=0) { goto free_and_end; } if(_error) { // get code from error json_t* _code = json_object_get(error, "code"); if(_code) { int code = json_integer_value(_code); // check if code is in global_retry_ranges retry_range_t* tmpr; for(tmpr = global_retry_ranges; tmpr != NULL; tmpr = tmpr->next) { if((tmpr->start < tmpr->end && tmpr->start <= code && code <= tmpr->end) || (tmpr->end < tmpr->start && tmpr->end <= code && code <= tmpr->start) || (tmpr->start == tmpr->end && tmpr->start == code)) { if(schedule_retry(req)==0) { goto end; } break; } } } error_s = json_dumps(error, JSON_COMPACT); if(error_s) { WARN("Request received an error: \n%s\n", error_s); free(error_s); } else { fail_request( JRPC_ERR_BAD_RESP, req, "Could not convert 'error' response to string"); retval = -1; goto end; } } free_and_end: free_req_cmd(req->cmd); free_request(req); end: if(freeme) free(freeme); if(return_obj) json_decref(return_obj); return retval; }
static void run_tests() { json_t *value; int i; char buffer[4] = {'t', 'e', 's', 't'}; json_error_t error; /* * Simple, valid json_pack cases */ /* true */ value = json_pack("b", 1); if(!json_is_true(value)) fail("json_pack boolean failed"); if(value->refcount != (size_t)-1) fail("json_pack boolean refcount failed"); json_decref(value); /* false */ value = json_pack("b", 0); if(!json_is_false(value)) fail("json_pack boolean failed"); if(value->refcount != (size_t)-1) fail("json_pack boolean refcount failed"); json_decref(value); /* null */ value = json_pack("n"); if(!json_is_null(value)) fail("json_pack null failed"); if(value->refcount != (size_t)-1) fail("json_pack null refcount failed"); json_decref(value); /* integer */ value = json_pack("i", 1); if(!json_is_integer(value) || json_integer_value(value) != 1) fail("json_pack integer failed"); if(value->refcount != (size_t)1) fail("json_pack integer refcount failed"); json_decref(value); /* integer from json_int_t */ value = json_pack("I", (json_int_t)555555); if(!json_is_integer(value) || json_integer_value(value) != 555555) fail("json_pack json_int_t failed"); if(value->refcount != (size_t)1) fail("json_pack integer refcount failed"); json_decref(value); /* real */ value = json_pack("f", 1.0); if(!json_is_real(value) || json_real_value(value) != 1.0) fail("json_pack real failed"); if(value->refcount != (size_t)1) fail("json_pack real refcount failed"); json_decref(value); /* string */ value = json_pack("s", "test"); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string failed"); if(value->refcount != (size_t)1) fail("json_pack string refcount failed"); json_decref(value); /* nullable string (defined case) */ value = json_pack("s?", "test"); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack nullable string (defined case) failed"); if(value->refcount != (size_t)1) fail("json_pack nullable string (defined case) refcount failed"); json_decref(value); /* nullable string (NULL case) */ value = json_pack("s?", NULL); if(!json_is_null(value)) fail("json_pack nullable string (NULL case) failed"); if(value->refcount != (size_t)-1) fail("json_pack nullable string (NULL case) refcount failed"); json_decref(value); /* string and length (int) */ value = json_pack("s#", "test asdf", 4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length failed"); if(value->refcount != (size_t)1) fail("json_pack string and length refcount failed"); json_decref(value); /* string and length (size_t) */ value = json_pack("s%", "test asdf", (size_t)4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length failed"); if(value->refcount != (size_t)1) fail("json_pack string and length refcount failed"); json_decref(value); /* string and length (int), non-NUL terminated string */ value = json_pack("s#", buffer, 4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length (int) failed"); if(value->refcount != (size_t)1) fail("json_pack string and length (int) refcount failed"); json_decref(value); /* string and length (size_t), non-NUL terminated string */ value = json_pack("s%", buffer, (size_t)4); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string and length (size_t) failed"); if(value->refcount != (size_t)1) fail("json_pack string and length (size_t) refcount failed"); json_decref(value); /* string concatenation */ value = json_pack("s++", "te", "st", "ing"); if(!json_is_string(value) || strcmp("testing", json_string_value(value))) fail("json_pack string concatenation failed"); if(value->refcount != (size_t)1) fail("json_pack string concatenation refcount failed"); json_decref(value); /* string concatenation and length (int) */ value = json_pack("s#+#+", "test", 1, "test", 2, "test"); if(!json_is_string(value) || strcmp("ttetest", json_string_value(value))) fail("json_pack string concatenation and length (int) failed"); if(value->refcount != (size_t)1) fail("json_pack string concatenation and length (int) refcount failed"); json_decref(value); /* string concatenation and length (size_t) */ value = json_pack("s%+%+", "test", (size_t)1, "test", (size_t)2, "test"); if(!json_is_string(value) || strcmp("ttetest", json_string_value(value))) fail("json_pack string concatenation and length (size_t) failed"); if(value->refcount != (size_t)1) fail("json_pack string concatenation and length (size_t) refcount failed"); json_decref(value); /* empty object */ value = json_pack("{}", 1.0); if(!json_is_object(value) || json_object_size(value) != 0) fail("json_pack empty object failed"); if(value->refcount != (size_t)1) fail("json_pack empty object refcount failed"); json_decref(value); /* empty list */ value = json_pack("[]", 1.0); if(!json_is_array(value) || json_array_size(value) != 0) fail("json_pack empty list failed"); if(value->refcount != (size_t)1) fail("json_pack empty list failed"); json_decref(value); /* non-incref'd object */ value = json_pack("o", json_integer(1)); if(!json_is_integer(value) || json_integer_value(value) != 1) fail("json_pack object failed"); if(value->refcount != (size_t)1) fail("json_pack integer refcount failed"); json_decref(value); /* non-incref'd nullable object (defined case) */ value = json_pack("o?", json_integer(1)); if(!json_is_integer(value) || json_integer_value(value) != 1) fail("json_pack nullable object (defined case) failed"); if(value->refcount != (size_t)1) fail("json_pack nullable object (defined case) refcount failed"); json_decref(value); /* non-incref'd nullable object (NULL case) */ value = json_pack("o?", NULL); if(!json_is_null(value)) fail("json_pack nullable object (NULL case) failed"); if(value->refcount != (size_t)-1) fail("json_pack nullable object (NULL case) refcount failed"); json_decref(value); /* incref'd object */ value = json_pack("O", json_integer(1)); if(!json_is_integer(value) || json_integer_value(value) != 1) fail("json_pack object failed"); if(value->refcount != (size_t)2) fail("json_pack integer refcount failed"); json_decref(value); json_decref(value); /* incref'd nullable object (defined case) */ value = json_pack("O?", json_integer(1)); if(!json_is_integer(value) || json_integer_value(value) != 1) fail("json_pack incref'd nullable object (defined case) failed"); if(value->refcount != (size_t)2) fail("json_pack incref'd nullable object (defined case) refcount failed"); json_decref(value); json_decref(value); /* incref'd nullable object (NULL case) */ value = json_pack("O?", NULL); if(!json_is_null(value)) fail("json_pack incref'd nullable object (NULL case) failed"); if(value->refcount != (size_t)-1) fail("json_pack incref'd nullable object (NULL case) refcount failed"); /* simple object */ value = json_pack("{s:[]}", "foo"); if(!json_is_object(value) || json_object_size(value) != 1) fail("json_pack array failed"); if(!json_is_array(json_object_get(value, "foo"))) fail("json_pack array failed"); if(json_object_get(value, "foo")->refcount != (size_t)1) fail("json_pack object refcount failed"); json_decref(value); /* object with complex key */ value = json_pack("{s+#+: []}", "foo", "barbar", 3, "baz"); if(!json_is_object(value) || json_object_size(value) != 1) fail("json_pack array failed"); if(!json_is_array(json_object_get(value, "foobarbaz"))) fail("json_pack array failed"); if(json_object_get(value, "foobarbaz")->refcount != (size_t)1) fail("json_pack object refcount failed"); json_decref(value); /* simple array */ value = json_pack("[i,i,i]", 0, 1, 2); if(!json_is_array(value) || json_array_size(value) != 3) fail("json_pack object failed"); for(i=0; i<3; i++) { if(!json_is_integer(json_array_get(value, i)) || json_integer_value(json_array_get(value, i)) != i) fail("json_pack integer array failed"); } json_decref(value); /* Whitespace; regular string */ value = json_pack(" s ", "test"); if(!json_is_string(value) || strcmp("test", json_string_value(value))) fail("json_pack string (with whitespace) failed"); json_decref(value); /* Whitespace; empty array */ value = json_pack("[ ]"); if(!json_is_array(value) || json_array_size(value) != 0) fail("json_pack empty array (with whitespace) failed"); json_decref(value); /* Whitespace; array */ value = json_pack("[ i , i, i ] ", 1, 2, 3); if(!json_is_array(value) || json_array_size(value) != 3) fail("json_pack array (with whitespace) failed"); json_decref(value); /* * Invalid cases */ /* newline in format string */ if(json_pack_ex(&error, 0, "{\n\n1")) fail("json_pack failed to catch invalid format '1'"); check_error("Expected format 's', got '1'", "<format>", 3, 1, 4); /* mismatched open/close array/object */ if(json_pack_ex(&error, 0, "[}")) fail("json_pack failed to catch mismatched '}'"); check_error("Unexpected format character '}'", "<format>", 1, 2, 2); if(json_pack_ex(&error, 0, "{]")) fail("json_pack failed to catch mismatched ']'"); check_error("Expected format 's', got ']'", "<format>", 1, 2, 2); /* missing close array */ if(json_pack_ex(&error, 0, "[")) fail("json_pack failed to catch missing ']'"); check_error("Unexpected end of format string", "<format>", 1, 2, 2); /* missing close object */ if(json_pack_ex(&error, 0, "{")) fail("json_pack failed to catch missing '}'"); check_error("Unexpected end of format string", "<format>", 1, 2, 2); /* garbage after format string */ if(json_pack_ex(&error, 0, "[i]a", 42)) fail("json_pack failed to catch garbage after format string"); check_error("Garbage after format string", "<format>", 1, 4, 4); if(json_pack_ex(&error, 0, "ia", 42)) fail("json_pack failed to catch garbage after format string"); check_error("Garbage after format string", "<format>", 1, 2, 2); /* NULL string */ if(json_pack_ex(&error, 0, "s", NULL)) fail("json_pack failed to catch null argument string"); check_error("NULL string argument", "<args>", 1, 1, 1); /* + on its own */ if(json_pack_ex(&error, 0, "+", NULL)) fail("json_pack failed to a lone +"); check_error("Unexpected format character '+'", "<format>", 1, 1, 1); /* NULL format */ if(json_pack_ex(&error, 0, NULL)) fail("json_pack failed to catch NULL format string"); check_error("NULL or empty format string", "<format>", -1, -1, 0); /* NULL key */ if(json_pack_ex(&error, 0, "{s:i}", NULL, 1)) fail("json_pack failed to catch NULL key"); check_error("NULL string argument", "<args>", 1, 2, 2); /* More complicated checks for row/columns */ if(json_pack_ex(&error, 0, "{ {}: s }", "foo")) fail("json_pack failed to catch object as key"); check_error("Expected format 's', got '{'", "<format>", 1, 3, 3); /* Complex object */ if(json_pack_ex(&error, 0, "{ s: {}, s:[ii{} }", "foo", "bar", 12, 13)) fail("json_pack failed to catch missing ]"); check_error("Unexpected format character '}'", "<format>", 1, 19, 19); /* Complex array */ if(json_pack_ex(&error, 0, "[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]")) fail("json_pack failed to catch extra }"); check_error("Unexpected format character '}'", "<format>", 1, 21, 21); /* Invalid UTF-8 in object key */ if(json_pack_ex(&error, 0, "{s:i}", "\xff\xff", 42)) fail("json_pack failed to catch invalid UTF-8 in an object key"); check_error("Invalid UTF-8 object key", "<args>", 1, 2, 2); /* Invalid UTF-8 in a string */ if(json_pack_ex(&error, 0, "{s:s}", "foo", "\xff\xff")) fail("json_pack failed to catch invalid UTF-8 in a string"); check_error("Invalid UTF-8 string", "<args>", 1, 4, 4); }
void graph_response_retrieveResponse(req_t * req, json_t * response, int32_t requestId, void *sweb, req_store_t * req_store) { json_t *nodeArray = json_object_get(req->response, "nodeArray"); json_t *nodeDataArray = json_object_get(response, "nodeArray"); //TODO handle this case /* assert(json_array_size(nodeArray) == json_array_size(nodeDataArray)); */ //add the content data to the location data int i; for (i = 0; i < json_array_size(nodeArray); i++) { json_t *node = json_array_get(nodeArray, i); int64_t id = json_integer_value(json_object_get(node, "id")); int j; for (j = 0; j < json_array_size(nodeDataArray); j++) { json_t *dataNode = json_array_get(nodeDataArray, j); if (id == json_integer_value(json_object_get (dataNode, "id"))) { json_object_set(node, "node", dataNode); break; } } //TODO Put an assert here so that we are sure that all nodes have content } json_t *web_resp = json_object(); json_object_set(web_resp, "sessionId", json_object_get(req->request, "sessionId")); json_object_set_new(web_resp, "type", json_string("response")); json_t *clientResponse = json_object(); json_object_set(clientResponse, "clientRequestId", json_object_get(json_object_get (req->request, "clientRequest"), "clientRequestId")); json_t *cl_response = json_object(); json_object_set_new(cl_response, "type", json_string("searchResponse")); json_object_set(cl_response, "nodeArray", nodeArray); json_object_set_new(clientResponse, "response", cl_response); json_object_set_new(web_resp, "clientResponse", clientResponse); zmsg_t *res = zmsg_new(); char *web_res_str = json_dumps(web_resp, JSON_COMPACT); printf("\nbroker:sweb sent: %s\n", web_res_str); zmsg_addstr(res, web_res_str); free(web_res_str); zmsg_wrap(res, req->address); zmsg_send(&res, sweb); request_store_delete(req_store, requestId); json_decref(web_resp); }
void get_data(const char *recording, double start, double duration) /*===============================================================*/ { int CHUNKSIZE = 10000 ; double *data = NULL ; int channels = 0 ; json_t *siguris = NULL ; const char *DATAFORMAT = STREAM_DOUBLE ; // Setup stream, set options (e.g. block size), add signals, etc, // then bsml_stream_start(strm) bsml_streamdata *strm = bsml_streamdata_request(recording, start, duration, DATAFORMAT, CHUNKSIZE) ; bsml_streamblock *sb ; int frameno = 0 ; while ((sb = bsml_streamdata_read(strm)) != NULL) { #ifdef LOG_HEADER fprintf(stderr, "%s Block %c: %d\n ", run_id, sb->type, sb->length) ; json_dumpf(sb->header, stderr, JSON_ENSURE_ASCII) ; fprintf(stderr, "\n") ; #endif if (sb->type == BSML_STREAM_ERROR_BLOCK) { fprintf(stderr, "ERROR: %-*s\n", sb->length, sb->content) ; } else if (sb->type == BSML_STREAM_INFO_BLOCK) { if (siguris) json_decref(siguris) ; siguris = json_object_get(sb->header, "signals") ; // Also have "channels" field (plus "rates" and "units"). if (siguris && json_is_array(siguris)) { size_t n = json_array_size(siguris) ; json_incref(siguris) ; if (channels != n) { channels = n ; if (data) free(data) ; data = calloc(sizeof(double), channels*CHUNKSIZE) ; } } } else if (sb->type == BSML_STREAM_RDF_BLOCK) { } else if (sb->type == BSML_STREAM_DATA_BLOCK) { // Need to check rates match... // Or have rates in Info block and check when it's received... // What about signals where the rate changes?? json_t *info = json_object_get(sb->header, "info") ; if (info && json_is_integer(info)) { int chan = json_integer_value(info) ; double *dp = data + chan ; double *cp = (double *)sb->content ; int l = sb->length/sizeof(double) ; while (l > 0) { *dp = *cp ; dp += channels ; ++cp ; --l ; } if (chan == (channels-1)) { double *dp = data ; int i ; l = sb->length/sizeof(double) ; while (l > 0) { printf("%d ", frameno) ; for (i = 0 ; i < channels ; ++i) { if (i > 0) printf(" ") ; printf("%8g", *dp) ; ++dp ; } printf("\n") ; ++frameno ; --l ; } } } // get dtype from sb->header // JSON *header ; // dtype *buffer = calloc(sb->length, sizeof(dtype)) ; // memcpy(buffer, (double *)sb->content, sb->length*sizeof(dtype)) ; } bsml_streamblock_free(sb) ; } if (strm->error != BSML_STREAM_ERROR_NONE) // Always check for errors... fprintf(stderr, "ERROR %d: %s\n", strm->error, bsml_stream_error_text(strm->error)) ; bsml_streamdata_free(strm) ; if (data) free(data) ; if (siguris) json_decref(siguris) ; }
static void LedActorOnRequestTurnOn(PVOID pParam) { char* message = (char*)pParam; char **znpSplitMessage; if (pLedActor == NULL) return; json_t* payloadJson = NULL; json_t* paramsJson = NULL; json_t* redJson = NULL; json_t* greenJson = NULL; json_t* blueJson = NULL; json_t* responseJson = NULL; json_t* statusJson = NULL; BYTE red, green, blue; PACTORHEADER header; char* responseTopic; char* responseMessage; char* colorMessage; znpSplitMessage = ActorSplitMessage(message); if (znpSplitMessage == NULL) return; // parse header to get origin of message header = ActorParseHeader(znpSplitMessage[0]); if (header == NULL) { ActorFreeSplitMessage(znpSplitMessage); return; } //parse payload payloadJson = json_loads(znpSplitMessage[1], JSON_DECODE_ANY, NULL); if (payloadJson == NULL) { ActorFreeSplitMessage(znpSplitMessage); ActorFreeHeaderStruct(header); return; } paramsJson = json_object_get(payloadJson, "params"); if (paramsJson == NULL) { json_decref(payloadJson); ActorFreeSplitMessage(znpSplitMessage); ActorFreeHeaderStruct(header); return; } redJson = json_object_get(paramsJson, "red"); if (redJson == NULL) red = 255; else red = json_integer_value(redJson); greenJson = json_object_get(paramsJson, "green"); if (greenJson == NULL) green = 255; else green = json_integer_value(greenJson); blueJson = json_object_get(paramsJson, "blue"); if (blueJson == NULL) blue = 255; else blue = json_integer_value(blueJson); int result = LedTurnOn(red, green, blue); //make response package responseJson = json_object(); statusJson = json_object(); json_t* requestJson = json_loads(znpSplitMessage[1], JSON_DECODE_ANY, NULL); json_object_set(responseJson, "request", requestJson); json_decref(requestJson); json_t* resultJson; colorMessage = calloc(20, sizeof(BYTE)); sprintf(colorMessage, "0x%02X%02X%02X", red, green, blue); if (result == 0) { LedActorPublishStateChange(colorMessage, LED_ON, 0); resultJson = json_string("status.success"); } else { LedActorPublishStateChange(colorMessage, LED_OFF, 0); resultJson = json_string("status.failure"); } if (redJson) json_decref(redJson); if (greenJson) json_decref(greenJson); if (blueJson) json_decref(blueJson); json_decref(paramsJson); json_decref(payloadJson); json_object_set(statusJson, "status", resultJson); json_decref(resultJson); json_object_set(responseJson, "response", statusJson); json_decref(statusJson); responseMessage = json_dumps(responseJson, JSON_INDENT(4) | JSON_REAL_PRECISION(4)); //responseTopic = ActorMakeTopicName(header->origin, "/:response"); responseTopic = StrDup(header->origin); ActorFreeHeaderStruct(header); json_decref(responseJson); ActorFreeSplitMessage(znpSplitMessage); ActorSend(pLedActor, responseTopic, responseMessage, NULL, FALSE, "response"); free(colorMessage); free(responseMessage); free(responseTopic); }
static char * add_task_common (SeafCloneManager *mgr, const char *repo_id, int repo_version, const char *peer_id, const char *repo_name, const char *token, const char *passwd, int enc_version, const char *random_key, const char *worktree, const char *peer_addr, const char *peer_port, const char *email, const char *more_info, gboolean sync_wt_name, GError **error) { CloneTask *task; task = clone_task_new (repo_id, peer_id, repo_name, token, worktree, passwd, peer_addr, peer_port, email); task->manager = mgr; task->enc_version = enc_version; task->random_key = g_strdup (random_key); task->repo_version = repo_version; task->sync_wt_name = sync_wt_name; if (more_info) { json_error_t jerror; json_t *object = NULL; object = json_loads (more_info, 0, &jerror); if (!object) { seaf_warning ("Failed to load more sync info from json: %s.\n", jerror.text); clone_task_free (task); return NULL; } json_t *integer = json_object_get (object, "is_readonly"); task->is_readonly = json_integer_value (integer); json_t *string = json_object_get (object, "server_url"); if (string) task->server_url = canonical_server_url (json_string_value (string)); json_decref (object); } if (save_task_to_db (mgr, task) < 0) { seaf_warning ("[Clone mgr] failed to save task.\n"); clone_task_free (task); return NULL; } if (task->repo_version > 0) { if (task->server_url) { check_http_protocol (task); } else { clone_task_free (task); return NULL; } } /* The old task for this repo will be freed. */ g_hash_table_insert (mgr->tasks, g_strdup(task->repo_id), task); return g_strdup(repo_id); }
static size_t http_write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) { json_t *response, *value, *in; json_error_t error; const char *etcd_value; const char *errmsg; struct etcd_data *data; int val; data = userdata; response = json_loads(ptr, 0, &error); if (!json_is_object(response)) { strcpy(data->errmsg, "'response' returned is not a json object"); goto error; } in = json_object_get(response, "index"); if (json_is_integer(in)) { data->index = json_integer_value(in); } value = json_object_get(response, "value"); if (!json_is_string(value)) { value = json_object_get(response, "action"); etcd_value = ""; if (json_is_string(value)) { etcd_value = json_string_value(value); } if (strcmp(etcd_value, DELETE_KEY) == 0) { value = json_object_get(response, "key"); etcd_value = json_string_value(value); strcpy(data->value, ++etcd_value); data->response = ETCD_SUCCESS; json_decref(response); return size * nmemb; } else { value = json_object_get(response, "errorCode"); if (!json_is_integer(value)) { strcpy(data->errmsg, "Invalid error message."); goto error; } val = json_integer_value(value); value = json_object_get(response, "message"); if (!json_is_string(value)) { strcpy(data->errmsg, "Invalid error message."); goto error; } errmsg = json_string_value(value); sprintf(data->errmsg, "%d:%s", val, errmsg); goto error; } } etcd_value = json_string_value(value); memcpy(data->value, etcd_value, strlen(etcd_value) + 1); data->response = ETCD_SUCCESS; json_decref(response); return size * nmemb; error: json_decref(response); data->value = NULL; data->response = ETCD_FAILURE; return size * nmemb; }
int urn_game_create(urn_game **game_ptr, const char *path) { int error = 0; urn_game *game; int i; json_t *json = 0; json_t *ref; json_error_t json_error; // allocate game game = calloc(1, sizeof(urn_game)); if (!game) { error = 1; goto game_create_done; } // copy path to file game->path = strdup(path); if (!game->path) { error = 1; goto game_create_done; } // load json json = json_load_file(game->path, 0, &json_error); if (!json) { error = 1; goto game_create_done; } // copy title ref = json_object_get(json, "title"); if (ref) { game->title = strdup(json_string_value(ref)); if (!game->title) { error = 1; goto game_create_done; } } // copy theme ref = json_object_get(json, "theme"); if (ref) { game->theme = strdup(json_string_value(ref)); if (!game->theme) { error = 1; goto game_create_done; } } // copy theme variant ref = json_object_get(json, "theme_variant"); if (ref) { game->theme_variant = strdup(json_string_value(ref)); if (!game->theme_variant) { error = 1; goto game_create_done; } } // get attempt count ref = json_object_get(json, "attempt_count"); if (ref) { game->attempt_count = json_integer_value(ref); } // get width ref = json_object_get(json, "width"); if (ref) { game->width = json_integer_value(ref); } // get height ref = json_object_get(json, "height"); if (ref) { game->height = json_integer_value(ref); } // get delay ref = json_object_get(json, "start_delay"); if (ref) { game->start_delay = urn_time_value( json_string_value(ref)); } // get wr ref = json_object_get(json, "world_record"); if (ref) { game->world_record = urn_time_value( json_string_value(ref)); } // get splits ref = json_object_get(json, "splits"); if (ref) { game->split_count = json_array_size(ref); // allocate titles game->split_titles = calloc(game->split_count, sizeof(char *)); if (!game->split_titles) { error = 1; goto game_create_done; } // allocate splits game->split_times = calloc(game->split_count, sizeof(long long)); if (!game->split_times) { error = 1; goto game_create_done; } game->segment_times = calloc(game->split_count, sizeof(long long)); if (!game->segment_times) { error = 1; goto game_create_done; } game->best_splits = calloc(game->split_count, sizeof(long long)); if (!game->best_splits) { error = 1; goto game_create_done; } game->best_segments = calloc(game->split_count, sizeof(long long)); if (!game->best_segments) { error = 1; goto game_create_done; } // copy splits for (i = 0; i < game->split_count; ++i) { json_t *split; json_t *split_ref; split = json_array_get(ref, i); split_ref = json_object_get(split, "title"); if (split_ref) { game->split_titles[i] = strdup( json_string_value(split_ref)); if (!game->split_titles[i]) { error = 1; goto game_create_done; } } split_ref = json_object_get(split, "time"); if (split_ref) { game->split_times[i] = urn_time_value( json_string_value(split_ref)); } if (i && game->split_times[i] && game->split_times[i-1]) { game->segment_times[i] = game->split_times[i] - game->split_times[i-1]; } else if (!i && game->split_times[0]) { game->segment_times[0] = game->split_times[0]; } split_ref = json_object_get(split, "best_time"); if (split_ref) { game->best_splits[i] = urn_time_value( json_string_value(split_ref)); } else if (game->split_times[i]) { game->best_splits[i] = game->split_times[i]; } split_ref = json_object_get(split, "best_segment"); if (split_ref) { game->best_segments[i] = urn_time_value( json_string_value(split_ref)); } else if (game->segment_times[i]) { game->best_segments[i] = game->segment_times[i]; } } } game_create_done: if (!error) { *game_ptr = game; } else if (game) { urn_game_release(game); } if (json) { json_decref(json); } return error; }
/* * resolve and validate an access_token against the configured Authorization Server */ static apr_byte_t oidc_oauth_resolve_access_token(request_rec *r, oidc_cfg *c, const char *access_token, json_t **token, char **response) { json_t *result = NULL; const char *json = NULL; /* see if we've got the claims for this access_token cached already */ c->cache->get(r, OIDC_CACHE_SECTION_ACCESS_TOKEN, access_token, &json); if (json == NULL) { /* not cached, go out and validate the access_token against the Authorization server and get the JSON claims back */ if (oidc_oauth_validate_access_token(r, c, access_token, &json) == FALSE) { oidc_error(r, "could not get a validation response from the Authorization server"); return FALSE; } /* decode and see if it is not an error response somehow */ if (oidc_util_decode_json_and_check_error(r, json, &result) == FALSE) return FALSE; json_t *active = json_object_get(result, "active"); if (active != NULL) { if ((!json_is_boolean(active)) || (!json_is_true(active))) { oidc_debug(r, "no \"active\" boolean object with value \"true\" found in response JSON object"); json_decref(result); return FALSE; } json_t *exp = json_object_get(result, "exp"); if ((exp != NULL) && (json_is_number(exp))) { /* set it in the cache so subsequent request don't need to validate the access_token and get the claims anymore */ c->cache->set(r, OIDC_CACHE_SECTION_ACCESS_TOKEN, access_token, json, apr_time_from_sec(json_integer_value(exp))); } else if (json_integer_value(exp) <= 0) { oidc_debug(r, "response JSON object did not contain an \"exp\" integer number; introspection result will not be cached"); } } else { /* assume PingFederate validation: get and check the expiry timestamp */ json_t *expires_in = json_object_get(result, "expires_in"); if ((expires_in == NULL) || (!json_is_number(expires_in))) { oidc_error(r, "response JSON object did not contain an \"expires_in\" number"); json_decref(result); return FALSE; } if (json_integer_value(expires_in) <= 0) { oidc_warn(r, "\"expires_in\" number <= 0 (%" JSON_INTEGER_FORMAT "); token already expired...", json_integer_value(expires_in)); json_decref(result); return FALSE; } /* set it in the cache so subsequent request don't need to validate the access_token and get the claims anymore */ c->cache->set(r, OIDC_CACHE_SECTION_ACCESS_TOKEN, access_token, json, apr_time_now() + apr_time_from_sec(json_integer_value(expires_in))); } } else { /* we got the claims for this access_token in our cache, decode it in to a JSON structure */ json_error_t json_error; result = json_loads(json, 0, &json_error); if (result == NULL) { oidc_error(r, "cached JSON was corrupted: %s", json_error.text); return FALSE; } } /* return the access_token JSON object */ json_t *tkn = json_object_get(result, "access_token"); if ((tkn != NULL) && (json_is_object(tkn))) { /* * assume PingFederate validation: copy over those claims from the access_token * that are relevant for authorization purposes */ json_object_set(tkn, "client_id", json_object_get(result, "client_id")); json_object_set(tkn, "scope", json_object_get(result, "scope")); //oidc_oauth_spaced_string_to_array(r, result, "scope", tkn, "scopes"); /* return only the pimped access_token results */ *token = json_deep_copy(tkn); char *s_token = json_dumps(*token, 0); *response = apr_pstrdup(r->pool, s_token); free(s_token); json_decref(result); } else { //oidc_oauth_spaced_string_to_array(r, result, "scope", result, "scopes"); /* assume spec compliant introspection */ *token = result; *response = apr_pstrdup(r->pool, json); } return TRUE; }
void graph_response(void *sgraph, req_store_t * req_store, void *sweb, void *spss) { zmsg_t *msg = zmsg_recv(sgraph); zframe_t *null = zmsg_unwrap(msg); zframe_destroy(&null); json_error_t error; printf("\nbroker:sgraph received: %s\n", (const char *)zframe_data(zmsg_first(msg))); const char *data; size_t data_size = zframe_size(zmsg_first(msg)); data = zframe_data(zmsg_first(msg)); json_t *graph_resp_json = json_loadb(data, data_size, 0, &error); zmsg_destroy(&msg); //identify the request int32_t requestId = json_integer_value(json_object_get(graph_resp_json, "requestId")); req_t *req = request_store_req(req_store, requestId); json_t *response = json_object_get(graph_resp_json, "response"); const char *resp_type = json_string_value(json_object_get(response, "type")); json_t *request = json_object_get(json_object_get(req->request, "clientRequest"), "request"); const char *req_type = json_string_value(json_object_get(request, "type")); if ((strcmp(resp_type, "retrieveResponse") == 0) && (strcmp(req_type, "searchRequest") == 0)) graph_response_retrieveResponse(req, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "newNodeResponse") == 0) && (strcmp(req_type, "newNode") == 0)) graph_response_newNodeResponse(request, response, requestId, spss, req_store); else if ((strcmp(resp_type, "newLinkResponse") == 0) && (strcmp(req_type, "newLink") == 0)) graph_response_newLinkResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "delLinkResponse") == 0) && (strcmp(req_type, "delLink") == 0)) graph_response_delLinkResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "delNode") == 0) && (strcmp(req_type, "delNode") == 0)) graph_response_delNodeResponse(req, request, response, requestId, spss, req_store); else if ((strcmp(resp_type, "newNodeData") == 0) && (strcmp(req_type, "newNodeData") == 0)) graph_response_newNodeDataResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "newLinkData") == 0) && (strcmp(req_type, "newLinkData") == 0)) graph_response_newLinkDataResponse(req, request, response, requestId, sweb, req_store); json_decref(graph_resp_json); }
status_t windows_system_map_lookup( const char *rekall_profile, const char *symbol, const char *subsymbol, addr_t *address, addr_t *size) { status_t ret = VMI_FAILURE; json_error_t error; json_t *root = json_load_file(rekall_profile, 0, &error); if (!root) { PRINT_DEBUG("Rekall profile error on line %d: %s\n", error.line, error.text); goto exit; } if (!json_is_object(root)) { PRINT_DEBUG("Rekall profile: root is not an objet\n"); goto err_exit; } if (!subsymbol && !size) { json_t *constants = json_object_get(root, "$CONSTANTS"); json_t *jsymbol = json_object_get(constants, symbol); if (!jsymbol) { PRINT_DEBUG("Rekall profile: constant '%s' not found\n", symbol); goto err_exit; } *address = json_integer_value(jsymbol); ret = VMI_SUCCESS; } else { json_t *structs = json_object_get(root, "$STRUCTS"); json_t *jstruct = json_object_get(structs, symbol); if (!jstruct) { PRINT_DEBUG("Rekall profile: structure '%s' not found\n", symbol); goto err_exit; } if (size) { json_t *jsize = json_array_get(jstruct, 0); *size = json_integer_value(jsize); } if (address) { json_t *jstruct2 = json_array_get(jstruct, 1); json_t *jmember = json_object_get(jstruct2, subsymbol); if (!jmember) { PRINT_DEBUG("Rekall profile: structure member '%s' not found\n", subsymbol); goto err_exit; } json_t *jvalue = json_array_get(jmember, 0); *address = json_integer_value(jvalue); } ret = VMI_SUCCESS; } err_exit: json_decref(root); exit: return ret; }
bool TwitPic::parseJSON(const string& json, TwitPicResult& result) { printf("result:\n%s\n", json.c_str()); json_t* root; json_error_t error; root = json_loads(json.c_str(), 0, &error); if(!root) { printf("Error: on line: %d, %s\n", error.line, error.text); json_decref(root); return false; } // id json_t* node = json_object_get(root, "id"); if(node == NULL) { printf("Error: cannot parse twitpic result, no id found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.id_str = json_string_value(node); } // text node = json_object_get(root, "text"); if(node == NULL) { printf("Error: cannot parse twitpic result, no text found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.text = json_string_value(node); } // url node = json_object_get(root, "url"); if(node == NULL) { printf("Error: cannot parse twitpic result, no url found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.url = json_string_value(node); } // width node = json_object_get(root, "width"); if(node == NULL) { printf("Error: cannot parse twitpic result, no width found.\n"); json_decref(root); return false; } if(json_is_integer(node)) { result.width = json_integer_value(node); } // height node = json_object_get(root, "height"); if(node == NULL) { printf("Error: cannot parse twitpic result, no height found.\n"); json_decref(root); return false; } if(json_is_integer(node)) { result.height = json_integer_value(node); } // size node = json_object_get(root, "size"); if(node == NULL) { printf("Error: cannot parse twitpic result, no size found.\n"); json_decref(root); return false; } if(json_is_integer(node)) { result.size = json_integer_value(node); } // type node = json_object_get(root, "type"); if(node == NULL) { printf("Error: cannot parse twitpic result, no type found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.type = json_string_value(node); } // timestamp node = json_object_get(root, "timestamp"); if(node == NULL) { printf("Error: cannot parse twitpic result, no timestamp found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.timestamp = json_string_value(node); } // user // -------------- json_t* subnode = json_object_get(root, "user"); if(node == NULL) { printf("Error: cannot parse twitpic result, no user found.\n"); json_decref(root); return false; } if(json_is_object(subnode)) { // user_id node = json_object_get(subnode, "id"); if(node == NULL) { printf("Error: cannot parse twitpic result, no user id found.\n"); json_decref(root); return false; } if(json_is_integer(node)) { result.user_id = json_integer_value(node); } // user_screen_name node = json_object_get(subnode, "screen_name"); if(node == NULL) { printf("Error: cannot parse twitpic result, no user screen_name found.\n"); json_decref(root); return false; } if(json_is_string(node)) { result.user_screen_name = json_string_value(node); } } result.print(); return true; }
static void send_json(char* str, size_t len) { json_t* root, *cmd, *data, *data_len, *ip, *port; json_error_t error; root = json_loads(str, 0, &error); if(!root || !json_is_object(root)) { fprintf(stderr, "JSON: Error on line %d: %s\n", error.line, error.text); return; } cmd = json_object_get(root, "cmd"); if(!json_is_integer(cmd)) { fprintf(stderr, "JSON: cmd is not an integer\n"); json_decref(root); return; } data = json_object_get(root, "data"); if(!json_is_null(data) && !json_is_string(data)) { fprintf(stderr, "JSON: data is not a string\n"); json_decref(root); return; } data_len = json_object_get(root, "data_len"); if(!json_is_integer(cmd)) { fprintf(stderr, "JSON: data_len is not an integer\n"); json_decref(root); return; } ip = json_object_get(root, "ip"); if(!ip || !json_is_string(ip)) { json_decref(ip); ip=NULL; } port = json_object_get(root, "port"); if(!port || !json_is_integer(port)) { json_decref(port); port=NULL; } int t_int = json_integer_value(cmd); if(t_int == -1) { welcome_message_sent=0; json_decref(root); return; } EventType t=(EventType)t_int; int datalen=json_integer_value(data_len); printf("Got: %s\n", str); if(ip && port) { event_send_simple_to_addr(t, datalen ? json_string_value(data) : NULL, datalen, json_string_value(ip), json_integer_value(port), corefd); } else { event_send_simple(t, datalen ? json_string_value(data) : NULL, datalen, corefd); } json_decref(root); // TODO: Does other json_t* variables need to be decref'd? return; }
int VtUrlDist_parse(struct VtUrlDist* url_dist, void (*cb)(const char *url, unsigned long long timestamp, int total, int positives, json_t *raw_json, void *data), void *user_data) { json_t *resp_json, *url_obj; json_t *url_str_json, *timestamp_json, *total_json, *positives_json; unsigned int index; if (!url_dist || !url_dist->response) { VT_ERROR("No data recieved\n"); return -1; } resp_json = VtResponse_getJanssonObj(url_dist->response); if (!json_is_array(resp_json)) { VT_ERROR("JSON is not array\n"); return -1; } json_array_foreach(resp_json, index, url_obj) { if (!json_is_object(url_obj)) { VT_ERROR("Parse error not a URL object\n"); return -1; } url_str_json = json_object_get(url_obj, "url"); if (!url_str_json || !json_is_string(url_str_json)) { VT_ERROR("Parse error: url string\n"); return -1; } timestamp_json = json_object_get(url_obj, "timestamp"); if (!timestamp_json || !json_is_integer(timestamp_json)) { VT_ERROR("JSON parse error timestamp\n"); return -1; } total_json = json_object_get(url_obj, "total"); if (!total_json || !json_is_integer(total_json)) { VT_ERROR("JSON parse error total\n"); return -1; } positives_json = json_object_get(url_obj, "positives"); if (!positives_json || !json_is_integer(positives_json)) { VT_ERROR("JSON parse error positives\n"); return -1; } // set the after value, so if we do another query, we will not repeat the same data url_dist->after = json_integer_value(timestamp_json); // Call user defined callback function if (cb) cb(json_string_value(url_str_json), json_integer_value(timestamp_json), (int) json_integer_value(total_json), (int) json_integer_value(positives_json), url_obj, user_data); } return 0; }
qeo_mgmt_client_retcode_t qeo_mgmt_json_util_parseGetFWDMessage(const char* data, ssize_t length, qeo_mgmt_client_forwarder_cb callback, void* cookie) { json_error_t json_error = {0}; qeo_mgmt_client_retcode_t result = QMGMTCLIENT_EBADREPLY; json_t* message = json_loadb(data, length, JSON_REJECT_DUPLICATES, &json_error); qeo_mgmt_client_forwarder_t* fwd = NULL; do { json_t* fwdArray; ssize_t fwdSize; ssize_t i; if (message == NULL) { qeo_log_w("Failed to parse json message %s (%s:%d:%d)", json_error.text, json_error.source, json_error.line, json_error.column); qeo_log_w("Data = (%s)", data); //JSON parsing error break; } if (!json_is_object(message)) { qeo_log_w("invalid message received - top level is not a JSON object"); break; } fwdArray = json_object_get(message, "forwarders"); if (fwdArray == NULL || !json_is_array(fwdArray)) { qeo_log_w("root object did not contain a field 'forwarders' of type array (%p)", fwdArray); } fwdSize = json_array_size(fwdArray); qeo_log_i("Found an array of %d forwarder(s) in message\n", fwdSize); for (i = 0; i < fwdSize; i++) { qeo_mgmt_client_retcode_t cb_result; json_t* fwdObject = json_array_get(fwdArray, i); json_t* idString; json_t* locatorArray; ssize_t nrOfLocators; ssize_t j; if (!json_is_object(fwdObject)) { qeo_log_w("unexpected content in fwdArray - object expected"); break; } idString = json_object_get(fwdObject, "id"); if (idString == NULL || !json_is_string(idString)) { qeo_log_w("forwarder object did not contain a string field called 'id' (%p)", idString); break; } locatorArray = json_object_get(fwdObject, "locators"); if (locatorArray == NULL || !json_is_array(locatorArray)) { qeo_log_w("forwarder object did not contain an array field called 'nrOfLocators' (%p)", locatorArray); break; } nrOfLocators = json_array_size(locatorArray); qeo_log_i("found forwarder with id='%s' and %d locator(s)", json_string_value(idString), nrOfLocators); fwd = malloc(sizeof(qeo_mgmt_client_forwarder_t)); if (fwd == NULL) { qeo_log_w("fwd == NULL"); result = QMGMTCLIENT_EMEM; break; } fwd->nrOfLocators = nrOfLocators; fwd->locators = calloc(nrOfLocators, sizeof(qeo_mgmt_client_locator_t)); fwd->deviceID = qeo_mgmt_util_hex_to_int(json_string_value(idString)); if (fwd->deviceID == -1){ qeo_log_w("Invalid device id inside json message"); break; } if (fwd->locators == NULL) { qeo_log_w("fwd->locators == NULL"); result = QMGMTCLIENT_EMEM; break; } for (j = 0; j < nrOfLocators; j++) { json_t* endpointObj = json_array_get(locatorArray, j); json_t* typeString = json_object_get(endpointObj,"type"); json_t* addrString = json_object_get(endpointObj,"address"); json_t* portInt = json_object_get(endpointObj,"port"); if (portInt == NULL || !json_is_integer(portInt)) { qeo_log_w("locator object did not contain a integer field called 'port' (%p)", portInt); break; } if (addrString == NULL || !json_is_string(addrString)) { qeo_log_w("locator object did not contain a string field called 'address' (%p)", addrString); break; } if (typeString == NULL || !json_is_string(typeString)) { qeo_log_w("locator object did not contain a string field called 'type' (%p)", typeString); break; } qeo_log_i("locator object %d = {type = '%s', address = '%s', port = %d}", j, json_string_value(typeString), json_string_value(addrString), (int) json_integer_value(portInt)); //valid locator fwd->locators[j].port = (int) json_integer_value(portInt); if (fwd->locators[j].port < -1 || fwd->locators[j].port > 0xffff){ qeo_log_w("Invalid port inside locator"); break; } fwd->locators[j].type = _get_locator_type(json_string_value(typeString)); fwd->locators[j].address = strdup(json_string_value(addrString)); //check value; don't forget to free! if (fwd->locators[j].address == NULL) { qeo_log_w("locator->address == NULL"); break; } } if (j != nrOfLocators){ break; } cb_result = callback(fwd, cookie); fwd = NULL; //pointer is handed over; set it to NULL so we wont free it. if (cb_result != QMGMTCLIENT_OK) {//the callback reports an error abort. result = cb_result; break; } } if (i != fwdSize){ break; } qeo_log_i("Successfully walked JSON object tree..."); result = QMGMTCLIENT_OK; } while(0); if (message) { json_decref(message); } if (fwd) { //if an error occurred, then the 'fwd' is not freed. qeo_mgmt_client_free_forwarder(fwd); } return result; }
void net_json_convert_min3(json_t* r) { // ADC has changed i/o count from [2,2] to [3,2], // and likewise size of byte-arry of state data. // there is only one ADC operator, so this isn't too bad. /// magic number based on what 0.3.x scenes looked like. int lastAdcIn = 29; json_t* ins = json_object_get(r, "ins"); json_t* insData = json_object_get(ins, "data"); int insCount = json_integer_value(json_object_get(ins, "count")); json_integer_set(json_object_get(ins, "count"), insCount + 1); // need to f*x // all we should have to do for input nodes is: // - insert a new node // - fix everyone's index json_t* o = json_object(); json_object_set(o, "idx", json_integer(lastAdcIn)); json_object_set(o, "name", json_string("MODE ")); json_object_set(o, "opIdx", json_integer(10)); json_object_set(o, "opInIdx", json_integer(2)); json_object_set(o, "value", json_integer(0)); json_object_set(o, "play", json_integer(0)); int err = json_array_insert(insData, lastAdcIn + 1, o ); if(err != 0) { printf(" error inserting input node in ADC op conversion."); } // loop over input nodes and fix idx fields for(int i=0; i<NET_INS_MAX; i++) { json_integer_set(json_object_get(json_array_get(insData, i), "idx"), i); } // we also have to add some dummy values to the byte array of the ADC op's state. json_t* ops = json_object_get(r, "ops"); // 10 is the magic number of the ADC op in 0.3.x json_t* adc = json_array_get(json_object_get(ops, "data"), 10); // mode pickle: 2 bytes input value, zero is fine json_array_append(json_object_get(adc, "state"), json_integer(0)); json_array_append(json_object_get(adc, "state"), json_integer(0)); /* // copy all input nodes above this operator's... */ /* // count down from top. src has fewer input nodes; otherwise we would lose last value. */ /* for(int i = NET_INS_MAX - 1; i > lastAdcIn; i--) { */ /* // get json object at this index in node array */ /* json_t* dst = json_array_get(insData, i); */ /* json_t* src = json_array_get(insData, i - 1); */ /* if(src != NULL) { */ /* if(dst == NULL) { */ /* int err; */ /* dst = json_object(); */ /* json_object_set(dst, "idx", json_integer(i)); */ /* err = json_array_insert(insData, i, dst); */ /* if(err != 0) { printf(" error inserting input node in ADC op conversion."); } */ /* } */ /* // shallow copy ok? */ /* json_array_set(insData, src); */ /* // custom-copy, leaving idx */ /* /\* json_object_(dst, "name", json_object_get(src, "name")); *\/ */ /* /\* json_object_set(dst, "opIdx", json_object_get(src, "opIdx")); *\/ */ /* /\* json_object_set(dst, "opInIdx", json_object_get(src, "opInIdx")); *\/ */ /* /\* json_object_set(dst, "value", json_object_get(src, "value")); *\/ */ /* /\* json_object_set(dst, "play", json_object_get(src, "play")); *\/ */ /* } */ /* } */ /* // finally, we need to fix up the values for the new input ("mode"); */ /* ///... FIXME */ //---- -outs json_t* outs = json_object_get(r, "outs"); json_t* outsData = json_object_get(outs, "data"); // loop over all outputs and check targets for(int i = 0; i< NET_OUTS_MAX; i++) { json_t* o = json_array_get(outsData, i); int t = json_integer_value(json_object_get(o, "target")); if(t > lastAdcIn) { json_integer_set(json_object_get(o, "target"), t + 1); } } // i don't think anyone really used presets in this rev, so skipping those for now. // write the output of the converted json for a visual check. json_dump_file(r, "converted.json", JSON_INDENT(4) | JSON_PRESERVE_ORDER | JSON_ESCAPE_SLASH); }
static void test_misc() { json_t *object, *string, *other_string, *value; object = json_object(); string = json_string("test"); other_string = json_string("other"); if(!object) fail("unable to create object"); if(!string || !other_string) fail("unable to create string"); if(json_object_get(object, "a")) fail("value for nonexisting key"); if(json_object_set(object, "a", string)) fail("unable to set value"); if(!json_object_set(object, NULL, string)) fail("able to set NULL key"); if(!json_object_set(object, "a", NULL)) fail("able to set NULL value"); /* invalid UTF-8 in key */ if(!json_object_set(object, "a\xefz", string)) fail("able to set invalid unicode key"); value = json_object_get(object, "a"); if(!value) fail("no value for existing key"); if(value != string) fail("got different value than what was added"); /* "a", "lp" and "px" collide in a five-bucket hashtable */ if(json_object_set(object, "b", string) || json_object_set(object, "lp", string) || json_object_set(object, "px", string)) fail("unable to set value"); value = json_object_get(object, "a"); if(!value) fail("no value for existing key"); if(value != string) fail("got different value than what was added"); if(json_object_set(object, "a", other_string)) fail("unable to replace an existing key"); value = json_object_get(object, "a"); if(!value) fail("no value for existing key"); if(value != other_string) fail("got different value than what was set"); if(!json_object_del(object, "nonexisting")) fail("able to delete a nonexisting key"); if(json_object_del(object, "px")) fail("unable to delete an existing key"); if(json_object_del(object, "a")) fail("unable to delete an existing key"); if(json_object_del(object, "lp")) fail("unable to delete an existing key"); /* add many keys to initiate rehashing */ if(json_object_set(object, "a", string)) fail("unable to set value"); if(json_object_set(object, "lp", string)) fail("unable to set value"); if(json_object_set(object, "px", string)) fail("unable to set value"); if(json_object_set(object, "c", string)) fail("unable to set value"); if(json_object_set(object, "d", string)) fail("unable to set value"); if(json_object_set(object, "e", string)) fail("unable to set value"); if(json_object_set_new(object, "foo", json_integer(123))) fail("unable to set new value"); value = json_object_get(object, "foo"); if(!json_is_integer(value) || json_integer_value(value) != 123) fail("json_object_set_new works incorrectly"); if(!json_object_set_new(object, NULL, json_integer(432))) fail("able to set_new NULL key"); if(!json_object_set_new(object, "foo", NULL)) fail("able to set_new NULL value"); json_decref(string); json_decref(other_string); json_decref(object); }
bool TrafficNetwork::loadFromFile(const string fileName){ int nbBands; long currentNode,otherNode; string roadName; double roadLength; double roadSpeedLimit; int metric; json_t *root; json_error_t error; root = json_load_file(fileName.c_str(), 0, &error); if(!root){ std::cout<<std::endl<<"ERROR: while opening "<<fileName<<" at line "<<error.line<<" - "<<error.text<<std::endl; return false; } if(!json_is_object(root)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - expected root to be an object"<<std::endl; json_decref(root); return false; } json_t *_metric, *_roads, *_nodes; _metric = json_object_get(root,"metric"); if(!json_is_integer(_metric)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'metric' field not present or wrong type"<<std::endl; json_decref(root); return false; } metric = json_integer_value(_metric); _nodes = json_object_get(root,"nodes"); if(!json_is_array(_nodes)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'nodes' field not present or not an array"<<std::endl; json_decref(root); return false; } size_t n = json_array_size(_nodes); nbNodes = n; nodes = NodeVec(nbNodes); json_t *nodeId,*_node, *nodeType; for(size_t i = 0; i < n; i++){ _node = json_array_get(_nodes,i); if(!json_is_object(_node)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - expected node "<<i<<" to be an object"<<std::endl; json_decref(root); return false; } nodeId = json_object_get(_node,"id"); if(!json_is_integer(nodeId)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'id' field of node "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } nodeType = json_object_get(_node,"type"); if(json_is_integer(nodeType)){ nodes[i] = new Node(json_integer_value(nodeId),json_integer_value(nodeType)); }else{ nodes[i] = new Node(json_integer_value(nodeId)); } } _roads = json_object_get(root,"roads"); if(!json_is_array(_roads)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'roads' field not present or not an array"<<std::endl; json_decref(root); return false; } n = json_array_size(_roads); json_t *_roadName,*_roadSpeedLimit,*_roadNbBands,*_roadLength,*_road,*startId,*endId; for(size_t i = 0; i < n; i++){ _road = json_array_get(_roads,i); if(!json_is_object(_road)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - expected road "<<i<<" to be an object"<<std::endl; json_decref(root); return false; } _roadName = json_object_get(_road,"name"); if(!json_is_string(_roadName)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'name' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } roadName = json_string_value(_roadName); _roadSpeedLimit = json_object_get(_road,"speedLimit"); if(!json_is_integer(_roadSpeedLimit)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'speedLimit' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } roadSpeedLimit = formatSpeedLimit(json_integer_value(_roadSpeedLimit),metric); _roadLength = json_object_get(_road,"length"); if(!json_is_real(_roadLength)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'length' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } roadLength = formatLength(json_real_value(_roadLength),metric); _roadNbBands = json_object_get(_road,"nbBands"); if(!json_is_integer(_roadNbBands)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'nbBands' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } nbBands = json_integer_value(_roadNbBands); startId = json_object_get(_road,"startId"); if(!json_is_integer(startId)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'startId' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } currentNode = json_integer_value(startId); endId = json_object_get(_road,"endId"); if(!json_is_integer(endId)){ std::cout<<std::endl<<"ERROR: input file "<<fileName<<" has not the correct structure - 'endId' field of road "<<i<<" not present or wrong type"<<std::endl; json_decref(root); return false; } otherNode = json_integer_value(endId); addRoad(currentNode, otherNode, roadName, roadLength, roadSpeedLimit,nbBands); } //clean up json_array_clear(_nodes); json_object_clear(_road); json_array_clear(_roads); json_object_clear(root); json_decref(root); return true; }
/* Call the simple functions not covered by other tests of the public API */ static void run_tests() { json_t *value; value = json_boolean(1); if(!json_is_true(value)) fail("json_boolean(1) failed"); json_decref(value); value = json_boolean(-123); if(!json_is_true(value)) fail("json_boolean(-123) failed"); json_decref(value); value = json_boolean(0); if(!json_is_false(value)) fail("json_boolean(0) failed"); if(json_boolean_value(value) != 0) fail("json_boolean_value failed"); json_decref(value); value = json_integer(1); if(json_typeof(value) != JSON_INTEGER) fail("json_typeof failed"); if(json_is_object(value)) fail("json_is_object failed"); if(json_is_array(value)) fail("json_is_array failed"); if(json_is_string(value)) fail("json_is_string failed"); if(!json_is_integer(value)) fail("json_is_integer failed"); if(json_is_real(value)) fail("json_is_real failed"); if(!json_is_number(value)) fail("json_is_number failed"); if(json_is_true(value)) fail("json_is_true failed"); if(json_is_false(value)) fail("json_is_false failed"); if(json_is_boolean(value)) fail("json_is_boolean failed"); if(json_is_null(value)) fail("json_is_null failed"); json_decref(value); value = json_string("foo"); if(!value) fail("json_string failed"); if(strcmp(json_string_value(value), "foo")) fail("invalid string value"); if (json_string_length(value) != 3) fail("invalid string length"); if(json_string_set(value, "barr")) fail("json_string_set failed"); if(strcmp(json_string_value(value), "barr")) fail("invalid string value"); if (json_string_length(value) != 4) fail("invalid string length"); if(json_string_setn(value, "hi\0ho", 5)) fail("json_string_set failed"); if(memcmp(json_string_value(value), "hi\0ho\0", 6)) fail("invalid string value"); if (json_string_length(value) != 5) fail("invalid string length"); json_decref(value); value = json_string(NULL); if(value) fail("json_string(NULL) failed"); /* invalid UTF-8 */ value = json_string("a\xefz"); if(value) fail("json_string(<invalid utf-8>) failed"); value = json_string_nocheck("foo"); if(!value) fail("json_string_nocheck failed"); if(strcmp(json_string_value(value), "foo")) fail("invalid string value"); if (json_string_length(value) != 3) fail("invalid string length"); if(json_string_set_nocheck(value, "barr")) fail("json_string_set_nocheck failed"); if(strcmp(json_string_value(value), "barr")) fail("invalid string value"); if (json_string_length(value) != 4) fail("invalid string length"); if(json_string_setn_nocheck(value, "hi\0ho", 5)) fail("json_string_set failed"); if(memcmp(json_string_value(value), "hi\0ho\0", 6)) fail("invalid string value"); if (json_string_length(value) != 5) fail("invalid string length"); json_decref(value); /* invalid UTF-8 */ value = json_string_nocheck("qu\xff"); if(!value) fail("json_string_nocheck failed"); if(strcmp(json_string_value(value), "qu\xff")) fail("invalid string value"); if (json_string_length(value) != 3) fail("invalid string length"); if(json_string_set_nocheck(value, "\xfd\xfe\xff")) fail("json_string_set_nocheck failed"); if(strcmp(json_string_value(value), "\xfd\xfe\xff")) fail("invalid string value"); if (json_string_length(value) != 3) fail("invalid string length"); json_decref(value); value = json_integer(123); if(!value) fail("json_integer failed"); if(json_integer_value(value) != 123) fail("invalid integer value"); if(json_number_value(value) != 123.0) fail("invalid number value"); if(json_integer_set(value, 321)) fail("json_integer_set failed"); if(json_integer_value(value) != 321) fail("invalid integer value"); if(json_number_value(value) != 321.0) fail("invalid number value"); json_decref(value); value = json_real(123.123); if(!value) fail("json_real failed"); if(json_real_value(value) != 123.123) fail("invalid integer value"); if(json_number_value(value) != 123.123) fail("invalid number value"); if(json_real_set(value, 321.321)) fail("json_real_set failed"); if(json_real_value(value) != 321.321) fail("invalid real value"); if(json_number_value(value) != 321.321) fail("invalid number value"); json_decref(value); value = json_true(); if(!value) fail("json_true failed"); json_decref(value); value = json_false(); if(!value) fail("json_false failed"); json_decref(value); value = json_null(); if(!value) fail("json_null failed"); json_decref(value); /* Test reference counting on singletons (true, false, null) */ value = json_true(); if(value->refcount != (size_t)-1) fail("refcounting true works incorrectly"); json_decref(value); if(value->refcount != (size_t)-1) fail("refcounting true works incorrectly"); json_incref(value); if(value->refcount != (size_t)-1) fail("refcounting true works incorrectly"); value = json_false(); if(value->refcount != (size_t)-1) fail("refcounting false works incorrectly"); json_decref(value); if(value->refcount != (size_t)-1) fail("refcounting false works incorrectly"); json_incref(value); if(value->refcount != (size_t)-1) fail("refcounting false works incorrectly"); value = json_null(); if(value->refcount != (size_t)-1) fail("refcounting null works incorrectly"); json_decref(value); if(value->refcount != (size_t)-1) fail("refcounting null works incorrectly"); json_incref(value); if(value->refcount != (size_t)-1) fail("refcounting null works incorrectly"); }
HueOutputLightRGB::HueOutputLightRGB(Params &p): OutputLightRGB(p) { ioDoc->friendlyNameSet("HueOutputLightRGB"); ioDoc->descriptionSet(_("RGB Light dimmer using a Philips Hue")); ioDoc->linkAdd("Meet Hue", _("http://www.meethue.com")); ioDoc->paramAdd("host", _("Hue bridge IP address"), IODoc::TYPE_STRING, true); ioDoc->paramAdd("api", _("API key return by Hue bridge when assciation has been made. Use Hue Wizard in calaos_installer to get this value automatically."), IODoc::TYPE_STRING, true); ioDoc->paramAdd("id_hue", _("Unique ID describing the Hue Light. This value is returned by the Hue Wizard."), IODoc::TYPE_STRING, true); m_host = get_param("host"); m_api = get_param("api"); m_idHue = get_param("id_hue"); m_timer = new EcoreTimer(2.0,[=](){ std::string url = "http://" + m_host + "/api/" + m_api + "/lights/" + m_idHue; UrlDownloader *dl = new UrlDownloader(url, true); dl->m_signalCompleteData.connect([&](Eina_Binbuf *downloadedData, int status) { if (status) { json_error_t error; const unsigned char* c = eina_binbuf_string_get(downloadedData); json_t *root = json_loads((const char*)eina_binbuf_string_get(downloadedData), 0, &error); if (!root) { cErrorDom("hue") << "Json received malformed : " << error.source << " " << error.text << " (" << Utils::to_string(error.line) << " )"; return; } if (!json_is_object(root)) { cErrorDom("hue") << "Protocol changed ? date received : " << eina_binbuf_string_get(downloadedData); return; } json_t *tstate = json_object_get(root, "state"); if (!tstate || !json_is_object(tstate)) { cErrorDom("hue") << "Protocol changed ? date received : " << eina_binbuf_string_get(downloadedData); return; } int sat, bri, hue; bool on, reachable; sat = json_integer_value(json_object_get(tstate, "sat")); bri = json_integer_value(json_object_get(tstate, "bri")); hue = json_integer_value(json_object_get(tstate, "hue")); on = jansson_bool_get(tstate, "on"); reachable = jansson_bool_get(tstate, "reachable"); cDebugDom("hue") << "State: " << on << " Hue : " << hue << " Bri: " << bri << " Hue : " << hue << "Data : " << c; if (reachable) stateUpdated(ColorValue::fromHsl((int)(hue * 360.0 / 65535.0), (int)(sat * 100.0 / 255.0), (int)(bri * 100.0 / 255.0)), on); else stateUpdated(ColorValue(0,0,0), reachable); json_decref(root); } else { stateUpdated(ColorValue(0,0,0), false); } }); if (!dl->httpGet()) delete dl; }); }
/* Main Code */ int main(int argc, char *argv[]) { janus_log_init(FALSE, TRUE, NULL); atexit(janus_log_destroy); /* Check the JANUS_PPREC_DEBUG environment variable for the debugging level */ if(g_getenv("JANUS_PPREC_DEBUG") != NULL) { int val = atoi(g_getenv("JANUS_PPREC_DEBUG")); if(val >= LOG_NONE && val <= LOG_MAX) janus_log_level = val; JANUS_LOG(LOG_INFO, "Logging level: %d\n", janus_log_level); } /* Evaluate arguments */ if(argc != 3) { JANUS_LOG(LOG_INFO, "Usage: %s source.mjr destination.[opus|wav|webm|mp4]\n", argv[0]); JANUS_LOG(LOG_INFO, " %s --header source.mjr (only parse header)\n", argv[0]); JANUS_LOG(LOG_INFO, " %s --parse source.mjr (only parse and re-order packets)\n", argv[0]); return -1; } char *source = NULL, *destination = NULL; gboolean header_only = !strcmp(argv[1], "--header"); gboolean parse_only = !strcmp(argv[1], "--parse"); if(header_only || parse_only) { /* Only parse the .mjr header and/or re-order the packets, no processing */ source = argv[2]; } else { /* Post-process the .mjr recording */ source = argv[1]; destination = argv[2]; JANUS_LOG(LOG_INFO, "%s --> %s\n", source, destination); } FILE *file = fopen(source, "rb"); if(file == NULL) { JANUS_LOG(LOG_ERR, "Could not open file %s\n", source); return -1; } fseek(file, 0L, SEEK_END); long fsize = ftell(file); fseek(file, 0L, SEEK_SET); JANUS_LOG(LOG_INFO, "File is %zu bytes\n", fsize); /* Handle SIGINT */ working = 1; signal(SIGINT, janus_pp_handle_signal); /* Pre-parse */ JANUS_LOG(LOG_INFO, "Pre-parsing file to generate ordered index...\n"); gboolean parsed_header = FALSE; int video = 0; int opus = 0, g711 = 0, vp8 = 0, vp9 = 0, h264 = 0; gint64 c_time = 0, w_time = 0; int bytes = 0, skip = 0; long offset = 0; uint16_t len = 0, count = 0; uint32_t last_ts = 0, reset = 0; int times_resetted = 0; uint32_t post_reset_pkts = 0; char prebuffer[1500]; memset(prebuffer, 0, 1500); /* Let's look for timestamp resets first */ while(working && offset < fsize) { if(header_only && parsed_header) { /* We only needed to parse the header */ exit(0); } /* Read frame header */ skip = 0; fseek(file, offset, SEEK_SET); bytes = fread(prebuffer, sizeof(char), 8, file); if(bytes != 8 || prebuffer[0] != 'M') { JANUS_LOG(LOG_WARN, "Invalid header at offset %ld (%s), the processing will stop here...\n", offset, bytes != 8 ? "not enough bytes" : "wrong prefix"); break; } if(prebuffer[1] == 'E') { /* Either the old .mjr format header ('MEETECHO' header followed by 'audio' or 'video'), or a frame */ offset += 8; bytes = fread(&len, sizeof(uint16_t), 1, file); len = ntohs(len); offset += 2; if(len == 5 && !parsed_header) { /* This is the main header */ parsed_header = TRUE; JANUS_LOG(LOG_WARN, "Old .mjr header format\n"); bytes = fread(prebuffer, sizeof(char), 5, file); if(prebuffer[0] == 'v') { JANUS_LOG(LOG_INFO, "This is a video recording, assuming VP8\n"); video = 1; vp8 = 1; } else if(prebuffer[0] == 'a') { JANUS_LOG(LOG_INFO, "This is an audio recording, assuming Opus\n"); video = 0; opus = 1; } else { JANUS_LOG(LOG_WARN, "Unsupported recording media type...\n"); exit(1); } offset += len; continue; } else if(len < 12) { /* Not RTP, skip */ JANUS_LOG(LOG_VERB, "Skipping packet (not RTP?)\n"); offset += len; continue; } } else if(prebuffer[1] == 'J') { /* New .mjr format, the header may contain useful info */ offset += 8; bytes = fread(&len, sizeof(uint16_t), 1, file); len = ntohs(len); offset += 2; if(len > 0 && !parsed_header) { /* This is the info header */ JANUS_LOG(LOG_WARN, "New .mjr header format\n"); bytes = fread(prebuffer, sizeof(char), len, file); parsed_header = TRUE; prebuffer[len] = '\0'; json_error_t error; json_t *info = json_loads(prebuffer, 0, &error); if(!info) { JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text); JANUS_LOG(LOG_WARN, "Error parsing info header...\n"); exit(1); } /* Is it audio or video? */ json_t *type = json_object_get(info, "t"); if(!type || !json_is_string(type)) { JANUS_LOG(LOG_WARN, "Missing/invalid recording type in info header...\n"); exit(1); } const char *t = json_string_value(type); if(!strcasecmp(t, "v")) { video = 1; } else if(!strcasecmp(t, "a")) { video = 0; } else { JANUS_LOG(LOG_WARN, "Unsupported recording type '%s' in info header...\n", t); exit(1); } /* What codec was used? */ json_t *codec = json_object_get(info, "c"); if(!codec || !json_is_string(codec)) { JANUS_LOG(LOG_WARN, "Missing recording codec in info header...\n"); exit(1); } const char *c = json_string_value(codec); if(video) { if(!strcasecmp(c, "vp8")) { vp8 = 1; } else if(!strcasecmp(c, "vp9")) { vp9 = 1; } else if(!strcasecmp(c, "h264")) { h264 = 1; } else { JANUS_LOG(LOG_WARN, "The post-processor only supports VP8, VP9 and H.264 video for now (was '%s')...\n", c); exit(1); } } else if(!video) { if(!strcasecmp(c, "opus")) { opus = 1; } else if(!strcasecmp(c, "g711")) { g711 = 1; } else { JANUS_LOG(LOG_WARN, "The post-processor only suupports Opus and G.711 audio for now (was '%s')...\n", c); exit(1); } } /* When was the file created? */ json_t *created = json_object_get(info, "s"); if(!created || !json_is_integer(created)) { JANUS_LOG(LOG_WARN, "Missing recording created time in info header...\n"); exit(1); } c_time = json_integer_value(created); /* When was the first frame written? */ json_t *written = json_object_get(info, "u"); if(!written || !json_is_integer(written)) { JANUS_LOG(LOG_WARN, "Missing recording written time in info header...\n"); exit(1); } w_time = json_integer_value(written); /* Summary */ JANUS_LOG(LOG_INFO, "This is %s recording:\n", video ? "a video" : "an audio"); JANUS_LOG(LOG_INFO, " -- Codec: %s\n", c); JANUS_LOG(LOG_INFO, " -- Created: %"SCNi64"\n", c_time); JANUS_LOG(LOG_INFO, " -- Written: %"SCNi64"\n", w_time); } } else { JANUS_LOG(LOG_ERR, "Invalid header...\n"); exit(1); } /* Only read RTP header */ bytes = fread(prebuffer, sizeof(char), 16, file); janus_pp_rtp_header *rtp = (janus_pp_rtp_header *)prebuffer; if(last_ts > 0) { /* Is the new timestamp smaller than the next one, and if so, is it a timestamp reset or simply out of order? */ if(ntohl(rtp->timestamp) < last_ts && (last_ts-ntohl(rtp->timestamp) > 2*1000*1000*1000)) { reset = ntohl(rtp->timestamp); JANUS_LOG(LOG_WARN, "Timestamp reset: %"SCNu32"\n", reset); times_resetted++; post_reset_pkts = 0; } else if(ntohl(rtp->timestamp) < reset) { if(post_reset_pkts < 1000) { JANUS_LOG(LOG_WARN, "Updating latest timestamp reset: %"SCNu32" (was %"SCNu32")\n", ntohl(rtp->timestamp), reset); reset = ntohl(rtp->timestamp); } else { reset = ntohl(rtp->timestamp); JANUS_LOG(LOG_WARN, "Timestamp reset: %"SCNu32"\n", reset); times_resetted++; post_reset_pkts = 0; } } } last_ts = ntohl(rtp->timestamp); post_reset_pkts++; /* Skip data for now */ offset += len; } if(!working) exit(0); JANUS_LOG(LOG_WARN, "Counted %d timestamp resets\n", times_resetted); /* Now let's parse the frames and order them */ offset = 0; /* Timestamp reset related stuff */ last_ts = 0; reset = 0; times_resetted = 0; post_reset_pkts = 0; uint64_t max32 = UINT32_MAX; /* Start loop */ while(working && offset < fsize) { /* Read frame header */ skip = 0; fseek(file, offset, SEEK_SET); bytes = fread(prebuffer, sizeof(char), 8, file); if(bytes != 8 || prebuffer[0] != 'M') { /* Broken packet? Stop here */ break; } prebuffer[8] = '\0'; JANUS_LOG(LOG_VERB, "Header: %s\n", prebuffer); offset += 8; bytes = fread(&len, sizeof(uint16_t), 1, file); len = ntohs(len); JANUS_LOG(LOG_VERB, " -- Length: %"SCNu16"\n", len); offset += 2; if(prebuffer[1] == 'J' || len < 12) { /* Not RTP, skip */ JANUS_LOG(LOG_VERB, " -- Not RTP, skipping\n"); offset += len; continue; } if(len > 2000) { /* Way too large, very likely not RTP, skip */ JANUS_LOG(LOG_VERB, " -- Too large packet (%d bytes), skipping\n", len); offset += len; continue; } /* Only read RTP header */ bytes = fread(prebuffer, sizeof(char), 16, file); janus_pp_rtp_header *rtp = (janus_pp_rtp_header *)prebuffer; JANUS_LOG(LOG_VERB, " -- RTP packet (ssrc=%"SCNu32", pt=%"SCNu16", ext=%"SCNu16", seq=%"SCNu16", ts=%"SCNu32")\n", ntohl(rtp->ssrc), rtp->type, rtp->extension, ntohs(rtp->seq_number), ntohl(rtp->timestamp)); if(rtp->extension) { janus_pp_rtp_header_extension *ext = (janus_pp_rtp_header_extension *)(prebuffer+12); JANUS_LOG(LOG_VERB, " -- -- RTP extension (type=%"SCNu16", length=%"SCNu16")\n", ntohs(ext->type), ntohs(ext->length)); skip = 4 + ntohs(ext->length)*4; } /* Generate frame packet and insert in the ordered list */ janus_pp_frame_packet *p = g_malloc0(sizeof(janus_pp_frame_packet)); if(p == NULL) { JANUS_LOG(LOG_ERR, "Memory error!\n"); return -1; } p->seq = ntohs(rtp->seq_number); p->pt = rtp->type; /* Due to resets, we need to mess a bit with the original timestamps */ if(last_ts == 0) { /* Simple enough... */ p->ts = ntohl(rtp->timestamp); } else { /* Is the new timestamp smaller than the next one, and if so, is it a timestamp reset or simply out of order? */ if(ntohl(rtp->timestamp) < last_ts && (last_ts-ntohl(rtp->timestamp) > 2*1000*1000*1000)) { reset = ntohl(rtp->timestamp); JANUS_LOG(LOG_WARN, "Timestamp reset: %"SCNu32"\n", reset); times_resetted++; post_reset_pkts = 0; } else if(ntohl(rtp->timestamp) < reset) { if(post_reset_pkts < 1000) { JANUS_LOG(LOG_WARN, "Updating latest timestamp reset: %"SCNu32" (was %"SCNu32")\n", ntohl(rtp->timestamp), reset); reset = ntohl(rtp->timestamp); } else { reset = ntohl(rtp->timestamp); JANUS_LOG(LOG_WARN, "Timestamp reset: %"SCNu32"\n", reset); times_resetted++; post_reset_pkts = 0; } } /* Take into account the number of resets when setting the internal, 64-bit, timestamp */ p->ts = (times_resetted*max32)+ntohl(rtp->timestamp); } p->len = len; p->drop = 0; if(rtp->padding) { /* There's padding data, let's check the last byte to see how much data we should skip */ fseek(file, offset + len - 1, SEEK_SET); fread(prebuffer, sizeof(char), 1, file); uint8_t padlen = (uint8_t)prebuffer[0]; JANUS_LOG(LOG_VERB, "Padding at sequence number %hu: %d/%d\n", ntohs(rtp->seq_number), padlen, p->len); p->len -= padlen; if((p->len - skip - 12) <= 0) { /* Only padding, take note that we should drop the packet later */ p->drop = 1; JANUS_LOG(LOG_VERB, " -- All padding, marking packet as dropped\n"); } } last_ts = ntohl(rtp->timestamp); post_reset_pkts++; /* Fill in the rest of the details */ p->offset = offset; p->skip = skip; p->next = NULL; p->prev = NULL; if(list == NULL) { /* First element becomes the list itself (and the last item), at least for now */ list = p; last = p; } else { /* Check where we should insert this, starting from the end */ int added = 0; janus_pp_frame_packet *tmp = last; while(tmp) { if(tmp->ts < p->ts) { /* The new timestamp is greater than the last one we have, append */ added = 1; if(tmp->next != NULL) { /* We're inserting */ tmp->next->prev = p; p->next = tmp->next; } else { /* Update the last packet */ last = p; } tmp->next = p; p->prev = tmp; break; } else if(tmp->ts == p->ts) { /* Same timestamp, check the sequence number */ if(tmp->seq < p->seq && (abs(tmp->seq - p->seq) < 10000)) { /* The new sequence number is greater than the last one we have, append */ added = 1; if(tmp->next != NULL) { /* We're inserting */ tmp->next->prev = p; p->next = tmp->next; } else { /* Update the last packet */ last = p; } tmp->next = p; p->prev = tmp; break; } else if(tmp->seq > p->seq && (abs(tmp->seq - p->seq) > 10000)) { /* The new sequence number (resetted) is greater than the last one we have, append */ added = 1; if(tmp->next != NULL) { /* We're inserting */ tmp->next->prev = p; p->next = tmp->next; } else { /* Update the last packet */ last = p; } tmp->next = p; p->prev = tmp; break; } } /* If either the timestamp ot the sequence number we just got is smaller, keep going back */ tmp = tmp->prev; } if(!added) { /* We reached the start */ p->next = list; list->prev = p; list = p; } } /* Skip data for now */ offset += len; count++; } if(!working) exit(0); JANUS_LOG(LOG_INFO, "Counted %"SCNu16" RTP packets\n", count); janus_pp_frame_packet *tmp = list; count = 0; while(tmp) { count++; JANUS_LOG(LOG_VERB, "[%10lu][%4d] seq=%"SCNu16", ts=%"SCNu64", time=%"SCNu64"s\n", tmp->offset, tmp->len, tmp->seq, tmp->ts, (tmp->ts-list->ts)/90000); tmp = tmp->next; } JANUS_LOG(LOG_INFO, "Counted %"SCNu16" frame packets\n", count); if(video) { /* Look for maximum width and height, if possible, and for the average framerate */ if(vp8 || vp9) { if(janus_pp_webm_preprocess(file, list, vp8) < 0) { JANUS_LOG(LOG_ERR, "Error pre-processing %s RTP frames...\n", vp8 ? "VP8" : "VP9"); exit(1); } } else if(h264) { if(janus_pp_h264_preprocess(file, list) < 0) { JANUS_LOG(LOG_ERR, "Error pre-processing H.264 RTP frames...\n"); exit(1); } } } if(parse_only) { /* We only needed to parse and re-order the packets, we're done here */ JANUS_LOG(LOG_INFO, "Parsing and reordering completed, bye!\n"); exit(0); } if(!video) { if(opus) { if(janus_pp_opus_create(destination) < 0) { JANUS_LOG(LOG_ERR, "Error creating .opus file...\n"); exit(1); } } else if(g711) { if(janus_pp_g711_create(destination) < 0) { JANUS_LOG(LOG_ERR, "Error creating .wav file...\n"); exit(1); } } } else { if(vp8 || vp9) { if(janus_pp_webm_create(destination, vp8) < 0) { JANUS_LOG(LOG_ERR, "Error creating .webm file...\n"); exit(1); } } else if(h264) { if(janus_pp_h264_create(destination) < 0) { JANUS_LOG(LOG_ERR, "Error creating .mp4 file...\n"); exit(1); } } } /* Loop */ if(!video) { if(opus) { if(janus_pp_opus_process(file, list, &working) < 0) { JANUS_LOG(LOG_ERR, "Error processing Opus RTP frames...\n"); } } else if(g711) { if(janus_pp_g711_process(file, list, &working) < 0) { JANUS_LOG(LOG_ERR, "Error processing G.711 RTP frames...\n"); } } } else { if(vp8 || vp9) { if(janus_pp_webm_process(file, list, vp8, &working) < 0) { JANUS_LOG(LOG_ERR, "Error processing %s RTP frames...\n", vp8 ? "VP8" : "VP9"); } } else { if(janus_pp_h264_process(file, list, &working) < 0) { JANUS_LOG(LOG_ERR, "Error processing H.264 RTP frames...\n"); } } } /* Clean up */ if(video) { if(vp8 || vp9) { janus_pp_webm_close(); } else { janus_pp_h264_close(); } } else { if(opus) { janus_pp_opus_close(); } else if(g711) { janus_pp_g711_close(); } } fclose(file); file = fopen(destination, "rb"); if(file == NULL) { JANUS_LOG(LOG_INFO, "No destination file %s??\n", destination); } else { fseek(file, 0L, SEEK_END); fsize = ftell(file); fseek(file, 0L, SEEK_SET); JANUS_LOG(LOG_INFO, "%s is %zu bytes\n", destination, fsize); fclose(file); } janus_pp_frame_packet *temp = list, *next = NULL; while(temp) { next = temp->next; g_free(temp); temp = next; } JANUS_LOG(LOG_INFO, "Bye!\n"); return 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[512]; json_t *root = NULL; while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) { msg = g_async_queue_pop(messages); if(msg == NULL) continue; if(msg == &exit_message) break; if(msg->handle == NULL) { janus_videocall_message_free(msg); 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; } JANUS_VALIDATE_JSON_OBJECT(root, request_parameters, error_code, error_cause, TRUE, JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT, JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT); if(error_code != 0) goto error; json_t *request = json_object_get(root, "request"); 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; } JANUS_VALIDATE_JSON_OBJECT(root, username_parameters, error_code, error_cause, TRUE, JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT, JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT); if(error_code != 0) goto error; json_t *username = json_object_get(root, "username"); 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; } JANUS_VALIDATE_JSON_OBJECT(root, username_parameters, error_code, error_cause, TRUE, JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT, JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT); if(error_code != 0) goto error; json_t *username = json_object_get(root, "username"); 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; session->has_audio = (strstr(msg->sdp, "m=audio") != NULL); session->has_video = (strstr(msg->sdp, "m=video") != NULL); 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); /* Make also sure we get rid of ULPfec, red, etc. */ char *sdp = g_strdup(msg->sdp); if(strstr(sdp, "ulpfec")) { /* FIXME This really needs some better code */ sdp = janus_string_replace(sdp, "a=rtpmap:116 red/90000\r\n", ""); sdp = janus_string_replace(sdp, "a=rtpmap:117 ulpfec/90000\r\n", ""); sdp = janus_string_replace(sdp, "a=rtpmap:96 rtx/90000\r\n", ""); sdp = janus_string_replace(sdp, "a=fmtp:96 apt=100\r\n", ""); sdp = janus_string_replace(sdp, "a=rtpmap:97 rtx/90000\r\n", ""); sdp = janus_string_replace(sdp, "a=fmtp:97 apt=101\r\n", ""); sdp = janus_string_replace(sdp, "a=rtpmap:98 rtx/90000\r\n", ""); sdp = janus_string_replace(sdp, "a=fmtp:98 apt=116\r\n", ""); sdp = janus_string_replace(sdp, " 116", ""); sdp = janus_string_replace(sdp, " 117", ""); sdp = janus_string_replace(sdp, " 96", ""); sdp = janus_string_replace(sdp, " 97", ""); sdp = janus_string_replace(sdp, " 98", ""); } g_atomic_int_set(&session->hangingup, 0); 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, sdp); g_free(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); session->has_audio = (strstr(msg->sdp, "m=audio") != NULL); session->has_video = (strstr(msg->sdp, "m=video") != NULL); /* 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); g_atomic_int_set(&session->hangingup, 0); 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, bitrate cap or recording) */ JANUS_VALIDATE_JSON_OBJECT(root, set_parameters, error_code, error_cause, TRUE, JANUS_VIDEOCALL_ERROR_MISSING_ELEMENT, JANUS_VIDEOCALL_ERROR_INVALID_ELEMENT); if(error_code != 0) goto error; json_t *audio = json_object_get(root, "audio"); json_t *video = json_object_get(root, "video"); json_t *bitrate = json_object_get(root, "bitrate"); json_t *record = json_object_get(root, "record"); json_t *recfile = json_object_get(root, "filename"); 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? */ } } if(record) { if(msg->sdp) { session->has_audio = (strstr(msg->sdp, "m=audio") != NULL); session->has_video = (strstr(msg->sdp, "m=video") != NULL); } gboolean recording = json_is_true(record); const char *recording_base = json_string_value(recfile); JANUS_LOG(LOG_VERB, "Recording %s (base filename: %s)\n", recording ? "enabled" : "disabled", recording_base ? recording_base : "not provided"); janus_mutex_lock(&session->rec_mutex); if(!recording) { /* Not recording (anymore?) */ if(session->arc) { janus_recorder_close(session->arc); JANUS_LOG(LOG_INFO, "Closed audio recording %s\n", session->arc->filename ? session->arc->filename : "??"); janus_recorder_free(session->arc); } session->arc = NULL; if(session->vrc) { janus_recorder_close(session->vrc); JANUS_LOG(LOG_INFO, "Closed video recording %s\n", session->vrc->filename ? session->vrc->filename : "??"); janus_recorder_free(session->vrc); } session->vrc = NULL; } else { /* We've started recording, send a PLI and go on */ char filename[255]; gint64 now = janus_get_real_time(); if(session->has_audio) { /* FIXME We assume we're recording Opus, here */ memset(filename, 0, 255); if(recording_base) { /* Use the filename and path we have been provided */ g_snprintf(filename, 255, "%s-audio", recording_base); session->arc = janus_recorder_create(NULL, "opus", filename); if(session->arc == NULL) { /* FIXME We should notify the fact the recorder could not be created */ JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this VideoCall user!\n"); } } else { /* Build a filename */ g_snprintf(filename, 255, "videocall-%s-%s-%"SCNi64"-audio", session->username ? session->username : "******", (session->peer && session->peer->username) ? session->peer->username : "******", now); session->arc = janus_recorder_create(NULL, "opus", filename); if(session->arc == NULL) { /* FIXME We should notify the fact the recorder could not be created */ JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this VideoCall user!\n"); } } } if(session->has_video) { /* FIXME We assume we're recording VP8, here */ memset(filename, 0, 255); if(recording_base) { /* Use the filename and path we have been provided */ g_snprintf(filename, 255, "%s-video", recording_base); session->vrc = janus_recorder_create(NULL, "vp8", filename); if(session->vrc == NULL) { /* FIXME We should notify the fact the recorder could not be created */ JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this VideoCall user!\n"); } } else { /* Build a filename */ g_snprintf(filename, 255, "videocall-%s-%s-%"SCNi64"-video", session->username ? session->username : "******", (session->peer && session->peer->username) ? session->peer->username : "******", now); session->vrc = janus_recorder_create(NULL, "vp8", filename); if(session->vrc == NULL) { /* FIXME We should notify the fact the recorder could not be created */ JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this VideoCall user!\n"); } } /* Send a PLI */ JANUS_LOG(LOG_VERB, "Recording video, sending a PLI to kickstart it\n"); char buf[12]; memset(buf, 0, 12); janus_rtcp_pli((char *)&buf, 12); gateway->relay_rtcp(session->handle, 1, buf, 12); } } janus_mutex_unlock(&session->rec_mutex); } /* 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); } } JANUS_LOG(LOG_VERB, "Leaving VideoCall handler thread\n"); return NULL; }
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; }
} else if (val->type == JSON_INTEGER) { printf("%s = %lli\n", json_string_value(name), json_integer_value(val)); } else if (val->type == JSON_REAL) { printf("%s = %f\n", json_string_value(name), json_real_value(val)); } else if (val->type == JSON_NULL) { printf("%s = NULL\n", json_string_value(name)); } else if (val->type == JSON_TRUE) { printf("%s = true\n", json_string_value(name)); } else if (val->type == JSON_FALSE) { printf("%s = false\n", json_string_value(name)); } else { printf("%s = (Unknown Type)\n", json_string_value(name)); } } dslink_requester_close(link, (uint32_t) json_integer_value(json_object_get(resp, "rid"))); } void on_value_update(struct DSLink *link, uint32_t sid, json_t *val, json_t *ts) { (void) link; (void) ts; (void) sid; printf("Got value %f\n", json_real_value(val)); dslink_requester_unsubscribe(link, sid); } void init(DSLink *link) { (void) link; log_info("Initialized!\n"); }