gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r9582: Fix 404 handling with non-blo


From: Sandro Santilli
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r9582: Fix 404 handling with non-blocking read (well, kind-of).
Date: Tue, 12 Aug 2008 15:11:56 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 9582
committer: Sandro Santilli <address@hidden>
branch nick: trunk
timestamp: Tue 2008-08-12 15:11:56 +0200
message:
  Fix 404 handling with non-blocking read (well, kind-of).
  Improve remoting by dropping any string_table lookups and properly
  handle 404.
modified:
  libbase/curl_adapter.cpp
  libcore/asobj/NetConnection.cpp
  libcore/namedStrings.cpp
  libcore/namedStrings.h
    ------------------------------------------------------------
    revno: 9580.1.1
    committer: Sandro Santilli <address@hidden>
    branch nick: mybranch
    timestamp: Tue 2008-08-12 14:53:44 +0200
    message:
      Add PROP_ON_RESULT
    modified:
      libcore/namedStrings.cpp
      libcore/namedStrings.h
    ------------------------------------------------------------
    revno: 9580.1.2
    committer: Sandro Santilli <address@hidden>
    branch nick: mybranch
    timestamp: Tue 2008-08-12 14:58:45 +0200
    message:
      Handle 404 or other http errors when doing non-blocking reads
    modified:
      libbase/curl_adapter.cpp
    ------------------------------------------------------------
    revno: 9580.1.3
    committer: Sandro Santilli <address@hidden>
    branch nick: mybranch
    timestamp: Tue 2008-08-12 14:59:08 +0200
    message:
      Handle IO errors by invoking NetConnection.onStatus
    modified:
      libcore/asobj/NetConnection.cpp
=== modified file 'libbase/curl_adapter.cpp'
--- a/libbase/curl_adapter.cpp  2008-07-10 16:36:19 +0000
+++ b/libbase/curl_adapter.cpp  2008-08-12 12:58:45 +0000
@@ -444,6 +444,9 @@
        // Will call libcurl routines to fetch data.
        void fillCache(long unsigned size);
 
+       // Process pending curl messages (handles 404)
+       void processMessages();
+
        // Filling the cache as much as possible w/out blocking.
        // Will call libcurl routines to fetch data.
        void fillCacheNonBlocking();
@@ -532,6 +535,9 @@
        {
                throw gnash::GnashException(curl_multi_strerror(mcode));
        }
+
+       // handle 404
+       processMessages();
 }
 
 
@@ -573,12 +579,12 @@
        while (_running)
        {
 
-               fillCacheNonBlocking();
+               fillCacheNonBlocking(); // NOTE: will handle 404
 
                // Do this here to avoid calling select()
                // when we have enough bytes anyway, or
                // we reached EOF
-               if (_cached >= size || !_running) break;
+               if (_cached >= size || !_running) break; // || _error ?
 
 #if GNASH_CURL_VERBOSE
                //gnash::log_debug("cached: %d, size: %d", _cached, size);
@@ -655,11 +661,22 @@
 
        }
 
+       // Processing messages is already done by fillCacheNonBlocking,
+       // so we might likely avoid it here.
+       processMessages();
+
+}
+
+/*private*/
+void
+CurlStreamFile::processMessages()
+{
        CURLMsg *curl_msg;
        
        // The number of messages left in the queue (not used by us).
        int msgs;
-       while ((curl_msg = curl_multi_info_read(_mhandle, &msgs))) {
+       while ((curl_msg = curl_multi_info_read(_mhandle, &msgs)))
+       {
 
                // Only for completed transactions
                if (curl_msg->msg == CURLMSG_DONE) {
@@ -696,7 +713,6 @@
                }
 
        }
-
 }
 
 

=== modified file 'libcore/asobj/NetConnection.cpp'
--- a/libcore/asobj/NetConnection.cpp   2008-08-12 09:59:57 +0000
+++ b/libcore/asobj/NetConnection.cpp   2008-08-12 12:59:08 +0000
@@ -46,6 +46,8 @@
 #include "amf.h"
 #include "SimpleBuffer.h"
 #include "timers.h"
+#include "namedStrings.h"
+
 using namespace amf;
 
 namespace gnash {
@@ -504,8 +506,8 @@
        int reply_start;
        int reply_end;
        int queued_count;
-       uint8_t am_ticking;
        unsigned int ticker;
+
 public:
        AMFQueue(NetConnection& nc, URL url)
                :
@@ -517,7 +519,7 @@
                reply_start(0),
                reply_end(0),
                queued_count(0),
-               am_ticking(0)
+               ticker(0)
        {
                // leave space for header
                postdata.append("\000\000\000\000\000\000", 6);
@@ -527,12 +529,12 @@
                stop_ticking();
        }
        
-       void enqueue(SimpleBuffer &amf, std::string identifier, 
boost::intrusive_ptr<as_object> callback) {
+       void enqueue(const SimpleBuffer &amf, const std::string& identifier, 
boost::intrusive_ptr<as_object> callback) {
                push_amf(amf);
                push_callback(identifier, callback);
                //log_aserror("NetConnection::call(): called with a non-object 
as the callback");
        };
-       void enqueue(SimpleBuffer &amf) {
+       void enqueue(const SimpleBuffer &amf) {
                push_amf(amf);
        };
        
@@ -542,8 +544,10 @@
        // it handles all networking for NetConnection::call() and dispatches
        // callbacks when needed
        void tick() {
+
                log_debug("tick running");
-               if(connection) {
+               if(connection)
+               {
                        log_debug("have connection");
                        int read = connection->readNonBlocking(reply.data() + 
reply_end, NCCALLREPLYMAX - reply_end);
                        if(read > 0) {
@@ -564,126 +568,143 @@
                        // FIXME make this parse on other conditions, 
including: 1) when
                        // the buffer is full, 2) when we have a "length in 
bytes" value
                        // thas is satisfied
+
+                       if(connection->get_error())
+                       {
+                               log_debug("connection is in error condition, 
calling NetConnection.onStatus");
+                               reply_start = 0;
+                               reply_end = 0;
+
+                               // FIXME: should only call NetConnection's 
onStatus
+                               //        if the IOChannel is in error 
condition.
+                               //        (tipically 404).
+                               //        When the response is empty, just 
nothing happens.
+                               _nc.callMethod(NSV::PROP_ON_STATUS, as_value());
+                               return;
+                       }
                        
-                       if(connection->eof() && reply_end > 8) {
-                               log_debug("hit eof");
-                               boost::int16_t si;
-                               boost::uint16_t li;
-                               boost::uint8_t *b = reply.data() + reply_start;
-                               boost::uint8_t *end = reply.data() + reply_end;
+                       if(connection->eof() )
+                       {
+                               if ( reply_end > 8)
+                               {
+                                       log_debug("hit eof");
+                                       boost::int16_t si;
+                                       boost::uint16_t li;
+                                       boost::uint8_t *b = reply.data() + 
reply_start;
+                                       boost::uint8_t *end = reply.data() + 
reply_end;
 
-                               // parse header
-                               b += 2; // skip version indicator and client id
-                               si = readNetworkShort(b); b += 2; // number of 
headers
-                               uint8_t headers_ok = 1;
-                               if(si != 0)
-                               {
-                                       log_debug("NetConnection::call(): amf 
headers section parsing");
-                                       as_value tmp;
-                                       for(int i = si; i > 0; --i)
+                                       // parse header
+                                       b += 2; // skip version indicator and 
client id
+                                       si = readNetworkShort(b); b += 2; // 
number of headers
+                                       uint8_t headers_ok = 1;
+                                       if(si != 0)
                                        {
-                                               if(b + 2 > end) {
-                                                       headers_ok = 0;
-                                                       break;
-                                               }
-                                               si = readNetworkShort(b); b += 
2; // name length
-                                               if(b + si > end) {
-                                                       headers_ok = 0;
-                                                       break;
-                                               }
-                                               b += si;
-                                               if ( b + 5 > end ) {
-                                                       headers_ok = 0;
-                                                       break;
-                                               }
-                                               b += 5; // skip past bool and 
length long
-                                               if( !amf0_read_value(b, end, 
tmp) )
+                                               
log_debug("NetConnection::call(): amf headers section parsing");
+                                               as_value tmp;
+                                               for(int i = si; i > 0; --i)
                                                {
-                                                       headers_ok = 0;
-                                                       break;
-                                               }
-                                               log_debug("Header value %s", 
tmp);
-                                       }
-                               }
-
-                               if(headers_ok == 1) {
-
-                                       si = readNetworkShort(b); b += 2; // 
number of replies
-
-                                       // TODO consider counting number of 
replies we
-                                       // actually parse and doing something 
if it
-                                       // doesn't match this value (does it 
matter?
-                                       if(si > 0) {
-                                               // parse replies until we get a 
parse error or we reach the end of the buffer
-                                               while(b < end) {
-                                                       if(b + 2 > end) break;
-                                                       si = 
readNetworkShort(b); b += 2; // reply length
-                                                       if(si < 11) {
-                                                               
log_error("NetConnection::call(): reply message name too short");
-                                                               break;
-                                                       }
-                                                       if(b + si > end) break;
-                                                       // TODO check that the 
last 9 bytes are "/onResult"
-                                                       // this should either 
split on the 2nd / or require onResult or onStatus
-                                                       std::string 
id(reinterpret_cast<char*>(b), si - 9);
-                                                       b += si;
-
-                                                       // parse past unused 
string in header
-                                                       if(b + 2 > end) break;
-                                                       si = 
readNetworkShort(b); b += 2; // reply length
-                                                       if(b + si > end) break;
-                                                       b += si;
-
-                                                       // this field is 
supposed to hold the
-                                                       // total number of 
bytes in the rest of
-                                                       // this particular 
reply value, but
-                                                       // openstreetmap.org 
(which works great
-                                                       // in the adobe player) 
sends
-                                                       // 0xffffffff. So we 
just ignore it
-                                                       if(b + 4 > end) break;
-                                                       li = 
readNetworkLong(b); b += 4; // reply length
-
-                                                       log_debug("about to 
parse amf value");
-                                                       // this updates b to 
point to the next unparsed byte
-                                                       as_value reply_as_value;
-                                                       if ( ! 
amf0_read_value(b, end, reply_as_value) )
+                                                       if(b + 2 > end) {
+                                                               headers_ok = 0;
+                                                               break;
+                                                       }
+                                                       si = 
readNetworkShort(b); b += 2; // name length
+                                                       if(b + si > end) {
+                                                               headers_ok = 0;
+                                                               break;
+                                                       }
+                                                       b += si;
+                                                       if ( b + 5 > end ) {
+                                                               headers_ok = 0;
+                                                               break;
+                                                       }
+                                                       b += 5; // skip past 
bool and length long
+                                                       if( !amf0_read_value(b, 
end, tmp) )
                                                        {
-                                                               
log_error("parse amf failed");
-                                                               // this will 
happen if we get
-                                                               // bogus data, 
or if the data runs
-                                                               // off the end 
of the buffer
-                                                               // provided, or 
if we get data we
-                                                               // don't know 
how to parse
+                                                               headers_ok = 0;
                                                                break;
                                                        }
-                                                       log_debug("parsed amf");
-
-                                                       // update variable to 
show how much we've parsed
-                                                       reply_start = b - 
reply.data();
-
-                                                       // if actionscript 
specified a callback object, call it
-                                                       
boost::intrusive_ptr<as_object> callback = pop_callback(id);
-                                                       if(callback) {
-                                                               
log_debug("calling callback");
-                                                               
string_table::key callback_method = callback -> getVM() . getStringTable() . 
find(std::string("onResult"));
-                                                               // FIXME check 
if above line can fail and we have to react
-                                                               
callback->callMethod(callback_method, reply_as_value);
-                                                               
log_debug("callback called");
-                                                       } else {
-                                                               
log_debug("couldn't find callback object");
+                                                       log_debug("Header value 
%s", tmp);
+                                               }
+                                       }
+
+                                       if(headers_ok == 1) {
+
+                                               si = readNetworkShort(b); b += 
2; // number of replies
+
+                                               // TODO consider counting 
number of replies we
+                                               // actually parse and doing 
something if it
+                                               // doesn't match this value 
(does it matter?
+                                               if(si > 0) {
+                                                       // parse replies until 
we get a parse error or we reach the end of the buffer
+                                                       while(b < end) {
+                                                               if(b + 2 > end) 
break;
+                                                               si = 
readNetworkShort(b); b += 2; // reply length
+                                                               if(si < 11) {
+                                                                       
log_error("NetConnection::call(): reply message name too short");
+                                                                       break;
+                                                               }
+                                                               if(b + si > 
end) break;
+                                                               // TODO check 
that the last 9 bytes are "/onResult"
+                                                               // this should 
either split on the 2nd / or require onResult or onStatus
+                                                               std::string 
id(reinterpret_cast<char*>(b), si - 9);
+                                                               b += si;
+
+                                                               // parse past 
unused string in header
+                                                               if(b + 2 > end) 
break;
+                                                               si = 
readNetworkShort(b); b += 2; // reply length
+                                                               if(b + si > 
end) break;
+                                                               b += si;
+
+                                                               // this field 
is supposed to hold the
+                                                               // total number 
of bytes in the rest of
+                                                               // this 
particular reply value, but
+                                                               // 
openstreetmap.org (which works great
+                                                               // in the adobe 
player) sends
+                                                               // 0xffffffff. 
So we just ignore it
+                                                               if(b + 4 > end) 
break;
+                                                               li = 
readNetworkLong(b); b += 4; // reply length
+
+                                                               
log_debug("about to parse amf value");
+                                                               // this updates 
b to point to the next unparsed byte
+                                                               as_value 
reply_as_value;
+                                                               if ( ! 
amf0_read_value(b, end, reply_as_value) )
+                                                               {
+                                                                       
log_error("parse amf failed");
+                                                                       // this 
will happen if we get
+                                                                       // 
bogus data, or if the data runs
+                                                                       // off 
the end of the buffer
+                                                                       // 
provided, or if we get data we
+                                                                       // 
don't know how to parse
+                                                                       break;
+                                                               }
+                                                               
log_debug("parsed amf");
+
+                                                               // update 
variable to show how much we've parsed
+                                                               reply_start = b 
- reply.data();
+
+                                                               // if 
actionscript specified a callback object, call it
+                                                               
boost::intrusive_ptr<as_object> callback = pop_callback(id);
+                                                               if(callback) {
+                                                                       
log_debug("calling callback");
+                                                                       // 
FIXME check if above line can fail and we have to react
+                                                                       
callback->callMethod(NSV::PROP_ON_RESULT, reply_as_value);
+                                                                       
log_debug("callback called");
+                                                               } else {
+                                                                       
log_debug("couldn't find callback object");
+                                                               }
                                                        }
                                                }
                                        }
                                }
-                       }
+                               else
+                               {
+                                       log_error("Response from remoting 
service < 8 bytes");
+                               }
 
-                       if(connection->eof()) {
                                log_debug("deleting connection");
                                connection.reset();
                                reply_start = 0;
                                reply_end = 0;
-
-                               // FIXME send onStatus callback to any callback 
objects from this batch (must change some code to distinguish somehow)
                        }
                }
 
@@ -717,9 +738,8 @@
 
 private:
        void start_ticking() {
-               if(am_ticking) {
-                       return;
-               }
+
+               if(ticker) return;
 
                boost::intrusive_ptr<builtin_function> ticker_as = \
                        new builtin_function(&AMFQueue::amfqueue_tick_wrapper);
@@ -727,10 +747,8 @@
                unsigned long delayMS = 500; // FIXME crank up to 50 or so
                timer->setInterval(*ticker_as, delayMS, &_nc);
                ticker = _nc.getVM().getRoot().add_interval_timer(timer, true);
-
-               am_ticking = 1;
        }
-       void push_amf(SimpleBuffer &amf) {
+       void push_amf(const SimpleBuffer &amf) {
                log_debug("pushing amf");
                postdata.append(amf.data(), amf.size());
                queued_count++;
@@ -738,13 +756,11 @@
                start_ticking();
        }
        void stop_ticking() {
-               if(!am_ticking) {
-                       return;
-               }
+               if(ticker) return;
                _nc.getVM().getRoot().clear_interval_timer(ticker);
-               am_ticking = 0;
+               ticker=0;
        }
-       void push_callback(std::string id, boost::intrusive_ptr<as_object> 
callback) {
+       void push_callback(const std::string& id, 
boost::intrusive_ptr<as_object> callback) {
                callbacks.insert(std::pair<std::string, 
boost::intrusive_ptr<as_object> >(id, callback));
        }
        boost::intrusive_ptr<as_object> pop_callback(std::string id) {
@@ -958,15 +974,14 @@
                                as_value response;
                                if ( amf0_read_value(b, end, response) )
                                {
-                                       string_table::key callbackMethod = 
asCallback -> getVM() . getStringTable() . find(std::string("onResult"));
-                                       asCallback->callMethod(callbackMethod, 
response);
+                                       
asCallback->callMethod(NSV::PROP_ON_RESULT, response);
                                }
                                else
                                {
                                        // TODO construct an object with info 
about the failure to pass to onStatus
                                        // see: 
http://livedocs.adobe.com/fms/2/docs/00000742.html
-                                       //string_table::key callbackMethod = 
asCallback->getVM().getStringTable().find(std::string("onStatus"));
-                                       
//asCallback->callMethod(callbackMethod, TODO);
+                                       log_unimpl("NetConnection.call() : 
triggering responder's onStatus on decoding error");
+                                       
//asCallback->callMethod(NSV::PROP_ON_STATUS, TODO);
                                }
                        }
                }

=== modified file 'libcore/namedStrings.cpp'
--- a/libcore/namedStrings.cpp  2008-07-21 09:56:09 +0000
+++ b/libcore/namedStrings.cpp  2008-08-12 12:53:44 +0000
@@ -94,6 +94,7 @@
        string_table::svt( "onKillFocus", NSV::PROP_ON_KILL_FOCUS ),
        string_table::svt( "onSelect", NSV::PROP_ON_SELECT ),
        string_table::svt( "onStatus", NSV::PROP_ON_STATUS ),
+       string_table::svt( "onResult", NSV::PROP_ON_RESULT ),
        string_table::svt( "onMetaData", NSV::PROP_ON_META_DATA ),
        string_table::svt( "onSockClose", NSV::PROP_ON_SOCK_CLOSE ),
        string_table::svt( "onSockConnect", NSV::PROP_ON_SOCK_CONNECT ),

=== modified file 'libcore/namedStrings.h'
--- a/libcore/namedStrings.h    2008-07-21 09:56:09 +0000
+++ b/libcore/namedStrings.h    2008-08-12 12:53:44 +0000
@@ -112,6 +112,7 @@
                PROP_ON_KILL_FOCUS,
                PROP_ON_SELECT,
                PROP_ON_STATUS,
+               PROP_ON_RESULT,
                PROP_ON_META_DATA,
                PROP_ON_SOCK_CLOSE,
                PROP_ON_SOCK_CONNECT,


reply via email to

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