[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/rtmp r9815: add process*Request methods fo
From: |
rob |
Subject: |
[Gnash-commit] /srv/bzr/gnash/rtmp r9815: add process*Request methods for the rest of the set. |
Date: |
Sun, 30 Nov 2008 18:19:12 -0700 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9815
committer: address@hidden
branch nick: rtmp
timestamp: Sun 2008-11-30 18:19:12 -0700
message:
add process*Request methods for the rest of the set.
move file streaming support to processGetRequest() instead of in http_handler.
modified:
libnet/http.cpp
libnet/http.h
=== modified file 'libnet/http.cpp'
--- a/libnet/http.cpp 2008-11-29 20:25:32 +0000
+++ b/libnet/http.cpp 2008-12-01 01:19:12 +0000
@@ -133,42 +133,57 @@
return *this;
}
-bool
-HTTP::processClientRequest()
+HTTP::http_method_e
+HTTP::processClientRequest(int fd)
{
// GNASH_REPORT_FUNCTION;
+ bool result;
boost::shared_ptr<amf::Buffer> buf(_que.peek());
if (buf) {
- switch (extractCommand(buf->reference())) {
+ _cmd = extractCommand(buf->reference());
+ switch (_cmd) {
case HTTP::HTTP_GET:
- return processGetRequest();
+ result = processGetRequest(fd);
break;
case HTTP::HTTP_POST:
- return processPostRequest();
+ result = processPostRequest(fd);
break;
case HTTP::HTTP_HEAD:
+ result = processHeadRequest(fd);
break;
case HTTP::HTTP_CONNECT:
+ result = processConnectRequest(fd);
break;
case HTTP::HTTP_TRACE:
+ result = processTraceRequest(fd);
break;
case HTTP::HTTP_OPTIONS:
+ result = processOptionsRequest(fd);
break;
case HTTP::HTTP_PUT:
+ result = processPutRequest(fd);
break;
case HTTP::HTTP_DELETE:
+ result = processDeleteRequest(fd);
break;
default:
break;
}
}
+
+ if (result) {
+ return _cmd;
+ } else {
+ return HTTP::HTTP_NONE;
+ }
}
+// A GET request asks the server to send a file to the client
bool
-HTTP::processGetRequest()
+HTTP::processGetRequest(int fd)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
// Network::byte_t buffer[readsize+1];
// const char *ptr = reinterpret_cast<const char *>(buffer);
@@ -185,7 +200,7 @@
boost::shared_ptr<amf::Buffer> buf(_que.pop());
// cerr << "YYYYYYY: " << (char *)buf->reference() << endl;
-// cerr << hexify(buf->reference(), buf->size(), false) << endl;
+// cerr << hexify(buf->reference(), buf->allocated(), false) << endl;
if (buf == 0) {
log_debug("Que empty, net connection dropped for fd #%d", getFileFd());
@@ -195,16 +210,82 @@
clearHeader();
processHeaderFields(*buf);
-// dump();
- if (_version.major > 0) {
- return true;
+ string url = _docroot + _filespec;
+ // See if the file is in the cache and already opened.
+ boost::shared_ptr<DiskStream> filestream(cache.findFile(url));
+ if (filestream) {
+ cerr << "FIXME: found file in cache!" << endl;
} else {
- return false;
- }
+ filestream.reset(new DiskStream);
+// cerr << "New Filestream at 0x" << hex << filestream.get() << endl;
+
+// cache.addFile(url, filestream); FIXME: always reload from disk
for now.
+
+ // Oopen the file and read the furst chunk into memory
+ filestream->open(url);
+
+ // Get the file size for the HTTP header
+ if (filestream->getFileType() == DiskStream::FILETYPE_NONE) {
+ formatErrorResponse(HTTP::NOT_FOUND);
+ } else {
+ cache.addPath(_filespec, filestream->getFilespec());
+ }
+ }
+
+ // Send the reply
+ amf::Buffer &reply = formatHeader(filestream->getFileType(),
+ filestream->getFileSize(),
+ HTTP::OK);
+ writeNet(fd, reply);
+
+ size_t filesize = filestream->getFileSize();
+ size_t bytes_read = 0;
+ int ret;
+ size_t page = 0;
+ if (filesize) {
+#ifdef USE_STATS_CACHE
+ struct timespec start;
+ clock_gettime (CLOCK_REALTIME, &start);
+#endif
+ size_t getbytes = 0;
+ if (filesize <= filestream->getPagesize()) {
+ getbytes = filesize;
+ } else {
+ getbytes = filestream->getPagesize();
+ }
+ if (filesize >= CACHE_LIMIT) {
+ do {
+ filestream->loadToMem(page);
+ ret = writeNet(fd, filestream->get(), getbytes);
+ if (ret <= 0) {
+ break;
+ }
+ bytes_read += ret;
+ page += filestream->getPagesize();
+ } while (bytes_read <= filesize);
+ } else {
+ filestream->loadToMem(filesize, 0);
+ ret = writeNet(fd, filestream->get(), filesize);
+ }
+ filestream->close();
+#ifdef USE_STATS_CACHE
+ struct timespec end;
+ clock_gettime (CLOCK_REALTIME, &end);
+ double time = (end.tv_sec - start.tv_sec) + ((end.tv_nsec -
start.tv_nsec)/1e9);
+ cerr << "File " << _filespec
+ << " transferred " << filesize << " bytes in: " << fixed
+ << time << " seconds." << endl;
+#endif
+ }
+
+ log_debug("http_handler all done transferring requested file \"%s\".",
_filespec);
+
+ return true;
}
+// A POST request asks sends a data from the client to the server.
bool
-HTTP::processPostRequest()
+HTTP::processPostRequest(int fd)
{
GNASH_REPORT_FUNCTION;
@@ -221,32 +302,58 @@
}
clearHeader();
extractCommand(*buf);
- processHeaderFields(*buf);
-
- if (_version.major > 0) {
- return true;
- } else {
- return false;
- }
-}
-
-// The order in which header fields with differing field names are
-// received is not significant. However, it is "good practice" to send
-// general-header fields first, followed by request-header or
-// response- header fields, and ending with the entity-header fields.
-bool
-HTTP::processPostRequest(amf::Buffer &buf)
-{
- GNASH_REPORT_FUNCTION;
- clearHeader();
- extractCommand(buf);
- processHeaderFields(buf);
+ gnash::Network::byte_t *data = processHeaderFields(*buf);
- if (!getFilespec().empty()) {
- return true;
- } else {
- return false;
- }
+ return true;
+}
+
+bool
+HTTP::processPutRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("PUT request");
+
+ return false;
+}
+
+bool
+HTTP::processDeleteRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("DELETE request");
+ return false;
+}
+
+bool
+HTTP::processConnectRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("CONNECT request");
+ return false;
+}
+
+bool
+HTTP::processOptionsRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("OPTIONS request");
+ return false;
+}
+
+bool
+HTTP::processHeadRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("HEAD request");
+ return false;
+}
+
+bool
+HTTP::processTraceRequest(int /* fd */)
+{
+// GNASH_REPORT_FUNCTION;
+ log_unimpl("TRACE request");
+ return false;
}
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5 (5.3 Request
Header Fields)
@@ -353,20 +460,34 @@
(int(*)(int)) tolower);
_fields[name] = value;
if (name == "keep-alive") {
- // log_debug("Got a Keep Alive HTTP header field!");
_keepalive = true;
if ((value != "on") && (value != "off")) {
_max_requests = strtol(value.c_str(), NULL, 0);
log_debug("Setting Max Requests for Keep-Alive to %d",
_max_requests);
}
}
- //
if (name == "connection") {
if (value.find("keep-alive", 0) != string::npos) {
- // log_debug("Got a Keep Alive in HTTP Connection header
field!");
_keepalive = true;
}
}
+ if (name == "content-length") {
+ _filesize = strtol(value.c_str(), NULL, 0);
+ log_debug("Setting Content Length to %d", _filesize);
+ }
+ if (name == "content-type") {
+ // This is the type used by flash when sending a AMF data via
POST
+ if (value == "application/x-amf") {
+ log_debug("Got AMF data in the POST request!");
+ _filetype = DiskStream::FILETYPE_AMF;
+ }
+ // This is the type used by wget when sending a file via POST
+ if (value == "application/x-www-form-urlencoded") {
+ log_debug("Got file data in the POST request");
+ _filetype = DiskStream::FILETYPE_ENCODED;
+ }
+ log_debug("Setting Content Type to %d", _filetype);
+ }
// cerr << "FIXME: " << (void *)i << " : " << dec << end << endl;
} else {
@@ -438,6 +559,7 @@
amf::Buffer &
HTTP::formatCommon(const string &data)
{
+// GNASH_REPORT_FUNCTION;
_buffer += data;
_buffer += "\r\n";
@@ -454,7 +576,7 @@
amf::Buffer &
HTTP::formatHeader(DiskStream::filetype_e type, size_t size, http_status_e
code)
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
clearHeader();
@@ -647,10 +769,8 @@
_buffer += "</body></html>\r\n";
// First build the header
-// _header << "HTTP/1.1 " << code << " Not Found" << "\r\n";
formatDate();
formatServer();
-// _filesize = _body.str().size();
formatContentLength(_filesize);
formatConnection("close");
formatContentType(_filetype);
@@ -670,25 +790,6 @@
// cout << now.time_of_day() << "\r\n";
boost::gregorian::date d(now.date());
-
-// cerr << boost::gregorian::to_simple_string(d) << endl;
-// cerr << boost::posix_time::to_simple_string(now.time_of_day()) << endl;
-// cerr << boost::posix_time::to_posix_string() << endl;
-// const char *months[] = {
-// "None",
-// "Jan",
-// "Feb",
-// "March",
-// "April",
-// "May",
-// "June",
-// "July",
-// "Aug",
-// "Sept",
-// "Oct",
-// "Nov",
-// "Dec"
-// };
char num[12];
@@ -768,7 +869,7 @@
amf::Buffer &
HTTP::formatContentType(DiskStream::filetype_e filetype)
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
switch (filetype) {
// default to HTML if the type isn't known
@@ -1114,7 +1215,7 @@
do {
boost::shared_ptr<amf::Buffer> buf(new amf::Buffer);
- int ret = net.readNet(fd, buf, 5);
+ int ret = net.readNet(fd, *buf, 5);
// cerr << __PRETTY_FUNCTION__ << endl << (char *)buf->reference() << endl;
@@ -1127,7 +1228,7 @@
// so we're done.
if ((ret == static_cast<int>(string::npos)) || (ret == -1)) {
log_debug("socket for fd #%d was closed...", fd);
- break;
+ return 0;
}
// We got data. Resize the buffer if necessary.
if (ret > 0) {
@@ -1142,14 +1243,14 @@
}
} else {
log_debug("no more data for fd #%d, exiting...", fd);
- break;
+ return 0;
}
} while (ret);
// We're done. Notify the other threads the socket is closed, and tell
them to die.
log_debug("Handler done for fd #%d...", fd);
- return _que.size();
+ return ret;
}
void
@@ -1190,7 +1291,8 @@
args->netfd, get_thread_id());
string docroot = args->filespec;
-
+
+ www.setDocRoot(docroot);
log_debug("Starting to wait for data in net for fd #%d", args->netfd);
// Wait for data, and when we get it, process it.
@@ -1200,59 +1302,22 @@
struct timespec start;
clock_gettime (CLOCK_REALTIME, &start);
#endif
-
- www.recvMsg(args->netfd);
-
- if (!www.processClientRequest()) {
+
+ // See if we have any messages waiting
+ if (www.recvMsg(args->netfd) == 0) {
+ done = true;
+ }
+
+ // Process incoming messages
+ if (!www.processClientRequest(args->netfd)) {
// hand->die(); // tell all the threads for this connection to
die
// hand->notifyin();
log_debug("Net HTTP done for fd #%d...", args->netfd);
// hand->closeNet(args->netfd);
- return;
+ done = true;
}
// www.dump();
- url = docroot;
- url += www.getFilespec();
-
- // See if the file is in the cache and already opened.
- boost::shared_ptr<DiskStream> filestream(cache.findFile(url));
- if (filestream) {
- cerr << "FIXME: found file in cache!" << endl;
- } else {
- filestream.reset(new DiskStream);
-// cerr << "New Filestream at 0x" << hex << filestream.get() << endl;
-
-// cache.addFile(url, filestream); FIXME: always reload from disk
for now.
-
- // Oopen the file and read the furst chunk into memory
- filestream->open(url);
-
- // Get the file size for the HTTP header
- if (filestream->getFileType() == DiskStream::FILETYPE_NONE) {
- www.formatErrorResponse(HTTP::NOT_FOUND);
- } else {
- cache.addPath(www.getFilespec(), filestream->getFilespec());
- }
- }
-
-
- // Send the reply
- amf::Buffer &reply = www.formatHeader(filestream->getFileType(),
- filestream->getFileSize(),
- HTTP::OK);
- www.writeNet(args->netfd, reply);
-// hand->writeNet(args->netfd, www.getHeader(),
www.getHeader().allocated());
-// strcpy(thread_data.filespec, filespec.c_str());
-// thread_data.statistics = conndata->statistics;
-
- // Keep track of the network statistics
-// conndata->statistics->stopClock();
-// log_debug (_("Bytes read: %d"), www.getBytesIn());
-// log_debug (_("Bytes written: %d"), www.getBytesOut());
-// st.setBytes(www.getBytesIn() + www.getBytesOut());
-// conndata->statistics->addStats();
-
#if 0
string response = cache.findResponse(filestream->getFilespec());
if (response.empty()) {
@@ -1267,53 +1332,6 @@
}
#endif
-// cerr << www.getHeader().c_str() << endl;
-
- size_t filesize = filestream->getFileSize();
- size_t bytes_read = 0;
- int ret;
- size_t page = 0;
- if (filesize) {
-#ifdef USE_STATS_CACHE
- struct timespec start;
- clock_gettime (CLOCK_REALTIME, &start);
-#endif
- size_t getbytes = 0;
- if (filesize <= filestream->getPagesize()) {
- getbytes = filesize;
- } else {
- getbytes = filestream->getPagesize();
- }
- if (filesize >= CACHE_LIMIT) {
- do {
- filestream->loadChunk(page);
- ret = www.writeNet(args->netfd, filestream->get(),
getbytes);
- if (ret <= 0) {
- break;
- }
- bytes_read += ret;
- page += filestream->getPagesize();
- } while (bytes_read <= filesize);
- } else {
- filestream->loadChunk(filesize, 0);
-// filestream->close();
- ret = www.writeNet(args->netfd, filestream->get(), filesize);
- }
- filestream->close();
-#ifdef USE_STATS_CACHE
- struct timespec end;
- clock_gettime (CLOCK_REALTIME, &end);
- double time = (end.tv_sec - start.tv_sec) + ((end.tv_nsec -
start.tv_nsec)/1e9);
- cerr << "File " << www.getFilespec()
- << " transferred " << filesize << " bytes in: " << fixed
- << time << " seconds." << endl;
-#endif
-// filestream->close();
- }
- log_debug("http_handler all done transferring requested file...");
-// cache.dump();
-// done = true;
-
// Unless the Keep-Alive flag is set, this isn't a persisant network
// connection.
if (!www.keepAlive()) {
@@ -1322,44 +1340,14 @@
} else {
log_debug("Keep-Alive is on", www.keepAlive());
}
-#if 0
- if (url != docroot) {
- log_debug (_("File to load is: %s"), filespec.c_str());
- log_debug (_("Parameters are: %s"), parameters.c_str());
- struct stat st;
- int filefd;
- size_t ret;
- if (stat(filespec.c_str(), &st) == 0) {
- filefd = ::open(filespec.c_str(), O_RDONLY);
- log_debug (_("File \"%s\" is %lld bytes in size, disk fd #%d"),
filespec,
- st.st_size, filefd);
- boost::shared_ptr<amf::Buffer> buf(new amf::Buffer);
- log_debug("Done transferring %s to net fd #%d", filespec,
args->netfd);
-
- // See if this is a persistant connection
-// if (!www.keepAlive()) {
-// log_debug("Keep-Alive is off", www.keepAlive());
- hand->closeNet();
-// }
- }
- }
-#endif
-
-
-
#ifdef USE_STATISTICS
struct timespec end;
clock_gettime (CLOCK_REALTIME, &end);
log_debug("Processing time for GET request was %f seconds",
(float)((end.tv_sec - start.tv_sec) + ((end.tv_nsec -
start.tv_nsec)/1e9)));
#endif
-// conndata->statistics->dump();
-// }
-// } while(!hand->timetodie());
} while(done != true);
-// www.closeNet(args->netfd);
-// hand->erasePollFD(args->netfd);
hand->notify();
log_debug("http_handler all done now finally...");
=== modified file 'libnet/http.h'
--- a/libnet/http.h 2008-11-29 19:33:11 +0000
+++ b/libnet/http.h 2008-12-01 01:19:12 +0000
@@ -125,10 +125,15 @@
~HTTP();
// These are for the protocol itself
- bool processClientRequest();
- bool processGetRequest();
- bool processPostRequest();
- bool processPostRequest(amf::Buffer &buf);
+ http_method_e processClientRequest(int fd);
+ bool processGetRequest(int fd);
+ bool processPostRequest(int fd);
+ bool processPutRequest(int fd);
+ bool processDeleteRequest(int fd);
+ bool processConnectRequest(int fd);
+ bool processOptionsRequest(int fd);
+ bool processHeadRequest(int fd);
+ bool processTraceRequest(int fd);
// Check the Header fields to make sure they're valid values.
bool checkRequestFields(amf::Buffer &buf);
@@ -285,33 +290,32 @@
http_version_t *getVersion() { return &_version; }
void setHandler(Handler *hand) { _handler = hand; };
+ void setDocRoot(const std::string &path) { _docroot = path; };
private:
typedef boost::char_separator<char> Sep;
typedef boost::tokenizer<Sep> Tok;
+ http_method_e _cmd;
- amf::Buffer _buffer;
+ amf::Buffer _buffer;
CQue _que;
-// std::stringstream _body;
-// std::string _command;
DiskStream::filetype_e _filetype;
std::string _filespec;
boost::uint32_t _filesize;
-// std::string _url;
std::map<int, struct status_codes *> _status_codes;
std::map<std::string, std::string> DSOEXPORT _fields;
http_version_t _version;
// Connection parameters we care about
- bool _keepalive;
- Handler *_handler;
+ bool _keepalive;
+ Handler *_handler;
// These two field hold the data from an RTMPT message
- int _clientid;
- int _index;
- int _max_requests;
-// bool _te;
+ int _clientid;
+ int _index;
+ int _max_requests;
+ std::string _docroot;
};
// This is the thread for all incoming HTTP connections
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/rtmp r9815: add process*Request methods for the rest of the set.,
rob <=