dodo  0.0.1
A C++ library to create containerized Linux services
tcpserver.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /**
19  * @file tcpserver.hpp
20  * Defines the dodo::network::TCPListener class.
21  */
22 
23 #ifndef network_tcpserver_hpp
24 #define network_tcpserver_hpp
25 
26 #include "network/tcplistener.hpp"
27 
28 namespace dodo {
29 
30  namespace network {
31 
32  /**
33  * Used in conjunction with TCPListener to implement high speed, multithreaded TCP services.
34  * Subclass TCPServer and implement virtual
35  *
36  * - bool handShake(network::BaseSocket*, ssize_t&, ssize_t& )
37  * - bool readSocket( TCPListener::SocketWork &work, ssize_t &sent )
38  * - void shutDown( BaseSocket* )
39  * - TCPServer* addServer()
40  *
41  * Each TCPServer is a thread that consumes work from the TCPListener. There
42  * can be multiple TCPServer threads consuming work together, and the TCPListener auto-scales TCPServers
43  * depending on the load.
44  *
45  * A TCPServer is tied to a TCPListener, The TCPListener produces work to the pool of TCPServer, either
46  *
47  * - new sockets.
48  * - readable sockets (incoming data present).
49  * - shutdown sockets (The TCPListener is informing the pool of TCPServer objects the BaseSocket will disappear).
50  *
51  * At any given moment, each TCPServer is in one of the TCPServer::ServerState states.
52  *
53  * @see TCPListener
54  *
55  */
56  class TCPServer : public threads::Thread {
57  public:
58 
59  /**
60  * The possible states of a TCPServer.
61  * @see getState()
62  */
63  enum ServerState {
64  ssWait = 0, /**< The TCPServer has entered waiting for activity or wait timeout. */
65  ssAwoken = 1, /**< The TCPServer has woken up from a wait either due to an event or the wait timing out. */
66  ssHandshake = 2, /**< The TCPServer is about to invoke handShake(BaseSocket*). */
67  ssHandshakeDone = 3, /**< ssHandshake completed. */
68  ssReadSocket = 4, /**< The TCPServer is about to invoke readSocket(BaseSocket*). */
69  ssReadSocketDone = 5, /**< ssReadSocket completed. */
70  ssShutdown = 6, /**< The TCPServer is about to invoke shutdown(BaseSocket*). */
71  ssShutdownDone = 7, /**< ssShutdown completed. */
72  ssReleaseWork = 8, /**< The TCPServer is releasing the request */
73  ssReleaseWorkDone = 9, /**< ssReleaseWork completed. */
74  };
75 
76  /**
77  * Construct a TCPServer for the TCPListener.
78  * @param listener TCPListener.
79  */
80  TCPServer( TCPListener &listener );
81  virtual ~TCPServer() {};
82 
83  /**
84  * Run the TCPServer thread.
85  */
86  virtual void run();
87 
88  /**
89  * Override to perform a protocol handshake. Note that the TCP handshake has already taken place,
90  * and handShake() will only be called for new sockets.
91  * @param socket A pointer to the socket to handshake. If this returns false,. the socket
92  * will be closed.
93  * @param received The number of bytes received by the call.
94  * @param sent The number of bytes sent by the call.
95  * @return true if the handshake succeeded.
96  */
97  virtual bool handShake( network::BaseSocket *socket, ssize_t &received, ssize_t &sent ) = 0;
98 
99  /**
100  * Override to perform a request-response cycle.
101  * @param work The work to perform.
102  * @param sent The number of bytes sent by the call.
103  * @return
104  *
105  * - common::SystemError::ecOK if all is well, the request is received completely, it is handled and a response is sent.
106  * - common::SystemError::ecEAGAIN if all is well but the data in work.data is not a complete request yet.
107  * - common::SystemError::ecECONNABORTED if the socket needs to be closed (for example by client request).
108  */
109  virtual common::SystemError readSocket( TCPListener::SocketWork &work, ssize_t &sent ) = 0;
110 
111  /**
112  * Override to perform a shutdown.
113  * @param socket The socket to work on.
114  */
115  virtual void shutDown( network::BaseSocket *socket ) = 0;
116 
117  /**
118  * Spawn a new TCPServer.
119  * @return a pointer to a new TCPServer
120  */
121  virtual TCPServer* addServer() = 0;
122 
123  /**
124  * Return a new TCPConnectionData pointer or override to return a descendant of TCPConnectionData.
125  * @return the new TCPConnectionData*.
126  */
127  virtual TCPConnectionData* newConnectionData() const { return new TCPConnectionData(); }
128 
129  /**
130  * Return true if the TCPServer has stopped working.
131  * @return True if the TCPServer has stopped on request.
132  */
133  bool hasStopped() const { return has_stopped_; };
134 
135  /**
136  * Return true if the TCPServer is busy.
137  * @return True if busy.
138  */
139  bool isBusy() const { return busy_; };
140 
141  /**
142  * Get the number of secodns the TCPServer has been idle.
143  * @return The idle seconds.
144  */
145  double getIdleSeconds();
146 
147  /**
148  * Set the request_stop_ flag, this call returns immediately, stopping will follow.
149  */
150  void requestStop() { request_stop_ = true; };
151 
152  /**
153  * Return true if the TCPServer was requested to stop.
154  * @return true if the TCPServer was requested to stop.
155  */
156  bool getRequestStop() const { return request_stop_; };
157 
158  /**
159  * Return the current ServerState.
160  * @return The current ServerState.
161  */
162  ServerState getState() const { return state_; };
163 
164  protected:
165 
166  /**
167  * The TCPListener the TCPServer is working for.
168  */
170 
171  /**
172  * If true, the TCPServer should stop.
173  */
175 
176  /**
177  * If true, the TCPServer has stopped.
178  */
180 
181  /**
182  * If true, the TCPServer is processing a request.
183  */
184  bool busy_;
185 
186  /**
187  * Time of last request handling
188  */
189  struct timeval last_active_;
190 
191  /**
192  * State of the TCPServer.
193  */
195  };
196 
197  }
198 
199 }
200 
201 #endif
dodo::network::TCPServer::ssReadSocket
@ ssReadSocket
The TCPServer is about to invoke readSocket(BaseSocket*).
Definition: tcpserver.hpp:68
dodo::network::TCPServer::TCPServer
TCPServer(TCPListener &listener)
Construct a TCPServer for the TCPListener.
Definition: tcpserver.cpp:36
dodo::network::TCPServer::getIdleSeconds
double getIdleSeconds()
Get the number of secodns the TCPServer has been idle.
Definition: tcpserver.cpp:183
dodo::network::TCPServer::ssShutdown
@ ssShutdown
The TCPServer is about to invoke shutdown(BaseSocket*).
Definition: tcpserver.hpp:70
dodo::network::TCPServer::handShake
virtual bool handShake(network::BaseSocket *socket, ssize_t &received, ssize_t &sent)=0
Override to perform a protocol handshake.
dodo::network::TCPServer::request_stop_
bool request_stop_
If true, the TCPServer should stop.
Definition: tcpserver.hpp:174
dodo::network::TCPServer::ssAwoken
@ ssAwoken
The TCPServer has woken up from a wait either due to an event or the wait timing out.
Definition: tcpserver.hpp:65
dodo::network::TCPServer::ssShutdownDone
@ ssShutdownDone
ssShutdown completed.
Definition: tcpserver.hpp:71
dodo::network::TCPServer::ssHandshakeDone
@ ssHandshakeDone
ssHandshake completed.
Definition: tcpserver.hpp:67
dodo::network::TCPServer::has_stopped_
bool has_stopped_
If true, the TCPServer has stopped.
Definition: tcpserver.hpp:179
dodo::network::TCPServer::ssHandshake
@ ssHandshake
The TCPServer is about to invoke handShake(BaseSocket*).
Definition: tcpserver.hpp:66
dodo::network::TCPServer::run
virtual void run()
Run the TCPServer thread.
Definition: tcpserver.cpp:44
dodo
A C++ platform interface to lean Linux services tailored for containerized deployment.
Definition: application.hpp:29
dodo::network::TCPServer::last_active_
struct timeval last_active_
Time of last request handling.
Definition: tcpserver.hpp:189
dodo::network::TCPServer::ServerState
ServerState
The possible states of a TCPServer.
Definition: tcpserver.hpp:63
dodo::network::TCPServer::isBusy
bool isBusy() const
Return true if the TCPServer is busy.
Definition: tcpserver.hpp:139
dodo::network::TCPServer::ssReleaseWork
@ ssReleaseWork
The TCPServer is releasing the request.
Definition: tcpserver.hpp:72
dodo::network::TCPServer::ssWait
@ ssWait
The TCPServer has entered waiting for activity or wait timeout.
Definition: tcpserver.hpp:64
dodo::network::TCPServer::getRequestStop
bool getRequestStop() const
Return true if the TCPServer was requested to stop.
Definition: tcpserver.hpp:156
dodo::network::TCPServer::busy_
bool busy_
If true, the TCPServer is processing a request.
Definition: tcpserver.hpp:184
dodo::network::TCPServer::addServer
virtual TCPServer * addServer()=0
Spawn a new TCPServer.
dodo::network::TCPServer::newConnectionData
virtual TCPConnectionData * newConnectionData() const
Return a new TCPConnectionData pointer or override to return a descendant of TCPConnectionData.
Definition: tcpserver.hpp:127
dodo::network::TCPServer
Used in conjunction with TCPListener to implement high speed, multithreaded TCP services.
Definition: tcpserver.hpp:56
dodo::network::TCPServer::ssReadSocketDone
@ ssReadSocketDone
ssReadSocket completed.
Definition: tcpserver.hpp:69
dodo::network::TCPServer::ssReleaseWorkDone
@ ssReleaseWorkDone
ssReleaseWork completed.
Definition: tcpserver.hpp:73
dodo::network::TCPServer::readSocket
virtual common::SystemError readSocket(TCPListener::SocketWork &work, ssize_t &sent)=0
Override to perform a request-response cycle.
dodo::network::TCPServer::getState
ServerState getState() const
Return the current ServerState.
Definition: tcpserver.hpp:162
dodo::network::TCPServer::state_
ServerState state_
State of the TCPServer.
Definition: tcpserver.hpp:194
dodo::network::TCPConnectionData
Class to track a connection.
Definition: tcplistener.hpp:55
dodo::common::SystemError
Linux system error primitive to provide a consistent interface to Linux error codes.
Definition: systemerror.hpp:53
dodo::threads::Thread
Abstract Thread class.
Definition: thread.hpp:38
dodo::network::TCPListener
The TCPListener listens, accepts connections and generates socket events to produce TCP work to a poo...
Definition: tcplistener.hpp:126
dodo::network::TCPServer::shutDown
virtual void shutDown(network::BaseSocket *socket)=0
Override to perform a shutdown.
dodo::network::TCPServer::requestStop
void requestStop()
Set the request_stop_ flag, this call returns immediately, stopping will follow.
Definition: tcpserver.hpp:150
dodo::network::TCPServer::listener_
TCPListener & listener_
The TCPListener the TCPServer is working for.
Definition: tcpserver.hpp:162
tcplistener.hpp
dodo::network::BaseSocket
Interface to and common implementation of concrete sockets (Socket, TLSSocket).
Definition: basesocket.hpp:36
dodo::network::TCPServer::hasStopped
bool hasStopped() const
Return true if the TCPServer has stopped working.
Definition: tcpserver.hpp:133