1 #ifndef CONNECT___NCBI_PRIV__H
2 #define CONNECT___NCBI_PRIV__H
3 
4 /* $Id: ncbi_priv.h,v 6.104 2016/11/18 17:34:14 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  * Authors:  Denis Vakatov, Anton Lavrentiev, Pavel Ivanov
30  *
31  * File Description:
32  *    Private aux. code for the "ncbi_*.[ch]"
33  *
34  *********************************
35  * Tracing and logging
36  *    C error codes:   NCBI_C_DEFINE_ERRCODE_X, NCBI_C_ERRCODE_X
37  *    private global:  g_CORE_Log
38  *    macros:          CORE_TRACE[F], CORE_LOG[F][_[EX]X],
39  *                     CORE_LOG[F]_ERRNO[_[EX]X](), CORE_DATA[F][_[EX]X]
40  * Critical section (basic multi-thread synchronization)
41  *    private global:  g_CORE_MT_Lock
42  *    macros:          CORE_LOCK_WRITE, CORE_LOCK_READ, CORE_UNLOCK
43  * Registry:
44  *    private global:  g_CORE_Registry
45  *    macros:          CORE_REG_GET, CORE_REG_SET
46  * Setup accounting:   ECORE_Set
47  *    private global:  g_CORE_Set
48  * Random generator seeding support
49  *    private global:  g_NCBI_ConnectRandomSeed
50  *    macro:           NCBI_CONNECT_SRAND_ADDEND
51  * App name / NCBI ID / DTab support
52  *    private globals: g_CORE_GetAppName
53  *                     g_CORE_GetRequestID
54  *                     g_CORE_GetRequestDtab
55  *
56  */
57 
58 
59 //#define NCBI_MONKEY
60 
61 #include "ncbi_assert.h"
62 #include <connect/ncbi_util.h>
63 #ifdef NCBI_MONKEY
64 #  if defined(NCBI_OS_MSWIN)
65 #    include <WinSock2.h>
66 #  else
67 #    include <sys/socket.h>
68 #    define SOCKET int
69 #  endif /*NCBI_OS_MSWIN*/
70 #endif /* NCBI_MONKEY */
71 
72 
73 #ifdef __cplusplus
74 extern "C" {
75 #endif
76 
77 
78 /******************************************************************************
79  *  Error handling and logging
80  *
81  * Several macros brought here from ncbidiag.hpp.  The names slightly
82  * changed (added _C) because some sources can include this header and
83  * ncbidiag.hpp simultaneously.
84  */
85 
86 /** Define global error code name with given value (err_code) */
87 #define NCBI_C_DEFINE_ERRCODE_X(name, err_code, max_err_subcode)        \
88     enum enum##name {                                                   \
89         eErrCodeX_##name = err_code                                     \
90         /* automatic subcode checking is not implemented in C code */   \
91     }
92 
93 /* Here are only error codes used in C sources.  For error codes used in
94  * C++ sources (in C++ Toolkit) see include/connect/error_codes.hpp.
95  */
96 NCBI_C_DEFINE_ERRCODE_X(Connect_Conn,     301,  36);
97 NCBI_C_DEFINE_ERRCODE_X(Connect_Socket,   302, 163);
98 NCBI_C_DEFINE_ERRCODE_X(Connect_Util,     303,   9);
99 NCBI_C_DEFINE_ERRCODE_X(Connect_LBSM,     304,  33);
100 NCBI_C_DEFINE_ERRCODE_X(Connect_FTP,      305,  13);
101 NCBI_C_DEFINE_ERRCODE_X(Connect_SMTP,     306,  33);
102 NCBI_C_DEFINE_ERRCODE_X(Connect_HTTP,     307,  23);
103 NCBI_C_DEFINE_ERRCODE_X(Connect_Service,  308,   9);
104 NCBI_C_DEFINE_ERRCODE_X(Connect_HeapMgr,  309,  33);
105                                        /* 310 unused */
106 NCBI_C_DEFINE_ERRCODE_X(Connect_Mghbn,    311,  16);
107 NCBI_C_DEFINE_ERRCODE_X(Connect_Crypt,    312,   5);
108 NCBI_C_DEFINE_ERRCODE_X(Connect_LocalNet, 313,   4);
109 
110 /** Make one identifier from 2 parts */
111 #define NCBI_C_CONCAT_IDENTIFIER(prefix, postfix)  prefix##postfix
112 
113 /** Return value of error code by its name defined by NCBI_DEFINE_ERRCODE_X
114  *
115  * @sa NCBI_C_DEFINE_ERRCODE_X
116  */
117 #define NCBI_C_ERRCODE_X_NAME(name)             \
118     NCBI_C_CONCAT_IDENTIFIER(eErrCodeX_, name)
119 
120 /** Return currently set default error code.  Default error code is set by
121  *  definition of NCBI_USE_ERRCODE_X with name of error code as its value.
122  *
123  * @sa NCBI_DEFINE_ERRCODE_X
124  */
125 #define NCBI_C_ERRCODE_X                        \
126     NCBI_C_ERRCODE_X_NAME(NCBI_USE_ERRCODE_X)
127 
128 
129 extern NCBI_XCONNECT_EXPORT LOG g_CORE_Log;
130 
131 /* Always use the following macros and functions to access "g_CORE_Log",
132  * do not access/change it directly!
133  */
134 
135 #ifdef _DEBUG
136 #  define CORE_TRACE(message)    CORE_LOG(eLOG_Trace, message)
137 #  define CORE_TRACEF(fmt_args)  CORE_LOGF(eLOG_Trace, fmt_args)
138 #  define CORE_DEBUG_ARG(arg)    arg
139 #else
140 #  define CORE_TRACE(message)    ((void) 0)
141 #  define CORE_TRACEF(fmt_args)  ((void) 0)
142 #  define CORE_DEBUG_ARG(arg)    /*arg*/
143 #endif /*_DEBUG*/
144 
145 #define CORE_LOG_X(subcode, level, message)                             \
146     DO_CORE_LOG(NCBI_C_ERRCODE_X, subcode, level,                       \
147                 message, 0)
148 
149 #define CORE_LOGF_X(subcode, level, fmt_args)                           \
150     DO_CORE_LOG(NCBI_C_ERRCODE_X, subcode, level,                       \
151                 g_CORE_Sprintf fmt_args, 1)
152 
153 #define CORE_LOG(level, message)                                        \
154     DO_CORE_LOG(0, 0, level,                                            \
155                 message, 0)
156 
157 #define CORE_LOGF(level, fmt_args)                                      \
158     DO_CORE_LOG(0, 0, level,                                            \
159                 g_CORE_Sprintf fmt_args, 1)
160 
161 #define CORE_LOG_ERRNO_X(subcode, level, error, message)                \
162     DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, 0,       \
163                       message, 0)
164 
165 #define CORE_LOGF_ERRNO_X(subcode, level, error, fmt_args)              \
166     DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, 0,       \
167                       g_CORE_Sprintf fmt_args, 1)
168 
169 #define CORE_LOG_ERRNO(level, error, message)                           \
170     DO_CORE_LOG_ERRNO(0, 0, level, error, 0,                            \
171                       message, 0)
172 
173 #define CORE_LOGF_ERRNO(level, error, fmt_args)                         \
174     DO_CORE_LOG_ERRNO(0, 0, level, error, 0,                            \
175                       g_CORE_Sprintf fmt_args, 1)
176 
177 #define CORE_LOG_ERRNO_EXX(subcode, level, error, descr, message)       \
178     DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, descr,   \
179                       message, 0)
180 
181 #define CORE_LOGF_ERRNO_EXX(subcode, level, error, descr, fmt_args)     \
182     DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, descr,   \
183                       g_CORE_Sprintf fmt_args, 1)
184 
185 #define CORE_LOG_ERRNO_EX(level, error, descr, message)                 \
186     DO_CORE_LOG_ERRNO(0, 0, level, error, descr,                        \
187                       message, 0)
188 
189 #define CORE_LOGF_ERRNO_EX(level, error, descr, fmt_args)               \
190     DO_CORE_LOG_ERRNO(0, 0, level, error, descr,                        \
191                       g_CORE_Sprintf fmt_args, 1)
192 
193 #define CORE_DATA_X(subcode, level, data, size, message)                \
194     DO_CORE_LOG_DATA(NCBI_C_ERRCODE_X, subcode, level, data, size,      \
195                      message, 0)
196 
197 #define CORE_DATAF_X(subcode, level, data, size, fmt_args)              \
198     DO_CORE_LOG_DATA(NCBI_C_ERRCODE_X, subcode, level, data, size,      \
199                      g_CORE_Sprintf fmt_args, 1)
200 
201 #define CORE_DATA(level, data, size, message)                           \
202     DO_CORE_LOG_DATA(0, 0, level, data, size,                           \
203                      message, 0)
204 
205 #define CORE_DATAF(level, data, size, fmt_args)                         \
206     DO_CORE_LOG_DATA(0, 0, level, data, size,                           \
207                      g_CORE_Sprintf fmt_args, 1)
208 
209 /* helpers follow */
210 #define DO_CORE_LOG_X(_code, _subcode, _level, _message, _dynamic,      \
211                       _error, _descr, _raw_data, _raw_size)             \
212     do {                                                                \
213         ELOG_Level _xx_level = (_level);                                \
214         if (g_CORE_Log  ||  _xx_level == eLOG_Fatal) {                  \
215             SLOG_Handler _mess;                                         \
216             _mess.dynamic     = _dynamic;                               \
217             _mess.message     = NcbiMessagePlusError(&_mess.dynamic,    \
218                                                      (_message),        \
219                                                      (_error),          \
220                                                      (_descr));         \
221             _mess.level       = _xx_level;                              \
222             _mess.module      = THIS_MODULE;                            \
223             _mess.func        = CORE_CURRENT_FUNCTION;                  \
224             _mess.file        = __FILE__;                               \
225             _mess.line        = __LINE__;                               \
226             _mess.raw_data    = (_raw_data);                            \
227             _mess.raw_size    = (_raw_size);                            \
228             _mess.err_code    = (_code);                                \
229             _mess.err_subcode = (_subcode);                             \
230             CORE_LOCK_READ;                                             \
231             LOG_WriteInternal(g_CORE_Log, &_mess);                      \
232             CORE_UNLOCK;                                                \
233         }                                                               \
234     } while (0)
235 
236 #define DO_CORE_LOG(code, subcode, level,                               \
237                           message, dynamic)                             \
238     DO_CORE_LOG_X(code, subcode, level, message, dynamic, 0, 0, 0, 0)
239 
240 #define DO_CORE_LOG_ERRNO(code, subcode, level, error, descr,           \
241                           message, dynamic)                             \
242     DO_CORE_LOG_X(code, subcode, level, message, dynamic, error, descr, 0, 0)
243 
244 #define DO_CORE_LOG_DATA(code, subcode, level, data, size,              \
245                          message, dynamic)                              \
246     DO_CORE_LOG_X(code, subcode, level, message, dynamic, 0, 0, data, size)
247 
248 extern NCBI_XCONNECT_EXPORT const char* g_CORE_Sprintf(const char* fmt, ...)
249 #ifdef __GNUC__
250     __attribute__((format(printf,1,2)))
251 #endif
252 ;
253 
254 
255 /******************************************************************************
256  *  Multi-Thread SAFETY
257  */
258 
259 extern struct MT_LOCK_tag g_CORE_MT_Lock_default;
260 
261 extern NCBI_XCONNECT_EXPORT MT_LOCK g_CORE_MT_Lock;
262 
263 
264 /* Always use the following macros and functions to access "g_CORE_MT_Lock",
265  * do not access/change it directly!
266  */
267 
268 #define CORE_LOCK_WRITE  verify(CORE_CHECK_LOCK  &&                     \
269                                 MT_LOCK_Do(g_CORE_MT_Lock, eMT_Lock    ))
270 #define CORE_LOCK_READ   verify(CORE_CHECK_LOCK  &&                     \
271                                 MT_LOCK_Do(g_CORE_MT_Lock, eMT_LockRead))
272 #define CORE_UNLOCK      verify(CORE_CHECK_UNLOCK  &&                   \
273                                 MT_LOCK_Do(g_CORE_MT_Lock, eMT_Unlock  ))
274 
275 #ifdef _DEBUG
276 extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckLock  (void);
277 extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckUnlock(void);
278 #  define CORE_CHECK_LOCK       g_NCBI_CoreCheckLock()
279 #  define CORE_CHECK_UNLOCK     g_NCBI_CoreCheckUnlock()
280 #else
281 #  define CORE_CHECK_LOCK       (1/*TRUE*/)
282 #  define CORE_CHECK_UNLOCK     (1/*TRUE*/)
283 #endif /*_DEBUG*/
284 
285 
286 /******************************************************************************
287  *  Registry
288  */
289 
290 extern NCBI_XCONNECT_EXPORT REG g_CORE_Registry;
291 
292 /* Always use the following macros and functions to access "g_CORE_Registry",
293  * do not access/change it directly!
294  */
295 
296 #define CORE_REG_GET(section, name, value, value_size, def_value)   \
297     g_CORE_RegistryGET(section, name, value, value_size, def_value)
298 
299 #define CORE_REG_SET(section, name, value, storage)                 \
300     g_CORE_RegistrySET(section, name, value, storage)
301 
302 
303 /* (private, to be used exclusively by the above macro CORE_REG_GET) */
304 extern NCBI_XCONNECT_EXPORT const char* g_CORE_RegistryGET
305 (const char*  section,
306  const char*  name,
307  char*        value,
308  size_t       value_size,
309  const char*  def_value
310  );
311 
312 /* (private, to be used exclusively by the above macro CORE_REG_SET) */
313 extern NCBI_XCONNECT_EXPORT int/*bool*/ g_CORE_RegistrySET
314 (const char*  section,
315  const char*  name,
316  const char*  value,
317  EREG_Storage storage
318  );
319 
320 
321 /******************************************************************************
322  *  Setup accounting
323  */
324 
325 typedef enum {
326     eCORE_SetSSL  = 1,
327     eCORE_SetREG  = 4,
328     eCORE_SetLOG  = 2,
329     eCORE_SetLOCK = 8
330 } ECORE_Set;
331 typedef unsigned int TCORE_Set;
332 
333 
334 extern TCORE_Set g_CORE_Set;
335 
336 
337 /******************************************************************************
338  *  Random generator seeding support
339  */
340 
341 extern NCBI_XCONNECT_EXPORT int    g_NCBI_ConnectRandomSeed;
342 extern NCBI_XCONNECT_EXPORT int    g_NCBI_ConnectSrandAddend(void);
343 #define NCBI_CONNECT_SRAND_ADDEND  g_NCBI_ConnectSrandAddend()
344 
345 
346 /******************************************************************************
347  *  App name support (may return NULL; gets converted to "" at the user level)
348  */
349 
350 typedef const char* (*FNcbiGetAppName)(void);
351 extern NCBI_XCONNECT_EXPORT FNcbiGetAppName g_CORE_GetAppName;
352 
353 
354 /******************************************************************************
355  *  NCBI request ID support (return "as is" to the user)
356  *  Return NULL on error;  otherwise, the returned ID is a non-empty string
357  *  allocated on the heap, and must be free()'d when no longer needed.
358  */
359 
360 typedef char* (*FNcbiGetRequestID)(ENcbiRequestID);
361 extern NCBI_XCONNECT_EXPORT FNcbiGetRequestID g_CORE_GetRequestID;
362 
363 
364 /******************************************************************************
365  *  DTab-Local support (returned NULL gets converted to "" at the user level)
366  */
367 typedef const char* (*FNcbiGetRequestDtab)(void);
368 extern NCBI_XCONNECT_EXPORT FNcbiGetRequestDtab g_CORE_GetRequestDtab;
369 
370 
371 /******************************************************************************
372  *  Miscellanea
373  */
374 
375 #ifdef __GNUC__
376 #  define likely(x)    __builtin_expect(!!(x),1)
377 #  define unlikely(x)  __builtin_expect(!!(x),0)
378 #else
379 #  define likely(x)    (x)
380 #  define unlikely(x)  (x)
381 #endif /*__GNUC__*/
382 
383 
384 /******************************************************************************
385  *  NCBI Crazy Monkey support
386  */
387 
388 #ifdef NCBI_MONKEY
389 /* UNIX and Windows have different prototypes for send(), recv(), etc., so
390  * some types have to be pre-selected based on current OS
391  */
392 #   ifdef NCBI_OS_MSWIN
393 #       define MONKEY_RETTYPE  int
394 #       define MONKEY_SOCKTYPE SOCKET
395 #       define MONKEY_DATATYPE char*
396 #       define MONKEY_LENTYPE  int
397 #       define MONKEY_SOCKLENTYPE  int
398 #       define MONKEY_STDCALL __stdcall /* in Windows, socket functions have
399                                            prototypes with __stdcall */
400 #   else
401 #       define MONKEY_RETTYPE  ssize_t
402 #       define MONKEY_SOCKTYPE int
403 #       define MONKEY_DATATYPE void*
404 #       define MONKEY_LENTYPE  size_t
405 #       define MONKEY_SOCKLENTYPE  socklen_t
406 #       define MONKEY_STDCALL /* empty*/
407 #   endif /* NCBI_OS_MSWIN */
408 
409 /******************************************************************************
410  *  Socket functions via Crazy Monkey
411  */
412 typedef MONKEY_RETTYPE
413             (MONKEY_STDCALL  *FMonkeyRecv)  (MONKEY_SOCKTYPE       sock,
414                                              MONKEY_DATATYPE       buf,
415                                              MONKEY_LENTYPE        size,
416                                              int                   flags,
417                                              void* /* SOCK* */     sock_ptr);
418 typedef MONKEY_RETTYPE
419             (MONKEY_STDCALL *FMonkeySend)  (MONKEY_SOCKTYPE        sock,
420                                             const MONKEY_DATATYPE  data,
421                                             MONKEY_LENTYPE         size,
422                                             int                    flags,
423                                             void* /* SOCK* */      sock_ptr);
424 typedef int(MONKEY_STDCALL *FMonkeyConnect)(MONKEY_SOCKTYPE        sock,
425                                             const struct sockaddr* name,
426                                             MONKEY_SOCKLENTYPE     namelen);
427 
428 typedef int /* bool */    (*FMonkeyPoll)   (size_t*                n,
429                                             void* /*SSOCK_Poll[]* */polls,
430                                             EIO_Status*            ret_status);
431 typedef void              (*FMonkeyClose)  (SOCKET sock);
432 typedef void              (*FSockHasSocket)(void* /* SOCK* */      sock,
433                                             MONKEY_SOCKTYPE        socket);
434 
435 
436 extern NCBI_XCONNECT_EXPORT FMonkeySend     g_MONKEY_Send;
437 extern NCBI_XCONNECT_EXPORT FMonkeyRecv     g_MONKEY_Recv;
438 extern NCBI_XCONNECT_EXPORT FMonkeyPoll     g_MONKEY_Poll;
439 extern NCBI_XCONNECT_EXPORT FMonkeyConnect  g_MONKEY_Connect;
440 extern NCBI_XCONNECT_EXPORT FMonkeyClose    g_MONKEY_Close;
441 extern NCBI_XCONNECT_EXPORT FSockHasSocket  g_MONKEY_SockHasSocket;
442 #endif /*NCBI_MONKEY*/
443 
444 
445 #ifdef __cplusplus
446 }  /* extern "C" */
447 #endif
448 
449 #endif /* CONNECT___NCBI_PRIV__H */
450