void AuthTimeoutHandler::run() { if (_req.method() != htp_method_POST) { send_http_reply(HTTP_BADMETHOD); delete this; return; } SAS::Marker start_marker(trail(), MARKER_ID_START, 1u); SAS::report_marker(start_marker); SAS::Marker calling_dn(trail(), MARKER_ID_CALLING_DN, 1u); calling_dn.add_var_param(_impu); SAS::report_marker(calling_dn); HTTPCode rc = handle_response(_req.body()); SAS::Marker end_marker(trail(), MARKER_ID_END, 1u); SAS::report_marker(end_marker); if (rc != HTTP_OK) { LOG_DEBUG("Unable to handle callback from Chronos"); send_http_reply(rc); delete this; return; } send_http_reply(HTTP_OK); delete this; }
void AuthTimeoutTask::run() { if (_req.method() != htp_method_POST) { send_http_reply(HTTP_BADMETHOD); delete this; return; } SAS::Marker start_marker(trail(), MARKER_ID_START, 1u); SAS::report_marker(start_marker); HTTPCode rc = handle_response(_req.get_rx_body()); SAS::Marker end_marker(trail(), MARKER_ID_END, 1u); SAS::report_marker(end_marker); if (rc != HTTP_OK) { LOG_DEBUG("Unable to handle callback from Chronos"); send_http_reply(rc); delete this; return; } send_http_reply(HTTP_OK); delete this; }
void ControllerTask::add_or_update_timer(int timer_id, int replica_hash) { Timer* timer = NULL; bool replicated_timer; if (_req.method() == htp_method_DELETE) { // Replicated deletes are implemented as replicated tombstones so no DELETE // can be a replication request. replicated_timer = false; timer = Timer::create_tombstone(timer_id, replica_hash); } else { std::string body = _req.get_rx_body(); std::string error_str; timer = Timer::from_json(timer_id, replica_hash, body, error_str, replicated_timer); if (!timer) { TRC_DEBUG("Unable to create timer"); send_http_reply(HTTP_BAD_REQUEST); return; } } TRC_DEBUG("Accepted timer definition, timer is%s a replica", replicated_timer ? "" : " not"); // Now we have a valid timer object, reply to the HTTP request. _req.add_header("Location", timer->url()); send_http_reply(HTTP_OK); // Replicate the timer to the other replicas if this is a client request if (!replicated_timer) { _cfg->_replicator->replicate(timer); } // If the timer belongs to the local node, store it. Otherwise, turn it into // a tombstone. std::string localhost; __globals->get_cluster_local_ip(localhost); if (!timer->is_local(localhost)) { timer->become_tombstone(); } _cfg->_handler->add_timer(timer); // The store takes ownership of the timer. timer = NULL; }
void ControllerTask::run() { std::string path = _req.full_path(); TRC_DEBUG("Path is %s", path.c_str()); boost::smatch matches; if (_req.method() == htp_method_GET) { handle_get(); } else if ((path == "/timers") || (path == "/timers/")) { if (_req.method() != htp_method_POST) { TRC_DEBUG("Empty timer, but the method wasn't POST"); send_http_reply(HTTP_BADMETHOD); } else { add_or_update_timer(Timer::generate_timer_id(), 0); } } else if (path == "/timers/references") { if (_req.method() != htp_method_DELETE) { TRC_DEBUG("Dealing with timer references, but the method wasn't DELETE"); send_http_reply(HTTP_BADMETHOD); } else { handle_delete(); } } else if (boost::regex_match(path, matches, boost::regex("/timers/([[:xdigit:]]{16})([[:xdigit:]]{16})"))) { if ((_req.method() != htp_method_PUT) && (_req.method() != htp_method_DELETE)) { TRC_DEBUG("Timer present, but the method wasn't PUT or DELETE"); send_http_reply(HTTP_BADMETHOD); } else { TimerID timer_id = std::stoul(matches[1].str(), NULL, 16); uint64_t replica_hash = std::stoull(matches[2].str(), NULL, 16); add_or_update_timer(timer_id, replica_hash); } } else { TRC_DEBUG("Invalid request, or timer present but badly formatted"); send_http_reply(HTTP_NOT_FOUND); } delete this; }
void BillingTask::run() { if (_req.method() != htp_method_POST) { send_http_reply(405); delete this; return; } bool timer_interim = false; if (_req.param(TIMER_INTERIM_PARAM) == "true") { timer_interim = true; SAS::Marker cid_assoc(trail(), MARKER_ID_SIP_CALL_ID, 0); cid_assoc.add_var_param(call_id()); SAS::report_marker(cid_assoc); SAS::Event timer_pop(trail(), SASEvent::INTERIM_TIMER_POPPED, 0); SAS::report_event(timer_pop); } Message* msg = NULL; HTTPCode rc = parse_body(call_id(), timer_interim, _req.get_rx_body(), &msg, trail()); if (rc != HTTP_OK) { SAS::Event rejected(trail(), SASEvent::REQUEST_REJECTED_INVALID_JSON, 0); SAS::report_event(rejected); send_http_reply(rc); } else { if (msg != NULL) { TRC_DEBUG("Handle the received message"); // The session manager takes ownership of the message object and is // responsible for deleting it. _sess_mgr->handle(msg); msg = NULL; } // The HTTP reply won't be sent until afer we leave this function, so by // putting this last we ensure that the load monitor will get a sensible // value for the latency send_http_reply(rc); } delete this; }
static int send_reply(struct evhttp_request *req, struct json_object *obj) { char *result_reason = NULL; int result_status; if (get_status_and_reason(obj, &result_status, &result_reason) == -1) send_http_reply(req, HTTP_INTERNAL_ERROR_STATUS, HTTP_INTERNAL_ERROR_REASON, JSON_RPC_INTERNAL_ERROR); else { char *obj_str = json_to_string(obj); send_http_reply(req, result_status, result_reason, obj_str); free(obj_str); } free(result_reason); return 0; }
static void json_rpc_call(struct evhttp_request *req, void *arg) { struct json_rpc_tt *jt = (struct json_rpc_tt *)arg; struct json_object *obj = get_json(req->input_buffer); if (obj == NULL) send_http_reply(req, HTTP_PARSE_ERROR_STATUS, HTTP_PARSE_ERROR_REASON, JSON_RPC_PARSE_ERROR); else json_rpc_process_request(jt->jr, obj, jrpc_result, (void *)req); }
static void jrpc_result(struct json_rpc *jr, struct json_object *res, void *arg) { struct evhttp_request *req = (struct evhttp_request *)arg; if (res == NULL) send_http_reply(req, HTTP_INTERNAL_ERROR_STATUS, HTTP_INTERNAL_ERROR_REASON, JSON_RPC_INTERNAL_ERROR); else send_reply(req, res); json_ref_put(res); }
void DeregistrationHandler::run() { // HTTP method must be a DELETE if (_req.method() != htp_method_DELETE) { LOG_WARNING("HTTP method isn't delete"); send_http_reply(HTTP_BADMETHOD); delete this; return; } // Mandatory query parameter 'send-notifications' that must be true or false _notify = _req.param("send-notifications"); if (_notify != "true" && _notify != "false") { LOG_WARNING("Mandatory send-notifications param is missing or invalid, send 400"); send_http_reply(HTTP_BAD_RESULT); delete this; return; } // Parse the JSON body HTTPCode rc = parse_request(_req.body()); if (rc != HTTP_OK) { LOG_WARNING("Request body is invalid, send %d", rc); send_http_reply(rc); delete this; return; } rc = handle_request(); send_http_reply(rc); delete this; }
void ControllerTask::handle_get() { // Check the request is valid. It must have the node-for-replicas, // sync-mode and cluster-view-id parameters set, the sync-mode parameter // must be SCALE (this will be extended later), the request-node // must correspond to a node in the Chronos cluster (it can be a // leaving node), and the cluster-view-id request must correspond to // the receiving nodes view of the cluster configuration std::string node_for_replicas = _req.param(PARAM_NODE_FOR_REPLICAS); std::string sync_mode = _req.param(PARAM_SYNC_MODE); std::string cluster_view_id = _req.param(PARAM_CLUSTER_VIEW_ID); if ((node_for_replicas == "") || (sync_mode == "") || (cluster_view_id == "")) { TRC_INFO("GET request doesn't have mandatory parameters"); send_http_reply(HTTP_BAD_REQUEST); return; } std::string global_cluster_view_id; __globals->get_cluster_view_id(global_cluster_view_id); if (cluster_view_id != global_cluster_view_id) { TRC_INFO("GET request is for an out of date cluster (%s and %s)", cluster_view_id.c_str(), global_cluster_view_id.c_str()); send_http_reply(HTTP_BAD_REQUEST); return; } if (!node_is_in_cluster(node_for_replicas)) { TRC_DEBUG("The request node isn't a Chronos node: %s", node_for_replicas.c_str()); send_http_reply(HTTP_BAD_REQUEST); return; } if (sync_mode == PARAM_SYNC_MODE_VALUE_SCALE) { std::string max_timers_from_req = _req.header(HEADER_RANGE); int max_timers_to_get = atoi(max_timers_from_req.c_str()); TRC_DEBUG("Range value is %d", max_timers_to_get); std::string get_response; HTTPCode rc = _cfg->_handler->get_timers_for_node(node_for_replicas, max_timers_to_get, cluster_view_id, get_response); _req.add_content(get_response); if (rc == HTTP_PARTIAL_CONTENT) { _req.add_header(HEADER_CONTENT_RANGE, max_timers_from_req); } send_http_reply(rc); } else { TRC_DEBUG("Sync mode is unsupported: %s", sync_mode.c_str()); send_http_reply(HTTP_BAD_REQUEST); } }
void ControllerTask::handle_delete() { // Check the request has a valid JSON body std::string body = _req.get_rx_body(); rapidjson::Document doc; doc.Parse<0>(body.c_str()); if (doc.HasParseError()) { TRC_INFO("Failed to parse document as JSON"); send_http_reply(HTTP_BAD_REQUEST); return; } // Now loop through the body, pulling out the IDs/replica numbers // The JSON body should have the format: // {"IDs": [{"ID": 123, "ReplicaIndex": 0}, // {"ID": 456, "ReplicaIndex": 2}, // ...] // The replica_index is zero-indexed (so the primary replica has an // index of 0). try { JSON_ASSERT_CONTAINS(doc, JSON_IDS); JSON_ASSERT_ARRAY(doc[JSON_IDS]); const rapidjson::Value& ids_arr = doc[JSON_IDS]; // The request is valid, so respond with a 202. Now loop through the // the body and update the replica trackers. send_http_reply(HTTP_ACCEPTED); for (rapidjson::Value::ConstValueIterator ids_it = ids_arr.Begin(); ids_it != ids_arr.End(); ++ids_it) { try { TimerID timer_id; int replica_index; JSON_GET_INT_64_MEMBER(*ids_it, JSON_ID, timer_id); JSON_GET_INT_MEMBER(*ids_it, JSON_REPLICA_INDEX, replica_index); // Update the timer's replica_tracker to show that the replicas // at level 'replica_index' and higher have been informed // about the timer. This will tombstone the timer if all // replicas have been informed. _cfg->_handler->update_replica_tracker_for_timer(timer_id, replica_index); } catch (JsonFormatError err) { TRC_INFO("JSON entry was invalid (hit error at %s:%d)", err._file, err._line); } } } catch (JsonFormatError err) { TRC_INFO("JSON body didn't contain the IDs array"); send_http_reply(HTTP_BAD_REQUEST); } }