gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash server/asobj/LocalConnection.cpp ChangeLog


From: Rob Savoye
Subject: [Gnash-commit] gnash server/asobj/LocalConnection.cpp ChangeLog
Date: Sat, 05 Jan 2008 04:25:47 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/01/05 04:25:47

Modified files:
        server/asobj   : LocalConnection.cpp 
        .              : ChangeLog 

Log message:
                * server/asobj/LocalConnection.cpp: A mostly implemented
                LocalConnection class.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/LocalConnection.cpp?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5305&r2=1.5306

Patches:
Index: server/asobj/LocalConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/LocalConnection.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/asobj/LocalConnection.cpp    1 Jul 2007 10:54:28 -0000       1.15
+++ server/asobj/LocalConnection.cpp    5 Jan 2008 04:25:46 -0000       1.16
@@ -21,30 +21,160 @@
 #include "config.h"
 #endif
 
+#include <unistd.h>
 #include <cerrno>
+#include <cstring>
 
+#include "VM.h"
+#include "URLAccessManager.h"
+#include "URL.h"
 #include "log.h"
 #include "LocalConnection.h"
 #include "network.h"
 #include "fn_call.h"
 #include "builtin_function.h" 
 
+using namespace std;
+using namespace amf;
+
+// http://www.osflash.org/localconnection
+//
+// Listening
+// To create a listening LocalConnection, you just have to set a thread to:
+
+//    1.register the application as a valid LocalConnection listener,
+//    2.require the mutex to have exclusive access to the shared memory,
+//    3.access the shared memory and check the recipient,
+//    4.if you are the recipient, read the message and mark it read,
+//    5.release the shared memory and the mutex,
+//    6.repeat indefinitely from step 2.
+//
+// Sending
+// To send a message to a LocalConnection apparently works like that:
+//    1. require the mutex to have exclusive access to the shared memory,
+//    2. access the shared memory and check that the listener is connected,
+//    3. if the recipient is registered, write the message,
+//    4. release the shared memory and the mutex.
+//
+// The main thing you have to care about is the timestamp - simply call 
GetTickCount()
+//  and the message size. If your message is correctly encoded, it should be 
received
+// by the listening LocalConnection 
+//
+// Some facts:
+//     * The header is 16 bytes,
+//     * The message can be up to 40k,
+//     * The listeners block starts at 40k+16 = 40976 bytes,
+//     * To add a listener, simply append its name in the listeners list (null 
terminated strings)
+namespace {
+gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();    
+}
+
 namespace gnash {
 
+// The maximum 
+const int LC_HEADER_SIZE = 16;
+const int MAX_LC_HEADER_SIZE = 40960;
+const int LC_LISTENERS_START  = MAX_LC_HEADER_SIZE +  LC_HEADER_SIZE;
+
+// This doesn't exist on all systems, but here's the vaue used on Unix.
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 64
+#endif
+
 // \class LocalConnection
 /// \brief Open a connection between two SWF movies so they can send
 /// each other Flash Objects to be executed.
 ///
-LocalConnection::LocalConnection() {
+LocalConnection::LocalConnection()
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+LocalConnection::~LocalConnection()
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+#if 0
+Listener::Listener()
+    : _baseaddr(0)
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+Listener::Listener(char *x)
+{
+    GNASH_REPORT_FUNCTION;
+    _baseaddr = x;
+}
+
+Listener::~Listener()
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+bool
+Listener::addListener(std::string &name)
+{
+    GNASH_REPORT_FUNCTION;
+
+    char *addr = _baseaddr + LC_LISTENERS_START;
+    char *item = addr;
+    // Walk to the end of the list
+    while (*item != 0) {
+        item += strlen(item)+1;
+    }
+    // Add ourselves to the list
+    if (memcpy(item, name.c_str(), name.size()) == 0) {
+        return false;
+    }
+    return true;
 }
 
-LocalConnection::~LocalConnection() {
+bool
+Listener::removeListener(std::string &name)
+{
+    GNASH_REPORT_FUNCTION;
+
+    char *addr = _baseaddr + LC_LISTENERS_START;
+
+    char *item = addr;
+    while (*item != 0) {
+        if (name == item) {
+            int len = strlen(item) + 1;
+            while (*item != 0) {
+                strcpy(item, item + len);
+                item += len + 1;
+            }
+            return true;
+        }
+        item += strlen(item) + 1;
+    }
+    return false;
+}
+
+std::vector<std::string> *
+Listener::listListeners()
+{
+    GNASH_REPORT_FUNCTION;
+
+    char *addr = _baseaddr + LC_LISTENERS_START;
+
+    vector<string> *listeners = new vector<string>;
+    const char *item = addr;
+    while (*item != 0) {
+        listeners->push_back(item);
+        item += strlen(item) + 1;
+    }    
+
+    return listeners;
 }
 
 /// \brief Closes (disconnects) the LocalConnection object.
 void
 LocalConnection::close()
 {
+    GNASH_REPORT_FUNCTION;
 #ifndef NETWORK_CONN
     closeMem();
 #endif
@@ -59,15 +189,58 @@
 bool
 LocalConnection::connect(const char *name)
 {
-#ifndef NETWORK_CONN
-    if (attach(name, true) == false) {
+    GNASH_REPORT_FUNCTION;
+    
+    _name = name;
+
+    log_debug("trying to open shared memory segment: \"%s\"", name);
+    
+    if (Shm::attach(name, true) == false) {
         return false;
     }
-#endif
-    _name = name;
+
+    if (Shm::getAddr() <= 0) {
+        log_error("Failed to open shared memory segment: \"%s\"", name);
+        return false; 
+    }
+    
+    Listener::setBaseAddress(Shm::getAddr());
+        
+    string str1 = "HelloWorld";
+    addListener(str1);
+    str1 = "GutenTag";
+    addListener(str1);
+    str1 = "Aloha";
+    addListener(str1);
+    
+    vector<string>::const_iterator it;
+    vector<string> *listeners = listListeners();
+    if (listeners->size() == 0) {
+        log_msg("Nobody is listening");
+    } else {
+        log_msg("There are %d", listeners->size());
+        for (it=listeners->begin(); it!=listeners->end(); it++) {
+            string str = *it;
+            log_debug("Listeners: %s", str.c_str());
+        }
+    }
+
+    delete listeners;
+    
+    str1 = "HelloWorld";
+    removeListener(str1);
+    listeners = listListeners();  
+    log_msg("There are %d", listeners->size());
+    for (it=listeners->begin(); it != listeners->end(); it++) {
+        string str = *it;
+        log_debug("Listeners: %s", str.c_str());
+    }
+    
+    delete listeners;
 
     return true;
 }
+#endif
 
 /// \brief Returns a string representing the superdomain of the
 /// location of the current SWF file.
@@ -76,89 +249,119 @@
 /// network connection. This behaviour changed for SWF v7. Prior to v7
 /// only the domain was returned, ie dropping off node names like
 /// "www". As of v7, the behaviour is to return the full host
-/// name. Gnash defaults to the v7 behaviour.
-/// \note If this becomes a problem, we'll have to implemented the
-/// older behaviour based on the version of the flash movie being
-/// played.
+/// name. Gnash supports both behaviours based on the version.
 std::string
-LocalConnection::domain(void)
+LocalConnection::domain(int version)
 {
-    if (_name.size() == 0) {
-        return "localhost";
-    } else {
+//    GNASH_REPORT_FUNCTION;
+    // We already figured out the name
+    if (_name.size()) {
         return _name;
     }
-}
 
-/// \brief Invokes a method on a specified LocalConnection object.
-void
-LocalConnection::send()
-{
-    log_unimpl (__FUNCTION__);
+    string url_s;
+    const URL& baseurl = get_base_url();
+    URL url(url_s, baseurl);
+//    log_msg(_("BASE URL=%s (%s)"), baseurl.str().c_str(), 
url.hostname().c_str());
+    if (url.hostname().size() == 0) {
+        _name = "localhost";
+    } else {
+        _name = url.hostname();
+    }
+
+    // Adjust the name based on the swf version. Prior to v7, the nodename part
+    // was removed. For v7 or later. the full hostname is returned. The 
localhost
+    // is always just the localhost.
+    if (version <= 6) {
+        string::size_type pos;
+        pos = _name.rfind(".", _name.size());
+        if (pos != string::npos) {
+            pos = _name.rfind(".", pos-1);
+            if (pos != string::npos) {
+                _name = _name.substr(pos+1, _name.size());
+            }
+        }
+    }
+
+    // If unset, pick the default. Yes, we're paranoid.
+    if (_name.size() == 0) {
+        _name =  "localhost";
+    }
+    
+    log_msg("The domain for this host is: %s", _name.c_str());
+
+    return _name;
 }
 
 /// \brief Instantiate a new LocalConnection object within a flash movie
 as_value
 localconnection_new(const fn_call& /* fn */)
 {
-    localconnection_as_object *localconnection_obj = new 
localconnection_as_object;
+//    GNASH_REPORT_FUNCTION;
+    LocalConnection *localconnection_obj = new LocalConnection;
 
     localconnection_obj->init_member("close", new 
builtin_function(localconnection_close));
     localconnection_obj->init_member("connect", new 
builtin_function(localconnection_connect));
     localconnection_obj->init_member("domain", new 
builtin_function(localconnection_domain));
     localconnection_obj->init_member("send", new 
builtin_function(localconnection_send));
-#if 0
-    // Apparently these AS methods were added for testing purposes. However,
-    // they do not appear to be part of the LocalConnection AS object.
-    localconnection_obj->init_member("getname",  new 
builtin_function(shm_getname));
-    localconnection_obj->init_member("getsize",  new 
builtin_function(shm_getsize));
-    localconnection_obj->init_member("getallocated",  new 
builtin_function(shm_getallocated));
-    localconnection_obj->init_member("exists",  new 
builtin_function(shm_exists));
-#endif
 
     return as_value(localconnection_obj);
 }
 
 /// \brief The callback for LocalConnection::close()
-as_value localconnection_close(const fn_call& fn)
+as_value
+localconnection_close(const fn_call& fn)
 {
-//    log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
+    GNASH_REPORT_FUNCTION;
     
-    boost::intrusive_ptr<localconnection_as_object> ptr = 
ensureType<localconnection_as_object>(fn.this_ptr);
+    boost::intrusive_ptr<LocalConnection> ptr = 
ensureType<LocalConnection>(fn.this_ptr);
     
-    ptr->obj.close();
+    ptr->close();
     return as_value();
 }
 
 /// \brief The callback for LocalConnection::connect()
-as_value localconnection_connect(const fn_call& fn)
+as_value
+localconnection_connect(const fn_call& fn)
 {
+    GNASH_REPORT_FUNCTION;
 //    log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
     bool ret;
-    boost::intrusive_ptr<localconnection_as_object> ptr = 
ensureType<localconnection_as_object>(fn.this_ptr);
-    
+    boost::intrusive_ptr<LocalConnection> ptr = 
ensureType<LocalConnection>(fn.this_ptr);
+    string name = fn.arg(0).to_string().c_str();
     if (fn.nargs != 0) {
-        ret = ptr->obj.connect(fn.arg(0).to_string().c_str());
+        ret = ptr->connect(name);
+        name = "localhost";
     } else {
         log_error(_("No connection name specified to 
LocalConnection.connect()"));
-        ret = ptr->obj.connect("localhost"); // FIXME: This should probably
+        ret = ptr->connect(name); // FIXME: This should probably
                                        // fail instead
     }
     return as_value(ret);
 }
 
 /// \brief The callback for LocalConnection::domain()
-as_value localconnection_domain(const fn_call& fn)
+as_value
+localconnection_domain(const fn_call& fn)
 {
-//    log_msg("%s:\n", __PRETTY_FUNCTION__);
-    boost::intrusive_ptr<localconnection_as_object> ptr = 
ensureType<localconnection_as_object>(fn.this_ptr);
-    return as_value(ptr->obj.domain().c_str());
+    GNASH_REPORT_FUNCTION;
+    boost::intrusive_ptr<LocalConnection> ptr = 
ensureType<LocalConnection>(fn.this_ptr);
+    VM& vm = ptr->getVM();
+    int swfVersion = vm.getSWFVersion();
+
+    return as_value(ptr->domain(swfVersion).c_str());
 }
 
 // \brief The callback for LocalConnection::send()
-as_value localconnection_send(const fn_call& /*fn*/)
+as_value
+localconnection_send(const fn_call& fn)
 {
-    log_unimpl (__FUNCTION__);
+    boost::intrusive_ptr<LocalConnection> obj = 
ensureType<LocalConnection>(fn.this_ptr);
+    if (rcfile.getLocalConnection() ) {
+        log_security("Attempting to write to disabled LocalConnection!");
+        return as_value(false);
+    }
+    
     return as_value();
 }
 

Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5305
retrieving revision 1.5306
diff -u -b -r1.5305 -r1.5306
--- ChangeLog   5 Jan 2008 03:55:00 -0000       1.5305
+++ ChangeLog   5 Jan 2008 04:25:47 -0000       1.5306
@@ -1,5 +1,8 @@
 2008-01-04  Rob Savoye  <address@hidden>
 
+       * server/asobj/LocalConnection.cpp: A mostly implemented
+       LocalConnection class.
+       
        * testsuite/actionscript.all/SharedObject.as: Use a multi level
        path.
        * testsuite/actionscript.all/NetConnection.as: Use check.a




reply via email to

[Prev in Thread] Current Thread [Next in Thread]