#ifndef __AlertConnection_h_ #define __AlertConnection_h_ #include #include "../shared/ServerConnection64.h" /* Connect to a "new" alert server. This isn't directly associated with grids, * but it may still be useful. The assumption is that you want to use the * scripting aspects of the tikiller server to consume alerts. * * See TclAlertConnectionWrapper.[Ch] and look for "ti::alerts" in "TCL API v2 * for TI Killer" in Google docs for examples, test code, and more information * about this unit. */ class AlertConnection : private ServerConnection64 { public: typedef std::vector< PropertyList > Alerts; struct MetaData { std::string collaborate; std::string windowName; std::vector< PropertyList > columns; }; typedef std::function< void(Alerts const &alerts, MetaData const &metaData, int64_t id) > Callback; private: static IContainerThread *defaultThread(); static uint64_t _lastId; static const uint64_t ALERT_DATA = 1; static const uint64_t LOGIN_RESPONSE = 2; static const uint64_t LAST_RESERVED_ID = LOGIN_RESPONSE; class SingleRequest { private: AlertConnection *const _manager; SocketInfo *const _socketInfo; const int64_t _id; const bool _saveToMru; const Callback _callback; MetaData _metaData; public: SingleRequest(AlertConnection *manager, SocketInfo *socketInfo, int64_t id, bool saveToMru, std::string const &collaborate, Callback callback); // This sends a message to the server telling it that we are done. This // does not notify the AlertConnection object. Presumably the // AlertConnection object is the one who deleted this SingleRequest. ~SingleRequest(); //int64_t getId() const { return _id; } SocketInfo *getSocketInfo() const { return _socketInfo; } void sendConfig(); void onMessage(std::string const &bytes); void sendResponse(Alerts const &alerts) const { _callback(alerts, _metaData, _id); } // You are explicitly allowed to call this on a NULL pointer. static std::string debugDump(SingleRequest *); }; std::map< int64_t, SingleRequest * > _allRequests; std::map< SocketInfo *, std::set< int64_t > > _bySocket; bool _listenerActive; enum LoginType : char { ltNone, ltProxy, ltDirect } _loginType; std::string _username, _password; int _userId; typedef int64_t AlertId; // Seems like I could import this from somewhere. AlertId _nextAlertId; void listen(int64_t id, std::string const &collaborate, bool saveToMru, SocketInfo *socket, Callback callback); void onAlertData(std::string const &bytes); void onLoginResponse(std::string const &bytes); void checkListenStatus(SingleRequest *newRequest); protected: // From TalkWithServer64::IMessageListener virtual void onMessage(std::string bytes, int64_t clientId, MessageId messageId); virtual void onAbort(int64_t clientId, MessageId messageId); // From ServerConnection64 virtual void onNewConnection(TalkWithServer64 *connection); virtual bool shouldTryToConnect(); // From IContainerThreadUser virtual void socketClosed(SocketInfo *socket); public: // This is thread safe. This will return a cancelId. It is possible // that the first response will come before this function returns, or before // the caller does something with the return value. That seems unlikely, // but there may be special circumstances. // // Socket can be null. Its only job is to help us clean up requests when // someone hangs up. int64_t listen(std::string collaborate, bool saveToMru, SocketInfo *socket, Callback callback); // This is thread safe. It is safe to call this as soon as listen() returns // a value to you. It is safe to call this more than once. void cancel(int64_t id); // Same as the previous version of cancel() with one extra feature. If we // find an item and cancel it, we call the action callback. void cancel(int64_t id, std::function< void(SocketInfo *) > action); // It is safe to use UNUSED_ID when there are no alerts. Calling cancel() // on UNUSED_ID will do nothing. listen() will never return UNUSED_ID. static const int64_t UNUSED_ID = 0; // These are thread safe. These will always reset the connection. (Some // APIs ignore this message unless the username or password changes.) void loginProxy(std::string username, std::string password); void loginDirect(int userId); void logOut(); // The default is to share a thread with other alert threads but nothing // else. AlertConnection(IContainerThread *thread = NULL); }; #endif