SessionStore::Session* SessionStore::JsonSerializerDeserializer:: deserialize_session(const std::string& data) { TRC_DEBUG("Deserialize JSON document: %s", data.c_str()); rapidjson::Document doc; doc.Parse<0>(data.c_str()); if (doc.HasParseError()) { TRC_DEBUG("Failed to parse document"); return NULL; } Session* session = new Session(); try { JSON_GET_STRING_MEMBER(doc, JSON_SESSION_ID, session->session_id); JSON_ASSERT_CONTAINS(doc, JSON_CCFS); JSON_ASSERT_ARRAY(doc[JSON_CCFS]); for (rapidjson::Value::ConstValueIterator ccfs_it = doc[JSON_CCFS].Begin(); ccfs_it != doc[JSON_CCFS].End(); ++ccfs_it) { JSON_ASSERT_STRING(*ccfs_it); session->ccf.push_back(ccfs_it->GetString()); } JSON_GET_INT_MEMBER(doc, JSON_ACCT_RECORD_NUM, session->acct_record_number); JSON_GET_STRING_MEMBER(doc, JSON_TIMER_ID, session->timer_id); JSON_GET_INT_MEMBER(doc, JSON_REFRESH_TIME, session->session_refresh_time); JSON_GET_INT_MEMBER(doc, JSON_INTERIM_INTERVAL, session->interim_interval); } catch(JsonFormatError err) { TRC_INFO("Failed to deserialize JSON document (hit error at %s:%d)", err._file, err._line); delete session; session = NULL; } return session; }
AuthStore::Digest* AuthStore::JsonSerializerDeserializer:: deserialize_digest(const std::string& digest_s) { TRC_DEBUG("Deserialize JSON document: %s", digest_s.c_str()); rapidjson::Document doc; doc.Parse<0>(digest_s.c_str()); if (doc.HasParseError()) { TRC_DEBUG("Failed to parse document"); return NULL; } Digest* digest = new Digest(); try { JSON_ASSERT_OBJECT(doc); JSON_ASSERT_CONTAINS(doc, JSON_DIGEST); JSON_ASSERT_OBJECT(doc[JSON_DIGEST]); const rapidjson::Value& digest_block = doc[JSON_DIGEST]; { JSON_GET_STRING_MEMBER(digest_block, JSON_HA1, digest->_ha1); // The QoP is assumed to always be 'auth'. JSON_GET_STRING_MEMBER(digest_block, JSON_REALM, digest->_realm); } JSON_GET_STRING_MEMBER(doc, JSON_OPAQUE, digest->_opaque); JSON_GET_STRING_MEMBER(doc, JSON_IMPU, digest->_impu); JSON_GET_INT_MEMBER(doc, JSON_NC, digest->_nonce_count); } catch(JsonFormatError err) { TRC_INFO("Failed to deserialize JSON document (hit error at %s:%d)", err._file, err._line); delete digest; digest = NULL; } return digest; }
JSONEnumService::JSONEnumService(std::string configuration) { // Check whether the file exists. struct stat s; if ((stat(configuration.c_str(), &s) != 0) && (errno == ENOENT)) { TRC_STATUS("No ENUM configuration (file %s does not exist)", configuration.c_str()); CL_SPROUT_ENUM_FILE_MISSING.log(configuration.c_str()); return; } TRC_STATUS("Loading ENUM configuration from %s", configuration.c_str()); // Read from the file std::ifstream fs(configuration.c_str()); std::string enum_str((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>()); if (enum_str == "") { // LCOV_EXCL_START TRC_ERROR("Failed to read ENUM configuration data from %s", configuration.c_str()); CL_SPROUT_ENUM_FILE_EMPTY.log(configuration.c_str()); return; // LCOV_EXCL_STOP } // Now parse the document rapidjson::Document doc; doc.Parse<0>(enum_str.c_str()); if (doc.HasParseError()) { TRC_ERROR("Failed to read ENUM configuration data: %s\nError: %s", enum_str.c_str(), rapidjson::GetParseError_En(doc.GetParseError())); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); return; } try { JSON_ASSERT_CONTAINS(doc, "number_blocks"); JSON_ASSERT_ARRAY(doc["number_blocks"]); const rapidjson::Value& nb_arr = doc["number_blocks"]; for (rapidjson::Value::ConstValueIterator nb_it = nb_arr.Begin(); nb_it != nb_arr.End(); ++nb_it) { try { std::string prefix; JSON_GET_STRING_MEMBER(*nb_it, "prefix", prefix); std::string regex; JSON_GET_STRING_MEMBER(*nb_it, "regex", regex); // Entry is well-formed, so add it. TRC_DEBUG("Found valid number prefix block %s", prefix.c_str()); NumberPrefix *pfix = new NumberPrefix; pfix->prefix = prefix; if (parse_regex_replace(regex, pfix->match, pfix->replace)) { _number_prefixes.push_back(pfix); TRC_STATUS(" Adding number prefix %s, regex=%s", pfix->prefix.c_str(), regex.c_str()); } else { TRC_WARNING("Badly formed regular expression in ENUM number block %s", regex.c_str()); delete pfix; } } catch (JsonFormatError err) { // Badly formed number block. TRC_WARNING("Badly formed ENUM number block (hit error at %s:%d)", err._file, err._line); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); } } } catch (JsonFormatError err) { TRC_ERROR("Badly formed ENUM configuration data - missing number_blocks object"); CL_SPROUT_ENUM_FILE_INVALID.log(configuration.c_str()); } }
Timer* Timer::from_json_obj(TimerID id, uint64_t replica_hash, std::string& error, bool& replicated, rapidjson::Value& doc) { Timer* timer = NULL; try { JSON_ASSERT_CONTAINS(doc, "timing"); JSON_ASSERT_CONTAINS(doc, "callback"); // Parse out the timing block rapidjson::Value& timing = doc["timing"]; JSON_ASSERT_OBJECT(timing); JSON_ASSERT_CONTAINS(timing, "interval"); rapidjson::Value& interval = timing["interval"]; JSON_ASSERT_INT(interval); // Extract the repeat-for parameter, if it's absent, set it to the interval // instead. int repeat_for_int; if (timing.HasMember("repeat-for")) { JSON_GET_INT_MEMBER(timing, "repeat-for", repeat_for_int); } else { repeat_for_int = interval.GetInt(); } if ((interval.GetInt() == 0) && (repeat_for_int != 0)) { // If the interval time is 0 and the repeat_for_int isn't then reject the timer. error = "Can't have a zero interval time with a non-zero (%s) repeat-for time", std::to_string(repeat_for_int); return NULL; } timer = new Timer(id, (interval.GetInt() * 1000), (repeat_for_int * 1000)); if (timing.HasMember("start-time-delta")) { // Timer JSON specified a time offset, use that to determine the true // start time. uint64_t start_time_delta; JSON_GET_INT_64_MEMBER(timing, "start-time-delta", start_time_delta); // This cast is safe as this sum is deliberately designed to wrap over UINT_MAX. timer->start_time_mono_ms = (uint32_t)(clock_gettime_ms(CLOCK_MONOTONIC) + start_time_delta); } else if (timing.HasMember("start-time")) { // Timer JSON specifies a start-time, use that instead of now. uint64_t real_start_time; JSON_GET_INT_64_MEMBER(timing, "start-time", real_start_time); uint64_t real_time = clock_gettime_ms(CLOCK_REALTIME); uint64_t mono_time = clock_gettime_ms(CLOCK_MONOTONIC); // This cast is safe as this sum is deliberately designed to wrap over UINT_MAX. timer->start_time_mono_ms = (uint32_t)(mono_time + real_start_time - real_time); } if (timing.HasMember("sequence-number")) { JSON_GET_INT_MEMBER(timing, "sequence-number", timer->sequence_number); } // Parse out the 'callback' block rapidjson::Value& callback = doc["callback"]; JSON_ASSERT_OBJECT(callback); JSON_ASSERT_CONTAINS(callback, "http"); rapidjson::Value& http = callback["http"]; JSON_ASSERT_OBJECT(http); JSON_GET_STRING_MEMBER(http, "uri", timer->callback_url); JSON_GET_STRING_MEMBER(http, "opaque", timer->callback_body); if (doc.HasMember("reliability")) { // Parse out the 'reliability' block rapidjson::Value& reliability = doc["reliability"]; JSON_ASSERT_OBJECT(reliability); if (reliability.HasMember("cluster-view-id")) { JSON_GET_STRING_MEMBER(reliability, "cluster-view-id", timer->cluster_view_id); } if (reliability.HasMember("replicas")) { rapidjson::Value& replicas = reliability["replicas"]; JSON_ASSERT_ARRAY(replicas); if (replicas.Size() == 0) { error = "If replicas is specified it must be non-empty"; delete timer; timer = NULL; return NULL; } timer->_replication_factor = replicas.Size(); for (rapidjson::Value::ConstValueIterator it = replicas.Begin(); it != replicas.End(); ++it) { JSON_ASSERT_STRING(*it); timer->replicas.push_back(std::string(it->GetString(), it->GetStringLength())); } } else { if (reliability.HasMember("replication-factor")) { JSON_GET_INT_MEMBER(reliability, "replication-factor", timer->_replication_factor); } else { // Default replication factor is 2. timer->_replication_factor = 2; } } } else { // Default to 2 replicas timer->_replication_factor = 2; } timer->_replica_tracker = pow(2, timer->_replication_factor) - 1; if (timer->replicas.empty()) { // Replicas not determined above, determine them now. Note that this implies // the request is from a client, not another replica. replicated = false; timer->calculate_replicas(replica_hash); } else { // Replicas were specified in the request, must be a replication message // from another cluster node. replicated = true; } } catch (JsonFormatError err) { error = "Badly formed Timer entry - hit error on line " + std::to_string(err._line); delete timer; timer = NULL; return NULL; } return timer; }
void JSONEnumService::update_enum() { // Check whether the file exists. struct stat s; if ((stat(_configuration.c_str(), &s) != 0) && (errno == ENOENT)) { TRC_STATUS("No ENUM configuration (file %s does not exist)", _configuration.c_str()); CL_SPROUT_ENUM_FILE_MISSING.log(_configuration.c_str()); return; } TRC_STATUS("Loading ENUM configuration from %s", _configuration.c_str()); // Read from the file std::ifstream fs(_configuration.c_str()); std::string enum_str((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>()); if (enum_str == "") { // LCOV_EXCL_START TRC_ERROR("Failed to read ENUM configuration data from %s", _configuration.c_str()); CL_SPROUT_ENUM_FILE_EMPTY.log(_configuration.c_str()); return; // LCOV_EXCL_STOP } // Now parse the document rapidjson::Document doc; doc.Parse<0>(enum_str.c_str()); if (doc.HasParseError()) { TRC_ERROR("Failed to read ENUM configuration data: %s\nError: %s", enum_str.c_str(), rapidjson::GetParseError_En(doc.GetParseError())); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); return; } try { std::vector<NumberPrefix> new_number_prefixes; std::map<std::string, NumberPrefix> new_prefix_regex_map; JSON_ASSERT_CONTAINS(doc, "number_blocks"); JSON_ASSERT_ARRAY(doc["number_blocks"]); const rapidjson::Value& nb_arr = doc["number_blocks"]; for (rapidjson::Value::ConstValueIterator nb_it = nb_arr.Begin(); nb_it != nb_arr.End(); ++nb_it) { try { std::string prefix; JSON_GET_STRING_MEMBER(*nb_it, "prefix", prefix); std::string regex; JSON_GET_STRING_MEMBER(*nb_it, "regex", regex); // Entry is well-formed, so strip off visual separators and add it. TRC_DEBUG("Found valid number prefix block %s", prefix.c_str()); NumberPrefix pfix; prefix = PJUtils::remove_visual_separators(prefix); pfix.prefix = prefix; if (parse_regex_replace(regex, pfix.match, pfix.replace)) { // Create an array in order of entries in json file, and a map // (automatically sorted in order of key length) so we can later // match numbers to the most specific prefixes new_number_prefixes.push_back(pfix); new_prefix_regex_map.insert(std::make_pair(prefix, pfix)); TRC_STATUS(" Adding number prefix %s, regex=%s", pfix.prefix.c_str(), regex.c_str()); } else { TRC_WARNING("Badly formed regular expression in ENUM number block %s", regex.c_str()); } } catch (JsonFormatError err) { // Badly formed number block. TRC_WARNING("Badly formed ENUM number block (hit error at %s:%d)", err._file, err._line); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); } } // Take a write lock on the mutex in RAII style boost::lock_guard<boost::shared_mutex> write_lock(_number_prefixes_rw_lock); _number_prefixes = new_number_prefixes; _prefix_regex_map = new_prefix_regex_map; } catch (JsonFormatError err) { TRC_ERROR("Badly formed ENUM configuration data - missing number_blocks object"); CL_SPROUT_ENUM_FILE_INVALID.log(_configuration.c_str()); } }
void SCSCFSelector::update_scscf() { // Check whether the file exists. struct stat s; if ((stat(_configuration.c_str(), &s) != 0) && (errno == ENOENT)) { TRC_STATUS("No S-CSCF configuration data (file %s does not exist)", _configuration.c_str()); CL_SPROUT_SCSCF_FILE_MISSING.log(); return; } TRC_STATUS("Loading S-CSCF configuration from %s", _configuration.c_str()); // Read from the file std::ifstream fs(_configuration.c_str()); std::string scscf_str((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>()); if (scscf_str == "") { // LCOV_EXCL_START TRC_ERROR("Failed to read S-CSCF configuration data from %s", _configuration.c_str()); CL_SPROUT_SCSCF_FILE_EMPTY.log(); return; // LCOV_EXCL_STOP } // Now parse the document rapidjson::Document doc; doc.Parse<0>(scscf_str.c_str()); if (doc.HasParseError()) { TRC_ERROR("Failed to read S-CSCF configuration data: %s\nError: %s", scscf_str.c_str(), rapidjson::GetParseError_En(doc.GetParseError())); CL_SPROUT_SCSCF_FILE_INVALID.log(); return; } try { std::vector<scscf_t> new_scscfs; JSON_ASSERT_CONTAINS(doc, "s-cscfs"); JSON_ASSERT_ARRAY(doc["s-cscfs"]); const rapidjson::Value& scscfs_arr = doc["s-cscfs"]; for (rapidjson::Value::ConstValueIterator scscfs_it = scscfs_arr.Begin(); scscfs_it != scscfs_arr.End(); ++scscfs_it) { try { scscf_t new_scscf; JSON_GET_STRING_MEMBER(*scscfs_it, "server", new_scscf.server); JSON_GET_INT_MEMBER(*scscfs_it, "priority", new_scscf.priority); JSON_GET_INT_MEMBER(*scscfs_it, "weight", new_scscf.weight); JSON_ASSERT_CONTAINS(*scscfs_it, "capabilities"); JSON_ASSERT_ARRAY((*scscfs_it)["capabilities"]); const rapidjson::Value& cap_arr = (*scscfs_it)["capabilities"]; std::vector<int> capabilities_vec; for (rapidjson::Value::ConstValueIterator cap_it = cap_arr.Begin(); cap_it != cap_arr.End(); ++cap_it) { capabilities_vec.push_back((*cap_it).GetInt()); } // Sort the capabilities and remove duplicates std::sort(capabilities_vec.begin(), capabilities_vec.end()); capabilities_vec.erase(unique(capabilities_vec.begin(), capabilities_vec.end()), capabilities_vec.end() ); new_scscf.capabilities = capabilities_vec; new_scscfs.push_back(new_scscf); capabilities_vec.clear(); } catch (JsonFormatError err) { // Badly formed number block. TRC_WARNING("Badly formed S-CSCF entry (hit error at %s:%d)", err._file, err._line); CL_SPROUT_SCSCF_FILE_INVALID.log(); } } // Take a write lock on the mutex in RAII style boost::lock_guard<boost::shared_mutex> write_lock(_scscfs_rw_lock); _scscfs = new_scscfs; } catch (JsonFormatError err) { TRC_ERROR("Badly formed S-CSCF configuration file - missing s-cscfs object"); CL_SPROUT_SCSCF_FILE_INVALID.log(); } }