00001
00002
00003
00004
00005
00006
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
00023
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
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
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)
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;
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 }