NCBI C++ ToolKit
srv_sockets.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef NETCACHE__SRV_SOCKETS__HPP
2 #define NETCACHE__SRV_SOCKETS__HPP
3 /* $Id: srv_sockets.hpp 79272 2017-08-28 14:38:49Z gouriano $
4  * ===========================================================================
5  *
6  * PUBLIC DOMAIN NOTICE
7  * National Center for Biotechnology Information
8  *
9  * This software/database is a "United States Government Work" under the
10  * terms of the United States Copyright Act. It was written as part of
11  * the author's official duties as a United States Government employee and
12  * thus cannot be copyrighted. This software/database is freely available
13  * to the public for use. The National Library of Medicine and the U.S.
14  * Government have not placed any restriction on its use or reproduction.
15  *
16  * Although all reasonable efforts have been taken to ensure the accuracy
17  * and reliability of the software and data, the NLM and the U.S.
18  * Government do not and cannot warrant the performance or results that
19  * may be obtained by using this software or data. The NLM and the U.S.
20  * Government disclaim all warranties, express or implied, including
21  * warranties of performance, merchantability or fitness for any particular
22  * purpose.
23  *
24  * Please cite the author in any work or product based on this material.
25  *
26  * ===========================================================================
27  *
28  * Authors: Pavel Ivanov
29  *
30  * File Description:
31  */
32 
33 
34 namespace intr = boost::intrusive;
35 
36 
38 
39 
40 /// For TaskServer's internal use only.
41 /// This structure is used as base for both CSrvSocketTask and internal
42 /// listening socket structure. Pointer to SSrvSocketInfo is remembered in
43 /// epoll and value of is_listening is used to distinguish between listening
44 /// socket structure and CSrvSocketTask.
46 {
48 };
49 
50 
51 /*
52  from here:
53  http://www.boost.org/doc/libs/1_56_0/doc/html/intrusive/usage.html
54 
55  If there is a virtual inheritance relationship between the parent and
56  the member hook, then the distance between the parent and the hook is not
57  a compile-time fixed value so obtaining the address of the parent from
58  the member hook is not possible without reverse engineering compiler produced RTTI.
59  Apart from this, the non-standard pointer to member implementation for classes with
60  complex inheritance relationships in MSVC ABI compatible-compilers is not supported
61  by member hooks since it also depends on compiler-produced RTTI information.
62 
63  This means member hooks are potentially dangerous, because we DO use virtual inheritance here.
64  With Boost 1.53 this compiles on MSVC
65  With Boost 1.56 it does not.
66  With GCC it compiles so far... but.. who knows...
67 */
68 #define NC_SOCKLIST_USE_MEMBER_HOOK 1
69 #define NC_SOCKLIST_USE_BASE_HOOK 2
70 #define NC_SOCKLIST_USE_STD_LIST 3
71 #define NC_SOCKLIST_USE_TYPE NC_SOCKLIST_USE_BASE_HOOK
72 
73 
74 #if NC_SOCKLIST_USE_TYPE == NC_SOCKLIST_USE_MEMBER_HOOK
75 struct SSrvSockList_tag;
76 typedef intr::list_member_hook<intr::tag<SSrvSockList_tag> > TSrvSockListHook;
77 #elif NC_SOCKLIST_USE_TYPE == NC_SOCKLIST_USE_BASE_HOOK
78 struct SSrvSockList_tag;
79 typedef intr::list_base_hook<intr::tag<SSrvSockList_tag> > TSrvSockListHook;
80 #endif
81 
82 
83 
84 
85 /// Task controlling a socket.
86 /// This task always becomes runnable in 3 cases:
87 /// - when socket changes from non-readable to readable (some data came into
88 /// socket and can be read by user);
89 /// - when socket changes from non-writable to writable (socket has been just
90 /// opened, connection established and data can be written to the other side);
91 /// - when some error appears in socket, e.g. client disconnected.
92 /// When task became runnable and ExecuteSlice() is called it's user's code
93 /// responsibility to process event completely (not necessarily immediately
94 /// but eventually). I.e. TaskServer won't set the task runnable again if user
95 /// didn't read all the data from socket.
96 /// CSrvSocketTask cannot attach to any random socket. It should be either
97 /// returned from CSrvSocketFactory and TaskServer will attach it to just
98 /// connected socket, or CSrvSocketTask::Connect() method should be called
99 /// to create socket with other server.
100 #if NC_SOCKLIST_USE_TYPE == NC_SOCKLIST_USE_BASE_HOOK
101 class CSrvSocketTask : public virtual CSrvTask, public SSrvSocketInfo,
102  public TSrvSockListHook
103 #else
104 class CSrvSocketTask : public virtual CSrvTask, public SSrvSocketInfo
105 #endif
106 {
107 public:
108  CSrvSocketTask(void);
109  virtual ~CSrvSocketTask(void);
110 
111  /// Checks if there's some data available for reading in internal buffers.
112  /// Method doesn't say anything about data available in socket but not yet
113  /// retrieved from kernel.
114  bool IsReadDataAvailable(void);
115  /// Checks if there's some data pending in write buffers and waiting to be
116  /// sent to kernel.
117  bool IsWriteDataPending(void);
118  /// Checks if socket has some error in it.
119  bool HasError(void);
120  /// Checks if socket can ever have more data to read even though it may not
121  /// have it at the moment. Socket won't have more data to read if EOF
122  /// received.
123  bool CanHaveMoreRead(void);
124  /// Checks if socket should be closed because of long inactivity or
125  /// because server is in "hard" shutdown phase. User code should always
126  /// check result of this method at some pivot points where it has the
127  /// ability to close.
128  bool NeedToClose(void);
129  /// Checks if socket should be closed because of internal reasons (long
130  /// inactivity or "hard" shutdown as in NeedToClose()) or because of
131  /// external reasons, like error or EOF in the socket.
132  bool NeedEarlyClose(void);
133 
134  /// Read from socket into internal buffer.
135  /// Method tries to completely fill the buffer even if there's some data
136  /// already waiting in it.
137  bool ReadToBuf(void);
138  /// Read from socket into memory.
139  /// Method combines reading from internal buffer and directly from socket
140  /// (without changing data order) and reads as much as possible to do
141  /// without blocking. Method returns total size of read data (can be 0 if
142  /// no data immediately available).
143  size_t Read(void* buf, size_t size);
144  /// Read from socket one line which ends with '\n', '\r\n' or '\0'.
145  /// Line read should fit into internal read buffer, i.e. it shouldn't be
146  /// too long, otherwise method returns FALSE and raises error flag which
147  /// means you won't be able to anything else with socket (besides closing).
148  /// Method returns TRUE if line was successfully read and FALSE if there's
149  /// no data or no line end markers in it. When method returned TRUE
150  /// variable line will point to internal read buffer. Thus it should be
151  /// used before calling any other Read*() methods -- after that memory can
152  /// become invalid.
153  bool ReadLine(CTempString* line);
154  /// Read from socket exactly the given data size. If given size is not
155  /// immediately available (without blocking) method doesn't read anything
156  /// and returns FALSE. Otherwise data is copied to buf and TRUE is
157  /// returned. Requested size must be less than internal read buffer.
158  bool ReadData(void* buf, Uint2 size);
159  /// Read from socket a number in native machine representation.
160  /// If sizeof(NumType) bytes is not immediately available in the socket
161  /// method returns FALSE and doesn't read anything. Otherwise it copies
162  /// data into num and returns TRUE.
163  template <typename NumType>
164  bool ReadNumber(NumType* num);
165 
166  /// Write text into socket.
167  /// The whole text message will be written, internal write buffer will be
168  /// expanded to accommodate the message if necessary.
170  /// Write number into socket as string, i.e. number is converted to string
171  /// using NStr::NumericToString() first and then the result is written to
172  /// socket as string. The whole number will be written, internal write
173  /// buffer will be expanded to accommodate it if necessary.
174  template <typename NumType>
175  CSrvSocketTask& WriteNumber(NumType num);
176  CSrvSocketTask& WriteBool(bool b);
177  /// Write the exact amount of data into the socket. All the data will be
178  /// written, internal write buffer will be expanded to accommodate it
179  /// if necessary.
180  void WriteData(const void* buf, size_t size);
181  /// Write into the socket as much as immediately possible (including
182  /// writing into internal write buffers and writing directly into socket)
183  /// without blocking and without expanding write buffer. Method returns
184  /// amount of data written which can be 0 if socket is not writable at the
185  /// moment.
186  size_t Write(const void* buf, size_t size);
187  /// Flush all data saved in internal write buffers to socket.
188  /// Method must be called from inside of ExecuteSlice() of this task and
189  /// no other writing methods should be called until FlushIsDone() returns
190  /// TRUE.
191  void Flush(void);
192  /// Request flushing of all data saved in internal write buffers to socket.
193  /// Method can be called from anywhere even concurrently with
194  /// ExecuteSlice() of this task. No other writing methods should be called
195  /// until FlushIsDone() returns TRUE.
196  void RequestFlush(void);
197  /// Check if data flushing requested earlier is complete.
198  bool FlushIsDone(void);
199 
200  /// Start proxying of raw data from this socket to the one in dst_task.
201  /// Method must be called from inside of ExecuteSlice() of this task. And
202  /// nothing else should be done with both sockets until IsProxyInProgress()
203  /// returns FALSE. Only proxy_size bytes is transferred between sockets.
204  /// Proxying can stop earlier only if NeedEarlyClose() on either socket
205  /// returns true. In this case ProxyHadError() will return true and
206  /// nothing else could be done with sockets except closing.
207  void StartProxyTo(CSrvSocketTask* dst_task, Uint8 proxy_size);
208  /// Check whether proxying started earlier is still in progress.
209  bool IsProxyInProgress(void);
210  /// Check whether proxying started earlier finished successfully or any of
211  /// sockets had some error in it.
212  bool ProxyHadError(void);
213 
214  /// Create new socket and connect it to given IP and port.
215  /// If operation is successful TRUE is returned, FALSE returned otherwise.
216  /// FALSE will be returned only in case of errors like network interface
217  /// is down or things like that. If server is inaccessible then Connect()
218  /// will return TRUE but later there will be error in the socket.
219  bool Connect(Uint4 host, Uint2 port);
220  /// Start processing of the socket and include it into TaskServer's
221  /// central epoll. Until this method is called TaskServer won't make this
222  /// task runnable and won't check if it's readable or writable -- any
223  /// Read/Write operation will be unsuccessful (processing 0 bytes).
224  bool StartProcessing(TSrvThreadNum thread_num = 0, bool boost = false);
225  /// Close the socket gracefully, i.e. if any socket's data is still in
226  /// kernel's buffers and didn't make it to wire it will be sent later. But
227  /// internal task's write buffers won't be flushed.
228  void CloseSocket(void);
229  /// Abort the socket, i.e. anything unsent in kernel buffers will be
230  /// dropped.
231  void AbortSocket(void);
232 
233  /// Get peer IP and port for this socket.
234  void GetPeerAddress(string& host, Uint2& port);
235  /// Get local port this socket was created on.
236  Uint2 GetLocalPort(void);
237 
238  /// Terminate the task. Method is overridden here to add some extra
239  /// processing for sockets.
240  virtual void Terminate(void);
241 
242 private:
245 
246  /// Internal function to execute time slice work. Overridden here to add
247  /// some extra socket processing before and after call to user's code in
248  /// ExecuteSlice().
249  virtual void InternalRunSlice(TSrvThreadNum thr_num);
250 
251  /// Close or abort the socket -- they have little difference, thus they
252  /// joined in one method.
253  void x_CloseSocket(bool do_abort);
254  /// Prints socket's error if there's any error pending on the socket.
255  void x_PrintError(void);
256 
257 // Consider this section private as it's public for internal use only
258 // to minimize implementation-specific clutter in headers.
259 public:
260  /// Source task for proxying.
261  /// This variable is set to non-NULL value only in destination tasks for
262  /// proxying.
264  /// Destination task for proxying.
265  /// This variable is set to non-NULL value only in source tasks for
266  /// proxying.
268  /// Amount left to proxy if proxying operation is in progress.
269  /// Value is set only in source tasks for proxying.
271 #if NC_SOCKLIST_USE_TYPE == NC_SOCKLIST_USE_MEMBER_HOOK
272  /// Hook to include the task to lists of open sockets.
273  TSrvSockListHook m_SockListHook;
274 #endif
275  /// Read buffer.
276  char* m_RdBuf;
277  /// Write buffer.
278  char* m_WrBuf;
279  /// Jiffy number when Connect() method was called. Variable is used to
280  /// track connection timeouts.
282  /// File descriptor for the socket.
283  int m_Fd;
284  /// Size of data available for reading in the read buffer.
286  /// Position of current reading in the read buffer, i.e. all data in
287  /// [0, m_RdPos) was already read; data in [m_RdPos, m_RdSize) are queued
288  /// for reading.
290  /// Size of memory allocated for write buffer. This size can grow in
291  /// methods requiring exact writing like WriteData(), WriteText() etc.
293  /// Size of data in the write buffer waiting for writing.
295  /// Position of current writing pointer in the write buffer.
297  /// Flag showing if '\r' symbol was seen at the end of last line but '\n'
298  /// wasn't seen yet.
299  bool m_CRMet;
300  /// Flag showing that last proxying operation finished with error.
302  /// Flag showing that socket is readable.
304  /// Flag showing that socket is writable.
306  /// Flag showing that socket can have more reads, i.e. there was no EOF yet.
308  /// Flag showing that socket needs to be closed because of long
309  /// inactivity.
311  /// Flag showing that task needs to flush all write buffers.
313  /// Flag showing that write buffers were flushed.
315  /// Number of last read event seen by Read() when it read from socket. If
316  /// this number is equal to m_RegReadEvts then no new "readable" events
317  /// came from epoll and thus result of last read defines if there is more
318  /// data in the socket to read (if last read returned less data than
319  /// provided buffer size then there's no more data in the socket).
321  /// Number of last write event seen by Write() when it wrote to socket. If
322  /// this number is equal to m_RegWriteEvts then no new "writable" events
323  /// came from epoll and thus result of last write defines if more data
324  /// can be written in the socket (if last write have written less data than
325  /// provided buffer size then nothing else can be written in the socket).
327  /// Total number of bytes read from socket.
329  /// Total number of bytes written to socket.
331  /// Counter of "readable" events received from epoll.
333  /// Counter of "writable" events received from epoll.
335  /// Flag showing if epoll returned RDHUP on this socket.
337  /// Flag showing if there's error pending on the socket.
339  /// Flag showing if pending error in socket was printed in logs.
341  /// Remembered peer port. Value valid only for sockets created from
342  /// listening sockets.
344  /// Remembered peer IP address. Value valid only for sockets created from
345  /// listening sockets.
347  ///
348  string m_ConnReqId;
349 };
350 
351 
352 /// Factory that creates CSrvSocketTask-derived object for each connection
353 /// coming to listening port which this factory is assigned to.
355 {
356 public:
357  CSrvSocketFactory(void);
358  virtual ~CSrvSocketFactory(void);
359 
360  virtual CSrvSocketTask* CreateSocketTask(void) = 0;
361 };
362 
363 
365 
366 #endif /* NETCACHE__SRV_SOCKETS__HPP */
Factory that creates CSrvSocketTask-derived object for each connection coming to listening port which...
virtual CSrvSocketTask * CreateSocketTask(void)=0
virtual ~CSrvSocketFactory(void)
Task controlling a socket.
Uint2 m_WrPos
Position of current writing pointer in the write buffer.
Uint8 m_ConnStartJfy
Jiffy number when Connect() method was called.
bool IsProxyInProgress(void)
Check whether proxying started earlier is still in progress.
bool NeedToClose(void)
Checks if socket should be closed because of long inactivity or because server is in "hard" shutdown ...
bool Connect(Uint4 host, Uint2 port)
Create new socket and connect it to given IP and port.
void x_CloseSocket(bool do_abort)
Close or abort the socket – they have little difference, thus they joined in one method.
bool m_RegReadHup
Flag showing if epoll returned RDHUP on this socket.
CSrvSocketTask * m_ProxySrc
Source task for proxying.
Uint1 m_SeenWriteEvts
Number of last write event seen by Write() when it wrote to socket.
bool HasError(void)
Checks if socket has some error in it.
bool m_CRMet
Flag showing if '\r' symbol was seen at the end of last line but ' ' wasn't seen yet.
Uint8 m_ReadBytes
Total number of bytes read from socket.
int m_Fd
File descriptor for the socket.
size_t Write(const void *buf, size_t size)
Write into the socket as much as immediately possible (including writing into internal write buffers ...
void AbortSocket(void)
Abort the socket, i.e.
Uint2 m_PeerPort
Remembered peer port.
CSrvSocketTask & WriteText(CTempString message)
Write text into socket.
CSrvSocketTask & WriteNumber(NumType num)
Write number into socket as string, i.e.
void GetPeerAddress(string &host, Uint2 &port)
Get peer IP and port for this socket.
bool IsReadDataAvailable(void)
Checks if there's some data available for reading in internal buffers.
void CloseSocket(void)
Close the socket gracefully, i.e.
Uint2 m_WrMemSize
Size of memory allocated for write buffer.
Uint8 m_ProxySize
Amount left to proxy if proxying operation is in progress.
bool ProxyHadError(void)
Check whether proxying started earlier finished successfully or any of sockets had some error in it.
CSrvSocketTask & operator=(const CSrvSocketTask &)
bool m_NeedToFlush
Flag showing that task needs to flush all write buffers.
virtual void InternalRunSlice(TSrvThreadNum thr_num)
Internal function to execute time slice work.
virtual void Terminate(void)
Terminate the task.
bool m_NeedToClose
Flag showing that socket needs to be closed because of long inactivity.
char * m_RdBuf
Read buffer.
Uint4 m_PeerAddr
Remembered peer IP address.
bool m_ErrorPrinted
Flag showing if pending error in socket was printed in logs.
bool CanHaveMoreRead(void)
Checks if socket can ever have more data to read even though it may not have it at the moment.
bool m_ProxyHadError
Flag showing that last proxying operation finished with error.
bool m_SockCanReadMore
Flag showing that socket can have more reads, i.e. there was no EOF yet.
bool m_FlushIsDone
Flag showing that write buffers were flushed.
bool m_RegError
Flag showing if there's error pending on the socket.
bool ReadData(void *buf, Uint2 size)
Read from socket exactly the given data size.
CSrvSocketTask * m_ProxyDst
Destination task for proxying.
bool ReadToBuf(void)
Read from socket into internal buffer.
void RequestFlush(void)
Request flushing of all data saved in internal write buffers to socket.
Uint2 m_RdPos
Position of current reading in the read buffer, i.e.
void Flush(void)
Flush all data saved in internal write buffers to socket.
size_t Read(void *buf, size_t size)
Read from socket into memory.
bool ReadNumber(NumType *num)
Read from socket a number in native machine representation.
char * m_WrBuf
Write buffer.
virtual ~CSrvSocketTask(void)
Uint2 GetLocalPort(void)
Get local port this socket was created on.
void WriteData(const void *buf, size_t size)
Write the exact amount of data into the socket.
Uint1 m_SeenReadEvts
Number of last read event seen by Read() when it read from socket.
bool IsWriteDataPending(void)
Checks if there's some data pending in write buffers and waiting to be sent to kernel.
Uint2 m_WrSize
Size of data in the write buffer waiting for writing.
Uint8 m_WrittenBytes
Total number of bytes written to socket.
Uint2 m_RdSize
Size of data available for reading in the read buffer.
bool m_SockCanWrite
Flag showing that socket is writable.
bool StartProcessing(TSrvThreadNum thread_num=0, bool boost=false)
Start processing of the socket and include it into TaskServer's central epoll.
bool ReadLine(CTempString *line)
Read from socket one line which ends with ' ', '\r ' or '\0'.
bool NeedEarlyClose(void)
Checks if socket should be closed because of internal reasons (long inactivity or "hard" shutdown as ...
void x_PrintError(void)
Prints socket's error if there's any error pending on the socket.
void StartProxyTo(CSrvSocketTask *dst_task, Uint8 proxy_size)
Start proxying of raw data from this socket to the one in dst_task.
Uint1 m_RegWriteEvts
Counter of "writable" events received from epoll.
CSrvSocketTask(const CSrvSocketTask &)
bool m_SockHasRead
Flag showing that socket is readable.
CSrvSocketTask & WriteBool(bool b)
bool FlushIsDone(void)
Check if data flushing requested earlier is complete.
Uint1 m_RegReadEvts
Counter of "readable" events received from epoll.
Main working entity in TaskServer.
Definition: srv_tasks.hpp:88
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
uint8_t Uint1
1-byte (8-bit) unsigned integer
Definition: ncbitype.h:99
uint32_t Uint4
4-byte (32-bit) unsigned integer
Definition: ncbitype.h:103
uint16_t Uint2
2-byte (16-bit) unsigned integer
Definition: ncbitype.h:101
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
char * buf
const struct ncbi::grid::netcache::search::fields::SIZE size
intr::list_base_hook< intr::tag< SSrvSockList_tag > > TSrvSockListHook
Definition: srv_sockets.hpp:78
For TaskServer's internal use only.
Definition: srv_sockets.hpp:46
Uint2 TSrvThreadNum
Type for thread number in TaskServer.
Definition: task_server.hpp:42
Modified on Mon May 20 05:06:02 2024 by modify_doxy.py rev. 669887