#ifndef __TclReplyToClient_h_ #define __TclReplyToClient_h_ #include "../shared/ContainerThread.h" #include "../shared/CommandDispatcher.h" #include "ServerSigner.h" class TclReplyToClient : private ForeverThreadUser { private: struct ChannelInfo { uint64_t socketId; ExternalRequest::MessageId messageId; ChannelInfo() : socketId(0) { } }; const ServerSigner _serverSigner; // Channel descriptors can't hold a socket because they don't have // a good way to clean up when the socket goes away. Instead they own a // a socket serial number. Serial numbers are never reused, so it's safe // to hold on to one and look it up in a table much later. std::map< uint64_t, SocketInfo * > _canSendResponse; static int getOutputChannelCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); int getOutputChannelCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int replyToClientCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); int replyToClientCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int closeWhenOutputQueueIsEmptyCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); int closeWhenOutputQueueIsEmptyCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int touchConnectionsCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); int touchConnectionsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int isChannelValidCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); int isChannelValidCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); bool inDispatcherThread(); int convertFromTcl(Tcl_Interp *interp, ChannelInfo &destination, Tcl_Obj *source); int convertFromTcl(Tcl_Interp *interp, ChannelInfo &destination, std::string const &source); // IContainerThreadUser virtual void socketClosed(SocketInfo *socket); TclReplyToClient(IContainerThread *container); public: void initializeSocket(SocketInfo *socket); void addGetCurrentChannel(Tcl_Interp *interp); // Dispatcher only. void addOtherCommands(Tcl_Interp *interp); static TclReplyToClient &instance(); }; #endif