Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvhttp.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvHTTPStream connects to an HTTP server and allows the requested file 00006 * to be retrieved using the usual WvStream-style calls. 00007 */ 00008 #include "wvhttp.h" 00009 #include "strutils.h" 00010 #include <assert.h> 00011 00012 00013 00014 WvHTTPStream::WvHTTPStream(const WvURL &_url) 00015 : WvStreamClone(NULL), headers(7), client_headers(7), 00016 url(_url) 00017 { 00018 state = Resolving; 00019 num_received = 0; 00020 tcp = NULL; 00021 00022 // we need this: if the URL tried to dns-resolve before, but failed, 00023 // this might make isok() true again if the name has turned up. 00024 url.resolve(); 00025 } 00026 00027 00028 bool WvHTTPStream::isok() const 00029 { 00030 if (cloned) 00031 return WvStreamClone::isok(); 00032 else 00033 return url.isok(); 00034 } 00035 00036 00037 int WvHTTPStream::geterr() const 00038 { 00039 if (cloned) 00040 return WvStreamClone::geterr(); 00041 else 00042 return -1; 00043 } 00044 00045 00046 WvString WvHTTPStream::errstr() const 00047 { 00048 if (cloned) 00049 return WvStreamClone::errstr(); 00050 else if (!url.isok()) 00051 return url.errstr(); 00052 else 00053 return "Unknown error! (no stream yet)"; 00054 } 00055 00056 00057 bool WvHTTPStream::pre_select(SelectInfo &si) 00058 { 00059 if (!isok()) return false; 00060 00061 switch (state) 00062 { 00063 case Resolving: 00064 if (!url.isok()) 00065 seterr("Invalid URL"); 00066 else if (url.resolve()) 00067 { 00068 state = Connecting; 00069 cloned = tcp = new WvTCPConn(url.getaddr()); 00070 } 00071 return false; 00072 00073 case Connecting: 00074 tcp->select(0, false, true, false); 00075 if (!tcp->isconnected()) 00076 return false; 00077 if (tcp->geterr()) 00078 return false; 00079 00080 // otherwise, we just finished connecting: start transfer. 00081 state = ReadHeader1; 00082 delay_output(true); 00083 print("GET %s HTTP/1.0\r\n", url.getfile()); 00084 print("Host: %s:%s\r\n", url.gethost(), url.getport()); 00085 { 00086 WvHTTPHeaderDict::Iter i(client_headers); 00087 for (i.rewind(); i.next(); ) 00088 { 00089 print("%s: %s\r\n", i().name, i().value); 00090 } 00091 } 00092 print("\r\n"); 00093 delay_output(false); 00094 00095 // FALL THROUGH! 00096 00097 default: 00098 return WvStreamClone::isok() 00099 && WvStreamClone::pre_select(si); 00100 } 00101 } 00102 00103 00104 size_t WvHTTPStream::uread(void *buf, size_t count) 00105 { 00106 char *line; 00107 int retval; 00108 size_t len; 00109 00110 switch (state) 00111 { 00112 case Resolving: 00113 case Connecting: 00114 break; 00115 00116 case ReadHeader1: 00117 line = trim_string(tcp->getline(0)); 00118 if (line) // got response code line 00119 { 00120 if (strncmp(line, "HTTP/", 5)) 00121 { 00122 seterr("Invalid HTTP response"); 00123 return 0; 00124 } 00125 00126 retval = atoi(trim_string(line+9)); 00127 00128 if (retval / 100 != 2) 00129 { 00130 seterr(WvString("HTTP error: %s", trim_string(line+9))); 00131 return 0; 00132 } 00133 00134 state = ReadHeader; 00135 } 00136 break; 00137 00138 case ReadHeader: 00139 line = trim_string(tcp->getline(0)); 00140 if (line) 00141 { 00142 if (!line[0]) 00143 state = ReadData; // header is done 00144 else 00145 { 00146 char *cptr = strchr(line, ':'); 00147 if (!cptr) 00148 headers.add(new WvHTTPHeader(line, ""), true); 00149 else 00150 { 00151 *cptr++ = 0; 00152 line = trim_string(line); 00153 cptr = trim_string(cptr); 00154 headers.add(new WvHTTPHeader(line, cptr), true); 00155 } 00156 } 00157 } 00158 break; 00159 00160 case ReadData: 00161 len = tcp->read(buf, count); 00162 num_received += len; 00163 return len; 00164 00165 case Done: 00166 break; 00167 } 00168 00169 return 0; 00170 }

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7