• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

http.h

Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
00003 // 
00004 // This program is free software; you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation; either version 3 of the License, or
00007 // (at your option) any later version.
00008 // 
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 // 
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017 //
00018 
00019 #ifndef GNASH_LIBNET_HTTP_H
00020 #define GNASH_LIBNET_HTTP_H
00021 
00022 #include <string>
00023 #include <map>
00024 #include <vector>
00025 #include <boost/shared_ptr.hpp>
00026 #include <boost/shared_array.hpp>
00027 #include <boost/scoped_array.hpp>
00028 #include <sstream>
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include "gnashconfig.h"
00032 #endif
00033 
00034 #include "amf.h"
00035 #include "cque.h"
00036 #include "rtmp.h"
00037 //#include "handler.h"
00038 #include "network.h"
00039 #include "buffer.h"
00040 #include "diskstream.h"
00041 
00042 namespace gnash
00043 {
00044     
00045 class DSOEXPORT HTTP : public gnash::Network
00046 {
00047 public:
00048 // as defined by the W3: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
00049     typedef enum {
00050         // 1xx: Informational - Request received, continuing process
00051         CONTINUE = 100,
00052         SWITCHPROTOCOLS = 101,
00053         // 2xx: Success - The action was successfully received,
00054         // understood, and accepted
00055         OK = 200,
00056         CREATED = 201,
00057         ACCEPTED = 202,
00058         NON_AUTHORITATIVE = 203,
00059         NO_CONTENT = 204,
00060         RESET_CONTENT = 205,
00061         PARTIAL_CONTENT = 206,
00062         // 3xx: Redirection - Further action must be taken in order to
00063         // complete the request
00064         MULTIPLE_CHOICES = 300,
00065         MOVED_PERMANENTLY = 301,
00066         FOUND = 302,
00067         SEE_OTHER = 303,
00068         NOT_MODIFIED = 304,
00069         USE_PROXY = 305,
00070         TEMPORARY_REDIRECT = 307,
00071         // 4xx: Client Error - The request contains bad syntax or
00072         // cannot be fulfilled
00073         BAD_REQUEST = 400,
00074         UNAUTHORIZED = 401,
00075         PAYMENT_REQUIRED = 402,
00076         FORBIDDEN = 403,
00077         NOT_FOUND = 404,
00078         METHOD_NOT_ALLOWED = 405,
00079         NOT_ACCEPTABLE = 406,
00080         PROXY_AUTHENTICATION_REQUIRED = 407,
00081         REQUEST_TIMEOUT = 408,
00082         CONFLICT = 409,
00083         GONE = 410,
00084         LENGTH_REQUIRED = 411,
00085         PRECONDITION_FAILED = 412,
00086         REQUEST_ENTITY_TOO_LARGE = 413,
00087         REQUEST_URI_TOO_LARGE = 414,
00088         UNSUPPORTED_MEDIA_TYPE = 415,
00089         REQUESTED_RANGE_NOT_SATISFIABLE = 416,
00090         EXPECTATION_FAILED = 417,
00091         // 5xx: Server Error - The server failed to fulfill an apparently valid request
00092         INTERNAL_SERVER_ERROR = 500,
00093         NOT_IMPLEMENTED = 501,
00094         BAD_GATEWAY = 502,
00095         SERVICE_UNAVAILABLE = 503,
00096         GATEWAY_TIMEOUT = 504,
00097         HTTP_VERSION_NOT_SUPPORTED = 505,
00098         // Gnash/Cygnal extensions for internal use
00099         LIFE_IS_GOOD = 1234,
00100         CLOSEPIPE = 1235
00101     } http_status_e;
00102     typedef enum {
00103         HTTP_NONE,
00104         HTTP_OPTIONS,
00105         HTTP_GET,
00106         HTTP_HEAD,
00107         HTTP_POST,
00108         HTTP_PUT,
00109         HTTP_DELETE,
00110         HTTP_TRACE,
00111         HTTP_CONNECT,
00112         HTTP_RESPONSE           // unique to gnash
00113     } http_method_e;
00114     typedef enum {
00115         OPEN,
00116         SEND,
00117         IDLE,
00118         CLOSE
00119     } rtmpt_cmd_e;
00120     // A response from an FTTP request has a code an an error message
00121     typedef struct {
00122         http_status_e code;
00123         std::string   msg;
00124     } http_response_t;
00125     typedef struct {
00126         int major;
00127         int minor;
00128     } http_version_t;
00129     HTTP();
00130 //     HTTP(Handler *hand);
00131     ~HTTP();
00132 
00133     // Check the Header fields to make sure they're valid values.
00134     bool checkRequestFields(cygnal::Buffer &buf);
00135     bool checkEntityFields(cygnal::Buffer &buf);
00136     bool checkGeneralFields(cygnal::Buffer &buf);
00137 
00138 //     // Parse an Echo Request message coming from the Red5 echo_test.
00139     std::vector<boost::shared_ptr<cygnal::Element > > parseEchoRequest(cygnal::Buffer &buf) { return parseEchoRequest(buf.reference(), buf.size()); };
00140     std::vector<boost::shared_ptr<cygnal::Element > > parseEchoRequest(boost::uint8_t *buf, size_t size);
00141     
00142     // Convert the Content-Length field to a number we can use
00143     size_t getContentLength();
00144 
00145     // process all the header fields in the Buffer, storing them internally
00146     // in _fields. The address returned is the address where the Content data
00147     // starts, and is "Content-Length" bytes long, of "Content-Type" data.
00148     boost::uint8_t *processHeaderFields(cygnal::Buffer *buf);
00149     
00150     // Get the field for header 'name' that was stored by processHeaderFields()
00151     std::string &getField(const std::string &name) { return _fields[name]; };
00152     size_t NumOfFields() { return _fields.size(); };
00153     void clearFields() { _fields.clear(); };
00154     std::map<std::string, std::string> &getFields() { return _fields; };
00155 
00156     // Get an array of values for header field 'name'.
00157     boost::shared_ptr<std::vector<std::string> > getFieldItem(const std::string &name);
00158 
00159     // Client side parsing of response message codes
00160     boost::shared_ptr<http_response_t> parseStatus(const std::string &line);
00161 
00162     // Handle the response for the request.
00163     boost::shared_ptr<cygnal::Buffer> formatServerReply(http_status_e code);
00164     cygnal::Buffer &formatGetReply(DiskStream::filetype_e type, size_t size, http_status_e code); 
00165     cygnal::Buffer &formatGetReply(size_t size, http_status_e code); 
00166     cygnal::Buffer &formatGetReply(http_status_e code); 
00167     cygnal::Buffer &formatPostReply(rtmpt_cmd_e code);
00168 
00169     // Make copies of ourself
00170     HTTP &operator = (HTTP &obj);
00171 
00174     bool clearHeader();
00175 
00181     bool startHeader();
00182     
00188     cygnal::Buffer &formatCommon(const std::string &data);
00189 
00190     cygnal::Buffer &formatHeader(DiskStream::filetype_e type, size_t filesize,
00191                             http_status_e code);
00192     cygnal::Buffer &formatHeader(size_t filesize, http_status_e type);
00193     cygnal::Buffer &formatHeader(http_status_e type);
00194     cygnal::Buffer &formatRequest(const std::string &url, http_method_e req);
00195     // format a response to the 'echo' test used for testing Gnash.
00196     cygnal::Buffer &formatEchoResponse(const std::string &num, cygnal::Element &el);
00197     cygnal::Buffer &formatEchoResponse(const std::string &num, cygnal::Buffer &data);
00198     cygnal::Buffer &formatEchoResponse(const std::string &num, boost::uint8_t *data, size_t size);
00199 
00200     cygnal::Buffer &formatMethod(const std::string &data)
00201         {return formatCommon("Method: " + data); };
00202     cygnal::Buffer &formatDate();
00203     cygnal::Buffer &formatServer();
00204     cygnal::Buffer &formatServer(const std::string &data);
00205     cygnal::Buffer &formatReferer(const std::string &data)
00206         {return formatCommon("Referer: " + data); };
00207     cygnal::Buffer &formatConnection(const std::string &data)
00208         {return formatCommon("Connection: " + data); };
00209     cygnal::Buffer &formatKeepAlive(const std::string &data)
00210         {return formatCommon("Keep-Alive: " + data); };
00211     cygnal::Buffer &formatContentLength();
00212     cygnal::Buffer &formatContentLength(boost::uint32_t filesize);
00213     cygnal::Buffer &formatContentType();
00214     cygnal::Buffer &formatContentType(DiskStream::filetype_e type);
00215     cygnal::Buffer &formatHost(const std::string &data)
00216         {return formatCommon("Host: " + data); };
00217     cygnal::Buffer &formatAgent(const std::string &data)
00218         {return formatCommon("User-Agent: " + data); };
00219     cygnal::Buffer &formatAcceptRanges(const std::string &data)
00220         {return formatCommon("Accept-Ranges: " + data); };
00221     cygnal::Buffer &formatLastModified();
00222     cygnal::Buffer &formatLastModified(const std::string &data)
00223         {return formatCommon("Last-Modified: " + data); }
00224     cygnal::Buffer &formatEtag(const std::string &data)
00225         {return formatCommon("Etag: " + data); };
00226     cygnal::Buffer &formatLanguage(const std::string &data)
00227         {return formatCommon("Accept-Language: " + data); };
00228     cygnal::Buffer &formatCharset(const std::string &data)
00229         {return formatCommon("Accept-Charset: " + data); };
00230     cygnal::Buffer &formatEncoding(const std::string &data)
00231         {return formatCommon("Accept-Encoding: " + data); };
00232     cygnal::Buffer &formatTE(const std::string &data)
00233         {return formatCommon("TE: " + data); };
00234     // All HTTP messages are terminated with a blank line
00235     void terminateHeader() { _buffer += "\r\n"; };    
00236     
00237 //     cygnal::Buffer &formatErrorResponse(http_status_e err);
00238     
00239     // Return the header that's been built up.
00240     boost::uint8_t *getHeader() { return _buffer.reference(); };
00241 
00242     // Return the header that's been built up.
00243     cygnal::Buffer &getBuffer() { return _buffer; };
00244 
00245 //     // Return the body that's been built up.
00246 //     std::string getBody() { return _body.str(); };
00247 
00248     // Get the file type, so we know how to set the
00249     // Content-type in the header.
00250 //    filetype_e getFileType(std::string &filespec);
00251 //    amf::AMF::filetype_e getFileStats(std::string &filespec);
00252     void dump();
00253 
00259     int recvMsg(int fd);
00260     int recvMsg(int fd, size_t size);
00261 
00262     size_t recvChunked(boost::uint8_t *data, size_t size);
00263     
00274     int sendMsg();
00275     int sendMsg(int fd);
00276     int sendMsg(const boost::uint8_t *data, size_t size);
00277     int sendMsg(boost::shared_ptr<cygnal::Buffer> &buf)
00278         { return sendMsg(buf->reference(), buf->size()); };
00279     int sendMsg(std::stringstream &sstr)
00280         { return sendMsg(reinterpret_cast<const boost::uint8_t *>(sstr.str().c_str()), sstr.str().size()); };
00281     
00282     // These accessors are used mostly just for debugging.
00283     bool keepAlive() { return _keepalive; }
00284     void keepAlive(bool x) { _keepalive = x; };
00285     
00286     int getMaxRequests() { return _max_requests; }
00287     int getFileSize() { return _filesize; }
00288     std::string &getFilespec() { return _filespec; }
00289     std::string &getParams() { return _params; }
00290   //    std::string &getURL() { return _url; }
00291     std::map<int, struct status_codes *> getStatusCodes()
00292         { return _status_codes; }
00293     http_version_t *getVersion() { return &_version; }
00294     
00295 //     void setHandler(Handler *hand) { _handler = hand; };
00296     void setDocRoot(const std::string &path) { _docroot = path; };
00297     std::string &getDocRoot() { return _docroot; };
00298     
00299     // Pop the first date element off the que
00300     boost::shared_ptr<cygnal::Buffer> DSOEXPORT popChunk() { return _que.pop(); };
00301     // Peek at the first date element witjhout removing it from the que
00302     boost::shared_ptr<cygnal::Buffer> DSOEXPORT peekChunk() { return _que.peek(); };
00303     // Get the number of elements in the que
00304     size_t DSOEXPORT sizeChunks() { return _que.size(); };
00305 
00306     boost::shared_ptr<cygnal::Buffer> DSOEXPORT mergeChunks() { return _que.merge(); };
00307 
00308     http_method_e getOperation() { return _cmd; };
00309     
00310 protected:
00311     // Examine the beginning of the data for an HTTP request command
00312     // like GET or POST, etc...
00313     http_method_e extractCommand(boost::uint8_t *data);
00314     http_method_e extractCommand(cygnal::Buffer &data)
00315         { return extractCommand(data.reference()); };    
00316 
00317     typedef boost::char_separator<char> Sep;
00318     typedef boost::tokenizer<Sep> Tok;
00319     http_method_e       _cmd;
00320 
00321     cygnal::Buffer              _buffer;
00322     CQue                _que;
00323     
00324     DiskStream::filetype_e  _filetype;
00325     std::string         _filespec;
00326     std::string         _params;
00327     boost::uint32_t     _filesize;
00328     std::map<int, struct status_codes *> _status_codes;
00329     
00330     std::map<std::string, std::string> _fields;
00331     http_version_t      _version;
00332     
00333     // Connection parameters we care about
00334     bool                _keepalive;
00335 //     Handler          *_handler;
00336     // These two field hold the data from an RTMPT message
00337     int                 _clientid;
00338     int                 _index;
00339     int                 _max_requests;
00340     std::string         _docroot;
00341 
00342     bool                _close;
00343 };  
00344 
00345 // This is the thread for all incoming HTTP connections for the server
00346 extern "C" {
00347     bool DSOEXPORT http_handler(Network::thread_params_t *args);
00348 }
00349 
00350 
00351 } // end of gnash namespace
00352 
00353 // end of _HTTP_H_
00354 #endif
00355 
00356 
00357 // local Variables:
00358 // mode: C++
00359 // indent-tabs-mode: t
00360 // End:

Generated on Fri Mar 16 2012 15:46:10 for Gnash by  doxygen 1.7.1