Sirikata
liboh/plugins/js/EmersonScript.hpp
Go to the documentation of this file.
00001 /*  Sirikata
00002  *  JSObjectScript.hpp
00003  *
00004  *  Copyright (c) 2010, Ewen Cheslack-Postava
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef __SIRIKATA_EMERSON_OBJECT_SCRIPT_HPP__
00034 #define __SIRIKATA_EMERSON_OBJECT_SCRIPT_HPP__
00035 
00036 
00037 
00038 #include <string>
00039 #include <sirikata/oh/ObjectScript.hpp>
00040 #include <sirikata/oh/ObjectScriptManager.hpp>
00041 #include <sirikata/oh/HostedObject.hpp>
00042 #include <sirikata/proxyobject/SessionEventListener.hpp>
00043 
00044 #include <boost/filesystem.hpp>
00045 
00046 #include <v8.h>
00047 
00048 
00049 #include "JSObjectStructs/JSPresenceStruct.hpp"
00050 #include "JSObjectStructs/JSContextStruct.hpp"
00051 #include "JSObjectStructs/JSVisibleStruct.hpp"
00052 #include <sirikata/proxyobject/ProxyCreationListener.hpp>
00053 #include "JSObjects/JSInvokableObject.hpp"
00054 #include "JSEntityCreateInfo.hpp"
00055 #include "JSObjectScript.hpp"
00056 #include "JSObjectScriptManager.hpp"
00057 #include "JSVisibleManager.hpp"
00058 #include "JS_JSMessage.pbj.hpp"
00059 #include "EmersonMessagingManager.hpp"
00060 #include "EmersonHttpManager.hpp"
00061 #include <sirikata/core/util/SerializationCheck.hpp>
00062 #include "JSCtx.hpp"
00063 
00064 namespace Sirikata {
00065 namespace JS {
00066 
00067 
00068 class EmersonScript : public JSObjectScript,
00069                       public SessionEventListener,
00070                       public EmersonMessagingManager
00071 {
00072 
00073 public:
00074     EmersonScript(HostedObjectPtr ho, const String& args,
00075         const String& script, JSObjectScriptManager* jMan,
00076         JSCtx* ctx);
00077 
00078 
00079     virtual ~EmersonScript();
00080 
00081     // Sirikata::Service Interface
00082     virtual void start();
00083     virtual void stop();
00084 
00085     // SessionEventListener Interface
00086     //called from main strand posts to object strand.
00087     virtual void onConnected(SessionEventProviderPtr from, const SpaceObjectReference& name,HostedObject::PresenceToken token);
00088     virtual void onDisconnected(SessionEventProviderPtr from, const SpaceObjectReference& name);
00089 
00090     //called by JSPresenceStruct.  requests the parent HostedObject disconnect
00091     //the presence associated with jspres
00092     void requestDisconnect(JSPresenceStruct* jspres);
00093 
00094     Time getHostedTime();
00095 
00096 
00097     virtual void  notifyProximateGone(ProxyObjectPtr proximateObject, const SpaceObjectReference& querier);
00098     virtual void  notifyProximate(ProxyObjectPtr proximateObject, const SpaceObjectReference& querier);
00099 
00100 
00101     /*
00102       Payload should be able to be parsed into JS::Proctocol::JSMessage.  If it
00103       can be, and deserialization is successful, processes the scripting
00104       message. (via deserializeMsgAndDispatch.)
00105       Return has no meaning.
00106      */
00107     virtual bool handleScriptCommRead(
00108         const SpaceObjectReference& src, const SpaceObjectReference& dst, const std::string& payload);
00109 
00110 
00117     void handleScriptCommUnreliable (const ODP::Endpoint& src, const ODP::Endpoint& dst, MemoryReference payload);
00118 
00119     boost::any invokeInvokable(std::vector<boost::any>& params,v8::Persistent<v8::Function> function_);
00120 
00121 
00122     // Post this function to an IOService to add an event to be handled. Must
00123     // take liveness token because while waiting to be processed the object may,
00124     // e.g., be killed.
00125     void invokeCallbackInContext(Liveness::Token alive, v8::Persistent<v8::Function> cb, JSContextStruct* jscontext);
00126 
00127 
00128     //function gets called when presences are connected.  functToCall is the
00129     //function that gets called back.  Does so in context associated with
00130     //jscont.  Binds first arg to presence object associated with jspres.
00131     //mostly used for contexts and presences to execute their callbacks on
00132     //connection and disconnection events.
00133     void handlePresCallback( v8::Handle<v8::Function> funcToCall,JSContextStruct* jscont, JSPresenceStruct* jspres);
00134 
00135     v8::Handle<v8::Value> restorePresence(PresStructRestoreParams& psrp,JSContextStruct* jsctx);
00136 
00137 
00152     void fireProxEvent(const SpaceObjectReference& localPresSporef,
00153         JSVisibleStruct* jsvis, JSContextStruct* jscont, bool isGone);
00154 
00155 
00156 
00157 
00161     bool valid() const;
00162 
00167     void killOtherPresences(JSPresVec& jspresVec);
00168 
00169 
00170     v8::Handle<v8::Value> killEntity(JSContextStruct* jscont);
00171 
00179     void sendMessageToEntityUnreliable(const SpaceObjectReference& receiver, const SpaceObjectReference& from, const std::string& msgBody);
00180 
00181 
00182     //takes the c++ object jspres, creates a new visible object out of it, if we
00183     //don't already have a c++ visible object associated with it (if we do, use
00184     //that one), wraps that c++ object in v8, and returns it as a v8 object to
00185     //user
00186     v8::Local<v8::Object> presToVis(JSPresenceStruct* jspres, JSContextStruct* jscont);
00187 
00188     // Create event handler
00189     v8::Handle<v8::Value> create_event(v8::Persistent<v8::Function>& cb, JSContextStruct* jscont);
00190 
00192     v8::Handle<v8::Value> create_timeout(double period, v8::Persistent<v8::Function>& cb,JSContextStruct* jscont);
00193 
00194     v8::Handle<v8::Value> create_timeout(double period,v8::Persistent<v8::Function>& cb, uint32 contID,double timeRemaining, bool isSuspended, bool isCleared,JSContextStruct* jscont);
00195 
00196     void registerFixupSuspendable(JSSuspendable* jssuspendable, uint32 contID);
00197 
00198 
00200     void create_entity(EntityCreateInfo& eci);
00201 
00202 
00203     //JSContextStructs request the JSObjectScript to call finishClear on them
00204     //when doing so won't invalidate any iterators on the JSObjectScript.
00205     virtual void registerContextForClear(JSContextStruct* jscont);
00206 
00207 
00219     v8::Local<v8::Object> createVisibleWeakPersistent(
00220         const SpaceObjectReference& presID, const SpaceObjectReference& visibleObj, JSVisibleDataPtr addParams);
00221     v8::Local<v8::Object> createVisibleWeakPersistent(
00222         const SpaceObjectReference& visibleObj, JSVisibleDataPtr addParams);
00223 
00224     //handling basic datatypes for JSPresences
00225     void setLocation(const SpaceObjectReference sporef, const TimedMotionVector3f& loc);
00226     void setOrientation(const SpaceObjectReference sporef, const TimedMotionQuaternion& orient);
00227     void setBounds(const SpaceObjectReference sporef, const BoundingSphere3f& bounds);
00228     void setVisual(const SpaceObjectReference sporef, const std::string& newMeshString);
00229 
00230     String getQuery(const SpaceObjectReference& sporef) const;
00231     void setQueryFunction(const SpaceObjectReference sporef, const String& query);
00232 
00233     void setPhysicsFunction(const SpaceObjectReference sporef, const String& newPhysicsString);
00234 
00235     /****Methods that return V8 wrappers for c++ objects **/
00236 
00237 
00238     v8::Handle<v8::Value> findVisible(const SpaceObjectReference& proximateObj);
00239 
00240 
00241     //wraps the c++ presence structure in a v8 object.
00242     v8::Local<v8::Object> wrapPresence(JSPresenceStruct* presToWrap, v8::Persistent<v8::Context>* ctxToWrapIn);
00243 
00244     //If a simulation for presence with sporef, sporef, and name simname already
00245     //exist, just return an object corresponding to those.
00246     Sirikata::JS::JSInvokableObject::JSInvokableObjectInt* runSimulation(const SpaceObjectReference& sporef, const String& simname);
00247 
00257     v8::Handle<v8::Value> requestReset(JSContextStruct* jscont, const std::map <SpaceObjectReference,std::vector <SpaceObjectReference> > & proxSetVis);
00258 
00259 
00268     void deletePres(JSPresenceStruct* toDelete);
00269 
00270 
00271     void resetPresence(JSPresenceStruct* jspresStruct);
00272 
00273 
00274     JSObjectScriptManager* manager() const { return mManager; }
00275 
00276 
00277     JSContextStruct* rootContext() const { return mContext; }
00278 
00279 
00280     JSVisibleManager jsVisMan;
00281 
00282     HostedObjectPtr mParent;
00283 
00290     EmersonHttpPtr getEmersonHttpPtr()
00291     {
00292         return emHttpPtr;
00293     }
00294 
00295 
00304     v8::Handle<v8::Value> sendSandbox(const String& msgToSend, uint32 senderID, uint32 receiverID);
00305 
00306 
00307     virtual void postCallbackChecks();
00308 private:
00309 
00310     void postDestroy(Liveness::Token alive);
00311 
00312     // Helper for disconnections
00313     void unsubscribePresenceEvents(const SpaceObjectReference& name);
00314     // Helper for *clearing* presences (not disconnections). When the presence
00315     // struct is destroyed (i.e. gc, shutdown), we can then clear out references
00316     // to the presence's data.
00317     void removePresenceData(const SpaceObjectReference& sporefToDelete);
00318 
00319 
00320     //wraps internal c++ jsvisiblestruct in a v8 object
00321     v8::Local<v8::Object> createVisibleWeakPersistent(JSVisibleStruct* jsvis);
00322 
00323     //Called internally by script when guaranteed to be outside of handler
00324     //execution loop.
00325     void killScript();
00326     void resetScript();
00327 
00328     /*
00329       Deserializes the object contained in js_msg, checks if have any pattern
00330       handlers that match it, and dispatch their callbacks if there are.
00331 
00332       If have any handlers that match pattern of message, dispatch their associated
00333       callbacks.
00334      */
00335     bool handleScriptCommRead(
00336         const SpaceObjectReference& src, const SpaceObjectReference& dst,
00337         Sirikata::JS::Protocol::JSMessage js_msg);
00338 
00339 
00340     bool mHandlingEvent;
00341     bool mResetting;
00342     bool mKilling;
00343 
00344 
00345     //This function returns to you the current value of present token and
00346     //incrmenets presenceToken so that get a unique one each time.  If
00347     //presenceToken is equal to default_presence_token, increments one beyond it
00348     //so that don't start inadvertently returning the DEFAULT_PRESENCE_TOKEN;
00349     HostedObject::PresenceToken incrementPresenceToken();
00350 
00351     void  printStackFrame(std::stringstream&, v8::Local<v8::StackFrame>);
00352 
00353     // Adds/removes presences from the javascript's system.presences array.
00354     //returns the jspresstruct associated with new object
00355     JSPresenceStruct* addConnectedPresence(const SpaceObjectReference& sporef,HostedObject::PresenceToken token);
00356 
00364     void processSandboxMessage(
00365         String msgToSend, uint32 senderID, uint32 receiverID,
00366         Liveness::Token alive);
00367 
00368 
00372     void finishContextClear(JSContextStruct* jscont);
00373 
00374 
00375     //looks through all previously connected presneces (located in mPresences).
00376     //returns the corresponding jspresencestruct that has a spaceobjectreference
00377     //that matches sporef.
00378     JSPresenceStruct* findPresence(const SpaceObjectReference& sporef);
00379 
00380 
00381     typedef std::map<SpaceObjectReference, ODP::Port*> MessagingPortMap;
00382     MessagingPortMap mMessagingPortMap;
00383 
00384 
00385     void callbackUnconnected(ProxyObjectPtr proxy, HostedObject::PresenceToken token);
00386     HostedObject::PresenceToken presenceToken;
00387 
00388     typedef std::map<SpaceObjectReference, JSPresenceStruct*> PresenceMap;
00389     typedef PresenceMap::iterator PresenceMapIter;
00390     PresenceMap mPresences;
00391 
00402     std::map<SpaceObjectReference,std::vector<JSVisibleStruct*> >resettingVisiblesResultSet;
00403 
00404     typedef std::vector<JSPresenceStruct*> PresenceVec;
00405     PresenceVec mUnconnectedPresences;
00406 
00407     //we do not want to invalidate message receiving iterator, so keep separate
00408     //tabs of all the context structs that we were supposed to delete when we
00409     //received a message.
00410     std::vector<JSContextStruct*> contextsToClear;
00411 
00412     EmersonHttpPtr emHttpPtr;
00413 
00414 
00415     // Called within mStrand.
00416     void iOnDisconnected(
00417         SessionEventProviderPtr from, const SpaceObjectReference& name,
00418         Liveness::Token alive);
00419     void eCreateEntityFinish(ObjectHost* oh,EntityCreateInfo& eci);
00420 
00421     //When we initiate stop of object from killEntity, we do not actually
00422     //want to call letDie in iStop.  This is because we've already locked
00423     //liveness of Script.  If letDie is false, then, we don't call letDie until
00424     //we get to destructor.
00425     void iStop(Liveness::Token alive, bool letDie);
00426 
00427     void iHandleScriptCommRead(
00428         const SpaceObjectReference& src, const SpaceObjectReference& dst,
00429         const String& payload,Liveness::Token alive);
00430 
00431     void iHandleScriptCommUnreliable(
00432         const ODP::Endpoint& src, const ODP::Endpoint& dst,
00433         MemoryReference payload,Liveness::Token alive);
00434 
00435     void mainStrandCompletePresConnect(Location newLoc,BoundingSphere3f bs,
00436         PresStructRestoreParams psrp,HostedObject::PresenceToken presToke,
00437         Liveness::Token alive);
00438 
00439     void iNotifyProximateGone(
00440         ProxyObjectPtr proximateObject, const SpaceObjectReference& querier,
00441         Liveness::Token alive);
00442 
00443     void iResetProximateHelper(
00444         JSVisibleStruct* proxVis, const SpaceObjectReference& proxTo);
00445 
00446     void  iNotifyProximate(
00447         ProxyObjectPtr proximateObject, const SpaceObjectReference& querier,
00448         Liveness::Token alive);
00449 
00450     void iOnConnected(SessionEventProviderPtr from,
00451         const SpaceObjectReference& name, HostedObject::PresenceToken token,
00452         bool duringInit,Liveness::Token alive);
00453 
00454     void iInvokeInvokable(
00455         std::vector<boost::any>& params,v8::Persistent<v8::Function> function_,
00456         Liveness::Token alive);
00457 
00458 
00459     //simname, sporef
00460     typedef std::vector< std::pair<String,SpaceObjectReference> > SimVec;
00461     SimVec mSimulations;
00462 
00463 };
00464 
00465 #define EMERSCRIPT_SERIAL_CHECK()\
00466     Sirikata::SerializationCheck::Scoped sc (JSObjectScript::mCtx->serializationCheck());
00467 
00468 
00469 } // namespace JS
00470 } // namespace Sirikata
00471 
00472 #endif //_SIRIKATA_JS_OBJECT_SCRIPT_HPP_