1998-02-10
1998-02-10 18:36:21 by Per Hedbor <ph@opera.com>
-
e5bad2a884ffb5e57effe6de7069bc486e4c5a9b
(348 lines)
(+37/-311)
[
Show
| Annotate
]
Branch: 5.2
Fixes...
Rev: server/base_server/cache.pike:1.19
Rev: server/base_server/color.pike:1.13
Rev: server/base_server/configuration.pike:1.94
Rev: server/base_server/disk_cache.pike:1.34
Rev: server/base_server/dummy_hosts.pike:1.5
Rev: server/base_server/html.pike:1.4
Rev: server/base_server/language.pike:1.12
Rev: server/base_server/lock.pike:1.3(DEAD)
Rev: server/base_server/mainconfig.pike:1.94
Rev: server/base_server/module_support.pike:1.15
Rev: server/base_server/newdecode.pike:1.7
Rev: server/base_server/privs.pike:1.33
Rev: server/base_server/read_config.pike:1.20
Rev: server/base_server/roxen.pike:1.166
Rev: server/base_server/roxenlib.pike:1.47
Rev: server/base_server/roxenloader.pike:1.58
Rev: server/base_server/smartpipe.pike:1.1
Rev: server/base_server/socket.pike:1.11
Rev: server/modules/filesystems/filesystem.pike:1.27
Rev: server/modules/filesystems/restrictedfs.pike:1.8
Rev: server/modules/filesystems/userfs.pike:1.18
Rev: server/modules/filters/htaccess.pike:1.29
Rev: server/modules/filters/redirect.pike:1.12
Rev: server/modules/graphics/graphic_text.pike:1.101
Rev: server/modules/misc/contenttypes.pike:1.11
Rev: server/modules/misc/demo.pike:1.2
Rev: server/modules/misc/ismap.pike:1.11
Rev: server/modules/misc/userdb.pike:1.24
Rev: server/modules/misc/ypuserdb.pike:1.7
Rev: server/protocols/http.pike:1.54
1:
// This is a roxen module. (c) Informationsvävarna AB 1996.
- constant cvs_version = "$Id: http.pike,v 1.53 1998/02/05 00:59:26 js Exp $";
+ constant cvs_version = "$Id: http.pike,v 1.54 1998/02/10 18:36:21 per Exp $";
// HTTP protocol module.
#include <config.h>
private inherit "roxenlib";
22:
constant version=roxen->version;
constant handle=roxen->handle;
constant _query=roxen->query;
+ constant thepipe = roxen->pipe;
import Simulate;
32:
object conf;
- #ifdef REQUEST_DEBUG
- int kept_alive;
- #endif
-
+
#include <roxen.h>
#include <module.h>
- #undef SPEED_MAX
+
#undef QUERY
#if constant(cpp)
88:
string rawauth, realauth;
string since;
- #if _DEBUG_HTTP_OBJECTS
- int my_id;
- int my_state;
- #endif
-
+
// Parse a HTTP/1.1 HTTP/1.0 or 0.9 request, including form data and
// state variables. Return 0 if more is expected, 1 if done, and -1
// if fatal error.
void end(string|void);
- private void setup_pipe(int noend)
+ private void setup_pipe()
{
- #ifndef __NT__
- #if _DEBUG_HTTP_OBJECTS
- my_state = 6;
- #endif
- if(!my_fd) {
+ if(!my_fd)
+ {
end();
return;
}
- if(!pipe) pipe=Pipe.pipe();
- // if(!noend) pipe->set_done_callback(end);
+ if(!pipe) pipe=thepipe();
#ifdef REQUEST_DEBUG
perror("REQUEST: Pipe setup.\n");
#endif
// pipe->output(my_fd);
- #endif
+
}
- void send(string|object what, int|void noend)
+ void send(string|object what, int|void len)
{
- #ifndef __NT__
- #if _DEBUG_HTTP_OBJECTS
- my_state = 7;
- #endif
+
if(!what) return;
- if(!pipe) setup_pipe(noend);
-
+ if(!pipe) setup_pipe();
+ if(!pipe) return;
#ifdef REQUEST_DEBUG
perror("REQUEST: Sending some data\n");
#endif
if(stringp(what)) pipe->write(what);
- else pipe->input(what);
- #else
- #endif
- my_fd->write(objectp(what)?what->read():what);
+ else pipe->input(what,len);
}
string scan_for_query( string f )
{
- #if _DEBUG_HTTP_OBJECTS
- my_state = 8;
- #endif
+
if(sscanf(f,"%s?%s", f, query) == 2)
{
string v, a, b;
172:
string url, m;
string base;
base = conf->query("MyWorldLocation")||"/";
- #if _DEBUG_HTTP_OBJECTS
- my_state = 8;
- #endif
+
if(supports->cookies)
{
#ifdef REQUEST_DEBUG
241:
private int parse_got(string s)
{
- #if _DEBUG_HTTP_OBJECTS
- if(my_fd) catch{mark_fd(my_fd->query_fd(), "HTTP: Parsing");};
- my_state = 9;
- #endif
+
multiset (string) sup;
array mod_config;
mixed f, line;
255:
real_raw = s;
s -= "\r"; // I just hate all thoose CR LF.
- // if(strlen(s) < 3)
- // return 0; // Not finished, I promise.
-
+
if((s[-1] != '\n') || (search(s, "HTTP/") >= 0))
if(search(s, "\n\n") == -1)
return 0;
321:
if(!remoteaddr)
{
if(my_fd) catch(remoteaddr = ((my_fd->query_address()||"")/" ")[0]);
- if(!remoteaddr) this_object()->end();
+ if(!remoteaddr) {
+ end();
+ return 0;
}
-
+ }
- #if 0
- sscanf(f,"%s;%s", f, range);
- #endif
-
+
f = scan_for_query( f );
// f = http_decode_string( f );
- if (sscanf(f, "/<%s>%s", a, f))
+ if (sscanf(f, "/<%s>/%s", a, f)==2)
{
config_in_url = 1;
mod_config = (a/",");
-
+ f = "/"+f;
}
- if (sscanf(f, "/(%s)%s", a, f) && strlen(a))
+ if ((sscanf(f, "/(%s)/%s", a, f)==2) && strlen(a))
+ {
prestate = aggregate_multiset(@(a/","-({""})));
-
+ f = "/"+f;
+ }
not_query = simplify_path(http_decode_string(f));
376:
if(strlen(data) <= l) // \r are included.
{
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] = "Parsed data - short post...";
- #endif
+
return 0;
}
data = data[..l];
536:
case "proxy-by":
case "proxy-maintainer":
case "proxy-software":
- #ifdef MORE_HEADERS
- if(misc[linename])
- misc[linename] += explode(contents-" ", ",");
- else
- misc[linename] = explode(contents-" ", ",");
- #endif
+
case "mime-version":
break;
590:
raw = tmp2 * "\n";
}
- #if _DEBUG_HTTP_OBJECTS
- my_state = 10;
- roxen->httpobjects[my_id] = sprintf("%O - %O", raw_url, remoteaddr);
- #endif
+
if(config_in_url) {
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] = "Configuration request?...";
- #endif
+
return really_set_config( mod_config );
}
if(!supports->cookies)
608:
&& not_query[0]=='/' && method!="PUT"
&& QUERY(set_cookie))
{
- #ifdef DEBUG
- perror("Setting unique ID.\n");
- #endif
+
if (!(QUERY(set_cookie_only_once) &&
cache_lookup("hosts_for_cookie",remoteaddr))) {
misc->moreheads = ([ "Set-Cookie":http_roxen_id_cookie(), ]);
618:
if (QUERY(set_cookie_only_once))
cache_set("hosts_for_cookie",remoteaddr,1);
}
- #ifdef DEBUG
- #if DEBUG_LEVEL > 30
- else
- perror("Unique ID: "+cookies->RoxenUserID+"\n");
- #endif
- #endif
+
return 1; // Done.
}
void disconnect()
{
- #if _DEBUG_HTTP_OBJECTS
- my_state = 2;
- #endif
+
if(do_not_disconnect)
{
#ifdef REQUEST_DEBUG
651:
destruct(file->file);
}
}
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] += " - disconnect";
- #endif
+
my_fd = 0;
// };
destruct();
}
- #ifdef KEEP_CONNECTION_ALIVE
- void no_more_keep_connection_alive(mapping foo)
- {
- if(!pipe || !objectp(my_fd)) end();
- }
- #endif
-
+
void end(string|void s)
{
-
+ #ifdef REQUEST_DEBUG
+ perror("REQUEST: End...\n");
+ #endif
#ifdef PROFILE
if(conf)
{
680: Inside #if defined(PROFILE)
if(elapsed > p[2]) p[2]=elapsed;
}
#endif
- // trace(9);
- #if _DEBUG_HTTP_OBJECTS
- if(my_fd) catch{mark_fd(my_fd->query_fd(), "");};
- my_state = 1;
- #endif
- // array err = catch {
- #ifdef REQUEST_DEBUG
- perror("REQUEST: End...\n");
- #endif
- #ifdef KEEP_CONNECTION_ALIVE
- remove_call_out(no_more_keep_connection_alive);
- #endif
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] += " - end";
- #endif
+
if(objectp(my_fd))
{
my_fd->set_blocking();
706:
}
my_fd = 0;
}
- // };
- // if(err)
- // roxen_perror("END: %O\n", describe_backtrace(err));
+
disconnect();
- // trace(0);
+
}
static void do_timeout(mapping foo)
718:
int elapsed = HRTIME()-req_time;
if(elapsed > HRSEC(30))
{
- #if _DEBUG_HTTP_OBJECTS
- my_state = 10;
+ #ifdef REQUEST_DEBUG
+ perror("Timeout. Closing down...\n");
#endif
- // perror("Timeout. Closing down...\n");
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] += " - timed out";
- #endif
+
end("HTTP/1.0 408 Timeout\r\n"
"Content-type: text/plain\r\n"
"Server: Roxen Challenger\r\n"
733:
"Please try again.\n");
} else {
// premature call_out...
- werror("got premature call_out to do_timeout. Odd.\n");
+
call_out(do_timeout, 10);
}
}
- #ifdef KEEP_CONNECTION_ALIVE
- void got_data(mixed fooid, string s);
+
- void keep_connection_alive()
- {
- pipe=0;
- if(my_fd) {
- my_fd->set_read_callback(got_data);
- my_fd->set_close_callback(end);
- }
- /*my_fd->set_write_callback(lambda(){});*/
-
- if(cache && strlen(cache))
- got_data(1, "");
- else
- call_out(no_more_keep_connection_alive, 100);
- }
- #endif
-
-
+
mapping internal_error(array err)
{
if(QUERY(show_internals))
812:
]);
- void do_log(array id)
+ void do_log(array|void id)
{
if(conf)
{
826:
conf->log(file, this_object());
}
}
- my_fd=0;
- pipe=file=0;
- destruct();
+ end();
+ return;
}
void handle_request( )
{
- #if _DEBUG_HTTP_OBJECTS
- mark_fd(my_fd->query_fd(), "HTTP: Handling");
- my_state = 15;
- #endif
+
mixed *err;
int tmp;
- #ifdef KEEP_CONNECTION_ALIVE
- int keep_alive;
- #endif
+
function funp;
mapping heads;
string head_string;
object thiso=this_object();
- #ifndef SPEED_MAX
- // perror("Removing timeout call_out...\n");
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] += " - handled";
- #endif
+
remove_call_out(do_timeout);
- #endif
+
if(conf)
{
952:
file->len += strlen(file->data);
}
- #ifdef KEEP_CONNECTION_ALIVE
- #ifdef REQUEST_DEBUG
- if(kept_alive)
- perror(sprintf("Connection: Kept alive %d times.\n", kept_alive));
- #endif
- if(misc->connection && search(misc->connection, "keep-alive") != -1)
- {
- if(file->len > 0)
- {
- heads->Connection = "keep-alive; timeout=100, maxreq=666";
- keep_alive=1;
- #ifdef REQUEST_DEBUG
- kept_alive++;
- #endif
- }
- }
- #endif
-
+
if(mappingp(file->extra_heads)) {
heads |= file->extra_heads;
}
992:
head_string = (myheads+({"",""}))*"\r\n";
if(conf) conf->hsent+=strlen(head_string||"");
-
- if(method=="HEAD")
- {
- if(conf)conf->log(file, thiso);
- #ifdef KEEP_CONNECTION_ALIVE
- if(keep_alive)
- {
- my_fd->write(head_string);
- misc->connection = 0;
- keep_connection_alive();
- } else
- #endif
- end(head_string);
- return;
+
}
-
- #ifdef USE_SHUFFLE
- if(!file->data &&
- (file->len<=0 || (file->len > 300000))
- #ifdef KEEP_CONNECTION_ALIVE
- && !keep_alive
- #endif
- && objectp(file->file))
+ if(head_string) send(head_string);
+ if(method != "HEAD")
{
- if(head_string) my_fd->write(head_string);
- shuffle( file->file, my_fd );
- if(conf)conf->log(file, thiso);
- my_fd=file->file=file=pipe=0;
- return;
+ if(file->data) send(file->data, file->len);
+ if(file->file) send(file->file, file->len);
}
- #endif
-
- if(file->len <
- #ifdef THREADS
- 65535
- #else
- 3000
- #endif
- &&
- #ifdef KEEP_CONNECTION_ALIVE
- !keep_alive &&
- #endif
- file->len >= 0)
- {
- if(file->data) head_string += file->data;
- if(file->file)
- {
- head_string += file->file->read();
- destruct(file->file);
- }
-
- if(conf)
- {
- file->len = strlen( head_string );
- conf->log(file, thiso);
- }
- end(head_string);
- return;
- }
- }
-
- if(head_string) send(head_string);
- if(file->data) send(file->data);
- if(file->file) send(file->file);
- #ifndef __NT__
- pipe->output(my_fd);
+
pipe->set_done_callback( do_log, ({ pipe, file }) );
- #endif
-
- #ifdef KEEP_CONNECTION_ALIVE
- if(keep_alive)
- {
- if(my_fd)
- {
- misc->connection=0;
- pipe->set_done_callback(keep_connection_alive);
+ pipe->output(my_fd);
}
- }
- #endif
- }
+
/* We got some data on a socket.
* =================================================
1080:
void got_data(mixed fooid, string s)
{
int tmp;
- #if _DEBUG_HTTP_OBJECTS
- my_state = 3;
- #endif
+
// perror("Got data.\n");
- #ifndef SPEED_MAX
- // perror("Removing timeout call_out...\n");
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] = ("Got data - "+remoteaddr +" - "+ctime(_time())) - "\n";
- #endif
+
remove_call_out(do_timeout);
call_out(do_timeout, 30); // Close down if we don't get more data
// within 30 seconds. Should be more than enough.
- #endif
+
if(wanted_data)
{
if(strlen(s)+have_data < wanted_data)
1109:
s = cache*"";
cache = 0;
}
- #ifdef KEEP_CONNECTION_ALIVE
- remove_call_out(no_more_keep_connection_alive);
- #endif
+
tmp = parse_got(s);
switch(-tmp)
{
1127:
end();
return;
}
- #if _DEBUG_HTTP_OBJECTS
- roxen->httpobjects[my_id] += " - finished getting data.";
- #endif
+
if(conf)
{
conf->received += strlen(s);
1140:
my_fd->set_read_callback(0);
my_fd->set_blocking();
#ifdef THREADS
- #if 0
- if(conf)
- #endif
+
roxen->handle(this_object()->handle_request);
- #if 0
- else // config interface requests get their own threads..
- {
- object t = thread_create(handle_request);
- catch(t->set_name("Config IF"));
- }
- #endif
+
#else
- this_object()->handle_request();
+ handle_request();
#endif
}
1162:
object clone_me()
{
object c,t;
- #if _DEBUG_HTTP_OBJECTS
- my_state = 4;
- #endif
+
c=object_program(t=this_object())();
c->first = first;
1209:
c->realauth = realauth;
c->rawauth = rawauth;
c->since = since;
- #if _DEBUG_HTTP_OBJECTS
- if(!c->my_id)
- c->my_id = roxen->new_id();
- roxen->httpobjects[c->my_id] = roxen->httpobjects[my_id] + " - clone";
- roxen->httpobjects[my_id] += " - CLONED";
- #endif
+
return c;
}
void clean()
{
- #if _DEBUG_HTTP_OBJECTS
- my_state = 4;
- #endif
+
if(!(my_fd && objectp(my_fd))) end();
else if((_time(1) - time) > 4800) end();
}
- #if _DEBUG_HTTP_OBJECTS
- void destroy()
- {
- if(my_fd) catch{mark_fd(my_fd->query_fd(), "");};
- roxen->httpobjects->num--;
- m_delete(roxen->httpobjects, my_id);
- }
- #endif
-
+
void create(object f, object c)
{
-
- #if _DEBUG_HTTP_OBJECTS
- my_state = 5;
- roxen->httpobjects->num++;
- #endif
+
if(f)
{
- #if _DEBUG_HTTP_OBJECTS
- if(!my_id)
- my_id = roxen->new_id();
- #endif
+
my_fd = f;
my_fd->set_read_callback(got_data);
my_fd->set_close_callback(end);
- #if _DEBUG_HTTP_OBJECTS
- if(my_fd) catch(remoteaddr = ((my_fd->query_address()||"")/" ")[0]);
- roxen->httpobjects[my_id] = ("Created - "+
- remoteaddr +" - "+ctime(_time())) - "\n" ;
- #endif
+
conf = c;
mark_fd(my_fd->query_fd(), "HTTP connection");
- #ifndef SPEED_MAX
+
// No need to wait more than 30 seconds to get more data.
call_out(do_timeout, 30);
- // There seems to be a bug where call_outs go missing... which is
- // now fixed...
- #endif
+
}
}