Roxen.git / server / plugins / protocols / http.pike

version» Context lines:

Roxen.git/server/plugins/protocols/http.pike:1:   // This is a ChiliMoon protocol module.   // Modified by Francesco Chemolli to add throttling capabilities.   // Copyright © 1996 - 2001, Roxen IS.    - constant cvs_version = "$Id: http.pike,v 1.393 2003/01/23 16:21:02 mani Exp $"; + constant cvs_version = "$Id: http.pike,v 1.394 2004/04/04 00:13:11 mani Exp $";   // #define REQUEST_DEBUG   #define MAGIC_ERROR      // HTTP protocol module.   #include <config.h>   #define TIMER_PREFIX "http:"   #include <timers.h>      inherit RequestID;   
Roxen.git/server/plugins/protocols/http.pike:48:   #define THROTTLING_DEBUG(X)   #endif      constant decode = MIME.decode_base64;   constant find_supports_and_vars = core.find_supports_and_vars;   constant version = core.version;   constant _query = core.query;      private static array(string) cache;   private static int wanted_data, have_data; + private static String.Buffer data_buffer;      #include <roxen.h>   #include <module.h>   #include <variables.h>   #include <request_trace.h>      #define MY_TRACE_ENTER(A, B) \    do {RequestID id = this_object(); TRACE_ENTER (A, B);} while (0)   #define MY_TRACE_LEAVE(A) \    do {RequestID id = this_object(); TRACE_LEAVE (A);} while (0)      mapping(string:array) real_variables = ([]);   mapping(string:mixed)|FakedVariables variables = FakedVariables( real_variables );      mapping (string:mixed) misc =   ([ - #if 0 +    #ifdef REQUEST_DEBUG    "trace_enter":lambda(mixed ...args) {    REQUEST_WERR(sprintf("TRACE_ENTER(%{%O,%})", args));    },    "trace_leave":lambda(mixed ...args) {    REQUEST_WERR(sprintf("TRACE_LEAVE(%{%O,%})", args));    }   #endif // REQUEST_DEBUG - #endif +    ]);   mapping (string:string) cookies = ([ ]);   mapping (string:string) request_headers = ([ ]);   mapping (string:string) client_var = ([ ]);      multiset (string) prestate = (< >);   multiset (string) config = (< >);   multiset (string) pragma = (< >);      mapping file;
Roxen.git/server/plugins/protocols/http.pike:324:      void start_sender( )   {   #ifdef FD_DEBUG    call_out(timer, 30, predef::time(1)); // Update FD with time...   #endif    if( throttler || conf->throttler )    pipe->set_throttler( throttler || conf->throttler );    pipe->set_done_callback( do_log );    pipe->start( ); +  data_buffer = 0;    pipe = 0;   }      string scan_for_query( string f )   {    query=0;    rest_query="";    if(sscanf(f,"%s?%s", f, query) == 2)    {    string v, a, b;
Roxen.git/server/plugins/protocols/http.pike:541: Inside #if undefined(DISABLE_SUPPORTS)
   if( !client_var->Fullname )    client_var->Fullname = "unknown";    client_var->fullname=lower_case(client_var->Fullname);    array s_and_v=find_supports_and_vars(client_var->fullname,supports,client_var);    supports = s_and_v[0];    client_var = s_and_v[1];    }    }    if ( client_var->charset && client_var->charset != "iso-8859-1" )    { -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    set_output_charset( client_var->charset );    input_charset = client_var->charset;    decode_charset_encoding( client_var->charset );    }   #else    supports = (< "images", "gifinline", "forms", "mailto">);   #endif    //REQUEST_WERR("HTTP: parse_got(): supports");    if(!referer) referer = ({ });    if(misc->proxyauth)
Roxen.git/server/plugins/protocols/http.pike:658:    clientprot = prot = "HTTP/0.9";    if(method != "PING")    method = "GET"; // 0.9 only supports get.    else    {    my_fd->write("PONG\r\n");    return 2;    }    s = data = ""; // no headers or extra data...    sscanf( f, "%s%*[\r\n]", f ); -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    break;       case 0:    /* Not reached */    break;    }    REQUEST_WERR(sprintf("HTTP: request line %O", line));    REQUEST_WERR(sprintf("HTTP: headers %O", request_headers));    REQUEST_WERR(sprintf("HTTP: data (length %d) %O", strlen(data),data));    raw_url = f;
Roxen.git/server/plugins/protocols/http.pike:1104:   }      array get_error(string eid)   {    return cache_lookup( "http_bt_error", (int)eid );   }         void internal_error(array _err)   { -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    mixed err = _err;    _err = 0; // hide in backtrace, they are bad enough anyway...    array err2;    if(port_obj && port_obj->query("show_internals"))    {    err2 = catch {    file = Roxen.http_low_answer(500, format_backtrace(store_error(err)));    };    if(err2) {    werror("Internal server error in internal_error():\n" +
Roxen.git/server/plugins/protocols/http.pike:1431:   #endif    ;    array p;    if(!(p=conf->profile_map[nid]))    p = conf->profile_map[nid] = ({0,0.0,0.0});    p[0]++;    p[1] += elapsed;    if(elapsed > p[2]) p[2]=elapsed;   #endif    -  REQUEST_WERR(sprintf("HTTP: response: prot %O, method %O, file %O", -  prot, method, file)); +  REQUEST_WERR(sprintf("HTTP: response: prot %O, method %O, file %O, misc: %O", +  prot, method, file, misc));    -  +  if( prot == "HTTP/0.9" ) misc->no_proto_cache = 1; +     if(!leftovers)    leftovers = data||"";       if(!mappingp(file))    { -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    if(misc->error_code)    file = Roxen.http_low_answer(misc->error_code, errors[misc->error]);    else if(err = catch {    file = conf->error_file( this_object() );    })    INTERNAL_ERROR(err);    }    else    {    if((file->file == -1) || file->leave_me)
Roxen.git/server/plugins/protocols/http.pike:1486:       if( Stat fstat = file->stat )    {    if( !file->len )    file->len = fstat[1];       if ( fstat[ST_MTIME] > misc->last_modified )    misc->last_modified = fstat[ST_MTIME];    }    -  if( misc->cacheable < INITIAL_CACHEABLE ) { +  if( !zero_type(misc->cacheable) && +  misc->cacheable < INITIAL_CACHEABLE ) {    if (misc->cacheable == 0) {    heads["Expires"] = Roxen.http_date( 0 );       if (!misc->last_modified) {    // Data with immediate expiry is assumed to have been generated    // at the same instant.    misc->last_modified = predef::time(1);    }    }    else
Roxen.git/server/plugins/protocols/http.pike:1511:    heads["Last-Modified"] = Roxen.http_date(misc->last_modified);       if(since && (!file->error || file->error == 200) && misc->last_modified)    {    // ({ time, len })    array(int) since_info = Roxen.parse_since( since );       if ( (since_info[0] >= misc->last_modified) &&    ((since_info[1] == -1) || (since_info[1] == file->len))    // never say 'not modified' if cacheable has been lowered. -  && (misc->cacheable >= INITIAL_CACHEABLE) ) +  && (zero_type(misc->cacheable) || +  misc->cacheable >= INITIAL_CACHEABLE) )    {    file->error = 304;    file->file = 0;    file->data="";    }    }       if(prot != "HTTP/0.9")    {    string h, charset="";
Roxen.git/server/plugins/protocols/http.pike:1569:    // Also we only bother with 200-requests. Anything else should be    // nicely and completely ignored. Also this is only used for GET and    // HEAD requests.    {    // split the range header. If no valid ranges are found, ignore it.    // If one is found, send that range. If many are found we need to    // use a wrapper and send a multi-part message.    array ranges = parse_range_header(file->len);    if(ranges) // No incorrect syntax...    { -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    if(sizeof(ranges)) // And we have valid ranges as well.    {    file->error = 206; // 206 Partial Content    if(sizeof(ranges) == 1)    {    heads["Content-Range"] = sprintf("bytes %d-%d/%d",    @ranges[0], file->len);    file->start = ranges[0][0];    file->len = ranges[0][1] - ranges[0][0]+1;    } else {
Roxen.git/server/plugins/protocols/http.pike:1803:    * =================================================    */   int processed;   // array ccd = ({});   void got_data(mixed fooid, string s)   {    REQUEST_WERR(sprintf("HTTP: Got %O", s));       if(wanted_data)    { -  data += s; +     if(strlen(s) + have_data < wanted_data)    { -  +  if(!data_buffer) { +  // The 16384 is some reasonable extra padding to +  // avoid having to realloc. +  data_buffer = String.Buffer(wanted_data + 16384); +  data_buffer->add(data); +  data = ""; +  } +  data_buffer->add(s);    have_data += strlen(s); -  +     // Reset timeout.    remove_call_out(do_timeout);    call_out(do_timeout, 90);    REQUEST_WERR("HTTP: We want more data.");    return;    } -  +  if(data_buffer) { +  data_buffer->add(s); +  data = (string)data_buffer; +  data_buffer = 0;    } -  +  else +  data += s; +  }       if (mixed err = catch {    MARK_FD("HTTP got data");    raw += s;       // The port has been closed, but old (probably keep-alive)    // connections remain. Close those connections.    if( !port_obj )    {    if( conf )
Roxen.git/server/plugins/protocols/http.pike:1856:    "\r\n");    end();    return; // Stupid request.       case 2:    REQUEST_WERR("HTTP: Done.");    end();    return;    }    -  if( method == "GET" ) +  if( (< "GET", "HEAD" >)[method] )    misc->cacheable = INITIAL_CACHEABLE; // FIXME: Make configurable.       TIMER_START(find_conf);    string path;    if( !conf || !(path = port_obj->path )    || (sizeof( path )    && raw_url[..sizeof(path) - 1] != path) )       {    // FIXME: port_obj->name & port_obj->default_port are constant
Roxen.git/server/plugins/protocols/http.pike:1910:    }    }    else if( strlen(path) )    adjust_for_config_path( path );       TIMER_END(find_conf);       if (rawauth)    {    /* Need to authenticate with the configuration */ -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    array(string) y = rawauth / " ";    realauth = 0;    auth = 0;    if (sizeof(y) >= 2)    {    y[1] = MIME.decode_base64(y[1]);    realauth = y[1];    }    }          if( misc->proxyauth )    {    /* Need to authenticate with the configuration */ -  misc->cacheable = 0; +  misc->no_proto_cache = 1;    if (sizeof(misc->proxyauth) >= 2)    {    // misc->proxyauth[1] = MIME.decode_base64(misc->proxyauth[1]);    if (conf->auth_module)    misc->proxyauth    = conf->auth_module->auth(misc->proxyauth,this_object() );    }    }    if( conf )    {
Roxen.git/server/plugins/protocols/http.pike:2028: Inside #if defined(RAM_CACHE)
   start_sender( );    return;    }   #ifndef RAM_CACHE_ASUME_STATIC_CONTENT    else    MY_TRACE_LEAVE (    sprintf ("Entry out of date (disk: %s, cache: mtime %d)",    st ? "mtime " + st->mtime : "gone", file->mtime));   #endif    } else -  misc->cacheable = 0; // Never cache in this case. +  misc->no_proto_cache = 1; // Never cache in this case.    file = 0;    }    }    TIMER_END(cache_lookup);   #endif // RAM_CACHE    TIMER_START(parse_request);    if( things_to_do_when_not_sending_from_cache( ) )    return;    TIMER_END(parse_request);