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 Sat Feb 21 21:05:28 2004 for WvStreams by doxygen 1.3.5