Roxen.git / server / protocols / http.pike

version» Context lines:

Roxen.git/server/protocols/http.pike:17:   #define TIMER_PREFIX "http:"   #include <timers.h>      inherit RequestID;      #ifdef PROFILE   #define HRTIME() gethrtime()   int req_time = HRTIME();   #endif    + #define WEBSOCKET_DEBUG +  + #ifdef WEBSOCKET_DEBUG + #define WS_DEBUG werror + #else + #define WS_DEBUG(X...) + #endif /* WEBSOCKET_DEBUG */ +    #ifdef REQUEST_DEBUG   int footime, bartime;   #define REQUEST_WERR(X) do { \    if (this) { \    bartime = gethrtime()-footime; \    werror("%s (%d)\n", (X), bartime); \    footime=gethrtime(); \    } else { \    werror("%s\n", (X)); \    } \
Roxen.git/server/protocols/http.pike:1482:    xml_data = 0;    request_uuid = UNDEFINED;   }      void end(int|void keepit)   {    if (my_fd) {    CHECK_FD_SAFE_USE;    }    +  if (websocket) { +  websocket->end(); +  websocket = 0; +  } +     cleanup_request_object();       if(keepit    && !file->raw    && misc->connection != "close"    && my_fd    // Is this necessary now when this function no longer is called    // from the close callback? /mast    && !catch(my_fd->query_address()) )    { -  +  if (file->upgrade_websocket) { + #ifdef CONNECTION_DEBUG +  werror("HTTP[%s]: Transitioning to WebSocket ------------------------\n", +  DEBUG_GET_FD); + #else +  REQUEST_WERR("HTTP: Transitioning to WebSocket."); + #endif +  websocket = WebSocket(this, file->websocket_api, leftovers); +  websocket->masking = file->masking; +  my_fd = 0; +  pipe = 0; +  return; +  }    // Now.. Transfer control to a new http-object. Reset all variables etc..    object o = object_program(this_object())(0, 0, 0);    o->remoteaddr = remoteaddr;       // Don't share these since proxies can send different user-agent headers    // when multiplexing several clients into one connection    //o->client = client;    //o->supports = supports;    //o->client_var = client_var;   
Roxen.git/server/protocols/http.pike:2025:    conf->log(file, this_object());       json_logger->log(([    "event" : "LOG_REQUEST",    "htime" : handle_time,    "qtime" : queue_time,    "rtime" : gethrtime()-hrtime,    ]));    }    } +     if( !port_obj )    {    TIMER_END(do_log);    MERGE_TIMERS(conf);    if( conf )    conf->connection_drop( this_object() );    call_out (disconnect, 0);    return;    }    TIMER_END(do_log);
Roxen.git/server/protocols/http.pike:3172:    }       handle_request();       }) {    call_out (disconnect, 0);    report_error("Internal server error: " + describe_backtrace(err));    }   }    + //! Set to a @[WebSocket] object if this connection is upgraded to a + //! websocket. + object websocket; +  + //! Call this method to send a text frame across the websocket + //! connection. + //! + //! @returns 1 if this isn't an open websocket connection. + public int websocket_send_text(string text) { +  if (!websocket || +  websocket->state != Protocols.WebSocket.Connection.OPEN) { +  return 1; +  } +  +  websocket->send_text(text); +  return 0; + } +  + //! Call this method to send a binary frame across the websocket + //! connection. + //! + //! @returns 1 if this isn't an open websocket connection. + public int websocket_send_binary(string data) { +  if (!websocket || +  websocket->state != Protocols.WebSocket.Connection.OPEN) { +  return 1; +  } +  +  websocket->send_binary(data); +  return 0; + } +  +  +    void handle_request()   {    if (mixed err = catch {       REQUEST_WERR("HTTP: handle_request()");    TIMER_START(handle_request);    json_logger->log(([    "event" : "HANDLE_REQUEST_BEGIN",    "qtime" : queue_time,    ]));   #ifdef TIMERS   #define LOG_HANDLE_END() do { json_logger->log((["event" : "HANDLE_REQUEST_END", "handle_time" : timers->handle_request ])); } while(0)   #else   #define LOG_HANDLE_END()   #endif    -  +    #ifdef MAGIC_ERROR    if(prestate->old_error)    {    array err = get_error(variables->error, variables->error_md5 || "NONE");    if(err && arrayp(err))    {    if(prestate->plain)    {    file = ([    "type":"text/plain",
Roxen.git/server/protocols/http.pike:3249:    // should probably be destruct_threadbound_session_objects calls    // there too. /mast       if (this)    destruct_threadbound_session_objects();       if(e)    INTERNAL_ERROR( e );       else { +  if (result && result->upgrade_websocket) { +  REQUEST_WERR("HTTP: handle_request: Preparing for upgrade to websocket.\n"); +  +  if (method != Roxen.WEBSOCKET_OPEN_METHOD) { +  error("Invalid attempt to upgrade to websocket.\n"); +  } +  +  Protocols.WebSocket.Request ws_req = Protocols.WebSocket.Request(0); +  ws_req->request_headers = request_headers; +  +  mapping(string:string) ws_headers = ([]); + #if constant(Protocols.WebSocket.Extension) +  array ws_extensions = ({}); +  [ws_headers, ws_extensions] = +  ws_req->low_websocket_accept(result->websocket_protocol, +  result->websocket_extensions); +  result->parsed_websocket_extensions = ws_extensions; + #else +  ws_headers = ws_req->low_websocket_accept(result->websocket_protocol); + #endif +  +  REQUEST_WERR(sprintf("HTTP: ws_headers: %O\n", ws_headers)); +  +  result->extra_heads += ws_headers; +  misc->connection = "Upgrade"; +  +  NO_PROTO_CACHE(); +  +  REQUEST_WERR("HTTP: handle_request: socket prepared for upgrade.\n"); +  } +     if (result && result->pipe) {    REQUEST_WERR("HTTP: handle_request: pipe in progress.");    TIMER_END(handle_request);    json_logger->log(([    "event" : "PIPE_BEGIN",    ]));    LOG_HANDLE_END();    return;    }    file = result;