RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
plugins/adserver/http_adserver_connector.cc
00001 /* http_adserver_connector.cc                                       -*- C++ -*-
00002    Wolfgang Sourdeau, April 2013
00003    Copyright (c) 2013 Datacratic.  All rights reserved.
00004 */
00005 
00006 
00007 #include <memory>
00008 
00009 #include "http_adserver_connector.h"
00010 
00011 
00012 using namespace std;
00013 using namespace RTBKIT;
00014 
00015 
00016 /****************************************************************************/
00017 /* HTTPADSERVERCONNECTIONHANDLER                                            */
00018 /****************************************************************************/
00019 
00020 HttpAdServerConnectionHandler::
00021 HttpAdServerConnectionHandler(HttpAdServerHttpEndpoint & endpoint,
00022                               const HttpAdServerRequestCb & requestCb)
00023     : endpoint_(endpoint), requestCb_(requestCb)
00024 {
00025 }
00026 
00027 void
00028 HttpAdServerConnectionHandler::
00029 handleJson(const HttpHeader & header, const Json::Value & json,
00030            const string & jsonStr)
00031 {
00032     string resultMsg;
00033 
00034     transport().assertLockedByThisThread();
00035 
00036     auto onSendFinished = [&] () {
00037         Date endRq = Date::now();
00038         double timeElapsedMs = endRq.secondsSince(this->firstData) * 1000;
00039         endpoint_.doEvent("rqTimeMs", ET_OUTCOME, timeElapsedMs);
00040 
00041         this->transport().associateWhenHandlerFinished
00042         (endpoint_.makeNewHandler(), "rqFinished");
00043     };
00044 
00045     try {
00046         requestCb_(header, json, jsonStr);
00047         resultMsg = ("HTTP/1.1 200 OK\r\n"
00048                      "Content-Type: none\r\n"
00049                      "Content-Length: 0\r\n"
00050                      "\r\n");
00051     }
00052     catch (const exception & exc) {
00053         cerr << "error parsing adserver request " << json << ": "
00054              << exc.what() << endl;
00055         endpoint_.doEvent("error.rqParsingError");
00056 
00057         Json::Value responseJson;
00058         responseJson["error"] = "error parsing AdServer message";
00059         responseJson["message"] = json;
00060         responseJson["details"] = exc.what();
00061 
00062         string response = responseJson.toString();
00063         resultMsg = ML::format("HTTP/1.1 400 Bad Request\r\n"
00064                                "Content-Type: text/json\r\n"
00065                                "Content-Length: %zd\r\n"
00066                                "\r\n%s",
00067                                response.size(), response.c_str());
00068     }
00069 
00070     send(resultMsg,
00071          NEXT_CONTINUE,
00072          onSendFinished);
00073 }
00074 
00075 
00076 /****************************************************************************/
00077 /* HTTPADSERVERHTTPENDPOINT                                                 */
00078 /****************************************************************************/
00079 
00080 HttpAdServerHttpEndpoint::
00081 HttpAdServerHttpEndpoint(int port, const HttpAdServerRequestCb & requestCb)
00082     : HttpEndpoint("adserver-ep-" + to_string(port)),
00083       port_(port), requestCb_(requestCb)
00084 {
00085 }
00086 
00087 HttpAdServerHttpEndpoint::
00088 HttpAdServerHttpEndpoint(HttpAdServerHttpEndpoint && otherEndpoint)
00089 : HttpEndpoint("adserver-ep-" + to_string(otherEndpoint.port_))
00090 {
00091     port_ = otherEndpoint.port_;
00092     requestCb_ = otherEndpoint.requestCb_;
00093 }
00094 
00095 HttpAdServerHttpEndpoint::
00096 ~HttpAdServerHttpEndpoint()
00097 {
00098     shutdown();
00099 }
00100 
00101 HttpAdServerHttpEndpoint &
00102 HttpAdServerHttpEndpoint::
00103 operator = (const HttpAdServerHttpEndpoint& other)
00104 {
00105     if (this != &other) {
00106         port_ = other.port_;
00107         requestCb_ = other.requestCb_;
00108     }
00109 
00110     return *this;
00111 }
00112 
00113 int
00114 HttpAdServerHttpEndpoint::
00115 getPort()
00116     const
00117 {
00118     return port_;
00119 }
00120 
00121 shared_ptr<ConnectionHandler>
00122 HttpAdServerHttpEndpoint::
00123 makeNewHandler()
00124 {
00125     return std::make_shared<HttpAdServerConnectionHandler>(*this, requestCb_);
00126 }
00127 
00128 
00129 /****************************************************************************/
00130 /* HTTPADSERVERCONNECTOR                                                    */
00131 /****************************************************************************/
00132 
00133 HttpAdServerConnector::
00134 HttpAdServerConnector(const string & serviceName,
00135                       const shared_ptr<Datacratic::ServiceProxies> & proxy)
00136     : AdServerConnector(serviceName, proxy)
00137 {
00138 }
00139 
00140 void
00141 HttpAdServerConnector::
00142 registerEndpoint(int port, const HttpAdServerRequestCb & requestCb)
00143 {
00144     endpoints_.emplace_back(port, requestCb);
00145 }
00146 
00147 void
00148 HttpAdServerConnector::
00149 init(const shared_ptr<ConfigurationService> & config)
00150 {
00151     AdServerConnector::init(config);
00152     for (HttpAdServerHttpEndpoint & endpoint: endpoints_) {
00153         auto onEvent = bind(&ServiceBase::recordEvent, this,
00154                             placeholders::_1, placeholders::_2,
00155                             placeholders::_3);
00156         endpoint.onEvent = onEvent;
00157     }
00158 }
00159 
00160 void
00161 HttpAdServerConnector::
00162 shutdown()
00163 {
00164     for (HttpAdServerHttpEndpoint & endpoint: endpoints_) {
00165         endpoint.shutdown();
00166     }
00167     AdServerConnector::shutdown();
00168 }
00169 
00170 void
00171 HttpAdServerConnector::
00172 bindTcp()
00173 {
00174     for (HttpAdServerHttpEndpoint & endpoint: endpoints_) {
00175         endpoint.init(endpoint.getPort(), "0.0.0.0", 4);
00176     }
00177 }
00178 
00179 void
00180 HttpAdServerConnector::
00181 start()
00182 {
00183     for (HttpAdServerHttpEndpoint & endpoint: endpoints_) {
00184         endpoint.makeRealTime(10);
00185     }
00186     AdServerConnector::start();
00187 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator