+/**
+ * StreamSocket is a class that wraps a TCP socket and handles send
+ * and receive queues, including passing them to IO hooks
+ */
+class CoreExport StreamSocket : public EventHandler
+{
+ /** Module that handles raw I/O for this socket, or NULL */
+ reference<Module> IOHook;
+ /** Private send queue. Note that individual strings may be shared
+ */
+ std::deque<std::string> sendq;
+ /** Length, in bytes, of the sendq */
+ size_t sendq_len;
+ /** Error - if nonempty, the socket is dead, and this is the reason. */
+ std::string error;
+ protected:
+ std::string recvq;
+ public:
+ StreamSocket() : sendq_len(0) {}
+ inline Module* GetIOHook();
+ inline void AddIOHook(Module* m);
+ inline void DelIOHook();
+ /** Handle event from socket engine.
+ * This will call OnDataReady if there is *new* data in recvq
+ */
+ virtual void HandleEvent(EventType et, int errornum = 0);
+ /** Dispatched from HandleEvent */
+ virtual void DoRead();
+ /** Dispatched from HandleEvent */
+ virtual void DoWrite();
+
+ /** Sets the error message for this socket. Once set, the socket is dead. */
+ void SetError(const std::string& err) { if (error.empty()) error = err; }
+
+ /** Gets the error message for this socket. */
+ const std::string& getError() const { return error; }
+
+ /** Called when new data is present in recvq */
+ virtual void OnDataReady() = 0;
+ /** Called when the socket gets an error from socket engine or IO hook */
+ virtual void OnError(BufferedSocketError e) = 0;
+
+ /** Send the given data out the socket, either now or when writes unblock
+ */
+ void WriteData(const std::string& data);
+ /** Convenience function: read a line from the socket
+ * @param line The line read
+ * @param delim The line delimiter
+ * @return true if a line was read
+ */
+ bool GetNextLine(std::string& line, char delim = '\n');
+ /** Useful for implementing sendq exceeded */
+ inline size_t getSendQSize() const { return sendq_len; }
+
+ /**
+ * Close the socket, remove from socket engine, etc
+ */
+ virtual void Close();
+ /** This ensures that close is called prior to destructor */
+ virtual CullResult cull();
+};