[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/cygnal Makefile.am alloc.cpp cygnal.cpp h...
From: |
Rob Savoye |
Subject: |
[Gnash-commit] gnash/cygnal Makefile.am alloc.cpp cygnal.cpp h... |
Date: |
Sun, 17 Dec 2006 02:34:58 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Rob Savoye <rsavoye> 06/12/17 02:34:58
Added files:
cygnal : Makefile.am alloc.cpp cygnal.cpp http.cpp
http.h netstats.cpp netstats.h statistics.cpp
statistics.h stream.cpp stream.h
Log message:
* cygnal: New directory for media server.
* cygnal/cygnal.cpp: Main entry for server.
* cygnal/Makefile.am: Makefile for media server.
* cygnal/README: Server specific info file for developers.
* cygnal/stream.cpp, stream.h: Streaming data class.
* cygnal/netstats.cpp, netstats.h: Collect statistics on
network performance.
* cygnal/statistics.cpp, statistics.h: Collect statistics on
each
movie being played for performance tweaking.
* cygnal/http.c, http.h: Support for a simple subset of HTTP,
enough to respond to GET requests.
* cygnal/alloc.cpp: Threadsafe new & delete to keep STL
containers
working in a multi-threaded application.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Makefile.am?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/alloc.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/cygnal.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/http.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/http.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/netstats.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/netstats.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/statistics.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/statistics.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/stream.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/stream.h?cvsroot=gnash&rev=1.1
Patches:
Index: Makefile.am
===================================================================
RCS file: Makefile.am
diff -N Makefile.am
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Makefile.am 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+## Process this file with automake to generate Makefile.in
+
+AUTOMAKE_OPTIONS = dejagnu
+
+AM_CPPFLAGS = # -Wall
+
+## WARNING: make sure GLIB_LIBS appears first
+## See: http://lists.gnu.org/archive/html/gnash-dev/2006-07/msg00076.html
+AM_LDFLAGS = \
+ ../libbase/libgnashbase.la \
+ ../libamf/libgnashamf.la \
+ $(GLIB_LIBS) \
+ $(LIBXML_LIBS) \
+ $(CURL_LIBS) \
+ $(BOOST_LIBS) \
+ $(PTHREAD_LIBS)
+
+INCLUDES = -I.. \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libamf \
+ -I$(top_srcdir)/libbase \
+ -I$(top_srcdir)/server \
+ $(LIBXML_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(DMALLOC_CFLAGS) \
+ $(CURL_CFLAGS) \
+ $(BOOST_CFLAGS) \
+ $(PTHREAD_CFLAGS)
+
+bin_PROGRAMS = cygnal
+
+cygnal_SOURCES = \
+ cygnal.cpp \
+ http.cpp \
+ alloc.cpp \
+ netstats.cpp \
+ stream.cpp \
+ statistics.cpp
+# transcode.cpp
+# flash.cpp
+
+noinst_HEADRRS = \
+ http.h \
+ netstats.h \
+ stream.h \
+ statistics.h
+# transcode.h
+# flash.h
+
+# protocol.cpp protocol.h
+cygnal_LDADD = $(AM_LDFLAGS)
+
+# Rebuild with GCC 4.x Mudflap support
+mudflap:
+ @echo "Rebuilding with GCC Mudflap support"
+ $(MAKE) CXXFLAGS="$(CXXFLAGS) $(MUDFLAP_OPT)" LIBS="$(LIBS)
$(MUDFLAP_LIB)"
+
+# EXTRA_PROGRAMS = talloc
+# talloc_SOURCES = talloc.cpp
+# talloc_LDADD = $(AM_LDFLAGS)
Index: alloc.cpp
===================================================================
RCS file: alloc.cpp
diff -N alloc.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ alloc.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/// This defines thread safe new/delete operators
+#include <new>
+#include <boost/thread/mutex.hpp>
+
+static boost::mutex mem_mutex;
+
+// Wrap new in a mutex, because it is not thread safe.
+void *
+operator new (std::size_t bytes) {
+ boost::mutex::scoped_lock lock(mem_mutex);
+ void *ptr = malloc (bytes);
+ return ptr;
+}
+
+// Wrap delete in a mutex, because it is not thread safe.
+void
+operator delete (void* vptr) {
+ boost::mutex::scoped_lock lock(mem_mutex);
+ free (vptr);
+}
+
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: cygnal.cpp
===================================================================
RCS file: cygnal.cpp
diff -N cygnal.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cygnal.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,359 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <signal.h>
+#include <vector>
+#include <sys/mman.h>
+#include <cerrno>
+
+#include "stream.h"
+#include "network.h"
+#include "log.h"
+#include "rc.h"
+#include "rtmp.h"
+#include "http.h"
+#include "limits.h"
+#include "netstats.h"
+#include "statistics.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+
+using gnash::log_msg;
+using namespace std;
+using namespace cygnal;
+using namespace gnash;
+using namespace amf;
+
+static void usage(const char *proc);
+static void version_and_copyright();
+static void cntrlc_handler(int sig);
+
+static void start_thread();
+static void rtmp_thread();
+static void http_thread();
+static void ssl_thread();
+static void stream_thread(struct thread_params *sendfile);
+
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
+}
+
+struct thread_params {
+ int netfd;
+ char filespec[256];
+ Statistics *statistics;
+};
+
+static struct sigaction act;
+
+// The next few global variables have to be global because Boost
+// threads don't take arguments. Since these are set in main() before
+// any of the threads are started, and it's value should never change,
+// it's safe to use these without a mutex, as all threads share the
+// same read-only value.
+
+// This is the default path to look in for files to be streamed.
+const char *docroot;
+
+// This is the number of times a thread loop continues, for debugging only
+int thread_retries;
+
+// This is added to the default ports for testing so it doesn't
+// conflict with apache on the same machine.
+static int port_offset = 0;
+
+// end of globals
+
+
+int
+main(int argc, char *argv[])
+{
+ // scan for the two main long GNU options
+ int c;
+ for (c=0; c<argc; c++) {
+ if (strcmp("--help", argv[c]) == 0) {
+ version_and_copyright();
+ printf("\n");
+ usage(argv[0]);
+ exit(0);
+ }
+
+ if (strcmp("--version", argv[c]) == 0) {
+ version_and_copyright();
+ exit(0);
+ }
+ }
+
+ dbglogfile.setWriteDisk(false);
+ rcfile.loadFiles();
+// rcfile.dump();
+
+ if (rcfile.useWriteLog()) {
+ dbglogfile.setWriteDisk(true);
+ }
+
+ if (rcfile.verbosityLevel() > 0) {
+ dbglogfile.setVerbosity(rcfile.verbosityLevel());
+ }
+
+ if (rcfile.getRetries() > 0) {
+ thread_retries = rcfile.getRetries();
+ } else {
+ thread_retries = 3;
+ }
+
+ if (rcfile.getDocumentRoot().size() > 0) {
+ docroot = rcfile.getDocumentRoot().c_str();
+ dbglogfile << "Document Root for media files is: "
+ << docroot << endl;
+ } else {
+ docroot = "/var/www";
+ }
+
+ while ((c = getopt (argc, argv, "hvwp:")) != -1) {
+ switch (c) {
+ case 'h':
+ usage (argv[0]);
+ exit(0);
+ case 'v':
+ dbglogfile.setVerbosity();
+ dbglogfile << "Verbose output turned on" << endl;
+ break;
+ case 'w':
+ dbglogfile.setWriteDisk(true);
+ dbglogfile << "Logging to disk enabled." << endl;
+ break;
+ case 'p':
+ dbglogfile << "Logging to disk enabled." << endl;
+ port_offset = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+
+ // get the file name from the command line
+ while (optind < argc) {
+ dbglogfile << "Extraneous argument!" << endl;
+ }
+
+ // Remove the logfile that's created by default, since leaving a short
+ // file is confusing.
+ if (dbglogfile.getWriteDisk() == false) {
+ dbglogfile.removeLog();
+ }
+
+ // Trap ^C so we can kill all the threads
+ act.sa_handler = cntrlc_handler;
+ sigaction (SIGINT, &act, NULL);
+
+ boost::thread rtmp_port(&rtmp_thread);
+ boost::thread http_port(&http_thread);
+ boost::thread ssl_port(&ssl_thread);
+
+ // wait for the thread to finish
+ rtmp_port.join();
+ http_port.join();
+ ssl_port.join();
+
+ dbglogfile << "All done I think..." << endl;
+
+ return(0);
+}
+
+static void
+rtmp_thread()
+{
+ GNASH_REPORT_FUNCTION;
+ int retries = 0;
+ RTMPproto proto;
+
+ Statistics st;
+ st.setFileType(NetStats::RTMP);
+
+ proto.createServer(RTMP);
+ while (retries++ < thread_retries) {
+ printf("%s: Thread for RTMP port looping...\n", __PRETTY_FUNCTION__);
+ proto.newConnection(true);
+ st.startClock();
+ proto.handShakeWait();
+ proto.handShakeResponse();
+ proto.serverFinish();
+
+ // Keep track of the network statistics
+ st.stopClock();
+ dbglogfile << "Bytes read: " << proto.getBytesIn() << endl;
+ dbglogfile << "Bytes written: " << proto.getBytesOut() << endl;
+ st.setBytes(proto.getBytesIn() + proto.getBytesOut());
+ st.addStats();
+ proto.resetBytesIn();
+ proto.resetBytesOut();
+ }
+}
+
+static void
+http_thread()
+{
+ GNASH_REPORT_FUNCTION;
+ int retries = 0;
+ HTTP www;
+ struct thread_params thread_data;
+ string url, filespec, parameters;
+ string::size_type pos;
+ int port = RTMPT + port_offset;
+ int filesize;
+ struct stat filestats;
+
+ www.createServer(port);
+ while (retries++ < thread_retries) {
+ printf("%s: Thread for port %d looping...\n", __PRETTY_FUNCTION__,
port);
+ www.newConnection(true);
+ Statistics st;
+ st.setFileType(NetStats::RTMPT);
+ st.startClock();
+ thread_data.netfd = www.getFileFd();
+ url = docroot;
+ url += www.waitForGetRequest();
+ pos = url.find("?");
+ filespec = url.substr(0, pos);
+ parameters = url.substr(pos + 1, url.size());
+ // Get the file size for the HTTP header
+ if (stat(filespec.c_str(), &filestats) == 0) {
+ filesize = filestats.st_size;
+ } else {
+ filesize = 0;
+ }
+ www.sendGetReply(filesize);
+ strcpy(thread_data.filespec, filespec.c_str());
+ thread_data.statistics = &st;
+
+ // Keep track of the network statistics
+ st.stopClock();
+// dbglogfile << "Bytes read: " << www.getBytesIn() << endl;
+// dbglogfile << "Bytes written: " << www.getBytesOut() << endl;
+// st.setBytes(www.getBytesIn() + www.getBytesOut());
+ st.addStats();
+// www.resetBytesIn();
+// www.resetBytesOut();
+
+ if (url != docroot) {
+ dbglogfile << "File to load is: " << filespec << endl;
+ dbglogfile << "Parameters are: " << parameters << endl;
+ memcpy(thread_data.filespec, filespec.c_str(), filespec.size());
+ boost::thread sendthr(boost::bind(&stream_thread, &thread_data));
+ sendthr.join();
+ }
+ // See if this is a persistant connection
+ if (!www.keepAlive()) {
+ www.closeConnection();
+ }
+ }
+// st.dump();
+}
+
+static void
+ssl_thread()
+{
+ GNASH_REPORT_FUNCTION;
+ int retries = 0;
+ HTTP www;
+ RTMPproto proto;
+ struct thread_params loadfile;
+ string filespec;
+ int port = RTMPTS + port_offset;
+
+ Statistics st;
+ st.setFileType(NetStats::RTMPTS);
+
+ www.createServer(port);
+
+ while (retries++ < thread_retries) {
+ printf("%s: Thread for port %d looping...\n", __PRETTY_FUNCTION__,
port);
+ www.newConnection(true);
+ loadfile.netfd = www.getFileFd();
+ strcpy(loadfile.filespec, "Hello World");
+ boost::thread sendthr(boost::bind(&stream_thread, &loadfile));
+ sendthr.join();
+ }
+}
+
+
+static void
+stream_thread(struct thread_params *params)
+{
+ GNASH_REPORT_FUNCTION;
+
+ struct stat stats;
+ struct thread_params loadfile;
+
+ dbglogfile << __PRETTY_FUNCTION__ << ": " << params->filespec << endl;
+
+ Stream str;
+ str.open(params->filespec, params->netfd, params->statistics);
+ str.play();
+}
+
+// Trap Control-C so we can cleanly exit
+static void
+cntrlc_handler (int sig)
+{
+ log_msg("Got a ^C !\n");
+
+ exit(-1);
+}
+
+static void
+version_and_copyright()
+{
+ printf (
+"Cygnal " VERSION "\n"
+"Copyright (C) 2006 Free Software Foundation, Inc.\n"
+"Cygnal comes with NO WARRANTY, to the extent permitted by law.\n"
+"You may redistribute copies of Cygnal under the terms of the GNU General\n"
+"Public License. For more information, see the file named COPYING.\n"
+ );
+}
+
+static void
+usage(const char *proc)
+{
+ printf(
+ "cygnal -- an streaming media server.\n"
+ "\n"
+ "usage: cygnal [options...]\n"
+ " --help(-h) Print this info.\n"
+ " --version Print the version numbers.\n"
+ " --verbose (-v) Output verbose debug info.\n"
+ " --port-offset (-p) RTMPT port offset.\n"
+ );
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: http.cpp
===================================================================
RCS file: http.cpp
diff -N http.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ http.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,396 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/mutex.hpp>
+#include <string>
+#include <iostream>
+#include <cstring>
+#include "http.h"
+#include "log.h"
+
+using namespace gnash;
+using namespace std;
+
+static boost::mutex stl_mutex;
+
+
+namespace cygnal
+{
+
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+}
+
+static const int readsize = 1024;
+
+HTTP::HTTP()
+{
+// GNASH_REPORT_FUNCTION;
+// struct status_codes *status = new struct status_codes;
+
+// _status_codes(CONTINUE, status);
+}
+
+HTTP::~HTTP()
+{
+// GNASH_REPORT_FUNCTION;
+}
+
+HTTP &
+HTTP::operator = (HTTP &obj)
+{
+ GNASH_REPORT_FUNCTION;
+// this = obj;
+}
+
+string
+HTTP::waitForGetRequest(Network &net)
+{
+ GNASH_REPORT_FUNCTION;
+
+}
+
+string
+HTTP::waitForGetRequest()
+{
+ GNASH_REPORT_FUNCTION;
+
+ char buffer[readsize+1];
+ memset(buffer, 0, readsize+1);
+ if (readNet(buffer, readsize) > 0) {
+ dbglogfile << "Read initial GET Request" << endl;
+ } else {
+ dbglogfile << "Couldn't read initial GET Request" << endl;
+ }
+
+ extractMethod(buffer);
+// extractReferer(buffer);
+// extractHost(buffer);
+ extractAgent(buffer);
+ extractLanguage(buffer);
+ extractCharset(buffer);
+ extractConnection(buffer);
+// extractEncoding(buffer);
+// extractTE(buffer);
+// dump();
+
+ // See if we got a legit GET request
+ if (strncmp(buffer, "GET ", 4) == 0) {
+ dbglogfile << "Got legit GET request: " << endl;
+ } else {
+ dbglogfile << "ERROR: Got bogus GET request!" << endl;
+ }
+
+ return _url;
+}
+
+bool
+HTTP::sendGetReply(int filesize)
+{
+ GNASH_REPORT_FUNCTION;
+ boost::posix_time::ptime now =
boost::posix_time::microsec_clock::local_time();
+
+ now.time_of_day();
+
+ const char reply[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Date: Sun, 20 Apr 2006 04:20:00 GMT\r\n"
+ "Content-Type: application/futuresplash\r\n"
+ "Connection: close\r\n"
+ "Content-Length: XX \r\n"
+ "\r\n" // All HTTP messages are followed by a blank
line.
+ ;
+
+ // This is a bit ugly, but we splice the file size onto the request string
+ // without any memory allocation, which could incur a small performance
hit.
+ char *length = strstr(reply, " XX");
+ sprintf(length, " %d", filesize);
+
+ if (writeNet(reply, strlen(reply)) == strlen(reply)) {
+ dbglogfile << "Sent GET Reply: " << reply << endl;
+ } else {
+ dbglogfile << "Couldn't send GET Reply" << endl;
+ }
+}
+
+// bool
+// HTTP::sendGetReply(Network &net)
+// {
+// GNASH_REPORT_FUNCTION;
+// }
+
+// This is what a GET request looks like.
+// GET
/software/gnash/tests/flvplayer2.swf?file=http://localhost:4080/software/gnash/tests/lulutest.flv
HTTP/1.1
+// User-Agent: Opera/9.01 (X11; Linux i686; U; en)
+// Host: localhost:4080
+// Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png,
image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
+// Accept-Language: en
+// Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
+// Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
+// Referer: http://localhost/software/gnash/tests/
+// Connection: Keep-Alive, TE
+// TE: deflate, gzip, chunked, identity, trailers
+string
+HTTP::extractMethod(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ boost::mutex::scoped_lock lock(stl_mutex);
+ string body = data;
+ string::size_type start, end;
+ int length;
+
+ length = body.size();
+ start = body.find(" ", 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ _method = body.substr(0, start);
+ end = body.find(" ", start+1);
+ if (end == string::npos) {
+ return "error";
+ }
+ _url = body.substr(start+1, end-start-1);
+ _version = body.substr(end+1, length);
+
+ end = _url.find("?", 0);
+// _filespec = _url.substr(start+1, end);
+ return "error";
+}
+
+string
+HTTP::extractReferer(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Referer: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _referer = body.substr(start+pattern.size(), end-start-1);
+ return _referer;
+};
+
+string
+HTTP::extractConnection(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Connection: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _connection = body.substr(start+pattern.size(), end-start-1);
+ return _connection;
+}
+
+string
+HTTP::extractHost(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Host: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _host = body.substr(start+pattern.size(), end-start-1);
+ return _host;
+}
+
+string
+HTTP::extractAgent(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "User-Agent: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _agent = body.substr(start+pattern.size(), end-start-1);
+ return _agent;
+}
+
+string
+HTTP::extractLanguage(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Accept-Language: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _language = body.substr(start+pattern.size(), end-start-1);
+ return _language;
+}
+
+string
+HTTP::extractCharset(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Accept-Charset: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _charset = body.substr(start+pattern.size(), end-start-1);
+ return _charset;
+}
+
+string
+HTTP::extractEncoding(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "Accept-Encoding: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _encoding = body.substr(start+pattern.size(), end-start-1);
+ return _encoding;
+}
+
+string
+HTTP::extractTE(const char *data) {
+// GNASH_REPORT_FUNCTION;
+
+ string body = data;
+ string::size_type start, end;
+ string pattern = "TE: ";
+
+ start = body.find(pattern, 0);
+ if (start == string::npos) {
+ return "error";
+ }
+ end = body.find("\r\n", start);
+ if (end == string::npos) {
+ return "error";
+ }
+
+ _te = body.substr(start+pattern.size(), end-start-1);
+ return _te;
+}
+
+bool
+HTTP::keepAlive(const char *data)
+{
+// GNASH_REPORT_FUNCTION;
+
+ if (strcasestr(data, "Keep-Alive")) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool
+HTTP::keepAlive()
+{
+// GNASH_REPORT_FUNCTION;
+ // FIXME: is their a way to make find case insensitive that's
+ // less than 20 lines long ?
+ return keepAlive(_connection.c_str());
+}
+
+void
+HTTP::dump() {
+ GNASH_REPORT_FUNCTION;
+
+ boost::mutex::scoped_lock lock(stl_mutex);
+
+ dbglogfile << "==== The HTTP header breaks down as follows: ====" << endl;
+ dbglogfile << "Filespec: " << _filespec.c_str() << endl;
+ dbglogfile << "URL: " << _url.c_str() << endl;
+ dbglogfile << "Version: " << _version.c_str() << endl;
+ dbglogfile << "Method: " << _method.c_str() << endl;
+ dbglogfile << "Referer: " << _referer.c_str() << endl;
+ dbglogfile << "Connection: " << _connection.c_str() << endl;
+ dbglogfile << "Host: " << _host.c_str() << endl;
+ dbglogfile << "User Agent: " << _agent.c_str() << endl;
+ dbglogfile << "Language: " << _language.c_str() << endl;
+ dbglogfile << "Charset: " << _charset.c_str() << endl;
+ dbglogfile << "Encoding: " << _encoding << endl;
+ dbglogfile << "TE: " << _te.c_str() << endl;
+ dbglogfile << "==== ==== ====" << endl;
+}
+
+} // end of cygnal namespace
+
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: http.h
===================================================================
RCS file: http.h
diff -N http.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ http.h 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,152 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef _HTTP_H_
+#define _HTTP_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+#include <map>
+#include "network.h"
+
+using namespace std;
+using namespace gnash;
+
+namespace cygnal
+{
+
+class HTTP : public Network
+{
+public:
+ typedef enum {
+ // 1xx: Informational - Request received, continuing process
+ CONTINUE = 100,
+ SWITCHPROTOCOLS = 101,
+ // 2xx: Success - The action was successfully received,
+ // understood, and accepted
+ OK = 200,
+ CREATED = 201,
+ ACCEPTED = 202,
+ NON_AUTHORITATIVE = 203,
+ NO_CONTENT = 204,
+ RESET_CONTENT = 205,
+ PARTIAL_CONTENT = 206,
+ // 3xx: Redirection - Further action must be taken in order to
+ // complete the request
+ MULTIPLE_CHOICES = 300,
+ MOVED_PERMANENTLY = 301,
+ FOUND = 302,
+ SEE_OTHER = 303,
+ NOT_MODIFIED = 304,
+ USE_PROXY = 305,
+ TEMPORARY_REDIRECT = 307,
+ // 4xx: Client Error - The request contains bad syntax or
+ // cannot be fulfilled
+ BAD_REQUEST = 400,
+ UNAUTHORIZED = 401,
+ PAYMENT_REQUIRED = 402,
+ FORBIDDEN = 403,
+ NOT_FOUND = 404,
+ METHOD_NOT_ALLOWED = 405,
+ NOT_ACCEPTABLE = 406,
+ PROXY_AUTHENTICATION_REQUIRED = 407,
+ REQUEST_TIMEOUT = 408,
+ CONFLICT = 409,
+ GONE = 410,
+ LENGTH_REQUIRED = 411,
+ PRECONDITION_FAILED = 412,
+ REQUEST_ENTITY_TOO_LARGE = 413,
+ REQUEST_URI_TOO_LARGE = 414,
+ UNSUPPORTED_MEDIA_TYPE = 415,
+ REQUESTED_RANGE_NOT_SATISFIABLE = 416,
+ EXPECTATION_FAILED = 417,
+ // 5xx: Server Error - The server failed to fulfill an apparently
valid request
+ INTERNAL_SERVER_ERROR = 500,
+ NOT_IMPLEMENTED = 501,
+ BAD_GATEWAY = 502,
+ SERVICE_UNAVAILABLE = 503,
+ GATEWAY_TIMEOUT = 504,
+ HTTP_VERSION_NOT_SUPPORTED = 505
+ } http_status_e;
+ typedef enum {
+ OPTIONS,
+ GET,
+ HEAD,
+ POST,
+ PUT,
+ DELETE,
+ TRACE,
+ CONNECT
+ } http_method_e;
+ struct status_codes {
+ const char *code;
+ const char *msg;
+ };
+ HTTP();
+ ~HTTP();
+ std::string waitForGetRequest();
+ std::string waitForGetRequest(Network &net);
+
+ // Handle the GET request response
+ bool sendGetReply(int filesize);
+// bool sendGetReply(Network &net);
+
+ // Make copies of ourself
+ HTTP &operator = (HTTP &obj);
+
+ // These methods extract the fields in the HTTP header.
+ std::string extractMethod(const char *data);
+ std::string extractReferer(const char *data);
+ std::string extractConnection(const char *data);
+ std::string extractHost(const char *data);
+ std::string extractAgent(const char *data);
+ std::string extractLanguage(const char *data);
+ std::string extractCharset(const char *data);
+ std::string extractEncoding(const char *data);
+ std::string extractTE(const char *data);
+ bool keepAlive(const char *data);
+ bool keepAlive();
+ void dump();
+private:
+ std::string _filespec;
+ std::string _url;
+ std::map<int, struct status_codes *> _status_codes;
+ std::string _version;
+ std::string _method;
+ std::string _referer;
+ std::string _connection;
+ std::string _host;
+ std::string _agent;
+ std::string _language;
+ std::string _charset;
+ std::string _encoding;
+ std::string _te;
+};
+
+} // end of cygnal namespace
+
+// end of _HTTP_H_
+#endif
+
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: netstats.cpp
===================================================================
RCS file: netstats.cpp
diff -N netstats.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ netstats.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,68 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include "netstats.h"
+#include "log.h"
+
+using namespace gnash;
+
+namespace cygnal {
+
+NetStats::NetStats() {
+ GNASH_REPORT_FUNCTION;
+}
+
+NetStats::~NetStats() {
+ GNASH_REPORT_FUNCTION;
+}
+
+boost::posix_time::ptime
+NetStats::startClock() {
+ GNASH_REPORT_FUNCTION;
+
+ _starttime = boost::posix_time::microsec_clock::local_time();
+ return _stoptime;
+}
+
+boost::posix_time::ptime
+NetStats::stopClock() {
+ GNASH_REPORT_FUNCTION;
+
+ _stoptime = boost::posix_time::microsec_clock::local_time();
+ return _stoptime;
+}
+
+NetStats &
+NetStats::operator = (NetStats &stats) {
+ _starttime = stats.getStartTime();
+ _stoptime = stats.getStopTime();
+ _bytes = stats.getBytes();
+ _codec = stats.getCodec();
+ _type = stats.getFileType();
+}
+
+} // end of cygnal namespace
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: netstats.h
===================================================================
RCS file: netstats.h
diff -N netstats.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ netstats.h 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef __NETSTATS_H__
+#define __NETSTATS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/date_time/posix_time/posix_time.hpp> //include all types plus
i/o
+
+namespace cygnal
+{
+
+class NetStats {
+public:
+ NetStats();
+ ~NetStats();
+ typedef enum {
+ NO_CODEC,
+ OGG,
+ THEORA,
+ MP3,
+ MPEG4,
+ FLV,
+ VP6,
+ VP7
+ } codec_e;
+ typedef enum {
+ NO_FILETYPE,
+ RTMP,
+ RTMPT,
+ RTMPTS,
+ FLASH6,
+ FLASH7,
+ FLASH8,
+ FLASH9,
+ AUDIO,
+ VIDEO
+ } filetypes_e;
+ // start the clock counting down
+ boost::posix_time::ptime startClock();
+ // stop the clock from counting down
+ boost::posix_time::ptime stopClock();
+
+ // Accessors to set to the private data
+ void setStartTime(boost::posix_time::ptime x) { _starttime = x; };
+ void setStopTime(boost::posix_time::ptime x) { _stoptime = x; };
+ void setBytes(int x) { _bytes = x; };
+ void setCodec(codec_e x) { _codec = x; };
+ void setFileType(filetypes_e x) { _type = x; };
+ // Accumulate the byts transferred
+ int addBytes(int x) { _bytes += x; return _bytes; };
+
+ // Accessors to get to the private data
+ int getBytes() { return _bytes; };
+ codec_e getCodec() { return _codec; };
+ filetypes_e getFileType() { return _type; };
+ boost::posix_time::ptime getStartTime() { return _starttime; };
+ boost::posix_time::ptime getStopTime() { return _stoptime; };
+ boost::posix_time::time_duration getTimeSpan() { return _stoptime -
_starttime; };
+ NetStats &operator = (NetStats &stats);
+private:
+ boost::posix_time::ptime _starttime;
+ boost::posix_time::ptime _stoptime;
+ int _bytes;
+ codec_e _codec;
+ filetypes_e _type;
+};
+
+} // end of cygnal namespace
+
+#endif // __NETSTATS_H__
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: statistics.cpp
===================================================================
RCS file: statistics.cpp
diff -N statistics.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ statistics.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,133 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/thread/mutex.hpp>
+#include <string>
+#include <list>
+#include <iostream>
+
+#include "log.h"
+#include "netstats.h"
+#include "statistics.h"
+
+using namespace gnash;
+using namespace std;
+
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+}
+
+static boost::mutex io_mutex;
+
+// The string versions of the codec, used for debugging. If you add
+// another enum type to codec_e, you have to add the string
+// representation here or you'll get the wrong output.
+const char *codec_names[] = {
+ "NO_CODEC",
+ "Ogg",
+ "Theora",
+ "MP3",
+ "MPEG4",
+ "FLV",
+ "VP6",
+ "VP7"
+};
+
+// The string versions of the codec, used for debugging. If you add
+// another enum type to filetypes_e, you have to add the string
+// representation here or you'll get the wrong output.
+const char *filetype_names[] = {
+ "NO_FILETYPE",
+ "RTMP",
+ "RTMPT",
+ "RTMPTS",
+ "FLASH5",
+ "FLASH6",
+ "FLASH7",
+ "FLASH8",
+ "FLASH9",
+ "AUDIO",
+ "VIDEO"
+};
+
+namespace cygnal
+{
+
+Statistics::Statistics() {
+}
+
+Statistics::~Statistics() {
+ dump();
+}
+
+float
+Statistics::getFPS() {
+
+}
+
+int
+Statistics::getBitRate() {
+
+ return (getStartTime() - getStopTime()).seconds() / getBytes();
+}
+
+int
+Statistics::addStats() {
+ NetStats *st = new NetStats;
+
+ st->setStartTime(getStartTime());
+ st->setStopTime(getStopTime());
+ st->setBytes(getBytes());
+ st->setCodec(getCodec());
+ st->setFileType(getFileType());
+
+ boost::mutex::scoped_lock lock(io_mutex);
+ _netstats.push_back(st);
+
+ return _netstats.size();
+}
+
+void
+Statistics::dump() {
+ boost::mutex::scoped_lock lock(io_mutex);
+ list<NetStats *>::iterator it;
+
+ for (it = _netstats.begin(); it != _netstats.end(); it++) {
+ NetStats *stats = (*it);
+ if (stats->getFileType() <= VIDEO) {
+ dbglogfile << "Stream type is: " <<
filetype_names[stats->getFileType()] << endl;
+ }
+ if (((stats->getFileType() == VIDEO) || (stats->getFileType() ==
AUDIO)) &&
+ stats->getCodec() <= VP7) {
+ dbglogfile << "Stream codec is: " <<
codec_names[stats->getCodec()];
+ }
+ dbglogfile << stats->getBytes() << " bytes were transfered in "
+ << to_simple_string(stats->getTimeSpan()).c_str()
+ << " seconds." << endl;
+ }
+}
+
+} // end of cygnal namespace
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: statistics.h
===================================================================
RCS file: statistics.h
diff -N statistics.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ statistics.h 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,83 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef __STATISTICS_H__
+#define __STATISTICS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/date_time/posix_time/posix_time.hpp> //include all types plus
i/o
+#include <sys/time.h>
+#include <network.h>
+#include <list>
+
+#include "netstats.h"
+
+namespace cygnal
+{
+
+class Statistics : public NetStats {
+public:
+ Statistics();
+ ~Statistics();
+ typedef enum {
+ NO_BROWSER,
+ MOZILLA,
+ FIREFOX,
+ OPERA,
+ KONQUEROR,
+ GALEON,
+ EPIPHANY,
+ SAFARI,
+ IE
+ } browser_e;
+ typedef enum {
+ NO_OSTYPE,
+ LINUX,
+ BSD,
+ DARWIN,
+ WIN32,
+ SOLARIS
+ } ostype_e;
+ void setIPaddr(in_addr_t x) { _ipaddr = x; };
+ void setBrowser(browser_e x) { _browser = x; } ;
+ int addStats();
+ // these make calculations on the collected network data.
+ float getFPS();
+ int getBitRate();
+ // Dump the collected network statistics in a human readable form.
+ void dump();
+ void clear();
+private:
+ in_addr_t _ipaddr;
+ const char *_filespec;
+ browser_e _browser;
+ ostype_e _os;
+ std::list<NetStats *> _netstats;
+};
+
+
+} // end of cygnal namespace
+
+#endif // __STATISTICS_H__
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: stream.cpp
===================================================================
RCS file: stream.cpp
diff -N stream.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ stream.cpp 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,330 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+#include <cerrno>
+#include <sys/mman.h>
+
+#include "stream.h"
+#include "network.h"
+#include "amf.h"
+#include "rtmp.h"
+#include "log.h"
+
+#include <boost/thread/mutex.hpp>
+static boost::mutex io_mutex;
+
+using namespace gnash;
+using namespace std;
+
+namespace cygnal {
+
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+}
+
+#if 0
+static void
+sendfile_thread()
+{
+ GNASH_REPORT_FUNCTION;
+
+ struct stat stats;
+ struct filedes loadfile;
+ int fd;
+ char *fdptr;
+
+ memcpy(&loadfile, arg, sizeof(struct filedes));
+
+ // Get the file stats
+ if (stat(loadfile.filespec, &stats) == 0) {
+
+ fd = open(loadfile.filespec, O_RDONLY);
+// dbglogfile << "File " << loadfile.filespec
+// << " is " << stats.st_size
+// << " bytes in size." << endl;
+ if (fd) {
+ fdptr = static_cast<char *>(mmap(0, stats.st_size,
+ PROT_READ, MAP_SHARED, fd, 0));
+ } else {
+ dbglogfile << "ERROR: Couldn't load "
+ << loadfile.filespec << endl;
+ }
+
+ if (fdptr == MAP_FAILED) {
+ dbglogfile << "ERROR: Couldn't map file "
+ << loadfile.filespec << " into memory! "
+ << strerror(errno) << endl;
+ } else {
+ dbglogfile << "File " << loadfile.filespec
+ << " mapped to: " << (void *)fdptr << endl;
+ }
+
+// if (stats.st_size > 1024*8) {
+// }
+
+// if (stats.st_blksize > 10) {
+// }
+
+// if (stats.st_blocks > 10) {
+// }
+ } else {
+ dbglogfile << "ERROR: File " << loadfile.filespec
+ << " doesn't exist!" << endl;
+ }
+
+ int filesize = stats.st_size;
+ int blocksize = 8192;
+ char *tmpptr = fdptr;
+ int nbytes = 0;
+ Network net;
+ while ((_seekptr - _dataptr) <= RTMP_BODY_SIZE) {
+ if (filesize < RTMP_BODY_SIZE) {
+ nbytes = net.writeNet(loadfile.fd, tmpptr, filesize);
+ filesize = 0;
+ } else {
+ nbytes = net.writeNet(loadfile.fd, tmpptr, blocksize);
+ filesize -= blocksize;
+ tmpptr += blocksize;
+ }
+
+ if (nbytes <= 0) {
+ dbglogfile << "Done..." << endl;
+ return &nbytes;
+ }
+ }
+
+ close(fd);
+ munmap(fdptr, stats.st_size);
+}
+#endif
+
+Stream::Stream()
+ : _bytes(0),
+ _filefd(0),
+ _netfd(0),
+ _filespec(0),
+ _statistics(0),
+ _dataptr(0),
+ _seekptr(0),
+ _filesize(0)
+{
+ GNASH_REPORT_FUNCTION;
+
+}
+
+Stream::~Stream() {
+ GNASH_REPORT_FUNCTION;
+ if (_filefd) {
+ close(_filefd);
+ }
+ if (_netfd) {
+ close(_netfd);
+ }
+}
+
+bool
+Stream::open(const char *filespec) {
+ GNASH_REPORT_FUNCTION;
+
+ return open(filespec, _netfd);
+}
+
+bool
+Stream::open(const char *filespec, int netfd) {
+ GNASH_REPORT_FUNCTION;
+
+ struct stat stats;
+ return open(filespec, _netfd, _statistics);
+}
+
+bool
+Stream::open(const char *filespec, int netfd, Statistics *statistics) {
+ GNASH_REPORT_FUNCTION;
+
+ struct stat st;
+
+ _netfd = netfd;
+ _statistics = statistics;
+
+ dbglogfile << "Trying to open " << filespec << endl;
+
+ if (stat(filespec, &st) == 0) {
+ _filesize = st.st_size;
+ boost::mutex::scoped_lock lock(io_mutex);
+ _filefd = ::open(filespec, O_RDONLY);
+ dbglogfile << "File " << filespec
+ << " is " << _filesize
+ << " bytes in size." << endl;
+ if (_filefd) {
+ _dataptr = static_cast<unsigned char *>(mmap(0, _filesize,
+ PROT_READ, MAP_SHARED, _filefd, 0));
+ } else {
+ dbglogfile << "ERROR: Couldn't load "
+ << filespec << endl;
+ return false;
+ }
+
+ if (_seekptr == MAP_FAILED) {
+ dbglogfile << "ERROR: Couldn't map file "
+ << filespec << " into memory! "
+ << strerror(errno) << endl;
+ return false;
+ } else {
+ dbglogfile << "File " << filespec
+ << " mapped to: " << (void *)_dataptr << endl;
+ _seekptr = _dataptr;
+ _state = OPEN;
+ return true;
+ }
+// if (stats.st_size > 1024*8) {
+// }
+
+// if (stats.st_blksize > 10) {
+// }
+
+// if (stats.st_blocks > 10) {
+// }
+ } else {
+ dbglogfile << "ERROR: File " << filespec
+ << " doesn't exist!" << endl;
+ }
+
+
+ return true;
+}
+
+// Stream the movie
+bool
+Stream::play() {
+ GNASH_REPORT_FUNCTION;
+
+ return play(_netfd);
+}
+
+bool
+Stream::play(int netfd) {
+ GNASH_REPORT_FUNCTION;
+
+ _netfd = netfd;
+ _state = PLAY;
+
+ while (_state != DONE) {
+ switch (_state) {
+ case PLAY:
+ _state = DONE;
+ break;
+ case PREVIEW:
+ break;
+ case THUMBNAIL:
+ break;
+ case PAUSE:
+ break;
+ case SEEK:
+ break;
+ case UPLOAD:
+ break;
+ case MULTICAST:
+ break;
+ case DONE:
+ break;
+ default:
+ break;
+ }
+ }
+
+ int blocksize = 8192;
+ int nbytes = 0;
+ Network net;
+// while ((_seekptr - _dataptr) >= 0) {
+ nbytes = net.writeNet(_netfd, (char *)_seekptr, _filesize);
+// if (nbytes <= 0) {
+// break;
+// }
+ _statistics->addBytes(nbytes);
+ _bytes += nbytes;
+ _seekptr += nbytes;
+
+ dbglogfile << "Done..." << endl;
+
+ munmap(_dataptr, _filesize);
+ _seekptr = 0;
+
+ return true;
+}
+
+// Stream a preview, instead of the full movie.
+bool
+Stream::preview(const char *filespec, int frames) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = PREVIEW;
+}
+
+// Stream a series of thumbnails
+bool
+Stream::thumbnail(const char *filespec, int quantity) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = THUMBNAIL;
+}
+
+// Pause the stream
+bool
+Stream::pause(int frame) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = PAUSE;
+}
+
+// Seek within the stream
+bool
+Stream::seek(int frame) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = SEEK;
+}
+
+// Upload a stream into a sandbox
+bool
+Stream::upload(const char *filespec) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = UPLOAD;
+}
+
+// Stream a single "real-time" source.
+bool Stream::multicast(const char *filespec) {
+ GNASH_REPORT_FUNCTION;
+
+ _state = MULTICAST;
+}
+
+} // end of cygnal namespace
+
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: stream.h
===================================================================
RCS file: stream.h
diff -N stream.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ stream.h 17 Dec 2006 02:34:58 -0000 1.1
@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef __STREAM_H__
+#define __STREAM_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "statistics.h"
+
+namespace cygnal {
+
+class Stream {
+public:
+ typedef enum {
+ NO_STATE,
+ OPEN,
+ PLAY,
+ PREVIEW,
+ THUMBNAIL,
+ PAUSE,
+ SEEK,
+ UPLOAD,
+ MULTICAST,
+ DONE
+ } state_e;
+ Stream();
+ ~Stream();
+ bool open(const char *filespec);
+ bool open(const char *filespec, int netfd);
+ bool open(const char *filespec, int netfd, Statistics *statistics);
+ // Stream the movie
+ bool play();
+ bool play(int netfd);
+ // Stream a preview, instead of the full movie.
+ bool preview(const char *filespec, int frames);
+ // Stream a series of thumbnails
+ bool thumbnail(const char *filespec, int quantity);
+ // Pause the stream
+ bool pause(int frame);
+ // Seek within the stream
+ bool seek(int frame);
+ // Upload a stream into a sandbox
+ bool upload(const char *filespec);
+ // Stream a single "real-time" source.
+ bool multicast(const char *filespec);
+
+private:
+ state_e _state;
+ int _bytes;
+ int _filefd;
+ int _netfd;
+ char *_filespec;
+ Statistics *_statistics;
+ unsigned char *_dataptr;
+ unsigned char *_seekptr;
+ int _filesize;
+};
+
+} // end of cygnal namespace
+
+
+#endif // __STREAM_H__
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash/cygnal Makefile.am alloc.cpp cygnal.cpp h...,
Rob Savoye <=