1 #ifndef CONNECT___NCBI_SOCKETP__H
2 #define CONNECT___NCBI_SOCKETP__H
3 
4 /* $Id: ncbi_socketp.h,v 1.31 2016/01/01 00:44:15 fukanchi Exp $
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(ENFILE)
127 #  define SOCK_ETOOMANY       ENFILE
128 #elif defined(EMFILE)
129 #  define SOCK_ETOOMANY       EMFILE
130 #elif defined(WSAEMFILE)
131 #  define SOCK_ETOOMANY       WSAEMFILE
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 /* Event trigger
159  */
160 typedef struct TRIGGER_tag {
161     TRIGGER_Handle     fd;      /* OS-specific trigger handle                */
162     unsigned int       id;      /* the internal ID (cf. "s_ID_Counter")      */
163 
164     union {
165         volatile void* ptr;     /* trigger state (UNIX only, otherwise MBZ)  */
166         int            int_[2]; /* pointer storage area w/proper alignment   */
167     } isset;
168 
169     /* type, status, EOF, log, read-on-write etc bit-field indicators */
170     TBSOCK_Type         type:2; /* eTrigger                                  */
171     EBSwitch             log:2; /* how to log events                         */
172     EBSwitch          r_on_w:2; /* MBZ                                       */
173     EBSwitch        i_on_sig:2; /* eDefault                                  */
174 
175     EBIO_Status     r_status:3; /* MBZ (NB: eIO_Success)                     */
176     unsigned/*bool*/     eof:1; /* MBZ                                       */
177     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
178     unsigned/*bool*/ pending:1; /* MBZ                                       */
179 
180     unsigned        reserved:16;/* MBZ                                       */
181 
182 #ifdef NCBI_OS_UNIX
183     int                out;     /* write end of the pipe                     */
184 #endif /*NCBI_OS_UNIX*/
185 } TRIGGER_struct;
186 
187 
188 /* Sides of socket
189  */
190 typedef enum {
191     eSOCK_Server = 0,
192     eSOCK_Client = 1
193 } ESOCK_Side;
194 
195 typedef unsigned EBSOCK_Side;
196 
197 
198 /* Listening socket [must be in one-2-one binary correspondene with TRIGGER]
199  */
200 typedef struct LSOCK_tag {
201     TSOCK_Handle     sock;      /* OS-specific socket handle                 */
202     unsigned int     id;        /* the internal ID (see also "s_ID_Counter") */
203 
204     unsigned int     n_accept;  /* total number of accepted clients          */
205     unsigned short   away;      /* MSWIN: run-away connect warning counter   */
206     unsigned short   port;      /* port on which listening (host byte order) */
207 
208     /* type, status, EOF, log, read-on-write etc bit-field indicators */
209     TBSOCK_Type         type:2; /* eListening                                */
210     EBSwitch             log:2; /* how to log events and data for this socket*/
211     EBSwitch          r_on_w:2; /* MBZ                                       */
212     EBSwitch        i_on_sig:2; /* eDefault                                  */
213 
214     EBIO_Status     r_status:3; /* MBZ (NB: eIO_Success)                     */
215     unsigned/*bool*/     eof:1; /* MBZ                                       */
216     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
217     unsigned/*bool*/ pending:1; /* MBZ                                       */
218 
219     EBSOCK_Side         side:1; /* MBZ (NB: eSOCK_Server)                    */
220     unsigned/*bool*/    keep:1; /* whether to keep OS handle upon close      */
221 #ifndef NCBI_OS_MSWIN
222     unsigned        reserved:14;/* MBZ                                       */
223 #else
224     unsigned        reserved:11;/* MBZ                                       */
225     unsigned        readable:1; /* =1 if known to have a pending accept      */
226     unsigned          unused:2; /* MBZ                                       */
227 
228     WSAEVENT         event;     /* event bound to I/O                        */
229 #endif /*!NCBI_OS_MSWIN*/
230 
231     void*            context;   /* per-server session/credentials (not impl) */
232 
233 #ifdef NCBI_OS_UNIX
234     char             path[1];   /* must go last                              */
235 #endif /*NCBI_OS_UNIX*/
236 } LSOCK_struct;
237 
238 
239 /* Socket [it must be in 1-2-1 binary correspondence with LSOCK above]
240  */
241 typedef struct SOCK_tag {
242     TSOCK_Handle     sock;      /* OS-specific socket handle                 */
243     unsigned int     id;        /* the internal ID (see also "s_ID_Counter") */
244 
245     /* connection point */
246     unsigned int     host;      /* peer host (network byte order)            */
247     unsigned short   port;      /* peer port (host byte order)               */
248     unsigned short   myport;    /* this socket's port number, host byte order*/
249 
250     /* type, status, EOF, log, read-on-write etc bit-field indicators */
251     TBSOCK_Type         type:2; /* |= eSocket ({ eSocket | eDatagram })      */
252     EBSwitch             log:2; /* how to log events and data for this socket*/
253     EBSwitch          r_on_w:2; /* enable/disable automatic read-on-write    */
254     EBSwitch        i_on_sig:2; /* enable/disable I/O restart on signals     */
255 
256     EBIO_Status     r_status:3; /* read  status:  eIO_Closed if was shut down*/
257     unsigned/*bool*/     eof:1; /* Stream sockets: 'End of file' seen on read
258                                    Datagram socks: 'End of message' written  */
259     EBIO_Status     w_status:3; /* write status:  eIO_Closed if was shut down*/
260     unsigned/*bool*/ pending:1; /* =1 if connection is still initing         */
261 
262     EBSOCK_Side         side:1; /* socket side: client- or server-side       */
263     unsigned/*bool*/    keep:1; /* whether to keep OS handle upon close      */
264     unsigned       crossexec:1; /* =1 if close-on-exec must NOT be set       */
265     unsigned       connected:1; /* =1 if remote end-point is fully connected */
266     unsigned        r_tv_set:1; /* =1 if read  timeout is set (i.e. finite)  */
267     unsigned        w_tv_set:1; /* =1 if write timeout is set (i.e. finite)  */
268     unsigned        c_tv_set:1; /* =1 if close timeout is set (i.e. finite)  */
269     unsigned       keepalive:1; /* =1 if needs to be kept alive (if OS supp.)*/
270 #ifndef NCBI_OS_MSWIN
271     unsigned        reserved:8; /* MBZ                                       */
272 #else
273     unsigned        reserved:5; /* MBZ                                       */
274     unsigned        readable:1; /* =1 if known to be readable                */
275     unsigned        writable:1; /* =1 if known to be writeable               */
276     unsigned         closing:1; /* =1 if FD_CLOSE posted                     */
277 
278     WSAEVENT         event;     /* event bound to I/O                        */
279 #endif /*!NCBI_OS_MSWIN*/
280 
281     void*            session;   /* secure session handle if used, else 0     */
282     NCBI_CRED        cred;      /* secure session credentials, 0 if none     */
283 
284     /* timeouts */
285     struct timeval   r_tv;      /* finite read  timeout value                */
286     struct timeval   w_tv;      /* finite write timeout value                */
287     struct timeval   c_tv;      /* finite close timeout value                */
288     STimeout         r_to;      /* finite read  timeout value (aux., temp.)  */
289     STimeout         w_to;      /* finite write timeout value (aux., temp.)  */
290     STimeout         c_to;      /* finite close timeout value (aux., temp.)  */
291 
292     /* aux I/O data */
293     BUF              r_buf;     /* read  buffer                              */
294     BUF              w_buf;     /* write buffer                              */
295     size_t           r_len;     /* DSOCK: size of last message received      */
296     size_t           w_len;     /* SOCK: how much data is pending for output */
297 
298     /* statistics */
299     TNCBI_BigCount   n_read;    /* DSOCK: total # of bytes read (in all msgs)
300                                    SOCK:  # of bytes read since last connect
301                                 */
302     TNCBI_BigCount   n_written; /* DSOCK: total # of bytes written (all msgs)
303                                    SOCK:  # of bytes written since last connect
304                                 */
305     TNCBI_BigCount   n_in;      /* DSOCK: total # of messages received
306                                    SOCK:  total # of bytes read in all
307                                    completed connections in this SOCK so far
308                                 */
309     TNCBI_BigCount   n_out;     /* DSOCK: total # of messages sent
310                                    SOCK:  total # of bytes written in all
311                                    completed connections in this SOCK so far
312                                 */
313 #ifdef NCBI_OS_UNIX
314     /* pathname for UNIX socket */
315     char             path[1];   /* must go last                              */
316 #endif /*NCBI_OS_UNIX*/
317 } SOCK_struct;
318 
319 
320 /*
321  * The following implementation details are worth noting:
322  *
323  * 1. w_buf is used for stream sockets to keep initial data segment
324  *    that has to be sent upon connection establishment.
325  *
326  * 2. eof is used differently for stream and datagram sockets:
327  *    =1 for stream sockets means that last read has hit EOF;
328  *    =1 for datagram sockets means that message in w_buf has been completed.
329  *
330  * 3. r_status keeps completion code of the last low-level read call;
331  *    however, eIO_Closed is there when the socket is shut down for reading;
332  *    see the table below for full details on stream sockets.
333  *
334  * 4. w_status keeps completion code of the last low-level write call;
335  *    however, eIO_Closed is there when the socket is shut down for writing.
336  *
337  * 5. The following table depicts r_status and eof combinations and their
338  *    meanings for stream sockets:
339  * -------------------------------+--------------------------------------------
340  *              Field             |
341  * ---------------+---------------+                  Meaning
342  * sock->r_status |   sock->eof   |           (stream sockets only)
343  * ---------------+---------------+--------------------------------------------
344  * eIO_Closed     |       0       |  Socket shut down for reading
345  * eIO_Closed     |       1       |  Read severely failed
346  * not eIO_Closed |       0       |  Read completed with r_status error
347  * not eIO_Closed |       1       |  Read hit EOF (and [maybe later] r_status)
348  * ---------------+---------------+--------------------------------------------
349  */
350 
351 
352 #if defined(NCBI_OS_MSWIN)  &&  defined(_WIN64)
353 #  pragma pack(pop)
354 #endif /*NCBI_OS_MSWIN && _WIN64*/
355 
356 
357 /* Global data */
358 extern const char g_kNcbiSockNameAbbr[];
359 
360 
361 /* Initial socket data & respective private ctors */
362 typedef struct {
363     const void* data;
364     size_t      size;
365     NCBI_CRED   cred;
366 } SSOCK_Init;
367 
368 
369 EIO_Status SOCK_CreateInternal(const char*     host,
370                                unsigned short  port,
371                                const STimeout* timeout,
372                                SOCK*           sock,
373                                SSOCK_Init*     init,
374                                TSOCK_Flags     flags);
375 
376 
377 EIO_Status SOCK_CreateOnTopInternal(const void* handle,
378                                     size_t      handle_size,
379                                     SOCK*       sock,
380                                     SSOCK_Init* init,
381                                     TSOCK_Flags flags);
382 
383 
384 /* Addtl socket API for internal use:  if flag != 0 and host is nonexistent,
385  * return it as INADDR_NONE (-1) rather than an error.
386  */
387 const char* SOCK_StringToHostPortEx(const char*     str,
388                                     unsigned int*   host,
389                                     unsigned short* port,
390                                     int/*bool*/     flag);
391 
392 
393 #ifdef __cplusplus
394 } /* extern "C" */
395 #endif /*__cplusplus*/
396 
397 
398 #endif /* CONNECT___NCBI_SOCKETP__H */
399