From 815fd86031dc233748168bda450c5d7aec6261b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sundstr=C3=B6m?= <oyasumi@gmail.com> Date: Sat, 25 Nov 2000 06:31:20 +0100 Subject: [PATCH] Fixed a randomly-lose bug in dns_lookup(), another bug in _sprintf(), made keep-alive work for synchronous requests and did some whitespace trimming. Rev: lib/modules/Protocols.pmod/HTTP.pmod/Query.pike:1.24 --- .../Protocols.pmod/HTTP.pmod/Query.pike | 140 +++++++++++------- 1 file changed, 84 insertions(+), 56 deletions(-) diff --git a/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike b/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike index 067953f740..86d6b7b240 100644 --- a/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike +++ b/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike @@ -10,7 +10,7 @@ **! method object thread_request(string server,int port,string query); **! method object thread_request(string server,int port,string query,mapping headers,void|string data); **! Create a new query object and begin the query. -**! +**! **! The query is executed in a background thread; **! call '() in this object to wait for the request **! to complete. @@ -73,13 +73,13 @@ **! string protocol,int status,string status_desc}); **! **! method mapping cast("mapping") -**! Gives back -**! headers | +**! Gives back +**! headers | **! (["protocol":protocol, **! "status":status number, **! "status_desc":status description, **! "data":data]); -**! +**! **! method string cast("string") **! Gives back the answer as a string. **! @@ -101,7 +101,7 @@ **! This could be used to copy the file to disc at **! a proper tempo. **! -**! datafile() doesn't give the complete request, +**! datafile() doesn't give the complete request, **! just the data. **! **! newheaders, removeheaders is applied as: @@ -129,7 +129,7 @@ string status_desc; int timeout=120; // seconds -// internal +// internal object con; string request; @@ -150,21 +150,19 @@ static void ponder_answer() { // read until we have all headers - int i=0; - int j=0; - - for (;;) + int i = 0, j = 0; + for(;;) { string s; if (i<0) i=0; - j=search(buf,"\r\n\r\n",i); if (j==-1) j=10000000; - i=search(buf,"\n\n",i); if (i==-1) i=10000000; + j=search(buf, "\r\n\r\n", i); if(j==-1) j=10000000; + i=search(buf, "\n\n", i); if(i==-1) i=10000000; if ((i=min(i,j))!=10000000) break; s=con->read(8192,1); if (s=="") { i=strlen(buf); break; } - + i=strlen(buf)-3; buf+=s; } @@ -239,9 +237,9 @@ static void async_read(mixed dummy,string s) #ifdef HTTP_QUERY_DEBUG werror("-> %d bytes of data\n",strlen(s)); #endif - + buf+=s; - if (-1!=search(buf,"\r\n\r\n") || -1!=search(buf,"\n\n")) + if (-1!=search(buf,"\r\n\r\n") || -1!=search(buf,"\n\n")) { con->set_blocking(); ponder_answer(); @@ -284,7 +282,7 @@ static void async_timeout() if (con) { catch { con->close(); }; - destruct(con); + destruct(con); } con=0; async_failed(); @@ -303,7 +301,7 @@ void async_got_host(string server,int port) con=Stdio.File(); if (!con->open_socket()) error("HTTP.Query(): can't open socket; "+strerror(con->errno)+"\n"); - }) + }) { return; // got timeout already, we're destructed } @@ -351,7 +349,7 @@ string headers_encode(mapping h) { if (stringp(headers[hname]) || intp(headers[hname])) - return String.capitalize(replace(hname,"_","-")) + + return String.capitalize(replace(hname,"_","-")) + ": " + headers[hname]; }, h )*"\r\n" + "\r\n"; } @@ -401,9 +399,9 @@ string dns_lookup(string hostname) (id=hostname_cache[hostname])) return id; - array hosts=((Protocols.DNS.client()->gethostbyname(hostname)|| - ({0,0}))[1]+({0})); - return hosts[random(sizeof(hosts))]; + array hosts = (Protocols.DNS.client()->gethostbyname( hostname )|| + ({ 0, 0 }))[1]; + return sizeof(hosts) && hosts[random(sizeof( hosts ))]; } @@ -425,7 +423,7 @@ object thread_request(string server,int port,string query, void|mapping|string headers,void|string data) { // start open the connection - + con=Stdio.File(); if (!con->open_socket()) error("HTTP.Query(): can't open socket; "+strerror(con->errno)+"\n"); @@ -448,7 +446,7 @@ object thread_request(string server,int port,string query, headers=headers_encode(headers); } - + request=query+"\r\n"+headers+"\r\n"+data; conthread=thread_create(connect,server,port); @@ -458,46 +456,70 @@ object thread_request(string server,int port,string query, #endif -object sync_request(string server,int port,string query, - void|mapping|string headers,void|string data) +object sync_request(string server, int port, string query, + void|mapping|string http_headers, + void|string data) { - // start open the connection - - con=Stdio.File(); - if (!con->open_socket()) + int kept_alive; + string ip = dns_lookup( server ); + if(ip) server = ip; // cheaty, if host doesn't exist + + // start open the connection + + if(con && con->_fd && + con->query_address() == server + " " + port && + lower_case( headers->connection ) != "close") + { +#ifdef HTTP_QUERY_DEBUG + werror("** Connection kept alive!\n"); +#endif + kept_alive = 1; + } + else + { + con = Stdio.File(); + if(!con->open_socket()) error("HTTP.Query(): can't open socket; "+strerror(con->errno)+"\n"); + } - string server1=dns_lookup(server); + // prepare the request - if (server1) server=server1; // cheaty, if host doesn't exist + errno = ok = protocol = headers = status_desc = status = datapos = 0; + buf = ""; - // prepare the request + if(!data) + data = ""; - if (!data) data=""; + if(!http_headers) + http_headers = ""; + else if(mappingp( http_headers )) + { + http_headers = mkmapping(map(indices( http_headers ), lower_case), + values( http_headers )); - if (!headers) headers=""; - else if (mappingp(headers)) - { - headers=mkmapping(Array.map(indices(headers),lower_case), - values(headers)); + if(data != "") + http_headers->content_length = strlen( data ); - if (data!="") headers->content_length=strlen(data); + http_headers = headers_encode( http_headers ); + } - headers=headers_encode(headers); - } - - request=query+"\r\n"+headers+"\r\n"+data; + request = query + "\r\n" + http_headers + "\r\n" + data; - connect(server,port); + if(kept_alive) + { + con->write( request ); + ponder_answer(); + } else + connect(server, port); - return this_object(); + return this_object(); } object async_request(string server,int port,string query, void|mapping|string headers,void|string data) { // start open the connection - + call_out(async_timeout,timeout); // prepare the request @@ -514,9 +536,9 @@ object async_request(string server,int port,string query, headers=headers_encode(headers); } - + request=query+"\r\n"+headers+"\r\n"+data; - + dns_lookup_async(server,async_got_host,port); return this_object(); @@ -540,7 +562,7 @@ string data() #endif int len=(int)headers["content-length"]; int l; - if (zero_type(len)) + if (zero_type(len)) l=0x7fffffff; else l=len-strlen(buf)+datapos; @@ -555,8 +577,13 @@ string data() else buf += con->read(l); } - // note! this can't handle keep-alive × HEAD requests. - return buf[datapos..]; +#ifdef HTTP_QUERY_NOISE + werror("buf[datapos..] : %O\n", buf[datapos + ..min(sizeof(buf), datapos+19)]); + werror("buf[..datapos+len] : %O\n", buf[max(0, datapos+len-19) + ..min(sizeof(buf), datapos+len)]); +#endif + return buf[datapos..datapos+len]; } int downloaded_bytes() @@ -615,7 +642,7 @@ class PseudoFile string read(int n) { string s; - + if (len && p+n>len) n=len-p; if (strlen(buf)<n && con) @@ -650,7 +677,7 @@ object file(void|mapping newheader,void|mapping removeheader) if (hbuf=="") hbuf="\r\n"; if (zero_type(headers["content-length"])) len=0x7fffffff; - else + else len=strlen(protocol+" "+status+" "+status_desc)+2+ strlen(hbuf)+2+(int)headers["content-length"]; return PseudoFile(con, @@ -659,7 +686,7 @@ object file(void|mapping newheader,void|mapping removeheader) } if (zero_type(headers["content-length"])) len=0x7fffffff; - else + else len=strlen(headerbuf)+4+(int)h["content-length"]; return PseudoFile(con,buf,len); } @@ -682,7 +709,7 @@ void async_fetch(function callback,mixed ... extra) if (!con) { callback(@extra); // nothing to do, stupid... - return; + return; } extra_args=extra; request_ok=callback; @@ -691,7 +718,8 @@ void async_fetch(function callback,mixed ... extra) string _sprintf() { - return sprintf("Query(%d %s)", status, status_desc); + return status ? sprintf("Query(%d %s)", status, status_desc) + : "Query()"; } /************************ example *****************************/ -- GitLab