1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <kns/extern.h>
28
29 #include <kfg/config.h>
30 #include <kfg/properties.h>
31
32 #include <klib/base64.h>
33 #include <klib/data-buffer.h>
34 #include <klib/printf.h>
35 #include <klib/rc.h>
36 #include <klib/strings.h>
37 #include <klib/writer.h>
38
39 #include <kproc/lock.h>
40 #include <kproc/timeout.h>
41
42 #include <kns/http.h>
43 #include <kns/manager.h>
44 #include <kns/socket.h>
45
46 #include <cloud/manager.h>
47
48 #include <atomic.h> /* atomic_ptr_t */
49 #include <ctype.h>
50 #include <strtol.h> /* strtou64 */
51 #include <sysalloc.h>
52
53 #include <assert.h>
54
55 #if LINUX
56 #include <gnu/libc-version.h>
57 #include <arpa/inet.h>
58 #include <netinet/in.h>
59 #endif
60
61 #include <stdio.h> /* fprintf */
62
63 #include "../klib/release-vers.h"
64 #include "http-priv.h"
65 #include "kns_manager-singleton.h" /* USE_SINGLETON */
66 #include "mgr-priv.h"
67 #include "stream-priv.h"
68 #include "sysmgr.h"
69
70 #ifndef MAX_CONN_LIMIT
71 #define MAX_CONN_LIMIT ( 60 * 1000 )
72 #endif
73
74 #ifndef MAX_CONN_READ_LIMIT
75 #define MAX_CONN_READ_LIMIT ( 10 * 60 * 1000 )
76 #endif
77
78 #ifndef MAX_CONN_WRITE_LIMIT
79 #define MAX_CONN_WRITE_LIMIT ( 10 * 60 * 1000 )
80 #endif
81
82 static KLock *kns_manager_lock = NULL; /* Protects below */
83 static KDataBuffer kns_manager_user_agent;
84
85 static KDataBuffer kns_manager_guid;
86
87 /* thread-local values */
88 _Thread_local char kns_manager_user_agent_append [ 4096 ] = { 0 };
89 _Thread_local char kns_manager_clientip [ KNSMANAGER_STRING_MAX ] = { 0 };
90 _Thread_local char kns_manager_sessionid [ KNSMANAGER_STRING_MAX ] = { 0 };
91 _Thread_local char kns_manager_pagehitid [ KNSMANAGER_STRING_MAX ] = { 0 };
92 _Thread_local char kns_manager_ua_suffix [ KNSMANAGER_STRING_MAX ] = { 0 };
93
94 quitting_t quitting;
95
96 #if USE_SINGLETON
97 static atomic_ptr_t kns_singleton;
98 #endif
99
100 /*
101 #define RELEASE( type, obj ) do { rc_t rc2 = type##Release ( obj ); \
102 if (rc2 != 0 && rc == 0) { rc = rc2; } obj = NULL; } while ( false )
103 */
104
KNSManagerHttpProxyOnly(const KNSManager * self)105 bool KNSManagerHttpProxyOnly ( const KNSManager *self )
106 {
107 if ( self == NULL ) { return false; }
108
109 return KNSProxiesHttpProxyOnly ( self->proxies );
110 }
111
KNSManagerGetProxies(const KNSManager * self,size_t * cnt)112 struct KNSProxies *KNSManagerGetProxies ( const KNSManager *self, size_t *cnt )
113 {
114 if ( self == NULL ) { return NULL; }
115 size_t dummy;
116 if ( cnt == NULL ) { cnt = &dummy; }
117 return KNSProxiesGetHttpProxy ( self->proxies, cnt );
118 }
119
120
KNSManagerWhack(KNSManager * self)121 static rc_t KNSManagerWhack ( KNSManager *self )
122 {
123 rc_t rc;
124
125 #if USE_SINGLETON
126 KNSManager *our_mgr
127 = atomic_test_and_set_ptr ( &kns_singleton, NULL, NULL );
128 if ( self == our_mgr ) {
129 if ( !self->notSingleton ) { return 0; }
130 atomic_test_and_set_ptr ( &kns_singleton, NULL, self );
131 }
132 #endif
133
134 KNSProxiesWhack ( self->proxies );
135 CloudMgrRelease ( self->cloud );
136
137 rc = HttpRetrySpecsDestroy ( &self->retry_specs );
138
139 KTLSGlobalsWhack ( &self->tlsg );
140
141 free ( self );
142
143 KNSManagerCleanup ();
144 if ( kns_manager_lock ) {
145 KLockRelease ( kns_manager_lock );
146 kns_manager_lock = NULL;
147 }
148 if ( !rc ) rc = KDataBufferWhack ( &kns_manager_user_agent );
149
150 return rc;
151 }
152
KNSManagerAddRef(const KNSManager * self)153 LIB_EXPORT rc_t CC KNSManagerAddRef ( const KNSManager *self )
154 {
155 if ( self != NULL ) {
156 switch ( KRefcountAdd ( &self->refcount, "KNSManager" ) ) {
157 case krefLimit:
158 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcExcessive );
159 case krefNegative:
160 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
161 }
162 }
163 return 0;
164 }
165
166
KNSManagerRelease(const KNSManager * self)167 LIB_EXPORT rc_t CC KNSManagerRelease ( const KNSManager *self )
168 {
169 if ( self != NULL ) {
170 switch ( KRefcountDrop ( &self->refcount, "KNSManager" ) ) {
171 case krefWhack: return KNSManagerWhack ( (KNSManager *)self );
172 case krefNegative:
173 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
174 }
175 }
176 else
177 return KDataBufferWhack(&kns_manager_user_agent);
178 return 0;
179 }
180
181 static rc_t CC KNSManagerMakeConfigImpl ( KNSManager **mgrp, KConfig *kfg );
182
183
KNSManagerMakeSingleton(KNSManager ** mgrp,KConfig * aKfg,bool local)184 static rc_t CC KNSManagerMakeSingleton (
185 KNSManager **mgrp, KConfig *aKfg, bool local )
186 {
187 rc_t rc = 0;
188
189 if ( mgrp == NULL ) {
190 rc = RC ( rcNS, rcMgr, rcAllocating, rcParam, rcNull );
191 } else {
192 KConfig *kfg = aKfg;
193 KNSManager *our_mgr = NULL;
194
195 *mgrp = NULL;
196
197 #if USE_SINGLETON
198 if ( !local ) {
199 /* grab single-shot singleton */
200 our_mgr = atomic_test_and_set_ptr ( &kns_singleton, NULL, NULL );
201 if ( our_mgr != NULL ) {
202 /* add a new reference and return */
203 rc = KNSManagerAddRef ( our_mgr );
204 if ( rc == 0 ) { *mgrp = our_mgr; }
205 return rc;
206 }
207 }
208 #endif
209
210 /* singleton was NULL. Make from scratch. */
211 if ( kfg == NULL ) { rc = KConfigMake ( &kfg, NULL ); }
212
213 if ( rc == 0 ) {
214 if ( !kns_manager_lock ) {
215 rc = KLockMake ( &kns_manager_lock );
216 if ( rc ) { return rc; }
217 }
218
219 if (kns_manager_user_agent.base == NULL) {
220 rc = KDataBufferMakeBytes ( &kns_manager_user_agent, 0 );
221 if ( rc ) { return rc; }
222 rc = KDataBufferPrintf ( &kns_manager_user_agent, "%s", "" );
223 if ( rc ) { return rc; }
224 }
225
226 if (kns_manager_guid.base == NULL) {
227 rc = KDataBufferMakeBytes ( &kns_manager_guid, 0 );
228 if ( rc ) { return rc; }
229 rc = KDataBufferPrintf ( &kns_manager_guid, "%s", "" );
230 if ( rc ) { return rc; }
231 }
232
233 rc = KNSManagerMakeConfigImpl ( &our_mgr, kfg );
234
235 if ( aKfg == NULL ) { KConfigRelease ( kfg ); }
236
237 if ( rc == 0 ) {
238 #if USE_SINGLETON
239 if ( !local ) {
240 /* try to set single-shot ( set once, never reset ) */
241 KNSManager *new_mgr = atomic_test_and_set_ptr (
242 &kns_singleton, our_mgr, NULL );
243 if ( new_mgr != NULL ) {
244 /* somebody else got here first - drop our version */
245 assert ( our_mgr != new_mgr );
246 KNSManagerRelease ( our_mgr );
247
248 /* use the new manager,
249 just add a reference and return */
250 rc = KNSManagerAddRef ( new_mgr );
251 if ( rc == 0 ) { *mgrp = new_mgr; }
252 return rc;
253 }
254 }
255 #endif
256 /* return parameter */
257 *mgrp = our_mgr;
258 }
259 }
260 }
261
262 return rc;
263 }
264
KNSManagerMake(KNSManager ** mgrp)265 LIB_EXPORT rc_t CC KNSManagerMake ( KNSManager **mgrp )
266 {
267 return KNSManagerMakeSingleton ( mgrp, NULL, false );
268 }
269
KNSManagerSetVerbose(KNSManager * self,bool verbosity)270 LIB_EXPORT void KNSManagerSetVerbose ( KNSManager *self, bool verbosity )
271 {
272 if ( self != NULL ) { self->verbose = verbosity; }
273 }
274
275
KNSManagerIsVerbose(const KNSManager * self)276 LIB_EXPORT bool KNSManagerIsVerbose ( const KNSManager *self )
277 {
278 return ( self != NULL ) ? self->verbose : false;
279 }
280
281
282 /* MakeConnection
283 * create a connection-oriented stream
284 *
285 * "conn" [ OUT ] - a stream for communication with the server
286 *
287 * "from" [ IN ] - client endpoint
288 *
289 * "to" [ IN ] - server endpoint
290 *
291 * both endpoints have to be of type epIP; creates a TCP connection
292 */
KNSManagerMakeConnection(const KNSManager * self,struct KSocket ** conn,struct KEndPoint const * from,struct KEndPoint const * to)293 LIB_EXPORT rc_t CC KNSManagerMakeConnection ( const KNSManager *self,
294 struct KSocket **conn, struct KEndPoint const *from,
295 struct KEndPoint const *to )
296 {
297 timeout_t tm;
298 timeout_t * ptm = NULL;
299
300 if ( self == NULL ) {
301 if ( conn == NULL ) {
302 return RC ( rcNS, rcStream, rcConstructing, rcParam, rcNull );
303 }
304
305 *conn = NULL;
306
307 return RC ( rcNS, rcStream, rcConstructing, rcSelf, rcNull );
308 }
309
310 if (self->conn_timeout >= 0) {
311 TimeoutInit ( &tm, self->conn_timeout );
312 ptm = &tm;
313 }
314
315 return KNSManagerMakeRetryTimedConnection ( self, conn, ptm,
316 self->conn_read_timeout, self->conn_write_timeout, from, to );
317 }
318 /* MakeTimedConnection
319 * create a connection-oriented stream
320 *
321 * "conn" [ OUT ] - a stream for communication with the server
322 *
323 * "retryTimeout" [ IN ] - if connection is refused, retry with 1ms intervals:
324 * when negative, retry infinitely, when 0, do not retry, positive gives maximum
325 * wait time in seconds
326 *
327 * "readMillis" [ IN ] and "writeMillis" - when negative, infinite timeout
328 * when 0, return immediately, positive gives maximum wait time in mS
329 * for reads and writes respectively.
330 *
331 * "from" [ IN ] - client endpoint
332 *
333 * "to" [ IN ] - server endpoint
334 *
335 * both endpoints have to be of type epIP; creates a TCP connection
336 */
KNSManagerMakeTimedConnection(struct KNSManager const * self,struct KSocket ** conn,int32_t readMillis,int32_t writeMillis,struct KEndPoint const * from,struct KEndPoint const * to)337 LIB_EXPORT rc_t CC KNSManagerMakeTimedConnection (
338 struct KNSManager const *self, struct KSocket **conn, int32_t readMillis,
339 int32_t writeMillis, struct KEndPoint const *from,
340 struct KEndPoint const *to )
341 {
342 timeout_t tm;
343 timeout_t * ptm = NULL;
344
345 if ( self == NULL ) {
346 if ( conn == NULL ) {
347 return RC ( rcNS, rcStream, rcConstructing, rcParam, rcNull );
348 }
349
350 *conn = NULL;
351
352 return RC ( rcNS, rcStream, rcConstructing, rcSelf, rcNull );
353 }
354
355 if (self->conn_timeout >=0 ) {
356 TimeoutInit ( &tm, self->conn_timeout );
357 ptm = &tm;
358 }
359
360 return KNSManagerMakeRetryTimedConnection (
361 self, conn, ptm, readMillis, writeMillis, from, to );
362 }
363
364 /* MakeRetryConnection
365 * create a connection-oriented stream
366 *
367 * "conn" [ OUT ] - a stream for communication with the server
368 *
369 * "retryTimeout" [ IN ] - if connection is refused, retry with 1ms intervals:
370 * when negative, retry infinitely, when 0, do not retry, positive gives maximum
371 * wait time in seconds
372 *
373 * "from" [ IN ] - client endpoint
374 *
375 * "to" [ IN ] - server endpoint
376 *
377 * both endpoints have to be of type epIP; creates a TCP connection
378 */
KNSManagerMakeRetryConnection(struct KNSManager const * self,struct KSocket ** conn,timeout_t * retryTimeout,struct KEndPoint const * from,struct KEndPoint const * to)379 LIB_EXPORT rc_t CC KNSManagerMakeRetryConnection (
380 struct KNSManager const *self, struct KSocket **conn,
381 timeout_t *retryTimeout, struct KEndPoint const *from,
382 struct KEndPoint const *to )
383 {
384 if ( self == NULL ) {
385 if ( conn == NULL ) {
386 return RC ( rcNS, rcStream, rcConstructing, rcParam, rcNull );
387 }
388
389 *conn = NULL;
390
391 return RC ( rcNS, rcStream, rcConstructing, rcSelf, rcNull );
392 }
393
394 return KNSManagerMakeRetryTimedConnection ( self, conn, retryTimeout,
395 self->conn_read_timeout, self->conn_write_timeout, from, to );
396 }
397
398 /* SetConnectionTimeouts
399 * sets default connect/read/write timeouts to supply to sockets
400 *
401 * "connectMillis", "readMillis", "writeMillis" [ IN ] - when negative,
402 * infinite timeout when 0, return immediately, positive gives maximum wait time
403 * in sec/mS for connects, reads and writes respectively.
404 */
KNSManagerSetConnectionTimeouts(KNSManager * self,int32_t connectMillis,int32_t readMillis,int32_t writeMillis)405 LIB_EXPORT rc_t CC KNSManagerSetConnectionTimeouts ( KNSManager *self,
406 int32_t connectMillis, int32_t readMillis, int32_t writeMillis )
407 {
408 if ( self == NULL ) {
409 return RC ( rcNS, rcMgr, rcUpdating, rcSelf, rcNull );
410 }
411
412 /* limit values */
413 if ( connectMillis > MAX_CONN_LIMIT ) {
414 connectMillis = MAX_CONN_LIMIT;
415 }
416
417 if ( readMillis > MAX_CONN_READ_LIMIT ) {
418 readMillis = MAX_CONN_READ_LIMIT;
419 }
420
421 if ( writeMillis > MAX_CONN_WRITE_LIMIT ) {
422 writeMillis = MAX_CONN_WRITE_LIMIT;
423 }
424
425 self->conn_timeout = connectMillis;
426 self->conn_read_timeout = readMillis;
427 self->conn_write_timeout = writeMillis;
428
429 return 0;
430 }
431
432
433 /* SetHTTPTimeouts
434 * sets default read/write timeouts to supply to HTTP connections
435 *
436 * "readMillis" [ IN ] and "writeMillis" - when negative, infinite timeout
437 * when 0, return immediately, positive gives maximum wait time in mS
438 * for reads and writes respectively.
439 */
KNSManagerSetHTTPTimeouts(KNSManager * self,int32_t readMillis,int32_t writeMillis)440 LIB_EXPORT rc_t CC KNSManagerSetHTTPTimeouts (
441 KNSManager *self, int32_t readMillis, int32_t writeMillis )
442 {
443 if ( self == NULL ) {
444 return RC ( rcNS, rcMgr, rcUpdating, rcSelf, rcNull );
445 }
446
447 /* limit values */
448 if ( readMillis < 0 || readMillis > MAX_HTTP_READ_LIMIT ) {
449 readMillis = MAX_HTTP_READ_LIMIT;
450 }
451
452 if ( writeMillis < 0 || writeMillis > MAX_HTTP_WRITE_LIMIT ) {
453 writeMillis = MAX_HTTP_WRITE_LIMIT;
454 }
455
456 self->http_read_timeout = readMillis;
457 self->http_write_timeout = writeMillis;
458
459 return 0;
460 }
461
462 /* GetHTTPProxyPath
463 * DEPRECATED
464 * returns path to HTTP proxy server ( if set ) or NULL.
465 * return status is 0 if the path is valid, non-zero otherwise
466 */
KNSManagerGetHTTPProxyPath(const KNSManager * self,const String ** proxy)467 LIB_EXPORT rc_t CC KNSManagerGetHTTPProxyPath (
468 const KNSManager *self, const String **proxy )
469 {
470 fprintf ( stderr,
471 "WARNING : KNSManagerGetHTTPProxyPath IS DEPRECATED AND SHOULD NOT BE "
472 "USED\n" );
473 return KNSProxiesGetHttpProxyPath ( self->proxies, proxy );
474 }
475
476
477 /* SetHTTPProxyPath
478 * sets a path to HTTP proxy server.
479 * a NULL path value removes all proxy settings.
480 *
481 * the VPath passed in must still be released using VPathRelease,
482 * because KNSManager will attach a new reference to it.
483 */
KNSManagerSetHTTPProxyPath(KNSManager * self,const char * fmt,...)484 LIB_EXPORT rc_t CC KNSManagerSetHTTPProxyPath (
485 KNSManager *self, const char *fmt, ... )
486 {
487 rc_t rc;
488
489 va_list args;
490 va_start ( args, fmt );
491 rc = KNSManagerVSetHTTPProxyPath ( self, fmt, args );
492 va_end ( args );
493
494 return rc;
495 }
496
KNSManagerVSetHTTPProxyPath(KNSManager * self,const char * fmt,va_list args)497 LIB_EXPORT rc_t CC KNSManagerVSetHTTPProxyPath (
498 KNSManager *self, const char *fmt, va_list args )
499 {
500 if ( self == NULL ) {
501 return RC ( rcNS, rcMgr, rcUpdating, rcSelf, rcNull );
502 }
503
504 return KNSProxiesVSetHTTPProxyPath ( self->proxies, fmt, args, true );
505 }
506
KNSManagerHttpProxyInit(KNSManager * self,const KConfig * kfg)507 static rc_t KNSManagerHttpProxyInit ( KNSManager *self, const KConfig *kfg )
508 {
509 assert ( self );
510 self->proxies = KNSManagerKNSProxiesMake ( self, kfg );
511 if ( self->proxies == NULL ) {
512 return RC ( rcNS, rcMgr, rcAllocating, rcMemory, rcExhausted );
513 }
514
515 return 0;
516 }
517
518 /* GetHTTPProxyEnabled
519 * returns true if a non-NULL proxy path exists and user wants to use it
520 * users indicate desire to use proxy through configuration
521 * or SetHTTPProxyEnabled
522 */
KNSManagerGetHTTPProxyEnabled(const KNSManager * self)523 LIB_EXPORT bool CC KNSManagerGetHTTPProxyEnabled ( const KNSManager *self )
524 {
525 if ( self != NULL ) {
526 return KNSProxiesGetHTTPProxyEnabled ( self->proxies );
527 }
528
529 return false;
530 }
531
532 /* SetHTTPProxyEnabled
533 * sets http-proxy enabled state to supplied value
534 * returns the prior value as a convenience
535 */
KNSManagerSetHTTPProxyEnabled(KNSManager * self,bool enabled)536 LIB_EXPORT bool CC KNSManagerSetHTTPProxyEnabled (
537 KNSManager *self, bool enabled )
538 {
539 bool prior = false;
540 if ( self != NULL ) {
541 prior = KNSProxiesSetHTTPProxyEnabled ( self->proxies, enabled );
542 }
543 return prior;
544 }
545
546
KNSManagerSetNCBI_VDB_NET(KNSManager * self,const KConfig * kfg)547 static void KNSManagerSetNCBI_VDB_NET ( KNSManager *self, const KConfig *kfg )
548 {
549 rc_t rc = 0;
550
551 const KConfigNode *node = NULL;
552
553 if ( self == NULL || kfg == NULL ) { return; }
554
555 rc = KConfigOpenNodeRead ( kfg, &node, "/libs/kns/NCBI_VDB_NET" );
556 if ( rc != 0 ) {
557 self->NCBI_VDB_NETkfgValueSet = self->NCBI_VDB_NETkfgValue = false;
558 return;
559 }
560
561 char buffer[1] = "";
562 size_t num_read = 0;
563 self->NCBI_VDB_NETkfgValueSet = true;
564 KConfigNodeRead ( node, 0, buffer, sizeof buffer, &num_read, 0 );
565 if ( num_read == 0 ) {
566 self->NCBI_VDB_NETkfgValue = false;
567 } else {
568 switch ( buffer[0] ) {
569 case '0':
570 case 'f': /* false */ self->NCBI_VDB_NETkfgValue = false; break;
571 default: self->NCBI_VDB_NETkfgValue = true; break;
572 }
573 }
574
575
576 KConfigNodeRelease ( node );
577 node = NULL;
578 }
579
580
581 /* VDB-DESIREMENTS:
582 1. to call *[s]/kfg/properties* to read configuration
583 2. to create a header file to keep constants (node names) */
KNSManagerLoadConnTimeout(KConfig * kfg)584 static int32_t KNSManagerLoadConnTimeout ( KConfig *kfg )
585 {
586 int64_t result = 0;
587
588 rc_t rc = KConfigReadI64 ( kfg, "/libs/kns/connect/timeout", &result );
589 if ( rc != 0 )
590 result = MAX_CONN_LIMIT;
591
592 return result;
593 }
KNSManagerLoadConnReadTimeout(KConfig * kfg)594 static int32_t KNSManagerLoadConnReadTimeout ( KConfig *kfg )
595 {
596 int64_t result = 0;
597
598 rc_t rc = KConfigReadI64 ( kfg, "/libs/kns/connect/timeout/read", &result );
599 if ( rc != 0 )
600 result = MAX_CONN_READ_LIMIT;
601
602 return result;
603 }
KNSManagerLoadConnWriteTimeout(KConfig * kfg)604 static int32_t KNSManagerLoadConnWriteTimeout ( KConfig *kfg )
605 {
606 int64_t result = 0;
607
608 rc_t rc
609 = KConfigReadI64 ( kfg, "/libs/kns/connect/timeout/write", &result );
610 if ( rc != 0 )
611 result = MAX_CONN_WRITE_LIMIT;
612
613 return result;
614 }
615
KNSManagerLoadHttpReadTimeout(KConfig * kfg)616 static int32_t KNSManagerLoadHttpReadTimeout ( KConfig *kfg )
617 {
618 int64_t result = 0; /* when negative - infinite timeout */
619
620 rc_t rc = KConfigReadI64 ( kfg, "/http/timeout/read", &result );
621 if ( rc != 0 )
622 result = MAX_HTTP_READ_LIMIT;
623
624 return result;
625 }
KNSManagerLoadHttpWriteTimeout(KConfig * kfg)626 static int32_t KNSManagerLoadHttpWriteTimeout ( KConfig *kfg )
627 {
628 int64_t result = 0; /* when negative - infinite timeout */
629
630 rc_t rc = KConfigReadI64 ( kfg, "/http/timeout/write", &result );
631 if ( rc != 0 )
632 result = MAX_HTTP_WRITE_LIMIT;
633
634 return result;
635 }
636
637 static
KNSManagerLoadTotalWaitForReliableURLs(const KConfig * kfg)638 int32_t KNSManagerLoadTotalWaitForReliableURLs(const KConfig *kfg)
639 {
640 rc_t rc = 0;
641
642 int64_t result = 0;
643
644 const char * str = getenv("NCBI_VDB_RELIABLE_WAIT");
645 if (str != NULL) {
646 char *end = NULL;
647 result = strtou64(str, &end, 0);
648 if (end[0] == 0)
649 return result;
650 }
651
652 rc = KConfigReadI64(kfg, "/http/reliable/wait", &result);
653 if (rc != 0
654 || result < 0) /* no support for infinite wait in HTTP retry loop in */
655 { /* StableHttpFile: it might lead to infinite loop of reading errors */
656 result = MAX_HTTP_TOTAL_READ_LIMIT;
657 }
658
659 return result;
660 }
661
KNSManagerLoadTotalConnectWaitForReliableURLs(const KConfig * kfg)662 static int32_t KNSManagerLoadTotalConnectWaitForReliableURLs(
663 const KConfig *kfg)
664 {
665 rc_t rc = 0;
666
667 int64_t result = 0;
668
669 const char * str = getenv("NCBI_VDB_RELIABLE_CONNECT_WAIT");
670 if (str != NULL) {
671 char *end = NULL;
672 result = strtou64(str, &end, 0);
673 if (end[0] == 0)
674 return result;
675 }
676
677 rc = KConfigReadI64(kfg, "/http/reliable/connect/wait", &result);
678 if (rc != 0)
679 result = MAX_HTTP_TOTAL_CONNECT_LIMIT;
680
681 return result;
682 }
683
KNSManagerLoadRetryFirstRead(const KConfig * kfg)684 static bool KNSManagerLoadRetryFirstRead(const KConfig *kfg) {
685 rc_t rc = 0;
686
687 bool result = 0;
688
689 const char * str = getenv("NCBI_VDB_RELIABLE_RETRY_FIRST_READ");
690 if (str != NULL && str[0] != '\0') {
691 switch (str[0]) {
692 case 'f':
693 return false;
694 case 't':
695 return true;
696 default:
697 break;
698 }
699 }
700
701 rc = KConfigReadBool(kfg, "/http/reliable/retryFirstRead", &result);
702 if (rc != 0)
703 result = false;
704
705 return result;
706 }
707
KNSManagerLoadRetryFile(const KConfig * kfg)708 static bool KNSManagerLoadRetryFile(const KConfig *kfg) {
709 rc_t rc = 0;
710
711 bool result = 0;
712
713 const char * str = getenv("NCBI_VDB_RELIABLE_RETRY_FILE");
714 if (str != NULL && str[0] != '\0') {
715 switch (str[0]) {
716 case 'f':
717 return false;
718 case 't':
719 return true;
720 default:
721 break;
722 }
723 }
724
725 rc = KConfigReadBool(kfg, "/http/reliable/retryFile", &result);
726 if (rc != 0)
727 result = true;
728
729 return result;
730 }
731
KNSManagerLoadMaxNumberOfRetriesOnFailureForReliableURLs(const KConfig * kfg)732 static uint8_t KNSManagerLoadMaxNumberOfRetriesOnFailureForReliableURLs
733 (const KConfig *kfg)
734 {
735 int64_t result = 0;
736 rc_t rc = KConfigReadI64(kfg, "/http/reliable/retries", &result);
737 if (rc != 0 || result < 0)
738 result = 10;
739
740 return result;
741 }
742
743 #if 0
744 static bool KNSManagerLoadLogTlsErrors(KConfig* kfg) {
745 const char * e = getenv("NCBI_VDB_TLS_LOG_ERR");
746 if (e != NULL)
747 if (e[0] == '\0')
748 return true;
749 else {
750 if (e[0] == '0' ||
751 e[0] == 'f') /* false */
752 {
753 return false;
754 }
755 else
756 return true;
757 }
758 else {
759 bool log = false;
760 rc_t rc = KConfigReadBool(kfg, "/tls/NCBI_VDB_TLS_LOG_ERR", &log);
761 if (rc != 0)
762 return false;
763 else
764 return log;
765 }
766 }
767
768 static int KNSManagerLoadEmulateTldReadErrors(KConfig* kfg) {
769 const char * e = getenv("NCBI_VDB_ERR_MBEDTLS_READ");
770 if (e != NULL)
771 return atoi(e);
772 else {
773 int64_t emult = 0;
774 rc_t rc = KConfigReadI64(kfg, "/tls/NCBI_VDB_ERR_MBEDTLS_READ", &emult);
775 if (rc != 0)
776 return 0;
777 else
778 return emult;
779 }
780 }
781 #endif
782
KNSManagerLoadResolveToCache(KConfig * kfg)783 static bool KNSManagerLoadResolveToCache ( KConfig *kfg )
784 {
785 /* VResolverCache resolve to user's cache vs. cwd/AD */
786 bool reslt = true;
787
788 /* TODO: call ncbi-vdb/interfaces/kfg/properties.h for exact key name */
789 rc_t rc
790 = KConfigReadBool ( kfg, "/tools/prefetch/download_to_cache", &reslt );
791 if ( rc == 0 ) { return reslt; }
792
793 return true;
794 }
795
KNSManagerLoadAcceptAwsCharges(KConfig * kfg)796 static bool KNSManagerLoadAcceptAwsCharges ( KConfig *kfg )
797 {
798 bool reslt = false;
799
800 /* TODO: call ncbi-vdb/interfaces/kfg/properties.h for exact key name */
801 rc_t rc = KConfigReadBool ( kfg, "/libs/cloud/accept_aws_charges", &reslt );
802 if ( rc == 0 ) { return reslt; }
803
804 return false;
805 }
806
KNSManagerLoadAcceptGcpCharges(KConfig * kfg)807 static bool KNSManagerLoadAcceptGcpCharges ( KConfig *kfg )
808 {
809 bool reslt = false;
810
811 /* TODO: call ncbi-vdb/interfaces/kfg/properties.h for exact key name */
812 rc_t rc = KConfigReadBool ( kfg, "/libs/cloud/accept_gcp_charges", &reslt );
813 if ( rc == 0 ) { return reslt; }
814
815 return false;
816 }
817
KNSManagerMakeConfigImpl(KNSManager ** mgrp,KConfig * kfg)818 static rc_t CC KNSManagerMakeConfigImpl ( KNSManager **mgrp, KConfig *kfg )
819 {
820 rc_t rc;
821
822 if ( mgrp == NULL || kfg == NULL ) {
823 rc = RC ( rcNS, rcMgr, rcAllocating, rcParam, rcNull );
824 } else {
825 KNSManager *mgr = calloc ( 1, sizeof *mgr );
826 if ( mgr == NULL ) {
827 rc = RC ( rcNS, rcMgr, rcAllocating, rcMemory, rcExhausted );
828 } else {
829 KRefcountInit ( &mgr->refcount, 1, "KNSManager", "init", "kns" );
830
831 mgr->conn_timeout = KNSManagerLoadConnTimeout ( kfg );
832 mgr->conn_read_timeout = KNSManagerLoadConnReadTimeout ( kfg );
833 mgr->conn_write_timeout = KNSManagerLoadConnWriteTimeout ( kfg );
834 mgr->http_read_timeout = KNSManagerLoadHttpReadTimeout ( kfg );
835 mgr->http_write_timeout = KNSManagerLoadHttpWriteTimeout ( kfg );
836
837 mgr->maxTotalWaitForReliableURLs_ms =
838 KNSManagerLoadTotalWaitForReliableURLs ( kfg );
839
840 mgr->maxTotalConnectWaitForReliableURLs_ms =
841 KNSManagerLoadTotalConnectWaitForReliableURLs ( kfg );
842
843 mgr->maxNumberOfRetriesOnFailureForReliableURLs =
844 KNSManagerLoadMaxNumberOfRetriesOnFailureForReliableURLs( kfg );
845
846 mgr->retryFirstRead = KNSManagerLoadRetryFirstRead(kfg);
847 mgr->retryFile = KNSManagerLoadRetryFile ( kfg );
848 mgr->max_http_read_timeout = 60 * 1000; /* 1 minute */
849 /* mgr->logTlsErrors = KNSManagerLoadLogTlsErrors(kfg);
850 mgr->emulateTlsReadErrors
851 = KNSManagerLoadEmulateTldReadErrors(kfg); */
852
853 mgr->resolveToCache = KNSManagerLoadResolveToCache ( kfg );
854
855 mgr->accept_aws_charges = KNSManagerLoadAcceptAwsCharges ( kfg );
856 mgr->accept_gcp_charges = KNSManagerLoadAcceptGcpCharges ( kfg );
857
858 if ( strlen ( kns_manager_guid.base ) == 0 ) {
859 rc = KDataBufferResize ( &kns_manager_guid, 37 );
860 size_t written = 0;
861 KConfig_Get_GUID ( kfg, kns_manager_guid.base,
862 KDataBufferBytes ( &kns_manager_guid ), &written );
863 assert ( written <= 37 );
864 }
865
866 rc = KNSManagerInit (); /* platform specific init in sysmgr.c ( in
867 unix|win etc. subdir ) */
868 if ( rc == 0 ) {
869 /* the manager is not a proper singleton */
870 if ( strlen ( kns_manager_user_agent.base ) == 0 ) {
871 ver_t version = RELEASE_VERS;
872 KNSManagerSetUserAgent (
873 mgr, PKGNAMESTR " ncbi-vdb.%V", version );
874 }
875
876 rc = HttpRetrySpecsInit ( &mgr->retry_specs, kfg );
877 if ( rc == 0 ) {
878 rc = KTLSGlobalsInit ( &mgr->tlsg, kfg );
879
880 if ( rc == 0 ) {
881 rc = KNSManagerHttpProxyInit ( mgr, kfg );
882 }
883
884 if ( rc == 0 ) {
885 KNSManagerSetNCBI_VDB_NET ( mgr, kfg );
886
887 *mgrp = mgr;
888
889 /*
890 printf("KNSManager.conn_timeout(%d) = %d\n",
891 MAX_CONN_LIMIT, mgr->conn_timeout);
892 printf("KNSManager.conn_read_timeout(%d) = %d\n",
893 MAX_CONN_READ_LIMIT, mgr->conn_read_timeout);
894 printf("KNSManager.conn_write_timeout(%d) = %d\n",
895 MAX_CONN_WRITE_LIMIT, mgr->conn_write_timeout);
896 printf("KNSManager.http_read_timeout(%d) = %d\n",
897 MAX_HTTP_READ_LIMIT, mgr->http_read_timeout);
898 printf("KNSManager.http_write_timeout(%d) = %d\n",
899 MAX_HTTP_WRITE_LIMIT, mgr->http_write_timeout);
900 */
901
902 return 0;
903 }
904 }
905 }
906
907 free ( mgr );
908 }
909
910 *mgrp = NULL;
911 }
912
913 return rc;
914 }
915
KNSManagerMakeWithConfig(KNSManager ** mgrp,KConfig * kfg)916 LIB_EXPORT rc_t CC KNSManagerMakeWithConfig ( KNSManager **mgrp, KConfig *kfg )
917 {
918 return KNSManagerMakeSingleton ( mgrp, kfg, false );
919 }
920
KNSManagerMakeLocal(KNSManager ** mgrp,KConfig * kfg)921 LIB_EXPORT rc_t CC KNSManagerMakeLocal ( KNSManager **mgrp, KConfig *kfg )
922 {
923 return KNSManagerMakeSingleton ( mgrp, kfg, true );
924 }
925
KNSManagerMakeConfig(KNSManager ** mgrp,KConfig * kfg)926 LIB_EXPORT rc_t CC KNSManagerMakeConfig ( KNSManager **mgrp, KConfig *kfg )
927 {
928 return KNSManagerMakeLocal ( mgrp, kfg );
929 }
930
KNSManagerSetUserAgent(KNSManager * self,const char * fmt,...)931 LIB_EXPORT rc_t CC KNSManagerSetUserAgent (
932 KNSManager *self, const char *fmt, ... )
933 {
934 /* 6/18/14 - don't check "self", since the current implementation
935 is actually static. Later implementations will not be...
936 Cast silences warning
937 */
938 (void)( self );
939
940 rc_t rc = 0;
941 if ( fmt == NULL ) {
942 rc = RC ( rcNS, rcMgr, rcUpdating, rcParam, rcNull );
943 return rc;
944 }
945
946 KDataBufferResize ( &kns_manager_user_agent, 0 );
947 va_list args;
948 va_start ( args, fmt );
949 rc = KDataBufferVPrintf ( &kns_manager_user_agent, fmt, args );
950 va_end ( args );
951
952 return rc;
953 }
954
KNSManagerGetUserAgent(const char ** user_agent)955 LIB_EXPORT rc_t CC KNSManagerGetUserAgent ( const char **user_agent )
956 {
957 rc_t rc = 0;
958 if ( user_agent == NULL ) {
959 rc = RC ( rcNS, rcMgr, rcAccessing, rcParam, rcNull );
960 return rc;
961 }
962
963 char cloudtrunc[64];
964 const char *cloudid = getenv ( ENV_MAGIC_CE_TOKEN );
965 if ( cloudid && strlen ( cloudid ) > 8 ) {
966 /* AWS access keys should always begin with AKIA,
967 * suffixes seems non-random */
968 strncpy ( cloudtrunc, cloudid + 4, sizeof cloudtrunc );
969 cloudtrunc[3] = '\0';
970 assert ( strlen ( cloudtrunc ) < ( sizeof cloudtrunc - 1 ) );
971 } else {
972 strcpy ( cloudtrunc, "noc" );
973 }
974
975 const char *sessid = getenv ( ENV_VAR_SESSION_ID );
976 if ( sessid == NULL ) { sessid = "nos"; }
977
978 const char *libc_version = "";
979 #if LINUX
980 libc_version = gnu_get_libc_version ();
981 #endif
982
983 /* Sometimes called before KNSManagerMake */
984 const char *guid = "nog";
985
986 if ( ( KDataBufferBytes ( &kns_manager_guid ) == 0 )
987 || ( strlen ( kns_manager_guid.base ) == 0 ) ) {
988 KConfig *kfg = NULL;
989 KConfigMake ( &kfg, NULL );
990 size_t written = 0;
991
992 rc = KDataBufferResize ( &kns_manager_guid, 37 );
993 if ( rc ) {
994 /* Some tests whack guid */
995 rc = KDataBufferMakeBytes ( &kns_manager_guid, 37 );
996 if ( rc ) { return rc; }
997 }
998
999 KConfig_Get_GUID ( kfg, kns_manager_guid.base,
1000 KDataBufferBytes ( &kns_manager_guid ), &written );
1001 assert ( written <= 37 );
1002
1003 if ( kfg ) KConfigRelease ( kfg );
1004 }
1005
1006 if ( strlen ( kns_manager_guid.base ) ) guid = kns_manager_guid.base;
1007
1008 KDataBuffer phid;
1009 KDataBufferMakeBytes ( &phid, 0 );
1010 rc = KDataBufferPrintf (
1011 &phid, "%.3s%.4s%.3s,libc=%s", cloudtrunc, guid, sessid, libc_version );
1012 if ( rc ) { return rc; }
1013
1014 if ( kns_manager_lock ) {
1015 rc_t rc = KLockAcquire ( kns_manager_lock );
1016 if ( rc ) { return rc; }
1017 }
1018
1019 /* Some tests call before these are initialized */
1020 if ( KDataBufferBytes ( &kns_manager_user_agent ) == 0 )
1021 KDataBufferPrintf ( &kns_manager_user_agent, "%s", "" );
1022
1023 if ( kns_manager_lock ) { KLockUnlock ( kns_manager_lock ); }
1024
1025 KDataBuffer sessids;
1026 KDataBufferMakeBytes ( &sessids, 0 );
1027
1028 /* If any are populated, emit all */
1029 if ( strlen ( kns_manager_clientip )
1030 || strlen ( kns_manager_sessionid )
1031 || strlen ( kns_manager_pagehitid ) ) {
1032 rc = KDataBufferPrintf ( &sessids, "cip=%s,sid=%s,pagehit=%s",
1033 kns_manager_clientip, kns_manager_sessionid,
1034 kns_manager_pagehitid );
1035 }
1036
1037 if ( rc ) { return rc; }
1038
1039 if ( sessids.base && strlen ( sessids.base ) ) {
1040 const String *b64;
1041 encodeBase64 ( &b64, sessids.base, strlen ( sessids.base ) );
1042 rc = string_printf ( kns_manager_user_agent_append, sizeof kns_manager_user_agent_append, NULL,
1043 "%s%s (phid=%s,%s)", kns_manager_user_agent.base,
1044 kns_manager_ua_suffix, phid.base, b64->addr );
1045 StringWhack ( b64 );
1046 } else {
1047 rc = string_printf ( kns_manager_user_agent_append, sizeof kns_manager_user_agent_append, NULL,
1048 "%s%s (phid=%s)", kns_manager_user_agent.base, kns_manager_ua_suffix, phid.base );
1049 }
1050
1051 KDataBufferWhack ( &phid );
1052 KDataBufferWhack ( &sessids );
1053
1054 ( *user_agent ) = kns_manager_user_agent_append;
1055 return rc;
1056 }
1057
1058
1059 /******************************************************************************/
1060
1061 #define NCBI_VDB_NET \
1062 1 /* VDB-3399 : temporarily enable for internal testing \
1063 */
1064
KNSManagerSetLogNcbiVdbNetError(KNSManager * self,bool set)1065 void KNSManagerSetLogNcbiVdbNetError ( KNSManager *self, bool set )
1066 {
1067 if ( self ) { self->NCBI_VDB_NETnoLogError = !set; }
1068 }
1069
KNSManagerLogNcbiVdbNetError(const KNSManager * self)1070 bool KNSManagerLogNcbiVdbNetError ( const KNSManager *self )
1071 {
1072 if ( self == NULL ) {
1073 #ifdef NCBI_VDB_NET
1074 return true;
1075 #else
1076 return false;
1077 #endif
1078 }
1079 if ( !self->logTlsErrors ) { return false; }
1080
1081 if ( self->NCBI_VDB_NETnoLogError ) { return false; }
1082 const char *e = getenv ( "NCBI_VDB_NET" );
1083 if ( e != NULL ) {
1084 if ( e[0] == '0' || e[0] == 'f' ) /* false */
1085 {
1086 return false;
1087 }
1088
1089 return true;
1090 }
1091 if ( self->NCBI_VDB_NETkfgValueSet ) { return self->NCBI_VDB_NETkfgValue; }
1092
1093
1094 #ifdef NCBI_VDB_NET
1095 return true;
1096 #else
1097 return false;
1098 #endif
1099 }
1100
KNSManagerSetAdCaching(struct KNSManager * self,bool enabled)1101 LIB_EXPORT rc_t CC KNSManagerSetAdCaching (
1102 struct KNSManager *self, bool enabled )
1103 {
1104 if ( self != NULL )
1105 self->enabledResolveToAd = enabled;
1106 return 0;
1107 }
1108
KNSManagerGetAdCaching(const KNSManager * self,bool * enabled)1109 LIB_EXPORT rc_t CC KNSManagerGetAdCaching(
1110 const KNSManager* self, bool * enabled)
1111 {
1112 assert(self && enabled);
1113 *enabled = self->enabledResolveToAd;
1114 return 0;
1115 }
1116
KNSManagerGetResolveToCache(const KNSManager * self,bool * resolveToCache)1117 LIB_EXPORT rc_t CC KNSManagerGetResolveToCache(
1118 const KNSManager* self, bool * resolveToCache)
1119 {
1120 assert(self && resolveToCache);
1121 *resolveToCache = self->resolveToCache;
1122 return 0;
1123 }
1124
1125 /*
1126 LIB_EXPORT rc_t CC KNSManagerSetClientIPv4 (
1127 KNSManager *self, uint32_t client_ipv4_addr)
1128 {
1129 if ( self == NULL )
1130 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1131 }
1132
1133 char str[INET6_ADDRSTRLEN];
1134 struct in_addr ina;
1135
1136 ina.s_addr=client_ipv4_addr;
1137
1138 if (inet_ntop(AF_INET, &ina, str, sizeof str)==NULL)
1139 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1140
1141 if ( kns_manager_lock ) {
1142 rc_t rc = KLockAcquire ( kns_manager_lock );
1143 if ( rc ) { return rc; }
1144 }
1145 string_copy ( kns_manager_clientip, sizeof kns_manager_clientip, ipv4,
1146 strlen ( ipv4 ) );
1147
1148 if ( kns_manager_lock ) { KLockUnlock ( kns_manager_lock ); }
1149 return 0;
1150 }
1151
1152 LIB_EXPORT rc_t CC KNSManagerSetClientIPv6 (
1153 KNSManager *self, uint16_t client_ipv6_addr[])
1154 {
1155 if ( self == NULL )
1156 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1157 }
1158
1159 char str[INET6_ADDSTRLEN];
1160 struct in6_addr ina;
1161
1162 memcpy(&ina.s6_addr,client_ipv6_addr, 16);
1163 ina.s_addr=client_ipv6_addr;
1164
1165 if (inet_ntop(AF_INET6, &ina, str, sizeof str)==NULL)
1166 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1167
1168 if ( kns_manager_lock ) {
1169 rc_t rc = KLockAcquire ( kns_manager_lock );
1170 if ( rc ) { return rc; }
1171 }
1172 string_copy ( kns_manager_clientip, sizeof kns_manager_clientip, ipv4,
1173 strlen ( ipv4 ) );
1174
1175 if ( kns_manager_lock ) { KLockUnlock ( kns_manager_lock ); }
1176 return 0;
1177 }
1178 */
KNSManagerSetUserAgentSuffix(const char * suffix)1179 LIB_EXPORT rc_t CC KNSManagerSetUserAgentSuffix ( const char *suffix )
1180 {
1181 if ( suffix == NULL ) {
1182 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1183 }
1184 size_t len = strlen( suffix );
1185 if ( len >= KNSMANAGER_STRING_MAX )
1186 {
1187 return RC ( rcNS, rcMgr, rcAttaching, rcParam, rcTooLong );
1188 }
1189
1190 string_copy ( kns_manager_ua_suffix, sizeof kns_manager_ua_suffix, suffix, len );
1191 return 0;
1192 }
1193
KNSManagerGetUserAgentSuffix(const char ** suffix)1194 LIB_EXPORT rc_t CC KNSManagerGetUserAgentSuffix ( const char ** suffix )
1195 {
1196 if ( suffix == NULL ) {
1197 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1198 }
1199 *suffix = kns_manager_ua_suffix;
1200 return 0;
1201 }
1202
KNSManagerSetClientIP(KNSManager * self,const char * clientip)1203 LIB_EXPORT rc_t CC KNSManagerSetClientIP (
1204 KNSManager *self, const char *clientip )
1205 {
1206 if ( self == NULL || clientip == NULL ) {
1207 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1208 }
1209 size_t len = strlen( clientip );
1210 if ( len >= KNSMANAGER_STRING_MAX )
1211 {
1212 return RC ( rcNS, rcMgr, rcAttaching, rcParam, rcTooLong );
1213 }
1214
1215 string_copy ( kns_manager_clientip, sizeof kns_manager_clientip, clientip, len );
1216 return 0;
1217 }
1218
KNSManagerSetSessionID(KNSManager * self,const char * sessionid)1219 LIB_EXPORT rc_t CC KNSManagerSetSessionID (
1220 KNSManager *self, const char *sessionid )
1221 {
1222 if ( self == NULL || sessionid == NULL ) {
1223 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1224 }
1225 size_t len = strlen( sessionid );
1226 if ( len >= KNSMANAGER_STRING_MAX )
1227 {
1228 return RC ( rcNS, rcMgr, rcAttaching, rcParam, rcTooLong );
1229 }
1230
1231 string_copy ( kns_manager_sessionid, sizeof kns_manager_sessionid, sessionid, len );
1232 return 0;
1233 }
1234
1235
KNSManagerSetPageHitID(KNSManager * self,const char * pagehitid)1236 LIB_EXPORT rc_t CC KNSManagerSetPageHitID (
1237 KNSManager *self, const char *pagehitid )
1238 {
1239 if ( self == NULL || pagehitid == NULL ) {
1240 return RC ( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
1241 }
1242 size_t len = strlen( pagehitid );
1243 if ( len >= KNSMANAGER_STRING_MAX )
1244 {
1245 return RC ( rcNS, rcMgr, rcAttaching, rcParam, rcTooLong );
1246 }
1247
1248 string_copy ( kns_manager_pagehitid, sizeof kns_manager_pagehitid, pagehitid, len );
1249 return 0;
1250 }
1251
1252
1253 LIB_EXPORT
KNSManagerSetQuitting(KNSManager * self,quitting_t aQuitting)1254 rc_t CC KNSManagerSetQuitting(KNSManager *self, quitting_t aQuitting)
1255 {
1256 quitting = aQuitting;
1257 return 0;
1258 }
1259
1260 LIB_EXPORT
KNSManagerGetQuitting(const KNSManager * self)1261 quitting_t CC KNSManagerGetQuitting(const KNSManager *self)
1262 {
1263 return quitting;
1264 }
1265
1266 /******************************************************************************/
1267 /**************** API to manage HTTP File read retry behavior *****************/
1268 /******************************************************************************/
1269
1270 /* SetRetryFailedReads
1271 * manages retry layer on HttpFileRead
1272 *
1273 * "retry" [ IN ] - true : turn on retry layer,
1274 * false: don't create retry layer.
1275 */
KNSManagerSetRetryFailedReads(KNSManager * self,bool retry)1276 KNS_EXTERN rc_t CC KNSManagerSetRetryFailedReads(KNSManager *self,
1277 bool retry)
1278 {
1279 if (self == NULL)
1280 return RC(rcNS, rcMgr, rcUpdating, rcSelf, rcNull);
1281 else {
1282 self->retryFile = retry;
1283 return 0;
1284 }
1285 }
1286
1287 /* GetRetryFailedReads
1288 * returns whether or not retry layer on HttpFileRead is turned on
1289 */
KNSManagerGetRetryFailedReads(const KNSManager * self,bool * retry)1290 LIB_EXPORT rc_t CC KNSManagerGetRetryFailedReads(const KNSManager *self,
1291 bool *retry)
1292 {
1293 if (self == NULL)
1294 return RC(rcNS, rcMgr, rcAccessing, rcSelf, rcNull);
1295 else if (retry == NULL)
1296 return RC(rcNS, rcMgr, rcAccessing, rcParam, rcNull);
1297 else {
1298 *retry = self->retryFile;
1299 return 0;
1300 }
1301 }
1302
1303 /* SetMaxConnectRetryTime
1304 * sets maximum time when opening HttpFile
1305 *
1306 * "millis" - when negative, infinite timeout
1307 */
KNSManagerSetMaxConnectRetryTime(KNSManager * self,int32_t millis)1308 LIB_EXPORT rc_t CC KNSManagerSetMaxConnectRetryTime(KNSManager *self,
1309 int32_t millis)
1310 {
1311 if (self == NULL)
1312 return RC(rcNS, rcMgr, rcUpdating, rcSelf, rcNull);
1313 else {
1314 if (millis < 0)
1315 self->maxTotalConnectWaitForReliableURLs_ms = ~0;
1316 else
1317 self->maxTotalConnectWaitForReliableURLs_ms = millis;
1318
1319 return 0;
1320 }
1321 }
1322
1323 /* SetMaxReadRetryTime
1324 * sets maximum time in HttpFileRead retry loop
1325 *
1326 * "millis" - when negative, infinite timeout
1327 */
KNSManagerSetMaxReadRetryTime(KNSManager * self,int32_t millis)1328 LIB_EXPORT rc_t CC KNSManagerSetMaxReadRetryTime(KNSManager *self,
1329 int32_t millis)
1330 {
1331 if (self == NULL)
1332 return RC(rcNS, rcMgr, rcUpdating, rcSelf, rcNull);
1333 else {
1334 if (millis < 0)
1335 self->maxTotalWaitForReliableURLs_ms = ~0;
1336 else
1337 self->maxTotalWaitForReliableURLs_ms = millis;
1338
1339 return 0;
1340 }
1341 }
1342
1343 /* GetMaxReadRetryTime
1344 * returns maximum time in HttpFileRead retry loop
1345 */
KNSManagerGetMaxReadRetryTime(const KNSManager * self,int32_t * millis)1346 LIB_EXPORT rc_t CC KNSManagerGetMaxReadRetryTime(const KNSManager *self,
1347 int32_t *millis)
1348 {
1349 if (self == NULL)
1350 return RC(rcNS, rcMgr, rcAccessing, rcSelf, rcNull);
1351 else if (millis == NULL)
1352 return RC(rcNS, rcMgr, rcAccessing, rcParam, rcNull);
1353 else {
1354 if (self->maxTotalWaitForReliableURLs_ms == ~0)
1355 *millis = -1;
1356 else
1357 *millis = self->maxTotalWaitForReliableURLs_ms;
1358
1359 return 0;
1360 }
1361 }
1362
1363
1364 /* GetMaxConnectRetryTime
1365 * returns maximum time when opening HttpFile
1366 */
KNSManagerGetMaxConnectRetryTime(const KNSManager * self,int32_t * millis)1367 LIB_EXPORT rc_t CC KNSManagerGetMaxConnectRetryTime(const KNSManager *self,
1368 int32_t *millis)
1369 {
1370 if (self == NULL)
1371 return RC(rcNS, rcMgr, rcAccessing, rcSelf, rcNull);
1372 else if (millis == NULL)
1373 return RC(rcNS, rcMgr, rcAccessing, rcParam, rcNull);
1374 else {
1375 if (self->maxTotalConnectWaitForReliableURLs_ms == ~0)
1376 *millis = -1;
1377 else
1378 *millis = self->maxTotalConnectWaitForReliableURLs_ms;
1379
1380 return 0;
1381 }
1382 }
1383
1384
1385 /* SetRetryFirstReads
1386 * manages retry on the first HttpFileRead
1387 */
KNSManagerSetRetryFirstReads(KNSManager * self,bool retry)1388 LIB_EXPORT rc_t CC KNSManagerSetRetryFirstReads(KNSManager *self,
1389 bool retry)
1390 {
1391 if (self == NULL)
1392 return RC(rcNS, rcMgr, rcUpdating, rcSelf, rcNull);
1393 else {
1394 self->retryFirstRead = retry;
1395 return 0;
1396 }
1397 }
1398
1399 /* GetRetryFirstReads
1400 * returns whether or not retry on the first HttpFileRead is turned on
1401 */
KNSManagerGetRetryFirstReads(const KNSManager * self,bool * retry)1402 LIB_EXPORT rc_t CC KNSManagerGetRetryFirstReads(const KNSManager *self,
1403 bool *retry)
1404 {
1405 if (self == NULL)
1406 return RC(rcNS, rcMgr, rcAccessing, rcSelf, rcNull);
1407 else if (retry == NULL)
1408 return RC(rcNS, rcMgr, rcAccessing, rcParam, rcNull);
1409 else {
1410 *retry = self->retryFirstRead;
1411 return 0;
1412 }
1413 }
1414
1415 /******************************************************************************/
1416