Sirikata
|
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_