00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00049 typedef enum {
00050
00051 CONTINUE = 100,
00052 SWITCHPROTOCOLS = 101,
00053
00054
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
00063
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
00072
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
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
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
00113 } http_method_e;
00114 typedef enum {
00115 OPEN,
00116 SEND,
00117 IDLE,
00118 CLOSE
00119 } rtmpt_cmd_e;
00120
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
00131 ~HTTP();
00132
00133
00134 bool checkRequestFields(cygnal::Buffer &buf);
00135 bool checkEntityFields(cygnal::Buffer &buf);
00136 bool checkGeneralFields(cygnal::Buffer &buf);
00137
00138
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
00143 size_t getContentLength();
00144
00145
00146
00147
00148 boost::uint8_t *processHeaderFields(cygnal::Buffer *buf);
00149
00150
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
00157 boost::shared_ptr<std::vector<std::string> > getFieldItem(const std::string &name);
00158
00159
00160 boost::shared_ptr<http_response_t> parseStatus(const std::string &line);
00161
00162
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
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
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
00235 void terminateHeader() { _buffer += "\r\n"; };
00236
00237
00238
00239
00240 boost::uint8_t *getHeader() { return _buffer.reference(); };
00241
00242
00243 cygnal::Buffer &getBuffer() { return _buffer; };
00244
00245
00246
00247
00248
00249
00250
00251
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
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
00291 std::map<int, struct status_codes *> getStatusCodes()
00292 { return _status_codes; }
00293 http_version_t *getVersion() { return &_version; }
00294
00295
00296 void setDocRoot(const std::string &path) { _docroot = path; };
00297 std::string &getDocRoot() { return _docroot; };
00298
00299
00300 boost::shared_ptr<cygnal::Buffer> DSOEXPORT popChunk() { return _que.pop(); };
00301
00302 boost::shared_ptr<cygnal::Buffer> DSOEXPORT peekChunk() { return _que.peek(); };
00303
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
00312
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
00334 bool _keepalive;
00335
00336
00337 int _clientid;
00338 int _index;
00339 int _max_requests;
00340 std::string _docroot;
00341
00342 bool _close;
00343 };
00344
00345
00346 extern "C" {
00347 bool DSOEXPORT http_handler(Network::thread_params_t *args);
00348 }
00349
00350
00351 }
00352
00353
00354 #endif
00355
00356
00357
00358
00359
00360