1 #ifndef CONNECT___NCBI_SOCKETP__H
2 #define CONNECT___NCBI_SOCKETP__H
3 
4 /* $Id: ncbi_socketp.h 606556 2020-04-23 14:39:23Z lavr $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author:  Anton Lavrentiev
30  *
31  * File Description:
32  *   Private API to define socket structure
33  *
34  */
35 
36 #include "ncbi_config.h"
37 /* OS must be specified in the command-line ("-D....") or in the conf. header
38  */
39 #if !defined(NCBI_OS_UNIX)  &&  !defined(NCBI_OS_MSWIN)
40 #  error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN!"
41 #endif /*supported platforms*/
42 
43 #include <connect/ncbi_socket.h>
44 #include <connect/ncbi_buffer.h>
45 
46 
47 /* Pull in a minial set of platform-specific system headers here.
48  */
49 
50 #ifdef NCBI_OS_MSWIN
51 #  define  _WINSOCK_DEPRECATED_NO_WARNINGS  1
52 #  include <winsock2.h>
53 #else /*NCBI_OS_UNIX*/
54 #  include <sys/socket.h>
55 #  include <sys/time.h>
56 #endif /*NCBI_OS_MSWIN*/
57 
58 /* Portable error codes.
59  */
60 #include <errno.h>
61 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif /*__cplusplus*/
65 
66 #ifdef NCBI_OS_MSWIN
67 
68 typedef SOCKET TSOCK_Handle;    /* NB: same as HANDLE   */
69 typedef HANDLE TRIGGER_Handle;  /* NB: same as WSAEVENT */
70 
71 #  ifdef _WIN64
72 #    pragma pack(push, 4)
73 #  endif /*_WIN64*/
74 
75 #  define SOCK_EINTR          WSAEINTR
76 #  define SOCK_EWOULDBLOCK    WSAEWOULDBLOCK/*EAGAIN*/
77 #  define SOCK_EADDRINUSE     WSAEADDRINUSE
78 #  define SOCK_ECONNRESET     WSAECONNRESET
79 #  define SOCK_EPIPE          WSAESHUTDOWN
80 #  define SOCK_EAGAIN         WSAEINPROGRESS/*special-case missing in WSA*/
81 #  define SOCK_EINPROGRESS    WSAEINPROGRESS
82 #  define SOCK_EALREADY       WSAEALREADY
83 #  define SOCK_ENOTCONN       WSAENOTCONN
84 #  define SOCK_ECONNABORTED   WSAECONNABORTED
85 #  define SOCK_ECONNREFUSED   WSAECONNREFUSED
86 #  define SOCK_ENETRESET      WSAENETRESET
87 #  define SOCK_ETIMEDOUT      WSAETIMEDOUT
88 #  define SOCK_SHUTDOWN_RD    SD_RECEIVE
89 #  define SOCK_SHUTDOWN_WR    SD_SEND
90 #  define SOCK_SHUTDOWN_RDWR  SD_BOTH
91 
92 #else /*NCBI_OS_UNIX*/
93 
94 typedef int TSOCK_Handle;
95 typedef int TRIGGER_Handle;
96 
97 #  define SOCK_EINTR          EINTR
98 #  define SOCK_EWOULDBLOCK    EWOULDBLOCK
99 #  define SOCK_EADDRINUSE     EADDRINUSE
100 #  define SOCK_ECONNRESET     ECONNRESET
101 #  define SOCK_EPIPE          EPIPE
102 #  define SOCK_EAGAIN         EAGAIN
103 #  define SOCK_EINPROGRESS    EINPROGRESS
104 #  define SOCK_EALREADY       EALREADY
105 #  define SOCK_ENOTCONN       ENOTCONN
106 #  define SOCK_ECONNABORTED   ECONNABORTED
107 #  define SOCK_ECONNREFUSED   ECONNREFUSED
108 #  define SOCK_ENETRESET      ENETRESET
109 #  define SOCK_ETIMEDOUT      ETIMEDOUT
110 
111 #  ifndef SHUT_RD
112 #    define SHUT_RD           0
113 #  endif /*SHUT_RD*/
114 #  define SOCK_SHUTDOWN_RD    SHUT_RD
115 #  ifndef SHUT_WR
116 #    define SHUT_WR           1
117 #  endif /*SHUT_WR*/
118 #  define SOCK_SHUTDOWN_WR    SHUT_WR
119 #  ifndef SHUT_RDWR
120 #    define SHUT_RDWR         2
121 #  endif /*SHUT_RDWR*/
122 #  define SOCK_SHUTDOWN_RDWR  SHUT_RDWR
123 
124 #endif /*NCBI_OS_MSWIN*/
125 
126 #if defined(WSAEMFILE)
127 #  define SOCK_ETOOMANY       WSAEMFILE
128 #elif defined(EMFILE)
129 #  define SOCK_ETOOMANY       EMFILE
130 #elif defined(ENFILE)
131 #  define SOCK_ETOOMANY       ENFILE
132 #elif defined(EINVAL)
133 #  define SOCK_ETOOMANY       EINVAL
134 #else
135 #  define SOCK_ETOOMANY       0
136 #endif
137 
138 
139 #if 0/*defined(__GNUC__)*/
140 typedef ESwitch    EBSwitch;
141 typedef EIO_Status EBIO_Status;
142 #else
143 typedef unsigned   EBSwitch;
144 typedef unsigned   EBIO_Status;
145 #endif
146 
147 
148 typedef enum {
149     eListening = 0,
150     eTrigger   = 1,
151     eSocket    = 2,
152     eDatagram  = 3/*2|1*/
153 } ESOCK_Type;
154 
155 typedef unsigned TBSOCK_Type;
156 
157 
158 typedef struct {
159     void*       sess;           /* secure session handle, 0 if none          */
160     NCBI_CRED   cred;           /* secure session credential(s), 0 if none   */
161     SOCK        sock;           /* sock that the above session handle using  */
162     const char* host;           /* hostname for named SSL extension          */
163 } SNcbiSSLctx;
164 
165 
166 /* Event trigger
167  */
168 typedef struct TRIGGER_tag {
169     TRIGGER_Handle     fd;      /* OS-specific trigger handle                */
170     unsigned int       id;      /* the internal ID (cf. "s_ID_Counter")      */
171 
172     union {
173         volatile void* ptr;     /* trigger state (UNIX only, otherwise MBZ)  */
174         int            int_[2]; /* pointer storage area w/proper alignment   */
175     } isset;
176 
177     int                err;     /* Last OS error                             */
178 
179     /* type, status, EOF, log, read-on-write etc bit-field indicators */
180     TBSOCK_Type         type:2; /* eTrigger                                  */
181     EBSwitch             log:2; /* how to log events                         */
182     EBSwitch          r_on_w:2; /* MBZ                                       */
183     EBSwitch        i_on_sig:2; /* eDefault                                  */
184 
185     EBIO_Status     r_status:3; /* MBZ (NB: eIO_Success)                     */
186     unsigned/*bool*/     eof:1; /* MBZ                                       */
187     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
188     unsigned/*bool*/ pending:1; /* MBZ                                       */
189 
190     unsigned        reserved:16;/* MBZ                                       */
191 
192 #ifdef NCBI_OS_UNIX
193     int                out;     /* write end of the pipe                     */
194 #endif /*NCBI_OS_UNIX*/
195 } TRIGGER_struct;
196 
197 
198 /* Sides of socket
199  */
200 typedef enum {
201     eSOCK_Server = 0,
202     eSOCK_Client = 1
203 } ESOCK_Side;
204 
205 typedef unsigned EBSOCK_Side;
206 
207 
208 /* Listening socket [must be in one-2-one binary correspondene with TRIGGER]
209  */
210 typedef struct LSOCK_tag {
211     TSOCK_Handle     sock;      /* OS-specific socket handle                 */
212     unsigned int     id;        /* the internal ID (see also "s_ID_Counter") */
213 
214     unsigned int     n_accept;  /* total number of accepted clients          */
215     unsigned short   away;      /* MSWIN: run-away connect warning counter   */
216     unsigned short   port;      /* port on which listening (host byte order) */
217 
218     int              err;       /* Last OS error                             */
219 
220     /* type, status, EOF, log, read-on-write etc bit-field indicators */
221     TBSOCK_Type         type:2; /* eListening                                */
222     EBSwitch             log:2; /* how to log events and data for this socket*/
223     EBSwitch          r_on_w:2; /* MBZ                                       */
224     EBSwitch        i_on_sig:2; /* eDefault                                  */
225 
226     EBIO_Status     r_status:3; /* MBZ (NB: eIO_Success)                     */
227     unsigned/*bool*/     eof:1; /* MBZ                                       */
228     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
229     unsigned/*bool*/ pending:1; /* MBZ                                       */
230 
231     EBSOCK_Side         side:1; /* MBZ (NB: eSOCK_Server)                    */
232     unsigned/*bool*/    keep:1; /* whether to keep OS handle upon close      */
233 #ifndef NCBI_OS_MSWIN
234     unsigned        reserved:14;/* MBZ                                       */
235 #else
236     unsigned        reserved:11;/* MBZ                                       */
237     unsigned        readable:1; /* =1 if known to have a pending accept      */
238     unsigned          unused:2; /* MBZ                                       */
239 
240     WSAEVENT         event;     /* event bound to I/O                        */
241 #endif /*!NCBI_OS_MSWIN*/
242 
243     void*            context;   /* per-server session/credentials (not impl) */
244 
245 #ifdef NCBI_OS_UNIX
246     char             path[1];   /* must go last                              */
247 #endif /*NCBI_OS_UNIX*/
248 } LSOCK_struct;
249 
250 
251 /* Socket [it must be in 1-2-1 binary correspondence with LSOCK above]
252  */
253 typedef struct SOCK_tag {
254     TSOCK_Handle     sock;      /* OS-specific socket handle                 */
255     unsigned int     id;        /* the internal ID (see also "s_ID_Counter") */
256 
257     /* connection point */
258     unsigned int     host;      /* peer host (network byte order)            */
259     unsigned short   port;      /* peer port (host byte order)               */
260     unsigned short   myport;    /* this socket's port number, host byte order*/
261 
262     int              err;       /* Last OS error                             */
263 
264     /* type, status, EOF, log, read-on-write etc bit-field indicators */
265     TBSOCK_Type         type:2; /* |= eSocket ({ eSocket | eDatagram })      */
266     EBSwitch             log:2; /* how to log events and data for this socket*/
267     EBSwitch          r_on_w:2; /* enable/disable automatic read-on-write    */
268     EBSwitch        i_on_sig:2; /* enable/disable I/O restart on signals     */
269 
270     EBIO_Status     r_status:3; /* read  status:  eIO_Closed if was shut down*/
271     unsigned/*bool*/     eof:1; /* Stream sockets: 'End of file' seen on read
272                                    Datagram socks: 'End of message' written  */
273     EBIO_Status     w_status:3; /* write status:  eIO_Closed if was shut down*/
274     unsigned/*bool*/ pending:1; /* =1 if connection is still initing         */
275 
276     EBSOCK_Side         side:1; /* socket side: client- or server-side       */
277     unsigned/*bool*/    keep:1; /* whether to keep OS handle upon close      */
278     unsigned       crossexec:1; /* =1 if close-on-exec must NOT be set       */
279     unsigned       connected:1; /* =1 if remote end-point is fully connected */
280     unsigned        r_tv_set:1; /* =1 if read  timeout is set (i.e. finite)  */
281     unsigned        w_tv_set:1; /* =1 if write timeout is set (i.e. finite)  */
282     unsigned        c_tv_set:1; /* =1 if close timeout is set (i.e. finite)  */
283     unsigned       keepalive:1; /* =1 if needs to be kept alive (if OS supp.)*/
284 #ifndef NCBI_OS_MSWIN
285     unsigned        reserved:8; /* MBZ                                       */
286 #else
287     unsigned        reserved:5; /* MBZ                                       */
288     unsigned        readable:1; /* =1 if known to be readable                */
289     unsigned        writable:1; /* =1 if known to be writeable               */
290     unsigned         closing:1; /* =1 if FD_CLOSE posted                     */
291 
292     WSAEVENT         event;     /* event bound to I/O                        */
293 #endif /*!NCBI_OS_MSWIN*/
294 
295     SNcbiSSLctx*     sslctx;    /* secure session context if SSL's on, else 0*/
296 
297     /* timeouts */
298     struct timeval   r_tv;      /* finite read  timeout value                */
299     struct timeval   w_tv;      /* finite write timeout value                */
300     struct timeval   c_tv;      /* finite close timeout value                */
301     STimeout         r_to;      /* finite read  timeout value (aux., temp.)  */
302     STimeout         w_to;      /* finite write timeout value (aux., temp.)  */
303     STimeout         c_to;      /* finite close timeout value (aux., temp.)  */
304 
305     /* aux I/O data */
306     BUF              r_buf;     /* read  buffer                              */
307     BUF              w_buf;     /* write buffer                              */
308     size_t           r_len;     /* SOCK: unused; DSOCK: sz of last msg recv'd*/
309     size_t           w_len;     /* SOCK: w_buf;  DSOCK: sz of last msg sent  */
310 
311     /* statistics */
312     TNCBI_BigCount   n_read;    /* DSOCK: total # of bytes read (in all msgs)
313                                    SOCK:  # of bytes read since last connect
314                                 */
315     TNCBI_BigCount   n_written; /* DSOCK: total # of bytes written (all msgs)
316                                    SOCK:  # of bytes written since last connect
317                                 */
318     TNCBI_BigCount   n_in;      /* DSOCK: total # of messages received
319                                    SOCK:  total # of bytes read in all
320                                    completed connections in this SOCK so far
321                                 */
322     TNCBI_BigCount   n_out;     /* DSOCK: total # of messages sent
323                                    SOCK:  total # of bytes written in all
324                                    completed connections in this SOCK so far
325                                 */
326 #ifdef NCBI_OS_UNIX
327     /* pathname for UNIX socket */
328     char             path[1];   /* must go last                              */
329 #endif /*NCBI_OS_UNIX*/
330 } SOCK_struct;
331 
332 
333 /*
334  * The following implementation details are worth noting:
335  *
336  * 1. w_buf is used for stream sockets to keep initial data segment
337  *    that has to be sent upon connection establishment.
338  *
339  * 2. eof is used differently for stream and datagram sockets:
340  *    =1 for stream sockets means that last read has hit EOF;
341  *    =1 for datagram sockets means that message in w_buf has been completed.
342  *
343  * 3. r_status keeps completion code of the last low-level read call;
344  *    however, eIO_Closed is there when the socket is shut down for reading;
345  *    see the table below for full details on stream sockets.
346  *
347  * 4. w_status keeps completion code of the last low-level write call;
348  *    however, eIO_Closed is there when the socket is shut down for writing.
349  *
350  * 5. The following table depicts r_status and eof combinations and their
351  *    meanings for stream sockets:
352  * -------------------------------+--------------------------------------------
353  *              Field             |
354  * ---------------+---------------+                  Meaning
355  * sock->r_status |   sock->eof   |           (stream sockets only)
356  * ---------------+---------------+--------------------------------------------
357  * eIO_Closed     |       0       |  Socket shut down for reading
358  * eIO_Closed     |       1       |  Read severely failed
359  * not eIO_Closed |       0       |  Read completed with r_status error
360  * not eIO_Closed |       1       |  Read hit EOF (and [maybe later] r_status)
361  * ---------------+---------------+--------------------------------------------
362  */
363 
364 
365 #if defined(NCBI_OS_MSWIN)  &&  defined(_WIN64)
366 #  pragma pack(pop)
367 #endif /*NCBI_OS_MSWIN && _WIN64*/
368 
369 
370 /* Global data */
371 extern const char g_kNcbiSockNameAbbr[];
372 
373 
374 /* Initial socket data & respective private ctors */
375 typedef struct {
376     const void* data;
377     size_t      size;
378     NCBI_CRED   cred;
379     const char* host;
380 } SSOCK_Init;
381 
382 
383 EIO_Status SOCK_CreateInternal(const char*       host,
384                                unsigned short    port,
385                                const STimeout*   timeout,
386                                SOCK*             sock,
387                                const SSOCK_Init* init,
388                                TSOCK_Flags       flags);
389 
390 
391 EIO_Status SOCK_CreateOnTopInternal(const void*       handle,
392                                     size_t            handle_size,
393                                     SOCK*             sock,
394                                     const SSOCK_Init* init,
395                                     TSOCK_Flags       flags);
396 
397 
398 /* Addtl socket API for internal use:  if flag != 0 and host is nonexistent,
399  * return it as INADDR_NONE (-1) rather than an error.
400  */
401 const char* SOCK_StringToHostPortEx(const char*     str,
402                                     unsigned int*   host,
403                                     unsigned short* port,
404                                     int/*bool*/     flag);
405 
406 
407 void SOCK_SetupSSLInternal(FSSLSetup setup, int/*bool*/ init);
408 
409 
410 #ifdef __cplusplus
411 } /* extern "C" */
412 #endif /*__cplusplus*/
413 
414 
415 #endif /* CONNECT___NCBI_SOCKETP__H */
416