Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
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);
}
Example #8
0
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);
}
Example #9
0
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;
}
Example #10
0
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);
  }
}
Example #11
0
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);
  }
}