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.394 2004/04/04 00:13:11 mani Exp $";
+ constant cvs_version = "$Id: http.pike,v 1.395 2004/04/04 00:37: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:597:
static Roxen.HeaderParser hp = Roxen.HeaderParser();
static function(string:array(string|mapping)) hpf = hp->feed;
int last;
private int parse_got( string new_data )
{
TIMER_START(parse_got);
if( !method )
{
array res;
- if( catch( res = hpf( new_data ) ) )
+ if( mixed err = catch( res = hpf( new_data ) ) ) {
+ #ifdef DEBUG
+ report_debug("Got bad request, HeaderParser error: " +
+ describe_error(err));
+ #endif
return 1;
-
+ }
if( !res )
{
TIMER_END(parse_got);
return 0; // Not enough data
}
data = res[0];
line = res[1];
request_headers = res[2];
}
return parse_got_2();
Roxen.git/server/plugins/protocols/http.pike:891:
o->chain(fd,port_obj,leftovers);
pipe = 0;
disconnect();
return;
}
pipe = 0;
if(objectp(my_fd))
{
MARK_FD("HTTP closed");
- catch
+ mixed err = catch
{
// Don't set to blocking mode if SSL.
if (!my_fd->CipherSpec) {
my_fd->set_blocking();
}
my_fd->close();
destruct(my_fd);
};
- catch {
+ #ifdef DEBUG
+ if (err) report_debug ("Close failure (1): %s", describe_backtrace (err));
+ #endif
+ err = catch {
my_fd = 0;
};
-
+ #ifdef DEBUG
+ if (err) report_debug ("Close failure (2): %s", describe_backtrace (err));
+ #endif
}
disconnect();
}
static void do_timeout()
{
int elapsed = predef::time(1)-time;
if(time && elapsed >= 30)
{
REQUEST_WERR("HTTP: Connection timed out. Closing.");
Roxen.git/server/plugins/protocols/http.pike:1135:
report_error("Internal server error: " +
describe_backtrace(err) + "\n");
#ifdef INTERNAL_ERROR_DEBUG
report_error("Raw backtrace:%O\n", err);
#endif /* INTERNAL_ERROR_DEBUG */
}
// This macro ensures that something gets reported even when the very
// call to internal_error() fails. That happens eg when this_object()
// has been destructed.
- #define INTERNAL_ERROR(err) \
- if (mixed __eRr = catch (internal_error (err))) \
- report_error("Internal server error: " + describe_backtrace(err) + \
- "internal_error() also failed: " + describe_backtrace(__eRr))
+ #define INTERNAL_ERROR(err) do { \
+ if (mixed __eRr = catch (internal_error (err))) \
+ report_error("Internal server error: " + describe_backtrace(err) + \
+ "internal_error() also failed: "+describe_backtrace(__eRr));\
+ } while(0)
int wants_more()
{
return !!cache;
}
void do_log( Shuffler.Shuffle r, int reason )
{
MARK_FD("HTTP logging"); // fd can be closed here
int fsent = r->sent_data();
Roxen.git/server/plugins/protocols/http.pike:1164:
file->len += misc->_log_cheat_addition;
conf->log(file, this_object());
}
if( !port_obj )
{
TIMER_END(do_log);
MERGE_TIMERS(conf);
if( conf )
conf->connection_drop( this_object() );
- catch // paranoia
+ mixed err = catch // paranoia
{
my_fd->close();
destruct( my_fd );
destruct( );
};
-
+ #ifdef DEBUG
+ if (err) report_debug ("Close failure (3): %s", describe_backtrace (err));
+ #endif
return;
}
TIMER_END(do_log);
end(1);
return;
}
#ifdef FD_DEBUG
void timer(int start)
{
Roxen.git/server/plugins/protocols/http.pike:1493:
if ( fstat[ST_MTIME] > misc->last_modified )
misc->last_modified = fstat[ST_MTIME];
}
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.
+ if (misc->cacheable < INITIAL_CACHEABLE) {
+ // Data with expiry is assumed to have been generated at
+ // the same instant.
misc->last_modified = predef::time(1);
}
}
else
heads["Expires"] = Roxen.http_date( predef::time(1)+misc->cacheable );
}
if (misc->last_modified)
heads["Last-Modified"] = Roxen.http_date(misc->last_modified);
Roxen.git/server/plugins/protocols/http.pike:1617:
heads["Content-Length"] = (string)file->len;
// Some browsers, e.g. Netscape 4.7, doesn't trust a zero
// content length when using keep-alive. So let's force a
// close in that case.
if( file->error/100 == 2 && file->len <= 0 )
{
heads->Connection = "close";
misc->connection = "close";
}
- if( catch( head_string += Roxen.make_http_headers( heads ) ) )
+ if( mixed err = catch( head_string += Roxen.make_http_headers( heads ) ) )
{
-
+ #ifdef DEBUG
+ report_debug("Roxen.make_http_headers failed: " +
+ describe_error(err));
+ #endif
foreach( heads; string x; mixed head )
if( stringp( head ) )
head_string += x+": "+head+"\r\n";
else if( arrayp( head ) )
foreach( head, string xx )
head_string += x+": "+xx+"\r\n";
else if( catch {
head_string += x+": "+(string)head;
} )
error("Illegal value in headers array! "
Roxen.git/server/plugins/protocols/http.pike:1734: Inside #if defined(MAGIC_ERROR)
return;
}
}
}
}
#endif /* MAGIC_ERROR */
MARK_FD("HTTP handling request");
array e;
- if(e= catch(file = conf->handle_request( this_object() )))
+ mapping result;
+ if(e= catch(result = conf->handle_request( this_object() )))
INTERNAL_ERROR( e );
-
+ else {
+ if (result && result->pipe)
+ // Could be destructed here already since handle_request might
+ // have handed over us to another thread that finished quickly.
+ return;
+ file = result;
+ }
+
if( file )
if( file->try_again_later )
{
if( objectp( file->try_again_later ) )
;
else
call_out( core.handle, file->try_again_later, handle_request );
return;
}
- else if( file->pipe )
- return;
+
TIMER_END(handle_request);
send_result();
}
string url_base()
// See the RequestID class for doc.
{
// Note: Code duplication in server_core/prototypes.pike.
if (!cached_url_base) {
Roxen.git/server/plugins/protocols/http.pike:1844:
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 )
conf->connection_drop( this_object() );
- catch // paranoia
+ mixed err = catch // paranoia
{
my_fd->set_blocking();
my_fd->close();
destruct( my_fd );
destruct( );
};
-
+ #ifdef DEBUG
+ if (err) report_debug ("Close failure (4): %s", describe_backtrace (err));
+ #endif
return;
}
switch( parse_got( s ) )
{
case 0:
REQUEST_WERR("HTTP: Request needs more data.");
return;
case 1:
Roxen.git/server/plugins/protocols/http.pike:1961:
}
}
if( conf )
{
conf->connection_add( this_object(), ([]) );
conf->received += strlen(raw);
conf->requests++;
}
my_fd->set_close_callback(0);
my_fd->set_read_callback(0);
+ if (my_fd->set_accept_callback) my_fd->set_accept_callback(0);
processed=1;
remove_call_out(do_timeout);
#ifdef RAM_CACHE
TIMER_START(cache_lookup);
array cv;
if( prot != "HTTP/0.9" &&
misc->cacheable &&
-
+ !misc->no_proto_cache &&
!since &&
(cv = conf->datacache->get( raw_url )) )
{
MY_TRACE_ENTER (sprintf ("Found %O in ram cache - checking entry", raw_url), 0);
if( !cv[1]->key ) {
MY_TRACE_LEAVE ("Entry invalid due to zero key");
conf->datacache->expire_entry( raw_url );
}
else
{
Roxen.git/server/plugins/protocols/http.pike:2141:
if(!(my_fd && objectp(my_fd)))
end();
else if((predef::time(1) - time) > 4800)
end();
}
static void create(object f, object c, object cc)
{
if(f)
{
- f->set_read_callback(got_data);
- f->set_close_callback(end);
+ f->set_nonblocking(got_data, f->query_write_callback(), end);
my_fd = f;
MARK_FD("HTTP connection");
if( c ) port_obj = c;
if( cc ) conf = cc;
time = predef::time(1);
call_out(do_timeout, 90);
}
root_id = this_object();
}
void chain( object f, object c, string le )
{
my_fd = f;
- f->set_read_callback(0);
- f->set_close_callback(end);
+ f->set_nonblocking(0, f->query_write_callback(), end);
port_obj = c;
processed = 0;
do_not_disconnect=-1; // Block destruction until we return.
MARK_FD("HTTP kept alive");
- time = predef::time(1);
+ time = predef::time();
if ( strlen( le ) )
got_data( 0,le );
else
{
// If no pipelined data is available, call out...
remove_call_out(do_timeout);
call_out(do_timeout, 90);
}
Roxen.git/server/plugins/protocols/http.pike:2186:
{
do_not_disconnect=0;
disconnect();
}
}
else
{
if(do_not_disconnect == -1)
do_not_disconnect = 0;
if(!processed)
- {
- my_fd->set_read_callback(got_data);
- my_fd->set_close_callback(end);
+ f->set_nonblocking(got_data, f->query_write_callback(), end);
}
}
- }
+
string _sprintf(int t)
{
if(t!='O') return 0;
return "RequestID(" + (raw_url||"") + ")"
#ifdef ID_OBJ_DEBUG
+ (__marker ? "[" + __marker->count + "]" : "")
#endif
;
}
Stdio.File connection( )
{
return my_fd;
}
Configuration configuration()
{
return conf;
}