// // $Id$ #pragma once #include #include "presents/InvocationDecoder.h" #include "presents/DisconnectReason.h" #include "presents/PresentsError.h" #include "presents/client/Registration.h" #include "presents/data/RegistrationMarshaller.h" class ObjectInputStream; class ObjectOutputStream; namespace presents { namespace data { class InvocationMarshaller; } namespace net { class AuthResponseData; class Credentials; class UpstreamMessage; } class FramedInputStream; class FramingOutputStream; class SocketStream; class PresentsClient : public boost::enable_shared_from_this { protected: typedef std::map > MarshallerMap; typedef std::map > DecoderMap; public: typedef boost::signal ClientEvent; typedef boost::signal AuthFailureEvent; PresentsClient (); virtual ~PresentsClient (); void update (float dt); template Shared requireService () { MarshallerMap::iterator it = _services.find(T::javaName()); if (it->second == NULL) { throw PresentsError((boost::format("No marshaller for %1%") % T::javaName()).str()); } return boost::static_pointer_cast(it->second); } template void registerReceiver (Shared receiver) { assert(_socket != NULL); Shared reg(new presents::client::Registration); reg->receiverId = _nextReceiverId++; Shared dec(new typename T::Decoder(receiver)); reg->receiverCode = Shared(new utf8(dec->receiverCode)); _decoders.insert(DecoderMap::value_type(reg->receiverId, dec)); requireService()->registerReceiver(getSharedThis(), reg); } bool isConnected () const; void connect (const std::string& hostname, int port, Shared creds, Shared version); void disconnect (); void postMessage (Shared msg); void sendRequest (int32 invOid, int32 invCode, int8 methodId, const Shared< std::vector< Shared > >& args); int getOid() const { assert(_oid != -1); return _oid; } connection_t onConnected (const ClientEvent::slot_type& slot) { return _onConnected.connect(slot); } connection_t onDisconnected (const DisconnectEvent::slot_type& slot) { return _onDisconnected.connect(slot); } connection_t onAuth (const AuthFailureEvent::slot_type& slot) { return _onAuth.connect(slot); } protected: void handleDisconnect (DisconnectReason); Shared getSharedThis(); boost::scoped_ptr _socket; boost::scoped_ptr _framingOut; boost::scoped_ptr _framedIn; boost::scoped_ptr _in; boost::scoped_ptr _out; int16 _outMessageId; int16 _nextReceiverId; int32 _oid; DecoderMap _decoders; MarshallerMap _services; float _idleTime; // If the connection to the presents server is authenticated and ready to go. _onConnected is // signaled when this becomes true bool _connected; // If we're connected or are trying to connect. This is always true when _connected is true, // but also before the connection is authed and before the bootstrap data arrives. bool _active; ClientEvent _onConnected; DisconnectEvent _onDisconnected; AuthFailureEvent _onAuth; connection_t _onSocketDisconnect; }; }