1 #ifndef WINDOWS
2 //#define DEPURAR 1
3 #endif
4 /*==============================================================================
5 *
6 * PUBLIC DOMAIN NOTICE
7 * National Center for Biotechnology Information
8 *
9 * This software/database is a "United States Government Work" under the
10 * terms of the United States Copyright Act. It was written as part of
11 * the author's official duties as a United States Government employee and
12 * thus cannot be copyrighted. This software/database is freely available
13 * to the public for use. The National Library of Medicine and the U.S.
14 * Government have not placed any restriction on its use or reproduction.
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * Please cite the author in any work or product based on this material.
25 *
26 * ==============================================================================
27 *
28 */
29
30 #include "diagnose/diagnose.h" /* KDiagnoseAdvanced */
31 #include "diagnose.h" /* endpoint_to_string */
32
33 #include <kfg/config.h> /* KConfigReadString */
34
35 #include <kfs/directory.h> /* KDirectoryRelease */
36 #include <kfs/file.h> /* KFile */
37
38 #include <klib/data-buffer.h> /* KDataBuffer */
39 #include <klib/out.h> /* KOutMsg */
40 #include <klib/printf.h> /* string_vprintf */
41 #include <klib/rc.h>
42 #include <klib/text.h> /* String */
43 #include <klib/vector.h> /* Vector */
44
45 #include <kns/ascp.h> /* aspera_get */
46 #include <kns/endpoint.h> /* KNSManagerInitDNSEndpoint */
47 #include <kns/http.h> /* KHttpRequest */
48 #include <kns/manager.h> /* KNSManager */
49 #include <kns/kns-mgr-priv.h> /* KNSManagerMakeReliableHttpFile */
50 #include <kns/stream.h> /* KStream */
51
52 #include <kproc/cond.h> /* KConditionRelease */
53 #include <kproc/lock.h> /* KLockRelease */
54
55 #include <vfs/manager.h> /* VFSManagerOpenDirectoryRead */
56 #include <vfs/path.h> /* VFSManagerMakePath */
57 #include <vfs/resolver.h> /* VResolverRelease */
58
59 #include <strtol.h> /* strtoi64 */
60
61 #include <ctype.h> /* isprint */
62 #include <limits.h> /* PATH_MAX */
63
64 #ifndef PATH_MAX
65 #define PATH_MAX 4096
66 #endif
67
68 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); \
69 if (rc2 != 0 && rc == 0) { rc = rc2; } obj = NULL; } while (false)
70
OutMsg(int level,unsigned type,const char * fmt,va_list args)71 static rc_t CC OutMsg ( int level, unsigned type,
72 const char * fmt, va_list args )
73 {
74 return KOutVMsg ( fmt, args );
75 }
76
77 static rc_t ( CC * LOGGER )
78 ( int level, unsigned type, const char * fmt, va_list args );
79
KDiagnoseLogHandlerSet(KDiagnose * self,rc_t (CC * logger)(int level,unsigned type,const char * fmt,va_list args))80 LIB_EXPORT rc_t CC KDiagnoseLogHandlerSet ( KDiagnose * self,
81 rc_t ( CC * logger ) ( int level, unsigned type,
82 const char * fmt, va_list args )
83 )
84 {
85 LOGGER = logger;
86 return 0;
87 }
88
89 LIB_EXPORT
KDiagnoseLogHandlerSetKOutMsg(KDiagnose * self)90 rc_t CC KDiagnoseLogHandlerSetKOutMsg ( KDiagnose * self )
91 {
92 return KDiagnoseLogHandlerSet ( self, OutMsg );
93 }
94
LogOut(int level,unsigned type,const char * fmt,...)95 static rc_t LogOut ( int level, unsigned type, const char * fmt, ... )
96 {
97 rc_t rc = 0;
98
99 va_list args;
100 va_start ( args, fmt );
101
102 if ( LOGGER != NULL )
103 rc = LOGGER ( level, type, fmt, args );
104
105 va_end ( args );
106
107 return rc;
108 }
109
110 typedef struct { const char * begin; char * end; } Block;
111
112 typedef struct {
113 KDataBuffer response; /* cgi response */
114 uint32_t code; /* cgi response status code */
115 char * location; /* cgi response redirect location */
116 KDataBuffer redirect; /* redirect response */
117
118 Block p;
119 Block mailto;
120
121 String ip;
122 String date;
123 char * server;
124 } Abuse;
125
AbuseFini(Abuse * self)126 static rc_t AbuseFini ( Abuse * self ) {
127 rc_t rc = 0, r2 = 0;
128
129 assert ( self );
130
131 free ( self -> location );
132 free ( self -> server );
133
134 rc = KDataBufferWhack ( & self -> response );
135
136 r2 = KDataBufferWhack ( & self -> redirect );
137 if ( r2 != 0 && rc == 0 )
138 rc = r2;
139
140 memset ( self, 0, sizeof * self );
141
142 return rc;
143 }
144
AbuseInit(Abuse * self)145 static void AbuseInit ( Abuse * self ) {
146 assert ( self );
147
148 memset ( self, 0, sizeof * self );
149
150 self -> response . elem_bits = self -> redirect . elem_bits = 8;
151 }
152
AbuseSetStatus(Abuse * self,uint32_t code)153 static void AbuseSetStatus ( Abuse * self, uint32_t code ) {
154 assert ( self );
155
156 self -> code = code;
157 }
158
159 static
AbuseSetLocation(Abuse * self,const char * str,size_t size)160 rc_t AbuseSetLocation ( Abuse * self, const char * str, size_t size )
161 {
162 assert ( self );
163
164 self -> location = string_dup ( str, size );
165 return self -> location != NULL
166 ? 0 : RC ( rcRuntime, rcString, rcCopying, rcMemory, rcExhausted );
167 }
168
169 static
AbuseSetCgi(Abuse * self,const String * cgi)170 rc_t AbuseSetCgi ( Abuse * self, const String * cgi ) {
171 const char * s = NULL, * e = NULL;
172
173 size_t i = 0;
174
175 assert ( self && cgi );
176
177 s = cgi -> addr;
178 if ( s == NULL )
179 return 0;
180
181 for ( i = 0; i < cgi -> size ; ++ i ) {
182 switch ( * s ) {
183 case '\0':
184 return 0;
185
186 case ':' :
187 if ( * ++ s != '/' )
188 return 0;
189 if ( * ++ s != '/' )
190 return 0;
191 if ( i >= cgi -> size )
192 return 0;
193
194 e = string_chr ( ++ s, cgi -> size - i, '/' );
195 if ( e == NULL )
196 return 0;
197
198 self -> server = string_dup ( s, e - s );
199 if ( self -> server == NULL )
200 return RC ( rcRuntime, rcString, rcCopying, rcMemory, rcExhausted );
201 else
202 return 0;
203
204 default:
205 ++ s;
206 }
207 }
208
209 return 0;
210 }
211
AbuseAdd(Abuse * self,const char * txt,int sz)212 static rc_t AbuseAdd ( Abuse * self, const char * txt, int sz ) {
213 rc_t rc = 0;
214
215 assert ( self );
216
217 if ( rc == 0 )
218 return KDataBufferPrintf ( & self -> response, "%s", txt );
219 else
220 return KDataBufferPrintf ( & self -> response, "%.*s", sz, txt );
221 }
222
find(const char * haystack,uint64_t n,const String * needle)223 static char * find ( const char * haystack, uint64_t n,
224 const String * needle )
225 {
226 uint64_t i = 0;
227
228 assert ( needle && needle -> addr );
229
230 for ( i = 0; ; ++ i ) {
231 char * c = NULL;
232 uint64_t size = n - i;
233
234 assert ( n >= i );
235
236 c = string_chr ( haystack + i, size, * needle -> addr );
237 if ( c == NULL )
238 return NULL;
239
240 i = c - haystack;
241 if ( i < needle -> size && i > 0)
242 return NULL;
243
244 if ( string_cmp ( c, needle -> size, needle -> addr, needle -> size,
245 ( uint32_t ) needle -> size) == 0)
246 {
247 return c;
248 }
249 }
250 }
251
252 typedef struct {
253 bool incompleteGapKfg;
254 bool firewall;
255 bool blocked;
256
257 Abuse abuse;
258 } Report;
259
260 struct KDiagnose {
261 atomic32_t refcount;
262
263 KConfig * kfg;
264 KNSManager * kmgr;
265 VFSManager * vmgr;
266 rc_t (CC * quitting) (void);
267
268 int verbosity;
269
270 Vector tests;
271 Vector errors;
272
273 KDiagnoseTestDesc * desc;
274
275 enum EState {
276 eRunning,
277 ePaused,
278 eCanceled,
279 } state;
280 KLock * lock;
281 KCondition * condition;
282
283 Report report;
284 };
285
286 struct KDiagnoseTest {
287 struct KDiagnoseTest * parent;
288 const struct KDiagnoseTest * next;
289 const struct KDiagnoseTest * nextChild;
290 const struct KDiagnoseTest * firstChild;
291 struct KDiagnoseTest * crntChild;
292 char * name;
293 uint64_t code;
294 uint32_t level;
295 char * message;
296 EKDiagTestState state;
297
298 char * number;
299 char * numberNode;
300 };
301
KDiagnoseTestWhack(KDiagnoseTest * self)302 static void KDiagnoseTestWhack ( KDiagnoseTest * self ) {
303 assert ( self );
304 free ( self -> name );
305 free ( self -> message );
306 free ( self -> number );
307 free ( self -> numberNode );
308 memset ( self, 0, sizeof * self );
309 free ( self );
310 }
311
312
KDiagnoseGetTests(const KDiagnose * self,const KDiagnoseTest ** test)313 LIB_EXPORT rc_t CC KDiagnoseGetTests ( const KDiagnose * self,
314 const KDiagnoseTest ** test )
315 {
316 if ( test == NULL )
317 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
318
319 * test = NULL;
320
321 if ( self == NULL )
322 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
323
324 * test = VectorGet ( & self -> tests, 0 );
325 return 0;
326 }
327
KDiagnoseTestNext(const KDiagnoseTest * self,const KDiagnoseTest ** test)328 LIB_EXPORT rc_t CC KDiagnoseTestNext ( const KDiagnoseTest * self,
329 const KDiagnoseTest ** test )
330 {
331 if ( test == NULL )
332 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
333
334 * test = NULL;
335
336 if ( self == NULL )
337 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
338
339 * test = self -> next;
340 return 0;
341 }
342
KDiagnoseTestChild(const KDiagnoseTest * self,uint32_t idx,const KDiagnoseTest ** test)343 LIB_EXPORT rc_t CC KDiagnoseTestChild ( const KDiagnoseTest * self,
344 uint32_t idx, const KDiagnoseTest ** test )
345 {
346 const KDiagnoseTest * t = NULL;
347 uint32_t i;
348
349 if ( test == NULL )
350 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
351
352 * test = NULL;
353
354 if ( self == NULL )
355 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
356
357 for ( i = 0, t = self -> firstChild; i < idx && t != NULL;
358 ++ i, t = t->nextChild );
359
360 * test = t;
361 return 0;
362 }
363
364 #define TEST_GET_INT( PROPERTY ) \
365 do { \
366 if ( PROPERTY == NULL ) \
367 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull ); \
368 * PROPERTY = 0; \
369 if ( self == NULL ) \
370 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull ); \
371 * PROPERTY = self -> PROPERTY; \
372 return 0; \
373 } while ( 0 )
374
375 #define TEST_GET( PROPERTY ) \
376 do { \
377 if ( PROPERTY == NULL ) \
378 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull ); \
379 * PROPERTY = NULL; \
380 if ( self == NULL ) \
381 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull ); \
382 * PROPERTY = self -> PROPERTY; \
383 return 0; \
384 } while ( 0 )
385
KDiagnoseTestName(const KDiagnoseTest * self,const char ** name)386 LIB_EXPORT rc_t CC KDiagnoseTestName ( const KDiagnoseTest * self,
387 const char ** name )
388 { TEST_GET ( name ); }
389
KDiagnoseTestCode(const KDiagnoseTest * self,uint64_t * code)390 LIB_EXPORT rc_t CC KDiagnoseTestCode ( const KDiagnoseTest * self,
391 uint64_t * code )
392 { TEST_GET_INT ( code ); }
393
KDiagnoseTestLevel(const KDiagnoseTest * self,uint32_t * level)394 LIB_EXPORT rc_t CC KDiagnoseTestLevel ( const KDiagnoseTest * self,
395 uint32_t * level )
396 { TEST_GET_INT ( level ); }
397
KDiagnoseTestNumber(const KDiagnoseTest * self,const char ** number)398 LIB_EXPORT rc_t CC KDiagnoseTestNumber ( const KDiagnoseTest * self,
399 const char ** number )
400 { TEST_GET ( number ); }
401
KDiagnoseTestMessage(const KDiagnoseTest * self,const char ** message)402 LIB_EXPORT rc_t CC KDiagnoseTestMessage ( const KDiagnoseTest * self,
403 const char ** message )
404 { TEST_GET ( message ); }
405
KDiagnoseTestState(const KDiagnoseTest * self,EKDiagTestState * state)406 LIB_EXPORT rc_t CC KDiagnoseTestState ( const KDiagnoseTest * self,
407 EKDiagTestState * state )
408 { TEST_GET_INT ( state ); }
409
410
411 struct KDiagnoseError {
412 atomic32_t refcount;
413
414 char * message;
415 };
416
417 static const char DIAGNOSERROR_CLSNAME [] = "KDiagnoseError";
418
419 LIB_EXPORT
KDiagnoseErrorAddRef(const KDiagnoseError * self)420 rc_t CC KDiagnoseErrorAddRef ( const KDiagnoseError * self )
421 {
422 if ( self != NULL )
423 switch ( KRefcountAdd ( & self -> refcount, DIAGNOSERROR_CLSNAME ) ) {
424 case krefLimit:
425 return RC ( rcRuntime,
426 rcData, rcAttaching, rcRange, rcExcessive );
427 }
428
429 return 0;
430 }
431
KDiagnoseErrorWhack(KDiagnoseError * self)432 static void KDiagnoseErrorWhack ( KDiagnoseError * self ) {
433 assert ( self );
434 free ( self -> message );
435 memset ( self, 0, sizeof * self );
436 free ( self );
437 }
438
439 LIB_EXPORT
KDiagnoseErrorRelease(const KDiagnoseError * cself)440 rc_t CC KDiagnoseErrorRelease ( const KDiagnoseError * cself )
441 {
442 rc_t rc = 0;
443
444 KDiagnoseError * self = ( KDiagnoseError * ) cself;
445
446 if ( self != NULL )
447 switch ( KRefcountDrop ( & self -> refcount,
448 DIAGNOSERROR_CLSNAME ) )
449 {
450 case krefWhack:
451 KDiagnoseErrorWhack ( self );
452 break;
453 case krefNegative:
454 return RC ( rcRuntime,
455 rcData, rcReleasing, rcRange, rcExcessive );
456 }
457
458 return rc;
459 }
460
KDiagnoseErrorGetMsg(const KDiagnoseError * self,const char ** message)461 LIB_EXPORT rc_t CC KDiagnoseErrorGetMsg ( const KDiagnoseError * self,
462 const char ** message )
463 {
464 if ( message == NULL )
465 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
466
467 * message = NULL;
468
469 if ( self == NULL )
470 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
471
472 * message = self -> message;
473 return 0;
474 }
475
KDiagnoseErrorMake(const KDiagnoseError ** self,const char * message)476 static rc_t KDiagnoseErrorMake ( const KDiagnoseError ** self,
477 const char * message )
478 {
479 KDiagnoseError * p = NULL;
480
481 assert ( self );
482
483 * self = NULL;
484
485 p = calloc ( 1, sizeof * p );
486 if ( p == NULL )
487 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
488
489 p -> message = string_dup_measure ( message, NULL );
490 if ( p == NULL ) {
491 KDiagnoseErrorWhack ( p );
492 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
493 }
494
495 KRefcountInit ( & p -> refcount, 1, DIAGNOSERROR_CLSNAME, "init", "" );
496
497 * self = p;
498
499 return 0;
500 }
501
502 static void ( CC * CALL_BACK )
503 ( EKDiagTestState state, const KDiagnoseTest * test, void * data );
504 static void * CALL_BACK_DATA;
505
KDiagnoseTestHandlerSet(KDiagnose * self,void (CC * callback)(EKDiagTestState state,const KDiagnoseTest * test,void * data),void * data)506 LIB_EXPORT rc_t CC KDiagnoseTestHandlerSet ( KDiagnose * self,
507 void ( CC * callback )
508 ( EKDiagTestState state, const KDiagnoseTest * test, void * data ),
509 void * data
510 )
511 {
512 CALL_BACK = callback;
513 CALL_BACK_DATA = data;
514 return 0;
515 }
516
517 LIB_EXPORT
KDiagnoseSetVerbosity(KDiagnose * self,int verbosity)518 rc_t CC KDiagnoseSetVerbosity ( KDiagnose * self, int verbosity )
519 {
520 if ( self == NULL )
521 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
522
523 self -> verbosity = verbosity - 1;
524
525 return 0;
526 }
527
KDiagnoseGetErrorCount(const KDiagnose * self,uint32_t * count)528 LIB_EXPORT rc_t CC KDiagnoseGetErrorCount ( const KDiagnose * self,
529 uint32_t * count )
530 {
531 if ( count == NULL )
532 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
533
534 * count = 0;
535
536 if ( self == NULL )
537 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
538
539 * count = VectorLength ( & self -> errors );
540 return 0;
541 }
542
KDiagnoseGetError(const KDiagnose * self,uint32_t idx,const KDiagnoseError ** error)543 LIB_EXPORT rc_t CC KDiagnoseGetError ( const KDiagnose * self, uint32_t idx,
544 const KDiagnoseError ** error )
545 {
546 rc_t rc = 0;
547
548 const KDiagnoseError * e = NULL;
549
550 if ( error == NULL )
551 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
552
553 * error = NULL;
554
555 if ( self == NULL )
556 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
557
558 if ( idx >= VectorLength ( & self -> errors ) )
559 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcInvalid );
560
561 e = VectorGet ( & self -> errors, idx );
562
563 rc = KDiagnoseErrorAddRef ( e );
564 if ( rc == 0 )
565 * error = e;
566
567 return rc;
568 }
569
570 typedef struct {
571 int n [ 7 ];
572 int level;
573 bool ended;
574 bool started; /* TestStart did not terminale string by EOL */
575 bool failedWhileSilent;
576
577 int verbosity; /* -3 none ( KVERBOSITY_NONE )
578 -2 error ( KVERBOSITY_ERROR )
579 -1 info ( KVERBOSITY_INFO )
580 0... last printed index of n [] */
581
582 int total;
583 int failures;
584 int warnings;
585 KDiagnoseTest * crnt;
586 KDiagnoseTest * root;
587 Vector * tests;
588 Vector * errors;
589
590 KDataBuffer msg;
591
592 const KConfig * kfg;
593 const KNSManager * kmgr;
594 const VFSManager * vmgr;
595 VResolver * resolver;
596 VResolverEnableState cacheState;
597 KDirectory * dir;
598
599 bool ascpChecked;
600 const char * ascp;
601 const char * asperaKey;
602
603 KDiagnose * dad;
604 } STest;
605
STestInit(STest * self,KDiagnose * test)606 static void STestInit ( STest * self, KDiagnose * test )
607 {
608 rc_t rc = 0;
609
610 assert ( self && test );
611
612 memset ( self, 0, sizeof * self );
613
614 self -> dad = test;
615
616 self -> level = -1;
617
618 self -> kfg = test -> kfg;
619 self -> kmgr = test -> kmgr;
620 self -> vmgr = test -> vmgr;
621 self -> errors = & test -> errors;
622 self -> tests = & test -> tests;
623
624 self -> verbosity = test -> verbosity;
625 if ( self -> verbosity > 0 )
626 -- self -> verbosity;
627 else if ( self -> verbosity == 0 ) /* max */
628 self -> verbosity = sizeof self -> n / sizeof self -> n [ 0 ] - 1;
629
630 rc = KDirectoryNativeDir ( & self -> dir );
631 if ( rc != 0 )
632 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT KDirectoryNativeDir: %R\n", rc );
633
634 rc = VFSManagerGetResolver ( self -> vmgr, & self -> resolver);
635 if ( rc != 0 )
636 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT GetResolver: %R\n", rc );
637 else
638 self -> cacheState = VResolverCacheEnable ( self -> resolver,
639 vrAlwaysEnable );
640 }
641
STestReport(const STest * self)642 static void STestReport ( const STest * self ) {
643 assert ( self && self -> dad );
644
645 if ( self -> level < KVERBOSITY_INFO )
646 return;
647
648 if ( self -> n [ 0 ] == 0 || self -> n [ 1 ] != 0 ||
649 self -> level != 0 )
650 { LogOut ( KVERBOSITY_INFO, 0, "= TEST WAS NOT COMPLETED\n" ); }
651
652 LogOut ( KVERBOSITY_INFO, 0, "= %d (%d) tests performed, %d failed\n",
653 self -> n [ 0 ], self -> total, self -> failures );
654
655 if ( self -> failures > 0 ) {
656 uint32_t i = 0;
657 LogOut ( KVERBOSITY_INFO, 0, "Errors:\n" );
658 for ( i = 0; i < VectorLength ( self -> errors ); ++ i ) {
659 const KDiagnoseError * e = VectorGet ( self -> errors, i );
660 assert ( e );
661 LogOut ( KVERBOSITY_INFO, 0, " %d: %s\n", i + 1, e -> message );
662 }
663 }
664
665 LogOut ( KVERBOSITY_INFO, 0, "\n\nANALYSIS:\n\n" );
666
667 if ( self -> failures == 0 )
668 LogOut ( KVERBOSITY_INFO, 0, "No errors detected.\n" );
669 else {
670 const Report * report = & self -> dad -> report;
671
672 if ( report -> firewall )
673 LogOut ( KVERBOSITY_INFO, 0,
674 "Most likely access to NCBI is blocked by your firewall.\n"
675 "Please look over the information about firewalls at\n"
676 "https://github.com/ncbi/sra-tools/wiki/Firewall-and-Routing-Information\n"
677 "and make sure that your IT people are aware of the requirements\n"
678 "for accessing SRA data at NCBI.\n\n" );
679
680 if ( report -> blocked ) {
681 const Abuse * test = & report -> abuse;
682 LogOut ( KVERBOSITY_INFO, 0,
683 "Your access to the NCBI website at %s has been\n"
684 "temporarily blocked due to a possible misuse/abuse situation\n"
685 "involving your site. This is not an indication of a security issue\n"
686 "such as a virus or attack.\n"
687 "To restore access and understand how to better interact with our site\n"
688 "to avoid this in the future, please have your system administrator\n"
689 "send an email with subject \"NCBI Web site BLOCKED: %S\"\n"
690 "to info@ncbi.nlm.nih.gov with the following information:\n"
691 "Error=blocked for possible abuse\n"
692 "Server=%s\n"
693 "Client=%S\n"
694 "Time=%S\n\n"
695 , test -> server
696 , & test -> ip
697 , test -> server
698 , & test -> ip
699 , & test -> date );
700 }
701 }
702
703 LogOut ( KVERBOSITY_INFO, 0,
704 "For more infotrmation mail the complete output\n"
705 "and your questions to sra-tools@ncbi.nlm.nih.gov .\n" );
706 }
707
STestFini(STest * self)708 static void STestFini ( STest * self ) {
709 rc_t rc = 0;
710
711 assert ( self );
712
713 if ( self -> level >= KVERBOSITY_INFO )
714 STestReport ( self );
715
716 VResolverCacheEnable ( self -> resolver, self -> cacheState );
717
718 RELEASE ( KDirectory, self -> dir );
719 RELEASE ( VResolver, self -> resolver );
720
721 KDataBufferWhack ( & self -> msg );
722
723 free ( ( void * ) self -> ascp );
724 free ( ( void * ) self -> asperaKey );
725
726 memset ( self, 0, sizeof * self );
727 }
728
KDiagnoseCheckState(KDiagnose * self)729 static rc_t KDiagnoseCheckState(KDiagnose * self) {
730 rc_t rc = 0;
731
732 assert ( self );
733
734 if ( self -> quitting && ( rc = self -> quitting () ) != 0 )
735 if ( rc == SILENT_RC ( rcExe,
736 rcProcess, rcExecuting, rcProcess, rcCanceled ) )
737 {
738 LogOut ( KVERBOSITY_INFO, 0,
739 "= Signal caught: CANCELED DIAGNOSTICS\n" );
740 self -> state = eCanceled;
741 if ( CALL_BACK )
742 CALL_BACK ( eKDTS_Canceled, NULL, CALL_BACK_DATA );
743 }
744
745 while ( self -> state != eRunning ) {
746 rc_t r2;
747
748 rc = KLockAcquire ( self -> lock );
749 if ( rc == 0 )
750 switch ( self -> state ) {
751 case eRunning:
752 break;
753
754 case ePaused:
755 LogOut ( KVERBOSITY_INFO, 0, "= PAUSED DIAGNOSTICS\n" );
756 if ( CALL_BACK )
757 CALL_BACK ( eKDTS_Paused, NULL, CALL_BACK_DATA );
758
759 rc = KConditionWait ( self -> condition, self -> lock );
760 if ( rc != 0 )
761 LogOut ( KVERBOSITY_INFO, 0,
762 "= FAILURE DURING PAUSE: %R\n" );
763 else if ( self -> state == eRunning ) {
764 LogOut ( KVERBOSITY_INFO, 0,
765 "= RESUMED DIAGNOSTICS\n" );
766 if ( CALL_BACK )
767 CALL_BACK ( eKDTS_Resumed, NULL, CALL_BACK_DATA );
768 }
769
770 break;
771
772 case eCanceled:
773 LogOut ( KVERBOSITY_INFO, 0, "= CANCELED DIAGNOSTICS\n" );
774 if ( rc == 0 )
775 rc = RC ( rcRuntime, rcProcess, rcExecuting,
776 rcProcess, rcCanceled );
777 if ( CALL_BACK )
778 CALL_BACK ( eKDTS_Canceled, NULL, CALL_BACK_DATA );
779
780 break;
781 }
782
783 r2 = KLockUnlock ( self -> lock );
784 if ( rc == 0 && r2 != 0 )
785 rc = r2;
786
787 if ( self -> state == eCanceled )
788 break;
789 }
790
791 return rc;
792 }
793
STestVStart(STest * self,bool checking,uint64_t code,const char * fmt,va_list args)794 static rc_t STestVStart ( STest * self, bool checking, uint64_t code,
795 const char * fmt, va_list args )
796 {
797 KDiagnoseTest * test = NULL;
798 rc_t rc = 0;
799 int i = 0;
800 char b [ 512 ] = "";
801 bool next = false;
802 KDataBuffer bf;
803
804 memset ( & bf, 0, sizeof bf );
805 rc = string_vprintf ( b, sizeof b, NULL, fmt, args );
806 if ( rc != 0 ) {
807 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R\n", rc );
808 return rc;
809 }
810
811 assert ( self );
812
813 test = calloc ( 1, sizeof * test );
814 if ( test == NULL )
815 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
816 test -> code = code;
817 test -> name = strdup (b); /*TODO*/
818 if ( test -> name == NULL ) {
819 free ( test );
820 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
821 }
822
823 if ( self -> ended ) {
824 next = true;
825 self -> ended = false;
826 }
827 else
828 ++ self -> level;
829
830 test -> level = self -> level;
831 test -> state = eKDTS_Started;
832
833 if ( self -> crnt != NULL ) {
834 if ( next ) {
835 self -> crnt -> next = test;
836 test -> parent = self -> crnt -> parent;
837 }
838 else {
839 if ( self -> crnt -> firstChild == NULL )
840 self -> crnt -> firstChild = test;
841 else {
842 KDiagnoseTest * child = self -> crnt -> crntChild;
843 assert ( child );
844 child -> nextChild = test;
845 }
846 self -> crnt -> crntChild = test;
847 test -> parent = self -> crnt;
848 }
849 }
850 else
851 self -> root = test;
852 self -> crnt = test;
853 rc = VectorAppend ( self -> tests, NULL, test );
854 if ( rc != 0 )
855 return rc;
856
857 assert ( self -> level >= 0 );
858 assert ( self -> level < sizeof self -> n / sizeof self -> n [ 0 ] );
859
860 ++ self -> n [ self -> level ];
861
862 if ( self -> msg . elem_count > 0 ) {
863 assert ( self -> msg . base );
864 ( ( char * ) self -> msg . base) [ 0 ] = '\0';
865 self -> msg . elem_count = 0;
866 }
867 rc = KDataBufferPrintf ( & self -> msg, "< %d", self -> n [ 0 ] );
868 #ifdef DEPURAR
869 const char*c=self->msg.base;
870 #endif
871 if ( rc != 0 )
872 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R\n", rc );
873 else {
874 size_t size = 0;
875 for ( i = 1; rc == 0 && i <= self -> level; ++ i ) {
876 rc = KDataBufferPrintf ( & self -> msg, ".%d", self -> n [ i ] );
877 if ( rc != 0 )
878 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R\n", rc );
879 }
880 assert ( self -> msg . base && self -> msg . elem_count > 2 );
881 test -> number = string_dup_measure ( ( char * ) self -> msg . base + 2,
882 NULL );
883 if ( test -> number == NULL )
884 return RC ( rcRuntime,
885 rcData, rcAllocating, rcMemory, rcExhausted );
886
887 test -> numberNode = string_dup_measure ( test -> number, & size );
888 if ( test -> numberNode == NULL )
889 return RC ( rcRuntime,
890 rcData, rcAllocating, rcMemory, rcExhausted );
891 else {
892 while ( true ) {
893 char * c = string_chr ( test -> numberNode, size, '.' );
894 if ( c == NULL )
895 break;
896 else
897 * c = '/';
898 }
899 }
900
901 }
902 if ( rc == 0 )
903 {
904 rc = KDataBufferPrintf ( & self -> msg, " %s ", b );
905 if ( rc != 0 )
906 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R\n", rc );
907 }
908
909 if ( self -> level <= self -> verbosity ) {
910 rc = LogOut ( self -> level, 0, "> %d", self -> n [ 0 ] );
911 for ( i = 1; i <= self -> level; ++ i )
912 rc = LogOut ( self -> level, 0, ".%d", self -> n [ i ] );
913
914 rc = LogOut ( self -> level, 0, " %s%s%s",
915 checking ? "Checking " : "", b, checking ? "..." : " " );
916 if ( checking ) {
917 if ( self -> level < self -> verbosity ) {
918 rc = LogOut ( self -> level, 0, "\n" );
919 self -> started = false;
920 }
921 else {
922 rc = LogOut ( self -> level, 0, " " );
923 self -> started = true;
924 }
925 }
926 }
927
928 if ( CALL_BACK )
929 CALL_BACK ( eKDTS_Started, test, CALL_BACK_DATA );
930
931 return rc;
932 }
933
934 typedef enum {
935 eFAIL,
936 eOK,
937 eMSG,
938 eEndFAIL,
939 eEndOK,
940 eDONE, /* never used */
941 eCANCELED,
942 eWarning
943 } EOK;
944
STestVEnd(STest * self,EOK ok,const char * fmt,va_list args)945 static rc_t STestVEnd ( STest * self, EOK ok,
946 const char * fmt, va_list args )
947 {
948 rc_t rc = 0;
949 #ifdef DEPURAR
950 switch(ok){
951 case eFAIL:
952 rc=0;
953 break;
954 case eOK:
955 rc=1;
956 break;
957 case eMSG:
958 rc=2;
959 break;
960 case eEndFAIL:
961 rc=3;
962 break;
963 case eEndOK:
964 rc=4;
965 break;
966 case eDONE:
967 rc=5; /* never used */
968 break;
969 }
970 rc=0;
971 #endif
972 bool failedWhileSilent = self -> failedWhileSilent;
973 bool print = false;
974 char b [ 1024 ] = "";
975 size_t num_writ = 0;
976 size_t num_warn = 0;
977
978 assert ( self );
979
980 if ( ok != eMSG ) {
981 if ( self -> ended ) {
982 self -> crnt = self -> crnt -> parent;
983 self -> n [ self -> level -- ] = 0;
984 }
985 else {
986 self -> ended = true;
987 ++ self -> total;
988 if ( ok == eFAIL || ok == eEndFAIL )
989 ++ self -> failures;
990 else if ( ok == eWarning )
991 ++ self -> warnings;
992 }
993 }
994
995 assert ( self -> level >= 0 );
996 #ifdef DEPURAR
997 const char*c=self->msg.base;
998 #endif
999 if ( ok == eWarning )
1000 rc = string_printf ( b, sizeof b, & num_warn, "WARNING: " );
1001 else if ( ok == eEndFAIL )
1002 rc = string_printf ( b, sizeof b, & num_warn, "FAILURE: " );
1003 rc = string_vprintf ( b + num_warn, sizeof b - num_warn,
1004 & num_writ, fmt, args );
1005 num_writ += num_warn;
1006 if ( rc != 0 ) {
1007 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R", rc );
1008 return rc;
1009 }
1010
1011 if ( self -> crnt -> message == NULL )
1012 self -> crnt -> message = string_dup_measure ( b, NULL );
1013 else {
1014 size_t m = string_measure ( self -> crnt -> message, NULL);
1015 size_t s = m + num_writ + 1;
1016 char * tmp = realloc ( self -> crnt -> message, s );
1017 if ( tmp == NULL )
1018 return RC ( rcRuntime,
1019 rcData, rcAllocating, rcMemory, rcExhausted );
1020 self -> crnt -> message = tmp;
1021 rc = string_printf ( self -> crnt -> message + m, s, NULL, b );
1022 assert ( rc == 0 );
1023 }
1024 if ( ok == eOK ) {
1025 free ( self -> crnt -> message );
1026 self -> crnt -> message = string_dup_measure ( "OK", NULL );
1027 }
1028
1029 if ( ok == eEndFAIL || ok == eMSG ) {
1030 rc = KDataBufferPrintf ( & self -> msg, b );
1031 if ( rc != 0 )
1032 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT PRINT: %R", rc );
1033 else if ( ok == eEndFAIL ) {
1034 const KDiagnoseError * e = NULL;
1035 rc = KDiagnoseErrorMake ( & e, self -> msg . base );
1036 if ( rc != 0 )
1037 return rc;
1038 rc = VectorAppend ( self -> errors, NULL, e );
1039 if ( rc != 0 ) {
1040 LogOut ( KVERBOSITY_ERROR, 0, "CANNOT rcRuntime: %R", rc );
1041 return rc;
1042 }
1043 }
1044 }
1045
1046 if ( self -> level > self -> verbosity ) {
1047 if ( ok == eEndFAIL || ok == eMSG ) {
1048 if ( ok == eEndFAIL ) {
1049 rc = KDataBufferPrintf ( & self -> msg, "\n" );
1050 if ( self -> started ) {
1051 LogOut ( KVERBOSITY_ERROR, 0, "\n" );
1052 self -> failedWhileSilent = true;
1053 self -> started = false;
1054 }
1055 if ( self -> level >= KVERBOSITY_ERROR )
1056 LogOut ( KVERBOSITY_ERROR, 0, self -> msg . base );
1057 assert ( self -> msg . base );
1058 ( ( char * ) self -> msg . base) [ 0 ] = '\0';
1059 self -> msg . elem_count = 0;
1060 }
1061 }
1062 }
1063 else {
1064 print = self -> level < self -> verbosity || failedWhileSilent;
1065 if ( ok == eFAIL || ok == eOK || ok == eDONE || ok == eCANCELED) {
1066 if ( print ) {
1067 int i = 0;
1068 rc = LogOut ( self -> level, 0, "< %d", self -> n [ 0 ] );
1069 for ( i = 1; i <= self -> level; ++ i )
1070 rc = LogOut ( self -> level, 0, ".%d", self -> n [ i ] );
1071 rc = LogOut ( self -> level, 0, " " );
1072 }
1073 }
1074 if ( print ||
1075 ( self -> level == self -> verbosity &&
1076 ok != eFAIL && ok != eOK ) )
1077 {
1078 rc = LogOut ( self -> level, 0, b );
1079 }
1080
1081 if ( print )
1082 switch ( ok ) {
1083 case eFAIL: rc = LogOut ( self -> level, 0, ": FAILURE\n" );
1084 break;
1085 case eOK : rc = LogOut ( self -> level, 0, ": OK\n" );
1086 break;
1087 case eCANCELED:
1088 case eEndFAIL:
1089 case eEndOK :
1090 case eWarning:
1091 case eDONE: rc = LogOut ( self -> level, 0, "\n" );
1092 break;
1093 default : break;
1094 }
1095 else if ( self -> level == self -> verbosity )
1096 switch ( ok ) {
1097 case eFAIL: rc = LogOut ( self -> level, 0, "FAILURE\n" );
1098 break;
1099 case eOK : rc = LogOut ( self -> level, 0, "OK\n" );
1100 break;
1101 case eEndFAIL:
1102 case eEndOK :
1103 case eWarning:
1104 case eDONE: rc = LogOut ( self -> level, 0, "\n" );
1105 break;
1106 default : break;
1107 }
1108
1109 self -> failedWhileSilent = false;
1110 }
1111
1112 if ( ok != eMSG ) {
1113 EKDiagTestState state = eKDTS_Succeed;
1114 switch ( ok ) {
1115 case eEndOK : state = eKDTS_Succeed ; break;
1116 case eOK : state = eKDTS_Succeed ; break;
1117 case eFAIL : state = eKDTS_Failed ; break;
1118 case eCANCELED: state = eKDTS_Canceled; break;
1119 case eWarning : state = eKDTS_Warning ; break;
1120 default : state = eKDTS_Failed ; break;
1121 }
1122 self -> crnt -> state = state;
1123 if ( CALL_BACK )
1124 CALL_BACK ( state, self -> crnt, CALL_BACK_DATA );
1125 }
1126
1127 if ( rc == 0 ) {
1128 assert ( self -> dad );
1129 rc = KDiagnoseCheckState ( self -> dad );
1130 }
1131
1132 return rc;
1133 }
1134
_RcCanceled(rc_t rc)1135 static bool _RcCanceled ( rc_t rc ) {
1136 return rc == SILENT_RC ( rcExe,
1137 rcProcess, rcExecuting, rcProcess, rcCanceled )
1138 || rc == SILENT_RC ( rcRuntime,
1139 rcProcess, rcExecuting, rcProcess, rcCanceled );
1140 }
STestCanceled(const STest * self,rc_t rc)1141 static bool STestCanceled ( const STest * self, rc_t rc ) {
1142 assert ( self && self -> dad );
1143 return _RcCanceled ( rc ) && self -> dad -> state == eCanceled;
1144 }
1145
STestFailure(const STest * self)1146 static rc_t STestFailure ( const STest * self ) {
1147 rc_t failure = 0;
1148
1149 rc_t rc = RC ( rcRuntime, rcProcess, rcExecuting, rcProcess, rcCanceled );
1150 const KConfigNode * node = NULL;
1151
1152 assert ( self && self -> crnt && self -> crnt -> numberNode );
1153
1154 rc = KConfigOpenNodeRead ( self -> kfg, & node,
1155 "tools/test-sra/diagnose/%s", self -> crnt -> numberNode );
1156 if ( rc == 0 ) {
1157 uint64_t result = 0;
1158 rc = KConfigNodeReadU64 ( node, & result );
1159 if ( rc == 0 ) {
1160 failure = ( rc_t ) result;
1161 // if ( _RcCanceled ( failure ) && CALL_BACK ) CALL_BACK ( eKDTS_Canceled,NULL);
1162 }
1163
1164 KConfigNodeRelease ( node );
1165 node = NULL;
1166 }
1167
1168 return failure;
1169 }
1170
STestEndOr(STest * self,rc_t * failure,EOK ok,const char * fmt,...)1171 static rc_t STestEndOr ( STest * self, rc_t * failure,
1172 EOK ok, const char * fmt, ... )
1173 {
1174 rc_t rc = 0;
1175 bool canceled = false;
1176
1177 va_list args;
1178 va_start ( args, fmt );
1179
1180 assert ( failure );
1181 * failure = 0;
1182
1183 rc = STestVEnd ( self, ok, fmt, args );
1184 canceled = STestCanceled ( self, rc );
1185
1186 va_end ( args );
1187
1188 if ( LOGGER == OutMsg ) {
1189 assert ( rc == 0 || canceled );
1190 }
1191
1192 if ( canceled )
1193 * failure = rc;
1194 else if ( rc == 0 )
1195 * failure = STestFailure ( self );
1196
1197 return rc;
1198 }
1199
STestEnd(STest * self,EOK ok,const char * fmt,...)1200 static rc_t STestEnd ( STest * self, EOK ok, const char * fmt, ... ) {
1201 rc_t rc = 0;
1202
1203 va_list args;
1204 va_start ( args, fmt );
1205
1206 rc = STestVEnd ( self, ok, fmt, args );
1207
1208 va_end ( args );
1209
1210 if ( LOGGER == OutMsg ) {
1211 assert ( rc == 0 || STestCanceled ( self, rc ) );
1212 }
1213
1214 return rc;
1215 }
1216
STestStart(STest * self,bool checking,uint64_t code,const char * fmt,...)1217 static rc_t STestStart ( STest * self, bool checking, uint64_t code,
1218 const char * fmt, ... )
1219 {
1220 rc_t rc = 0;
1221
1222 va_list args;
1223 va_start ( args, fmt );
1224
1225 rc = STestVStart ( self, checking, code, fmt, args );
1226
1227 va_end ( args );
1228
1229 if ( LOGGER == OutMsg ) {
1230 assert ( rc == 0 );
1231 }
1232
1233 return rc;
1234 }
1235
STestFail(STest * self,rc_t failure,uint64_t code,const char * start,...)1236 static rc_t STestFail ( STest * self, rc_t failure, uint64_t code,
1237 const char * start, ... )
1238 {
1239 va_list args;
1240
1241 rc_t rc = 0;
1242
1243 rc_t r2 = 0;
1244
1245 va_start ( args, start );
1246
1247 rc = STestVStart ( self, false, code, start, args );
1248
1249 r2 = STestEnd ( self, eEndFAIL, "%R", failure );
1250 if ( rc == 0 && r2 != 0 )
1251 rc = r2;
1252
1253 va_end ( args );
1254
1255 return rc;
1256 }
1257
1258 typedef struct {
1259 VPath * vpath;
1260 const String * acc;
1261 } Data;
1262
DataInit(Data * self,const VFSManager * mgr,const char * path)1263 static rc_t DataInit ( Data * self, const VFSManager * mgr,
1264 const char * path )
1265 {
1266 rc_t rc = 0;
1267
1268 assert ( self );
1269
1270 memset ( self, 0, sizeof * self );
1271
1272 rc = VFSManagerMakePath ( mgr, & self -> vpath, path );
1273 if ( rc != 0 )
1274 LogOut ( KVERBOSITY_ERROR, 0,
1275 "VFSManagerMakePath(%s) = %R\n", path, rc );
1276 else {
1277 VPath * vacc = NULL;
1278 rc = VFSManagerExtractAccessionOrOID ( mgr, & vacc, self -> vpath );
1279 if ( rc != 0 )
1280 rc = 0;
1281 else {
1282 String acc;
1283 rc = VPathGetPath ( vacc, & acc );
1284 if ( rc == 0 )
1285 StringCopy ( & self -> acc, & acc );
1286 else
1287 LogOut ( KVERBOSITY_ERROR, 0, "Cannot VPathGetPath"
1288 "(VFSManagerExtractAccessionOrOID(%R))\n", rc );
1289 RELEASE ( VPath, vacc );
1290 }
1291 }
1292
1293 return rc;
1294 }
1295
DataFini(Data * self)1296 static rc_t DataFini ( Data * self ) {
1297 rc_t rc = 0;
1298
1299 assert ( self );
1300
1301 free ( ( void * ) self -> acc );
1302
1303 rc = VPathRelease ( self -> vpath );
1304
1305 memset ( self, 0, sizeof * self );
1306
1307 return rc;
1308 }
1309
1310 static const ver_t HTTP_VERSION = 0x01010000;
1311
STestCheckFile(STest * self,const String * path,uint64_t * sz,rc_t * rc_read)1312 static rc_t STestCheckFile ( STest * self, const String * path,
1313 uint64_t * sz, rc_t * rc_read )
1314 {
1315 rc_t rc = 0;
1316
1317 const KFile * file = NULL;
1318
1319 assert ( self && sz && rc_read );
1320
1321 STestStart ( self, false, 0,
1322 "KFile = KNSManagerMakeReliableHttpFile(%S):", path );
1323
1324 rc = KNSManagerMakeReliableHttpFile ( self -> kmgr, & file, NULL,
1325 HTTP_VERSION, true, false, false, "%S", path );
1326 if ( rc != 0 )
1327 STestEnd ( self, eEndFAIL, "%R", rc );
1328 else {
1329 if ( rc == 0 )
1330 STestEndOr ( self, & rc, eEndOK, "OK" );
1331 if ( rc != 0 ) {
1332 if ( _RcCanceled ( rc ) )
1333 STestEnd ( self, eCANCELED, "CANCELED" );
1334 else
1335 STestEnd ( self, eEndFAIL, "%R", rc );
1336 }
1337 else {
1338 STestStart ( self, false, 0, "KFileSize(KFile(%S)) =", path );
1339 rc = KFileSize ( file, sz );
1340 if ( rc == 0 )
1341 STestEndOr ( self, & rc, eEndOK, "%lu: OK", * sz );
1342 if ( rc != 0 ) {
1343 if ( _RcCanceled ( rc ) )
1344 STestEnd ( self, eCANCELED, "CANCELED" );
1345 else
1346 STestEnd ( self, eEndFAIL, "%R", rc );
1347 }
1348 }
1349 }
1350
1351 if ( rc == 0 ) {
1352 char buffer [ 304 ] = "";
1353 uint64_t pos = 0;
1354 size_t bsize = sizeof buffer;
1355 size_t num_read = 0;
1356 if ( * sz < 256 ) {
1357 pos = 0;
1358 bsize = ( size_t ) * sz;
1359 }
1360 else
1361 pos = ( * sz - sizeof buffer ) / 2;
1362 STestStart ( self, false, 0,
1363 "KFileRead(%S,%lu,%zu):", path, pos, bsize );
1364 * rc_read = KFileRead ( file, pos, buffer, bsize, & num_read );
1365 if ( * rc_read == 0 )
1366 STestEndOr ( self, rc_read, eEndOK, "OK" );
1367 if ( * rc_read != 0 ) {
1368 if ( _RcCanceled ( * rc_read ) )
1369 STestEnd ( self, eCANCELED, "CANCELED" );
1370 else
1371 STestEnd ( self, eEndFAIL, "%R", * rc_read );
1372 }
1373 }
1374
1375 KFileRelease ( file );
1376 file = NULL;
1377
1378 return rc;
1379 }
1380
1381 static
STestCheckRanges(STest * self,const Data * data,uint64_t sz)1382 rc_t STestCheckRanges ( STest * self, const Data * data, uint64_t sz )
1383 {
1384 rc_t rc = 0;
1385 uint64_t pos = 0;
1386 size_t bytes = 4096;
1387 uint64_t ebytes = bytes;
1388 bool https = false;
1389 char buffer [ 2048 ] = "";
1390 size_t num_read = 0;
1391 KClientHttp * http = NULL;
1392 KHttpRequest * req = NULL;
1393 KHttpResult * rslt = NULL;
1394 String host;
1395 String scheme;
1396 assert ( self && data );
1397 STestStart ( self, true, 0, "Support of Range requests" );
1398 rc = VPathGetHost ( data -> vpath, & host );
1399 if ( rc != 0 )
1400 STestFail ( self, rc, 0, "VPathGetHost" );
1401 if ( rc == 0 )
1402 rc = VPathGetScheme ( data -> vpath, & scheme );
1403 if ( rc != 0 )
1404 STestFail ( self, rc, 0, "VPathGetScheme" );
1405 if ( rc == 0 ) {
1406 String sHttps;
1407 String sHttp;
1408 CONST_STRING ( & sHttp, "http" );
1409 CONST_STRING ( & sHttps, "https" );
1410 if ( StringEqual ( & scheme, & sHttps ) )
1411 https = true;
1412 else if ( StringEqual ( & scheme, & sHttp ) )
1413 https = false;
1414 else {
1415 LogOut ( KVERBOSITY_ERROR, 0,
1416 "Unexpected scheme '(%S)'\n", & scheme );
1417 return 0;
1418 }
1419 }
1420 if ( rc == 0 ) {
1421 if ( https ) {
1422 STestStart ( self, false, 0, "KClientHttp = "
1423 "KNSManagerMakeClientHttps(%S):", & host );
1424 rc = KNSManagerMakeClientHttps ( self -> kmgr, & http, NULL,
1425 HTTP_VERSION, & host, 0 );
1426 }
1427 else {
1428 STestStart ( self, false, 0, "KClientHttp = "
1429 "KNSManagerMakeClientHttp(%S):", & host );
1430 rc = KNSManagerMakeClientHttp ( self -> kmgr, & http, NULL,
1431 HTTP_VERSION, & host, 0 );
1432 }
1433 if ( rc == 0 )
1434 STestEndOr ( self, & rc, eEndOK, "OK" );
1435 if ( rc != 0 ) {
1436 if ( _RcCanceled ( rc ) )
1437 STestEnd ( self, eCANCELED, "CANCELED" );
1438 else
1439 STestEnd ( self, eEndFAIL, "%R", rc );
1440 }
1441 }
1442 if ( rc == 0 ) {
1443 String path;
1444 rc = VPathGetPath ( data -> vpath, & path );
1445 if ( rc != 0 )
1446 STestFail ( self, rc, 0, "VPathGetPath" );
1447 else {
1448 rc = KHttpMakeRequest ( http, & req, "%S", & path );
1449 if ( rc != 0 ) {
1450 self -> dad -> report . firewall = true;
1451 STestFail ( self, rc, 0, "KHttpMakeRequest(%S)", & path );
1452 }
1453 }
1454 }
1455 if ( rc == 0 ) {
1456 STestStart ( self, false, 0, "KHttpResult = "
1457 "KHttpRequestHEAD(KHttpMakeRequest(KClientHttp)):" );
1458 rc = KHttpRequestHEAD ( req, & rslt );
1459 if ( rc == 0 )
1460 STestEndOr ( self, & rc, eEndOK, "OK" );
1461 if ( rc != 0 ) {
1462 if ( _RcCanceled ( rc ) )
1463 STestEnd ( self, eCANCELED, "CANCELED" );
1464 else
1465 STestEnd ( self, eEndFAIL, "%R", rc );
1466 }
1467 }
1468 if ( rc == 0 ) {
1469 STestStart ( self, false, 0,
1470 "KHttpResultGetHeader(KHttpResult, Accept-Ranges) =" );
1471 rc = KHttpResultGetHeader ( rslt, "Accept-Ranges",
1472 buffer, sizeof buffer, & num_read );
1473 if ( rc == 0 ) {
1474 const char bytes [] = "bytes";
1475 if ( string_cmp ( buffer, num_read, bytes, sizeof bytes - 1,
1476 sizeof bytes - 1 ) == 0 )
1477 {
1478 rc = STestEnd ( self, eEndOK, "'%.*s': OK",
1479 ( int ) num_read, buffer );
1480 }
1481 else {
1482 STestEnd ( self, eEndFAIL, "'%.*s'", ( int ) num_read, buffer );
1483 rc = RC ( rcRuntime,
1484 rcFile, rcOpening, rcFunction, rcUnsupported );
1485 }
1486 }
1487 else
1488 STestEnd ( self, eEndFAIL, "%R", rc );
1489 }
1490 KHttpResultRelease ( rslt );
1491 rslt = NULL;
1492 if ( sz < ebytes )
1493 ebytes = sz;
1494 if ( sz > bytes * 2 )
1495 pos = sz / 2;
1496 if ( rc == 0 ) {
1497 STestStart ( self, false, 0, "KHttpResult = KHttpRequestByteRange"
1498 "(KHttpMakeRequest, %lu, %zu):", pos, bytes );
1499 rc = KHttpRequestByteRange ( req, pos, bytes );
1500 if ( rc == 0 )
1501 STestEndOr ( self, & rc, eEndOK, "OK" );
1502 if ( rc != 0 ) {
1503 if ( _RcCanceled ( rc ) )
1504 STestEnd ( self, eCANCELED, "CANCELED" );
1505 else
1506 STestEnd ( self, eEndFAIL, "%R", rc );
1507 }
1508 }
1509 if ( rc == 0 ) {
1510 STestStart ( self, false, 0,
1511 "KHttpResult = KHttpRequestGET(KHttpMakeRequest(KClientHttp)):" );
1512 rc = KHttpRequestGET ( req, & rslt );
1513 if ( rc == 0 )
1514 STestEndOr ( self, & rc, eEndOK, "OK" );
1515 if ( rc != 0 ) {
1516 if ( _RcCanceled ( rc ) )
1517 STestEnd ( self, eCANCELED, "CANCELED" );
1518 else
1519 STestEnd ( self, eEndFAIL, "%R", rc );
1520 }
1521 }
1522 if ( rc == 0 ) {
1523 uint64_t po = 0;
1524 size_t byte = 0;
1525 rc = KClientHttpResultRange ( rslt, & po, & byte );
1526 if ( rc == 0 ) {
1527 if ( po != pos || ( ebytes > 0 && byte != ebytes ) ) {
1528 rc = RC ( rcRuntime, rcFile, rcReading, rcRange, rcOutofrange );
1529 STestFail ( self, rc, 0,
1530 "KClientHttpResultRange(KHttpResult,&p,&b): "
1531 "got:{%lu,%zu}", pos, ebytes, po, byte );
1532 /* STestStart ( self, false,
1533 "KClientHttpResultRange(KHttpResult,&p,&b):" );
1534 STestEnd ( self, eEndFAIL, "FAILURE: expected:{%lu,%zu}, "
1535 "got:{%lu,%zu}", pos, ebytes, po, byte );*/
1536 }
1537 }
1538 else {
1539 STestFail ( self, rc, 0, "KClientHttpResultRange(KHttpResult)" );
1540 /* STestStart ( self, false, "KClientHttpResultRange(KHttpResult):" );
1541 STestEnd ( self, eEndFAIL, "FAILURE: %R", rc );*/
1542 }
1543 }
1544 if ( rc == 0 ) {
1545 STestStart ( self, false, 0,
1546 "KHttpResultGetHeader(KHttpResult, Content-Range) =" );
1547 rc = KHttpResultGetHeader ( rslt, "Content-Range",
1548 buffer, sizeof buffer, & num_read );
1549 if ( rc == 0 )
1550 STestEndOr ( self, & rc, eEndOK, "'%.*s': OK",
1551 ( int ) num_read, buffer );
1552 if ( rc != 0 ) {
1553 if ( _RcCanceled ( rc ) )
1554 STestEnd ( self, eCANCELED, "CANCELED" );
1555 else
1556 STestEnd ( self, eEndFAIL, "%R", rc );
1557 }
1558 }
1559 KHttpResultRelease ( rslt );
1560 rslt = NULL;
1561 KHttpRequestRelease ( req );
1562 req = NULL;
1563 KHttpRelease ( http );
1564 http = NULL;
1565
1566 if ( rc == 0 ) {
1567 rc_t r2 = STestEnd ( self, eOK, "Support of Range requests" );
1568 if ( r2 != 0 && rc == 0 )
1569 rc = r2;
1570 }
1571 else if ( _RcCanceled ( rc ) )
1572 STestEnd ( self, eCANCELED, "Support of Range requests: CANCELED" );
1573 else
1574 STestEnd ( self, eFAIL, "Support of Range requests" );
1575
1576 return rc;
1577 }
1578
STestRemoveCache(STest * self,const char * cache)1579 static KPathType STestRemoveCache ( STest * self, const char * cache ) {
1580 KPathType type = kptNotFound;
1581
1582 assert ( self );
1583
1584 type = KDirectoryPathType ( self -> dir, cache );
1585
1586 if ( type != kptNotFound ) {
1587 if ( ( type & ~ kptAlias ) == kptFile ) {
1588 rc_t rc = KDirectoryRemove ( self -> dir, false, cache );
1589 if ( rc != 0 )
1590 STestFail ( self, rc, 0, "KDirectoryRemove(%s)", cache );
1591 else
1592 type = kptNotFound;
1593 }
1594 else
1595 LogOut ( KVERBOSITY_ERROR, 0,
1596 "UNEXPECTED FILE TYPE OF '%s': %d\n", cache, type );
1597 }
1598
1599 return type;
1600 }
1601
STestCheckStreamRead(STest * self,const KStream * stream,const char * cache,uint64_t * cacheSize,uint64_t sz,bool print,const char ** exp,size_t esz,bool * tooBig)1602 static rc_t STestCheckStreamRead ( STest * self, const KStream * stream,
1603 const char * cache, uint64_t * cacheSize, uint64_t sz, bool print,
1604 const char ** exp, size_t esz, bool * tooBig )
1605 {
1606 rc_t rc = 0;
1607 size_t total = 0;
1608 char buffer [ 1024 ] = "";
1609 KFile * out = NULL;
1610 rc_t rw = 0;
1611 uint64_t pos = 0;
1612 assert ( cache && cacheSize && tooBig );
1613 if ( cache [ 0 ] != '\0' ) {
1614 if ( STestRemoveCache ( self, cache ) == kptNotFound ) {
1615 rw = KDirectoryCreateFile ( self -> dir, & out, false, 0664,
1616 kcmCreate | kcmParents, cache );
1617 if ( rw != 0 )
1618 LogOut ( KVERBOSITY_ERROR, 0,
1619 "CANNOT CreateFile '%s': %R\n", cache, rw );
1620 }
1621 }
1622 STestStart ( self, false, 0, "KStreamRead(KHttpResult):" );
1623 while ( rc == 0 ) {
1624 size_t num_read = 0;
1625 rc = KStreamRead ( stream, buffer, sizeof buffer, & num_read );
1626 if ( rc != 0 )
1627 STestEnd ( self, eEndFAIL, "%R", rc );
1628 else if ( num_read != 0 ) {
1629 if ( rw == 0 && out != NULL ) {
1630 size_t num_writ = 0;
1631 rw = KFileWriteAll ( out, pos, buffer, num_read, & num_writ );
1632 if ( rw == 0 ) {
1633 assert ( num_writ == num_read );
1634 pos += num_writ;
1635 }
1636 else
1637 LogOut ( KVERBOSITY_ERROR, 0,
1638 "CANNOT WRITE TO '%s': %R\n", cache, rw );
1639 }
1640 if ( total == 0 && esz > 0 ) {
1641 int i = 0;
1642 size_t s = esz;
1643 if ( num_read < esz )
1644 s = num_read;
1645 rc = STestEnd ( self, eMSG, "'" );
1646 if ( rc != 0 ) {
1647 if ( STestCanceled ( self, rc ) )
1648 STestEnd ( self, eCANCELED, "CANCELED" );
1649 else
1650 STestEnd ( self, eEndFAIL, "%R", rc );
1651 break;
1652 }
1653 for ( i = 0; i < s && rc == 0; ++ i ) {
1654 if ( isprint ( ( unsigned char ) buffer [ i ] ) )
1655 rc = STestEnd ( self, eMSG, "%c", buffer [ i ] );
1656 else if ( buffer [ i ] == 0 )
1657 rc = STestEnd ( self, eMSG, "\\0" );
1658 else
1659 rc = STestEnd ( self, eMSG, "\\%03o",
1660 ( unsigned char ) buffer [ i ] );
1661 }
1662 if ( rc == 0 )
1663 rc = STestEnd ( self, eMSG, "': " );
1664 if ( rc != 0 ) {
1665 if ( STestCanceled ( self, rc ) )
1666 STestEnd ( self, eCANCELED, "CANCELED" );
1667 else
1668 STestEnd ( self, eEndFAIL, "%R", rc );
1669 break;
1670 }
1671 for ( i = 0; i < 2; ++ i ) {
1672 if ( string_cmp ( buffer, num_read, exp [ i ], esz,
1673 (uint32_t) esz ) == 0 )
1674 { break; }
1675 else if ( i == 1 ) {
1676 STestEnd ( self, eEndFAIL, "bad content" );
1677 rc = RC ( rcRuntime,
1678 rcFile, rcReading, rcString, rcUnequal );
1679 }
1680 }
1681 }
1682 total += num_read;
1683 if ( total > 1000000 /* 1mb */ ) {
1684 * tooBig = true;
1685 rc = STestEnd ( self, eEndOK,
1686 "Interrupted (file is too big): OK" );
1687 assert ( total < sz );
1688 break;
1689 }
1690 }
1691 else {
1692 assert ( num_read == 0 );
1693 if ( total == sz ) {
1694 if ( print ) {
1695 if ( total >= sizeof buffer )
1696 buffer [ sizeof buffer - 1 ] = '\0';
1697 else {
1698 buffer [ total ] = '\0';
1699 while ( total > 0 ) {
1700 -- total;
1701 if ( buffer [ total ] == '\n' )
1702 buffer [ total ] = '\0';
1703 else
1704 break;
1705 }
1706 }
1707 rc = STestEnd ( self, eMSG, "%s: ", buffer );
1708 }
1709 if ( rc == 0 )
1710 rc = STestEnd ( self, eEndOK, "OK" );
1711 if ( rc != 0 ) {
1712 if ( STestCanceled ( self, rc ) )
1713 STestEnd ( self, eCANCELED, "CANCELED" );
1714 else
1715 STestEnd ( self, eEndFAIL, "%R", rc );
1716 }
1717 }
1718 else
1719 STestEnd ( self, eEndFAIL, "%s: SIZE DO NOT MATCH (%zu)\n",
1720 total );
1721 break;
1722 }
1723 }
1724 {
1725 rc_t r2 = KFileRelease ( out );
1726 if ( rw == 0 )
1727 rw = r2;
1728 }
1729 if ( rw == 0 )
1730 * cacheSize = pos;
1731 return rc;
1732 }
1733
STestCheckHttpUrl(STest * self,uint64_t tests,uint64_t atest,const Data * data,const char * cache,uint64_t * cacheSize,bool print,const char ** exp,size_t esz,bool * tooBig)1734 static rc_t STestCheckHttpUrl ( STest * self, uint64_t tests, uint64_t atest,
1735 const Data * data, const char * cache, uint64_t * cacheSize,
1736 bool print, const char ** exp, size_t esz, bool * tooBig )
1737 {
1738 rc_t rc = 0;
1739 rc_t rc_read = 0;
1740 rc_t r2 = 0;
1741 KHttpRequest * req = NULL;
1742 KHttpResult * rslt = NULL;
1743 const String * full = NULL;
1744 uint64_t sz = 0;
1745 assert ( self && data );
1746 rc = VPathMakeString ( data -> vpath, & full );
1747 if ( rc != 0 )
1748 STestFail ( self, rc, 0, "VPathMakeString" );
1749 if ( rc == 0 )
1750 STestStart ( self, true, atest, "Access to '%S'", full );
1751 if ( rc == 0 )
1752 rc = STestCheckFile ( self, full, & sz, & rc_read );
1753 r2 = STestCheckRanges ( self, data, sz );
1754 if ( rc == 0 ) {
1755 STestStart ( self, false, 0,
1756 "KHttpRequest = KNSManagerMakeRequest(%S):", full );
1757 rc = KNSManagerMakeRequest ( self -> kmgr, & req,
1758 HTTP_VERSION, NULL, "%S", full );
1759 if ( rc == 0 )
1760 STestEndOr ( self, & rc, eEndOK, "OK" );
1761 if ( rc != 0 ) {
1762 if ( _RcCanceled ( rc ) )
1763 STestEnd ( self, eCANCELED, "CANCELED" );
1764 else {
1765 self -> dad -> report . firewall = true;
1766 STestEnd ( self, eEndFAIL, "%R", rc );
1767 }
1768 }
1769 }
1770 if ( rc == 0 ) {
1771 STestStart ( self, false, 0,
1772 "KHttpResult = KHttpRequestGET(KHttpRequest):" );
1773 rc = KHttpRequestGET ( req, & rslt );
1774 if ( rc == 0 )
1775 STestEndOr ( self, & rc, eEndOK, "OK" );
1776 if ( rc != 0 ) {
1777 if ( _RcCanceled ( rc ) )
1778 STestEnd ( self, eCANCELED, "CANCELED" );
1779 else
1780 STestEnd ( self, eEndFAIL, "%R", rc );
1781 }
1782 }
1783 if ( rc == 0 ) {
1784 uint32_t code = 0;
1785 STestStart ( self, false, 0, "KHttpResultStatus(KHttpResult) =" );
1786 rc = KHttpResultStatus ( rslt, & code, NULL, 0, NULL );
1787 if ( rc != 0 )
1788 STestEnd ( self, eEndFAIL, "%R", rc );
1789 else {
1790 rc = STestEnd ( self, eMSG, "%u: ", code );
1791 if ( rc == 0 )
1792 if ( code == 200 )
1793 STestEnd ( self, eEndOK, "OK" );
1794 else {
1795 STestEnd ( self, eEndFAIL, "bad status" );
1796 rc = RC ( rcRuntime, rcFile, rcReading, rcFile, rcInvalid );
1797 }
1798 else if ( STestCanceled ( self, rc ) )
1799 STestEnd ( self, eCANCELED, "CANCELED" );
1800 else
1801 STestEnd ( self, eEndFAIL, "%R", rc );
1802 }
1803 }
1804 if ( rc == 0 && tests & KDIAGN_DOWNLOAD_HTTP ) {
1805 KStream * stream = NULL;
1806 rc = KHttpResultGetInputStream ( rslt, & stream );
1807 if ( rc != 0 )
1808 STestFail ( self, rc, KDIAGN_DOWNLOAD_HTTP,
1809 "KHttpResultGetInputStream(KHttpResult)" );
1810 else
1811 rc = STestCheckStreamRead ( self, stream, cache, cacheSize,
1812 sz, print, exp, esz, tooBig );
1813 KStreamRelease ( stream );
1814 stream = NULL;
1815 }
1816 if ( rc == 0 && r2 != 0 )
1817 rc = r2;
1818 if ( rc == 0 && rc_read != 0 )
1819 rc = rc_read;
1820 KHttpRequestRelease ( req );
1821 req = NULL;
1822 KHttpResultRelease ( rslt );
1823 rslt = NULL;
1824
1825 if ( rc == 0 )
1826 STestEnd ( self, eOK, "Access to '%S'", full );
1827 else if ( _RcCanceled ( rc ) )
1828 STestEnd ( self, eCANCELED, "Access to '%S': CANCELED", full );
1829 else
1830 STestEnd ( self, eFAIL, "Access to '%S'", full );
1831
1832 free ( ( void * ) full );
1833 full = NULL;
1834 return rc;
1835 }
1836
DataIsAccession(const Data * self)1837 static bool DataIsAccession ( const Data * self ) {
1838 assert ( self );
1839
1840 if ( self -> acc == NULL )
1841 return false;
1842 else
1843 return self -> acc -> size != 0;
1844 }
1845
STestCheckVfsUrl(STest * self,uint64_t atest,const Data * data,bool warn)1846 static rc_t STestCheckVfsUrl ( STest * self, uint64_t atest, const Data * data,
1847 bool warn )
1848 {
1849 rc_t rc = 0;
1850
1851 const KDirectory * d = NULL;
1852
1853 String path;
1854
1855 assert ( self && data );
1856
1857 if ( ! DataIsAccession ( data ) )
1858 return 0;
1859
1860 rc = VPathGetPath ( data -> vpath, & path );
1861 if ( rc != 0 ) {
1862 STestFail ( self, rc, 0, "VPathGetPath" );
1863 return rc;
1864 }
1865
1866 STestStart ( self, false, atest, "VFSManagerOpenDirectoryReadDecrypt(%S):",
1867 & path );
1868 rc = VFSManagerOpenDirectoryReadDecrypt ( self -> vmgr, & d,
1869 data -> vpath );
1870 if ( rc == 0 )
1871 STestEndOr ( self, & rc, eEndOK, "OK" );
1872 if ( rc != 0 ) {
1873 if ( _RcCanceled ( rc ) )
1874 STestEnd ( self, eCANCELED, "CANCELED" );
1875 else
1876 STestEnd ( self, eEndFAIL, "%R", rc );
1877 }
1878
1879 RELEASE ( KDirectory, d );
1880
1881 return rc;
1882 }
1883
STestCheckUrlImpl(STest * self,uint64_t tests,uint64_t htest,uint64_t vtest,const Data * data,const char * cache,uint64_t * cacheSize,bool print,const char ** exp,size_t esz,bool * tooBig)1884 static rc_t STestCheckUrlImpl ( STest * self, uint64_t tests, uint64_t htest,
1885 uint64_t vtest, const Data * data, const char * cache,
1886 uint64_t * cacheSize, bool print, const char ** exp, size_t esz,
1887 bool * tooBig )
1888 {
1889 rc_t rc = 0;
1890 rc_t r2 = 0;
1891 if ( tests & htest )
1892 rc = STestCheckHttpUrl ( self, tests, htest, data,
1893 cache, cacheSize, print, exp, esz, tooBig );
1894 if ( tests & vtest )
1895 r2 = STestCheckVfsUrl ( self, vtest, data, cacheSize == 0 );
1896 return rc != 0 ? rc : r2;
1897 }
1898
STestCheckUrl(STest * self,uint64_t tests,uint64_t htest,uint64_t vtest,const Data * data,const char * cache,uint64_t * cacheSize,bool print,const char ** exp,size_t esz,bool * tooBig)1899 static rc_t STestCheckUrl ( STest * self, uint64_t tests, uint64_t htest,
1900 uint64_t vtest, const Data * data, const char * cache, uint64_t * cacheSize,
1901 bool print, const char ** exp, size_t esz, bool * tooBig )
1902 {
1903 rc_t rc = 0;
1904
1905 String path;
1906
1907 bool dummy;
1908 if ( tooBig == NULL )
1909 tooBig = & dummy;
1910
1911 assert ( data );
1912
1913 rc = VPathGetPath ( data -> vpath, & path );
1914 if ( rc != 0 ) {
1915 STestFail ( self, rc, 0, "VPathGetPath" );
1916 return rc;
1917 }
1918
1919 if ( path . size == 0 ) /* does not exist */
1920 return 0;
1921
1922 return STestCheckUrlImpl ( self, tests, htest, vtest, data,
1923 cache, cacheSize, print, exp, esz, tooBig );
1924 }
1925
KConfig_Resolver(const KConfig * self)1926 static String * KConfig_Resolver ( const KConfig * self ) {
1927 String * s = NULL;
1928
1929 rc_t rc = KConfigReadString ( self,
1930 "tools/test-sra/diagnose/resolver-cgi", & s );
1931 if ( rc != 0 ) {
1932 String str;
1933 CONST_STRING ( & str,
1934 "https://trace.ncbi.nlm.nih.gov/Traces/names/names.fcgi" );
1935 rc = StringCopy ( ( const String ** ) & s, & str );
1936 assert ( rc == 0 );
1937 }
1938
1939 assert ( s );
1940 return s;
1941 }
1942
KConfig_Verbosity(const KConfig * self)1943 static int KConfig_Verbosity ( const KConfig * self ) {
1944 int64_t v = -1;
1945
1946 String * s = NULL;
1947 rc_t rc = KConfigReadString ( self,
1948 "tools/test-sra/diagnose/verbosity", & s );
1949 if ( rc != 0 )
1950 return 0;
1951
1952 assert ( s );
1953
1954 if ( s -> size > 0 )
1955 if ( isdigit ( s -> addr [ 0 ] ) )
1956 v = strtoi64 ( s -> addr, NULL, 0 );
1957
1958 free ( s );
1959 s = NULL;
1960
1961 return ( int ) v;
1962 }
1963
STestAbuseRedirect(const STest * self,Abuse * test,bool * abuse)1964 static rc_t STestAbuseRedirect ( const STest * self,
1965 Abuse * test, bool * abuse )
1966 {
1967 rc_t rc = 0;
1968
1969 KHttpRequest * req = NULL;
1970 KHttpResult * rslt = NULL;
1971 KStream * stream = NULL;
1972
1973 size_t i = 0;
1974 size_t total = 0;
1975 char * base = NULL;
1976 const char * c = NULL;
1977
1978 Block * p = NULL;
1979 KDataBuffer * buffer = NULL;
1980
1981 String open, close, needle;
1982 CONST_STRING ( & open, "<p>" );
1983 CONST_STRING ( & close, "</p>" );
1984
1985 assert ( self && test && abuse );
1986
1987 buffer = & test -> redirect;
1988 p = & test -> p;
1989
1990 if ( rc == 0 )
1991 rc = KNSManagerMakeRequest ( self -> kmgr, & req, HTTP_VERSION,
1992 NULL, test -> location );
1993 if ( rc == 0 )
1994 rc = KHttpRequestGET ( req, & rslt );
1995
1996 if ( rc == 0 )
1997 rc = KHttpResultGetInputStream ( rslt, & stream );
1998
1999 #if 0
2000 if(false){
2001 char*c="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"> \n<html>\n<head>\n<title>NCBI - WWW Error Blocked Diagnostic</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n<meta http-equiv=\"pragma\" content=\"no-cache\" />\n<meta http-equiv=\"cache-control\" content=\"no-cache\" />\n<meta name=\"robots\" content=\"noarchive,none\" />\n\n<style type=\"text/css\">\nbody {\nmin-width: 950px;\n_width: 950px;\n}\nh1.error {color: red; font-size: 40pt}\n\n#mainContent {\npadding: 1em 2em;\n}\n\ndl#diags {\npadding: 0.5em 0.5em 1.5em 0.5em;\npadding-left: 2em;\nborder: solid 1px #888;\nborder-left: none;\nborder-right: none;\nmargin-bottom:0;\nbackground-color:#eeeeee;\ncolor:#666;\nfont-size: 80%;\n_font-size: 70%;\nfont-family: Verdana, sans-serif;\n}\n\ndl#diags dt {\nfloat: left;\nfont-weight: bold;\nwidth: auto;\n}\n\ndl#diags dd {\nmargin-left:1em;\nfloat: left;\nmargin-right: 2em;\n}\n\n#footer span {\nfloat: left;\ncolor: #888;\nfont-size: 80%;\n}\n\n#footer {\ntext-align: right;\npadding: 0 0.5em;\nclear: left;\n}\n\n#footer img {\nborder: none;\n}\n\n.ncbi {\nmargin: 0;\npadding:0;\nfont-size:240%;\nfont-weight: bold;\nfont-family: Times, serif;\ncolor: #336699;\nfloat: left;\ndisplay: inline;\n}\n\n.ncbi a {\ntext-decoration: none;\ncolor: #336699;\n}\n\n.ncbi a:visited {\ntext-decoration: none;\ncolor: #336699;\n}\n\n.ncbi a:hover {\ntext-decoration: underline;\n}\n\n.message {\nfont-family: Verdana, sans-serif;\nbackground-color: #336699;\ncolor: white;\npadding: .35em;\nmargin-left: 7em;\nmargin-top: .67em;\n_margin-top: 0.5em;\nfont-weight: bold;\nfont-size: 100%;\nmargin-bottom: 0;\n}\n\nh1 {\nclear: left;\nfont-size: 110%;\nfont-family: Verdana, sans-serif;\n}\n\n\nbody.denied {\nbackground-color: black;\ncolor: white;\n}\n\nbody.denied h1 {\ncolor: red;\n}\n\nbody.denied a {\ncolor: green;\n}\n\nbody.denied #footer, body.denied #diags {\ncolor: black;\n}\n\n#searchme:focus {\nbackground-color: #ffa;\n}\n\n.errurl {\nletter-spacing: 0;\nmargin: 0 1em;\npadding: 0.25em;\nbackground-color: #fff0f0;\ncolor: #c00;\nfont-family: \"Courier New\", Courier, monospace;\nfont-size: 90%;\n_font-size: 80%;\n}\n\nbody.denied .errurl {\nbackground-color: black;\ncolor: yellow;\n}\n\nspan.x {\ndisplay: none;\n}\n\n</style>\n\n</head>\n<body class='denied'>\n\n\n\n\n\n\n<div id='header'>\n<a href=\"#mainContent\" title=\"Skip to main content\" />\n<p class=\"ncbi\"><a href=\"http://www.ncbi.nlm.nih.gov\">NCBI</a></p>\n<p class=\"message\">Error</p>\n</div>\n\n<div id='mainContent'>\n\n\n<h1 class=\"error\">Access Denied</h1>\n\n\n<p>\nYour access to the NCBI website at <b>www.ncbi.nlm.nih.gov</b> has been\ntemporarily blocked due to a possible misuse/abuse situation\ninvolving your site. This is not an indication of a security issue\nsuch as a virus or attack. It could be something as simple as a run\naway script or learning how to better use E-utilities,\n<a href=\"http://www.ncbi.nlm.nih.gov/books/NBK25497/\">http://www.ncbi.nlm.nih.gov/books/NBK25497/</a>,\nfor more efficient work such that your work does not impact the ability of other researchers\nto also use our site.\nTo restore access and understand how to better interact with our site\nto avoid this in the future, please have your system administrator\ncontact \n<a href=\"mailto:info@ncbi.nlm.nih.gov?subject=NCBI Web site BLOCKED: 12.34.567.890&body=%3E%20Error%3Dblocked for possible abuse%0D%3E%20Server%3Dmisuse.ncbi.nlm.nih.gov%0D%3E%20Client%3D12.34.567.890%0D%3E%20Time%3DTuesday, 03-Apr-2018 13:30:17 EDT %0D%0DPlease%20enter%20comments%20below:%0D%0D\">info@ncbi.nlm.nih.gov</a>.\n</p>\n\n</div>\n\n<dl id='diags'>\n\n<dt>Error</dt><dd>blocked for possible abuse </dd>\n<dt>Server</dt><dd>misuse.ncbi.nlm.nih.gov</dd>\n<dt>Client</dt><dd>12.34.567.890</dd>\n<dt>Time</dt><dd>Tuesday, 03-Apr-2018 13:30:17 EDT</dd>\n\n</dl>\n \n\n<p id='footer'>\n<span id='rev'>Rev. 05/18/15</span>\n</p>\n\n</body>\n</html>\n\n";
2002 size_t s = string_size ( c );KDataBufferMakeBytes ( buffer, s + 9 );
2003 memmove(buffer->base,c,s);base = buffer -> base;
2004 buffer->elem_count=s;
2005 }
2006 else
2007 #endif
2008 while ( rc == 0 )
2009 {
2010 size_t num_read = 0;
2011
2012 uint64_t avail = buffer -> elem_count - total;
2013 if ( avail == 0 ) {
2014 rc = KDataBufferResize ( buffer, buffer -> elem_count + 1024 );
2015 if ( rc != 0 )
2016 break;
2017 }
2018
2019 base = buffer -> base;
2020 rc = KStreamRead ( stream, & base [ total ],
2021 ( size_t ) buffer -> elem_count - total, & num_read );
2022 if ( num_read == 0 ) {
2023 buffer -> elem_count = total;
2024 break;
2025 }
2026 if ( rc != 0 ) /* TBD - look more closely at rc */
2027 rc = 0;
2028
2029 total += num_read;
2030 }
2031
2032 if ( rc == 0 ) {
2033 p -> begin = find ( base + i, buffer -> elem_count - i, & open );
2034 if ( p -> begin != NULL ) {
2035 i = p -> begin - base;
2036 p -> end = find ( base + i, buffer -> elem_count - i, & close );
2037 if ( p -> end != NULL )
2038 * ( p -> end ) = '\0';
2039 }
2040 }
2041
2042 if ( p -> end != NULL ) {
2043 CONST_STRING ( & needle, "<a href=\"mailto:" );
2044 test -> mailto . begin = find ( p -> begin, p -> end - p -> begin,
2045 & needle );
2046 if ( test -> mailto . begin != NULL ) {
2047 CONST_STRING ( & needle, "</a>" );
2048 test -> mailto . end = find ( test -> mailto . begin,
2049 p -> end - test -> mailto . begin, & needle );
2050 }
2051 }
2052
2053 if ( test -> mailto . end != NULL ) {
2054 CONST_STRING ( & needle, "Client%3D" );
2055 test -> ip . addr = find ( test -> mailto . begin,
2056 test -> mailto . end - test -> mailto . begin, & needle );
2057 if ( test -> ip . addr == NULL )
2058 test -> ip . addr = "";
2059 else {
2060 test -> ip . addr += needle . size;
2061 c = string_chr ( test -> ip . addr,
2062 test -> mailto . end - test -> ip . addr, '%' );
2063 if ( c != NULL )
2064 test -> ip . len = test -> ip . size = c - test -> ip . addr;
2065 }
2066 }
2067
2068 if ( test -> mailto . end != NULL ) {
2069 CONST_STRING ( & needle, "Time%3D" );
2070 test -> date . addr = find ( test -> mailto . begin,
2071 test -> mailto . end - test -> mailto . begin, & needle );
2072 if ( test -> date . addr == NULL )
2073 test -> date . addr = "";
2074 else {
2075 test -> date . addr += needle . size;
2076 c = string_chr ( test -> date . addr,
2077 test -> mailto . end - test -> date . addr, '%' );
2078 if ( c != NULL )
2079 test -> date . len = test -> date . size
2080 = c - test -> date . addr;
2081 }
2082 }
2083
2084 * abuse = true;
2085
2086 RELEASE ( KStream, stream );
2087 RELEASE ( KHttpResult, rslt );
2088 RELEASE ( KHttpRequest, req );
2089
2090 return rc;
2091 }
2092
STestAbuse(STest * self,Abuse * test,bool * ok,bool * abuse)2093 static rc_t STestAbuse ( STest * self, Abuse * test,
2094 bool * ok, bool * abuse )
2095 {
2096 size_t i = 0;
2097 const char * s = NULL;
2098 const char * h;
2099
2100 String misuse;
2101 CONST_STRING ( & misuse,
2102 "https://misuse.ncbi.nlm.nih.gov/error/abuse.shtml" );
2103
2104 assert ( test && ok && abuse );
2105
2106 * ok = * abuse = false;
2107
2108 if ( test -> code == 200 ) {
2109 * ok = true;
2110 return 0;
2111 }
2112
2113 if ( test -> code != 302 )
2114 return 0;
2115
2116 if ( test -> location != NULL )
2117 return STestAbuseRedirect ( self, test, abuse );
2118
2119 s = test -> response . base;
2120 h = find ( s + i, test -> response . elem_count - i,
2121 & misuse );
2122 if ( h != NULL ) {
2123 rc_t rc = AbuseSetLocation ( test, misuse . addr, misuse . size );
2124 return rc == 0 ? STestAbuseRedirect ( self, test, abuse ) : rc;
2125 }
2126
2127 return 0;
2128 }
2129
processResponse(char * response,size_t size)2130 static char * processResponse ( char * response, size_t size ) {
2131 int n = 0;
2132
2133 size_t i = 0;
2134 for ( i = 0; i < size; ++ n ) {
2135 const char * p = string_chr ( response + i, size - i, '|' );
2136 if ( p == NULL )
2137 return NULL;
2138
2139 i = p - response + 1;
2140
2141 if ( n == 5 ) {
2142 for ( ; response [ i ] != '|' && i < size; ++i )
2143 response [ i ] = 'x';
2144
2145 return response [ i ] == '|' ? response + i + 1 : NULL;
2146 }
2147 }
2148
2149 return NULL;
2150 }
2151
STestCallCgi(STest * self,uint64_t atest,const String * acc,char * response,size_t response_sz,size_t * resp_read,const char ** url,bool http)2152 static rc_t STestCallCgi ( STest * self, uint64_t atest, const String * acc,
2153 char * response, size_t response_sz, size_t * resp_read,
2154 const char ** url, bool http )
2155 {
2156 rc_t rc = 0;
2157
2158 rc_t rs = 0;
2159 KHttpRequest * req = NULL;
2160 const String * cgi = NULL;
2161 KHttpResult * rslt = NULL;
2162 KStream * stream = NULL;
2163 Abuse * test = NULL;
2164
2165 assert ( url && self && self -> dad );
2166
2167 test = & self -> dad -> report . abuse;
2168
2169 STestStart ( self, true, atest,
2170 "Resolving of %s path to '%S'", http ? "HTTPS": "FASP", acc );
2171
2172 * url = NULL;
2173
2174 cgi = KConfig_Resolver ( self -> kfg );
2175 AbuseSetCgi ( test, cgi );
2176 STestStart ( self, false, 0,
2177 "KHttpRequest = KNSManagerMakeReliableClientRequest(%S):", cgi );
2178 rc = KNSManagerMakeReliableClientRequest ( self -> kmgr, & req,
2179 HTTP_VERSION, NULL, "%S", cgi);
2180 if ( rc == 0 )
2181 STestEndOr ( self, & rc, eEndOK, "OK" );
2182 if ( rc != 0 ) {
2183 if ( _RcCanceled ( rc ) )
2184 STestEnd ( self, eCANCELED, "CANCELED" );
2185 else {
2186 self -> dad -> report . firewall = true;
2187 STestEnd ( self, eEndFAIL, "%R", rc );
2188 }
2189 }
2190 if ( rc == 0 ) {
2191 const char param [] = "accept-proto";
2192 const char * v = "http,fasp";
2193 if ( http )
2194 v = "http,https";
2195 rc = KHttpRequestAddPostParam ( req, "%s=%s", param, v );
2196 if ( rc != 0 )
2197 STestFail ( self, rc, 0,
2198 "KHttpRequestAddPostParam(%s=%s)", param, v );
2199 }
2200 if ( rc == 0 ) {
2201 const char param [] = "object";
2202 rc = KHttpRequestAddPostParam ( req, "%s=0||%S", param, acc );
2203 if ( rc != 0 )
2204 STestFail ( self, rc, 0,
2205 "KHttpRequestAddPostParam(%s=0||%S)", param, acc );
2206 }
2207 if ( rc == 0 ) {
2208 const char param [] = "version";
2209 rc = KHttpRequestAddPostParam ( req, "%s=3.0", param );
2210 if ( rc != 0 )
2211 STestFail ( self, rc, 0,
2212 "KHttpRequestAddPostParam(%s=3.0)", param );
2213 }
2214 if ( rc == 0 ) {
2215 rc_t r1 = 0;
2216 const KConfigNode * nProtected = NULL;
2217 KNamelist * names = NULL;
2218 uint32_t count = 0;
2219 const char path [] = "/repository/user/protected";
2220 if ( KConfigOpenNodeRead ( self -> kfg, & nProtected, path ) != 0 )
2221 return 0;
2222 r1 = KConfigNodeListChildren ( nProtected, & names );
2223 if ( r1 == 0 )
2224 r1 = KNamelistCount ( names, & count );
2225 if ( r1 == 0 ) {
2226 uint32_t i = 0;
2227 for ( i = 0; i < count; ++ i ) {
2228 const KConfigNode * node = NULL;
2229 String * tic = NULL;
2230 const char * name = NULL;
2231 r1 = KNamelistGet ( names, i, & name );
2232 if ( r1 != 0 )
2233 continue;
2234 r1 = KConfigNodeOpenNodeRead ( nProtected, & node,
2235 "%s/download-ticket", name );
2236 if ( r1 != 0 )
2237 continue;
2238 r1 = KConfigNodeReadString ( node, & tic );
2239 if ( r1 == 0 ) {
2240 const char param[] = "tic";
2241 rc = KHttpRequestAddPostParam ( req, "%s=%S", param, tic );
2242 if ( rc != 0 )
2243 STestFail ( self, rc, 0,
2244 "KHttpRequestAddPostParam(%s)", param );
2245 free ( tic );
2246 tic = NULL;
2247 }
2248 RELEASE ( KConfigNode, node );
2249 }
2250 }
2251 RELEASE ( KConfigNode, nProtected );
2252 }
2253 if ( rc == 0 ) {
2254 STestStart ( self, false, 0,
2255 "KHttpRequestPOST(KHttpRequest(%S)):", cgi );
2256 rc = KHttpRequestPOST ( req, & rslt );
2257 if ( rc == 0 )
2258 STestEndOr ( self, & rc, eEndOK, "OK" );
2259 if ( rc != 0 ) {
2260 if ( _RcCanceled ( rc ) )
2261 STestEnd ( self, eCANCELED, "CANCELED" );
2262 else
2263 STestEnd ( self, eEndFAIL, "%R", rc );
2264 }
2265 }
2266 if ( rc == 0 ) {
2267 uint32_t code = 0;
2268 STestStart ( self, false, 0,
2269 "KHttpResultStatus(KHttpResult(%S)) =", cgi );
2270 rc = KHttpResultStatus ( rslt, & code, NULL, 0, NULL );
2271 if ( rc != 0 )
2272 STestEnd ( self, eEndFAIL, "%R", rc );
2273 else {
2274 rc = STestEnd ( self, eMSG, "%u: ", code );
2275 if ( rc == 0 ) {
2276 if ( code == 200 )
2277 STestEnd ( self, eEndOK, "OK" );
2278 else {
2279 STestEnd ( self, eEndFAIL, "bad status" );
2280 rs = RC ( rcRuntime, rcFile, rcReading, rcFile, rcInvalid );
2281 }
2282 AbuseSetStatus ( test, code );
2283 }
2284 else if ( STestCanceled ( self, rc ) )
2285 STestEnd ( self, eCANCELED, "CANCELED" );
2286 else
2287 STestEnd ( self, eEndFAIL, "%R", rc );
2288 }
2289 }
2290 if ( rc == 0 ) {
2291 const char name [] = "Location";
2292 rc_t r2 = 0;
2293 char buffer [ PATH_MAX ] = "";
2294 size_t num_read = 0;
2295 STestStart ( self, false, 0, "KClientHttpResultGetHeader(%s)", name );
2296 r2 = KClientHttpResultGetHeader ( rslt, name,
2297 buffer, sizeof buffer, & num_read );
2298 if ( r2 != 0 ) {
2299 if ( r2 == SILENT_RC ( rcNS,rcTree,rcSearching,rcName,rcNotFound ) )
2300 rc = STestEnd ( self, eEndOK, ": not found: OK" );
2301 else
2302 STestEnd ( self, eEndFAIL, "%R", r2 );
2303 }
2304 else {
2305 STestEnd ( self, eEndFAIL, "'%.*s'", ( int ) num_read, buffer );
2306 r2 = AbuseSetLocation ( test, buffer, num_read );
2307 if ( r2 != 0 && rc == 0)
2308 rc = r2;
2309 }
2310 }
2311 if ( rc == 0 ) {
2312 rc = KHttpResultGetInputStream ( rslt, & stream );
2313 if ( rc != 0 )
2314 STestFail ( self, rc, 0, "KHttpResultGetInputStream" );
2315 }
2316 if ( rc == 0 ) {
2317 assert ( resp_read );
2318 STestStart ( self, false, 0, "KStreamRead(KHttpResult(%S)) =", cgi );
2319 rc = KStreamRead ( stream, response, response_sz, resp_read );
2320 if ( rc != 0 )
2321 STestEnd ( self, eEndFAIL, "%R", rc );
2322 else {
2323 if ( * resp_read > response_sz - 4 ) {
2324 response [ response_sz - 4 ] = '.';
2325 response [ response_sz - 3 ] = '.';
2326 response [ response_sz - 2 ] = '.';
2327 response [ response_sz - 1 ] = '\0';
2328 }
2329 else {
2330 response [ * resp_read + 1 ] = '\0';
2331 for ( ; * resp_read > 0 && ( response [ * resp_read ] == '\n' ||
2332 response [ * resp_read ] == '\0' );
2333 -- ( * resp_read ) )
2334 {
2335 response [ * resp_read ] = '\0';
2336 }
2337 }
2338 * url = processResponse ( response, * resp_read );
2339 if ( rs != 0 )
2340 * url = NULL;
2341 rc = STestEnd ( self, eEndOK, "'%s': OK", response );
2342 if ( true )
2343 AbuseAdd ( test, response, * resp_read );
2344 else AbuseAdd(test,"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
2345 "<html><head>\n"
2346 "<title>302 Found</title>\n"
2347 "</head><body>\n"
2348 "<h1>Found</h1>\n"
2349 "<p>The document has moved <a href=\"https://misuse.ncbi.nlm.nih.gov/error/abuse.shtml\">here</a>.</p>\n"
2350 "</body></html>",0);
2351 }
2352 }
2353 {
2354 bool ok = false;
2355 bool abuse = true;
2356 STestAbuse ( self, test, & ok, & abuse );
2357 if ( abuse )
2358 self -> dad -> report . blocked = true;
2359 }
2360 KStreamRelease ( stream );
2361 stream = NULL;
2362 KHttpResultRelease ( rslt );
2363 rslt = NULL;
2364 KHttpRequestRelease ( req );
2365 req = NULL;
2366 free ( ( void * ) cgi );
2367 cgi = NULL;
2368 /*AbuseAdd(test,"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
2369 "<html><head>\n"
2370 "<title>302 Found</title>\n"
2371 "</head><body>\n"
2372 "<h1>Found</h1>\n"
2373 "<p>The document has moved <a href=\"https://misuse.ncbi.nlm.nih.gov/error/abuse.shtml\">here</a>.</p>\n"
2374 "</body></html>",0);*/
2375 if ( rc == 0 ) {
2376 const char * server = test -> server;
2377 if ( server == NULL )
2378 server = "www.ncbi.nlm.nih.gov ";
2379 if ( rs == 0 )
2380 rc = STestEnd ( self, eOK, "Resolving of %s path to '%S'",
2381 http ? "HTTPS": "FASP", acc );
2382 else {
2383 rc = rs;
2384 STestEnd ( self, eFAIL, "Resolving of %s path to '%S'",
2385 http ? "HTTPS": "FASP", acc );
2386 }
2387 }
2388 else if ( _RcCanceled ( rc ) )
2389 STestEnd ( self, eCANCELED, "Resolving of %s path to '%S': CANCELED",
2390 http ? "HTTPS": "FASP", acc );
2391 else
2392 STestEnd ( self, eFAIL, "Resolving of %s path to '%S'",
2393 http ? "HTTPS": "FASP", acc );
2394 return rc;
2395 }
2396
STestCheckFaspDownload(STest * self,const char * url,const char * cache,uint64_t * cacheSz)2397 static rc_t STestCheckFaspDownload ( STest * self, const char * url,
2398 const char * cache, uint64_t * cacheSz )
2399 {
2400 rc_t rc = 0;
2401
2402 uint32_t m = 0;
2403 String fasp;
2404 String schema;
2405
2406 assert ( self );
2407
2408 if ( ! self -> ascpChecked ) {
2409 ascp_locate ( & self -> ascp, & self -> asperaKey, true, true);
2410 self -> ascpChecked = true;
2411
2412 if ( self -> ascp == NULL ) {
2413 STestStart ( self, false, 0, "ascp download test:" );
2414 rc = STestEnd ( self, eEndOK, "skipped: ascp not found" );
2415 }
2416 }
2417
2418 if ( self -> ascp == NULL )
2419 return rc;
2420
2421 STestStart ( self, false, KDIAGN_ASCP_DOWNLOAD, "ascp download test:" );
2422
2423 CONST_STRING ( & fasp, "fasp://" );
2424
2425 m = string_measure ( url, NULL );
2426 if ( m < fasp . size ) {
2427 LogOut ( KVERBOSITY_ERROR, 0, "UNEXPECTED SCHEMA IN '%s'", url );
2428 return 0;
2429 }
2430
2431 StringInit( & schema, url, fasp . size, fasp . len );
2432 if ( ! StringEqual ( & schema, & fasp ) ) {
2433 LogOut ( KVERBOSITY_ERROR, 0, "UNEXPECTED SCHEMA IN '%s'", url );
2434 return 0;
2435 }
2436
2437 if ( rc == 0 ) {
2438 STestRemoveCache ( self, cache );
2439 rc = aspera_get ( self -> ascp, self -> asperaKey,
2440 url + fasp . size, cache, 0 );
2441 }
2442
2443 if ( rc == 0 )
2444 rc = KDirectoryFileSize ( self -> dir, cacheSz, cache );
2445 if ( rc == 0 )
2446 STestEndOr ( self, & rc, eEndOK, "OK" );
2447 if ( rc != 0 ) {
2448 if ( _RcCanceled ( rc ) )
2449 STestEnd ( self, eCANCELED, "CANCELED" );
2450 else
2451 STestEnd ( self, eEndFAIL, "%R", rc );
2452 }
2453
2454 return rc;
2455 }
2456
2457 /******************************************************************************/
2458
2459 /*
2460 static rc_t _STestCheckAcc ( STest * self, const Data * data, bool print,
2461 const char * exp, size_t esz )
2462 {
2463 rc_t rc = 0;
2464 char response [ 4096 ] = "";
2465 size_t resp_len = 0;
2466 const char * url = NULL;
2467 String acc;
2468 bool checked = false;
2469
2470 const VPath * vcache = NULL;
2471 char faspCache [ PATH_MAX ] = "";
2472 uint64_t faspCacheSize = 0;
2473 char httpCache [ PATH_MAX ] = "";
2474 uint64_t httpCacheSize = 0;
2475
2476 assert ( self && data );
2477
2478 memset ( & acc, 0, sizeof acc );
2479 if ( DataIsAccession ( data ) ) {
2480 Abuse test;
2481 AbuseInit ( & test );
2482 acc = * data -> acc;
2483 rc = STestCallCgi ( self, & acc, response, sizeof response,
2484 & resp_len, & url, & test, true | false );
2485 AbuseFini ( & test );
2486 }
2487 if ( acc . size != 0 ) {
2488 String cache;
2489 VPath * path = NULL;
2490 rc_t r2 = VFSManagerMakePath ( self -> vmgr, & path,
2491 "%S", data -> acc );
2492 if ( r2 == 0 )
2493 r2 = VResolverQuery ( self -> resolver, eProtocolFasp,
2494 path, NULL, NULL, & vcache);
2495 // TODO: find another cache location if r2 != 0
2496 if ( r2 == 0 )
2497 r2 = VPathGetPath ( vcache, & cache );
2498 if ( r2 == 0 ) {
2499 rc_t r1 = string_printf ( faspCache, sizeof faspCache, NULL,
2500 "%S.fasp", & cache );
2501 r2 = string_printf ( httpCache, sizeof httpCache, NULL,
2502 "%S.http", & cache );
2503 if ( r2 == 0 )
2504 r2 = r1;
2505 }
2506 RELEASE ( VPath, path );
2507 if ( rc == 0 && r2 != 0 )
2508 rc = r2;
2509 }
2510 if ( url != NULL ) {
2511 char * p = string_chr ( url, resp_len - ( url - response ), '|' );
2512 if ( p == NULL ) {
2513 rc = RC ( rcRuntime, rcString ,rcParsing, rcString, rcIncorrect );
2514 STestFail ( self, rc, "UNEXPECTED RESOLVER RESPONSE" );
2515 }
2516 else {
2517 const String * full = NULL;
2518 rc_t r2 = VPathMakeString ( data -> vpath, & full );
2519 char * d = NULL;
2520 if ( r2 != 0 )
2521 LogOut ( KVERBOSITY_ERROR, 0,
2522 "CANNOT VPathMakeString: %R\n", r2 );
2523 d = string_chr ( url, resp_len - ( url - response ), '$' );
2524 if ( d == NULL )
2525 d = p;
2526 while ( d != NULL && d <= p ) {
2527 if ( ! checked && full != NULL && string_cmp ( full -> addr,
2528 full -> size, url, d - url, d - url ) == 0 )
2529 {
2530 checked = true;
2531 }
2532 * d = '\0';
2533 switch ( * url ) {
2534 case 'h': {
2535 Data dt;
2536 if ( rc == 0 )
2537 rc = DataInit ( & dt, self -> vmgr, url );
2538 if ( rc == 0 ) {
2539 rc_t r1 = STestCheckUrl ( self, & dt,
2540 httpCache, & httpCacheSize, print, exp, esz );
2541 if ( rc == 0 && r1 != 0 )
2542 rc = r1;
2543 }
2544 DataFini ( & dt );
2545 break;
2546 }
2547 case 'f': {
2548 rc_t r1 = STestCheckFaspDownload ( self, url,
2549 faspCache, & faspCacheSize );
2550 if ( rc == 0 && r1 != 0 )
2551 rc = r1;
2552 break;
2553 }
2554 default:
2555 break;
2556 }
2557 if ( d == p )
2558 break;
2559 url = d + 1;
2560 d = string_chr ( d, resp_len - ( d - response ), '$' );
2561 if ( d > p )
2562 d = p;
2563 }
2564 free ( ( void * ) full );
2565 full = NULL;
2566 }
2567 }
2568 if ( ! checked ) {
2569 rc_t r1 = STestCheckUrl ( self, data, httpCache, & httpCacheSize,
2570 print, exp, esz );
2571 if ( rc == 0 && r1 != 0 )
2572 rc = r1;
2573 }
2574 if ( faspCacheSize != 0 && httpCacheSize != 0 ) {
2575 uint64_t pos = 0;
2576 rc_t r1 = 0;
2577 STestStart ( self, false, "HTTP vs ASCP download:" );
2578 if ( faspCacheSize != httpCacheSize ) {
2579 r1 = RC ( rcRuntime, rcFile, rcComparing, rcSize, rcUnequal );
2580 STestEnd ( self, eEndFAIL, "FAILURE: size does not match: "
2581 "ascp(%lu)/http(%lu)", faspCacheSize, httpCacheSize );
2582 }
2583 else {
2584 const KFile * ascp = NULL;
2585 const KFile * http = NULL;
2586 rc_t r1 = KDirectoryOpenFileRead ( self -> dir, & ascp, faspCache );
2587 if ( r1 != 0 )
2588 LogOut ( KVERBOSITY_ERROR, 0,
2589 "KDirectoryOpenFileRead(%s)=%R\n", faspCache, r1 );
2590 else {
2591 r1 = KDirectoryOpenFileRead ( self -> dir, & http, httpCache );
2592 if ( r1 != 0 )
2593 LogOut ( KVERBOSITY_ERROR, 0,
2594 "KDirectoryOpenFileRead(%s)=%R\n", httpCache, r1 );
2595 }
2596 if ( r1 == 0 ) {
2597 char bAscp [ 1024 ] = "";
2598 char bHttp [ 1024 ] = "";
2599 size_t ascp_read = 0;
2600 size_t http_read = 0;
2601 while ( r1 == 0 ) {
2602 r1 = KFileReadAll ( ascp, pos, bAscp, sizeof bAscp,
2603 & ascp_read );
2604 if ( r1 != 0 ) {
2605 STestEnd ( self, eEndFAIL, "FAILURE to read '%s': %R",
2606 faspCache, r1 );
2607 break;
2608 }
2609 r1 = KFileReadAll ( http, pos, bHttp, sizeof bHttp,
2610 & http_read );
2611 if ( r1 != 0 ) {
2612 STestEnd ( self, eEndFAIL, "FAILURE to read '%s': %R",
2613 httpCache, r1 );
2614 break;
2615 }
2616 else if ( ascp_read != http_read ) {
2617 r1 = RC (
2618 rcRuntime, rcFile, rcComparing, rcSize, rcUnequal );
2619 STestEnd ( self, eEndFAIL,
2620 "FAILURE to read the same amount from files" );
2621 break;
2622 }
2623 else if ( ascp_read == 0 )
2624 break;
2625 else {
2626 pos += ascp_read;
2627 if ( string_cmp ( bAscp, ascp_read,
2628 bHttp, http_read, ascp_read ) != 0 )
2629 {
2630 r1 = RC ( rcRuntime,
2631 rcFile, rcComparing, rcData, rcUnequal );
2632 STestEnd ( self, eEndFAIL,
2633 "FAILURE: files are different" );
2634 break;
2635 }
2636 }
2637 }
2638 }
2639 RELEASE ( KFile, ascp );
2640 RELEASE ( KFile, http );
2641 }
2642 if ( r1 == 0 ) {
2643 rc_t r2 = 0;
2644 r1 = KDirectoryRemove ( self -> dir, false, faspCache );
2645 if ( r1 != 0 )
2646 STestEnd ( self, eEndFAIL, "FAILURE: cannot remove '%s': %R",
2647 faspCache, r1 );
2648 r2 = KDirectoryRemove ( self -> dir, false, httpCache );
2649 if ( r2 != 0 ) {
2650 if ( r1 == 0 ) {
2651 r1 = r2;
2652 STestEnd ( self, eEndFAIL,
2653 "FAILURE: cannot remove '%s': %R", httpCache, r1 );
2654 }
2655 else
2656 LogOut ( KVERBOSITY_ERROR, 0,
2657 "Cannot remove '%s': %R\n", httpCache, r2 );
2658 }
2659 if ( r1 == 0 )
2660 rc = STestEnd ( self, eEndOK, "%lu bytes compared: OK", pos );
2661 else if ( rc == 0 )
2662 rc = r1;
2663 }
2664 }
2665
2666 if ( acc . size != 0 ) {
2667 if ( rc == 0 )
2668 rc = STestEnd ( self, eOK, "Access to '%S'", & acc );
2669 else if ( _RcCanceled ( rc ) )
2670 STestEnd ( self, eCANCELED, "Access to '%S': CANCELED", & acc );
2671 else
2672 STestEnd ( self, eFAIL, "Access to '%S'", & acc );
2673 }
2674
2675 RELEASE ( VPath, vcache );
2676 return rc;
2677 }
2678 */
2679 # if 0
2680 static rc_t _STestCheckNetwork ( STest * self, const Data * data,
2681 const char * exp, size_t esz, const Data * data2,
2682 const char * fmt, ... )
2683 {
2684 rc_t rc = 0;
2685 KEndPoint ep;
2686 char b [ 512 ] = "";
2687 String host;
2688
2689 va_list args;
2690 va_start ( args, fmt );
2691 rc = string_vprintf ( b, sizeof b, NULL, fmt, args );
2692 if ( rc != 0 )
2693 STestFail ( self, rc, "CANNOT PREPARE MESSAGE" );
2694 va_end ( args );
2695
2696 assert ( self && data );
2697
2698 STestStart ( self, true, b );
2699 rc = VPathGetHost ( data -> vpath, & host );
2700 if ( rc != 0 )
2701 STestFail ( self, rc, "VPathGetHost" );
2702 else {
2703 rc_t r1 = 0;
2704 uint16_t port = 443;
2705 STestStart ( self, false, "KNSManagerInitDNSEndpoint(%S:%hu)",
2706 & host, port );
2707 rc = KNSManagerInitDNSEndpoint ( self -> kmgr, & ep, & host, port );
2708 if ( rc != 0 )
2709 STestEnd ( self, eEndFAIL, ": FAILURE: %R", rc );
2710 else {
2711 char endpoint [ 1024 ] = "";
2712 rc_t rx = endpoint_to_string ( endpoint, sizeof endpoint, & ep );
2713 if ( rx == 0 )
2714 STestEndOr ( self, & rx, eEndOK, "= '%s': OK", endpoint );
2715 if ( rx != 0 ) {
2716 if ( _RcCanceled ( rx ) )
2717 STestEnd ( self, eCANCELED, "CANCELED" );
2718 else
2719 STestEnd ( self, eEndFAIL,
2720 "CANNOT CONVERT TO STRING: %R", rx );
2721 }
2722 }
2723 port = 80;
2724 STestStart ( self, false, "KNSManagerInitDNSEndpoint(%S:%hu)",
2725 & host, port );
2726 r1 = KNSManagerInitDNSEndpoint ( self -> kmgr, & ep,
2727 & host, port );
2728 if ( r1 != 0 )
2729 STestEnd ( self, eEndFAIL, "FAILURE: %R", r1 );
2730 else {
2731 char endpoint [ 1024 ] = "";
2732 rc_t rx = endpoint_to_string ( endpoint, sizeof endpoint, & ep );
2733 if ( rx == 0 )
2734 STestEndOr ( self, & rx, eEndOK, "= '%s': OK", endpoint );
2735 if ( rx != 0 ) {
2736 if ( _RcCanceled ( rx ) )
2737 STestEnd ( self, eCANCELED, "CANCELED" );
2738 else
2739 STestEnd ( self, eEndFAIL,
2740 "CANNOT CONVERT TO STRING: %R", rx );
2741 }
2742 }
2743 rc = KNSManagerInitDNSEndpoint ( self -> kmgr, & ep, & host, port );
2744 if ( rc == 0 ) {
2745 rc = _STestCheckAcc ( self, data, false, exp, esz );
2746 if ( data2 != NULL ) {
2747 rc_t r2 = _STestCheckAcc ( self, data2, true, 0, 0 );
2748 if ( rc == 0 && r2 != 0 )
2749 rc = r2;
2750 }
2751 }
2752 if ( rc == 0 && r1 != 0 )
2753 rc = r1;
2754 }
2755
2756 if ( rc == 0 )
2757 rc = STestEnd ( self, eOK, b );
2758 else if ( _RcCanceled ( rc ) )
2759 STestEnd ( self, eCANCELED, "%s: CANCELED", b );
2760 else
2761 STestEnd ( self, eFAIL, b );
2762 return rc;
2763 }
2764 #endif
2765
2766 struct KDiagnoseTestDesc {
2767 const char * name;
2768 const char * desc;
2769 uint64_t code;
2770 uint32_t level;
2771 KDiagnoseTestDesc * next;
2772 KDiagnoseTestDesc * child;
2773 const KDiagnoseTestDesc * depends;
2774 };
2775
KDiagnoseTestDescRelease(KDiagnoseTestDesc * self)2776 static rc_t KDiagnoseTestDescRelease ( KDiagnoseTestDesc * self ) {
2777 if ( self != NULL ) {
2778 if ( self -> child )
2779 KDiagnoseTestDescRelease ( self -> child );
2780
2781 if ( self -> next )
2782 KDiagnoseTestDescRelease ( self -> next );
2783
2784 memset ( self, 0, sizeof * self );
2785
2786 free ( self );
2787 }
2788
2789 return 0;
2790 }
2791
KDiagnoseTestDescMake(KDiagnoseTestDesc ** self,uint32_t level,const char * name,uint64_t code)2792 static rc_t KDiagnoseTestDescMake ( KDiagnoseTestDesc ** self,
2793 uint32_t level, const char * name, uint64_t code )
2794 {
2795 assert ( self );
2796
2797 * self = calloc ( 1, sizeof ** self );
2798
2799 if ( * self == NULL )
2800 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
2801 else {
2802 ( * self ) -> name = name;
2803 ( * self ) -> desc = "";
2804 ( * self ) -> code = code;
2805 ( * self ) -> level = level;
2806
2807 return 0;
2808 }
2809 }
2810
KDiagnoseMakeDesc(KDiagnose * self)2811 static rc_t KDiagnoseMakeDesc ( KDiagnose * self ) {
2812 rc_t rc = 0;
2813
2814 KDiagnoseTestDesc * root = NULL;
2815 KDiagnoseTestDesc * kfg = NULL;
2816
2817 KDiagnoseTestDesc * net = NULL;
2818 KDiagnoseTestDesc * netNcbi = NULL;
2819 KDiagnoseTestDesc * netHttp = NULL;
2820 KDiagnoseTestDesc * netAscp = NULL;
2821 KDiagnoseTestDesc * netHttpVsAscp = NULL;
2822
2823 assert ( self );
2824
2825 if ( rc == 0 )
2826 rc = KDiagnoseTestDescMake ( & root, 0, "System", KDIAGN_ALL );
2827 {
2828 KDiagnoseTestDesc * kfgRemote = NULL;
2829 KDiagnoseTestDesc * kfgSite = NULL;
2830 KDiagnoseTestDesc * kfgUser = NULL;
2831 KDiagnoseTestDesc * kfgAscp = NULL;
2832 KDiagnoseTestDesc * kfgGap = NULL;
2833
2834 if ( rc == 0 ) {
2835 rc = KDiagnoseTestDescMake ( & kfg, 1, "Configuration", KDIAGN_CONFIG );
2836 if ( rc == 0 )
2837 root -> child = kfg;
2838 }
2839 if ( rc == 0 ) {
2840 rc = KDiagnoseTestDescMake ( & kfgRemote, 2, "Remote repository",
2841 KDIAGN_REPO_REMOTE );
2842 if ( rc == 0 )
2843 kfg -> child = kfgRemote;
2844 }
2845 if ( rc == 0 ) {
2846 rc = KDiagnoseTestDescMake ( & kfgSite, 2, "Site repository",
2847 KDIAGN_REPO_SITE );
2848 if ( rc == 0 )
2849 kfgRemote -> next = kfgSite;
2850 }
2851 if ( rc == 0 ) {
2852 rc = KDiagnoseTestDescMake ( & kfgUser, 2, "Public user repository",
2853 KDIAGN_REPO_USER_PUBLIC );
2854 if ( rc == 0 )
2855 kfgSite -> next = kfgUser;
2856 }
2857 if ( rc == 0 ) {
2858 rc = KDiagnoseTestDescMake ( & kfgAscp, 2, "ascp transfer rate",
2859 KDIAGN_KFG_ASCP );
2860 if ( rc == 0 )
2861 kfgUser -> next = kfgAscp;
2862 }
2863 if ( rc == 0 ) {
2864 rc = KDiagnoseTestDescMake ( & kfgGap, 2, "DbGaP configuration",
2865 KDIAGN_REPO_GAP );
2866 if ( rc == 0 )
2867 kfgAscp -> next = kfgGap;
2868 }
2869 }
2870
2871 if ( rc == 0 ) {
2872 rc = KDiagnoseTestDescMake ( & net, 1, "Network", KDIAGN_NETWORK );
2873 if ( rc == 0 )
2874 kfg -> next = net;
2875 }
2876
2877 {
2878 KDiagnoseTestDesc * netNcbiHttp = NULL;
2879 KDiagnoseTestDesc * netNcbiHttps = NULL;
2880 KDiagnoseTestDesc * netNcbiFtp = NULL;
2881 KDiagnoseTestDesc * netNcbiVers = NULL;
2882 if ( rc == 0 ) {
2883 rc = KDiagnoseTestDescMake ( & netNcbi, 2, "Access to NCBI",
2884 KDIAGN_ACCESS_NCBI );
2885 if ( rc == 0 ) {
2886 net -> child = netNcbi;
2887 //netNcbi -> depends = kfgCommon;
2888 }
2889 }
2890 if ( rc == 0 ) {
2891 rc = KDiagnoseTestDescMake ( & netNcbiHttp, 3,
2892 "KNSManagerInitDNSEndpoint(www.ncbi.nlm.nih.gov:80)",
2893 KDIAGN_ACCESS_NCBI_HTTP );
2894 if ( rc == 0 ) {
2895 netNcbi -> child = netNcbiHttp;
2896 }
2897 }
2898 if ( rc == 0 ) {
2899 rc = KDiagnoseTestDescMake ( & netNcbiHttps, 3,
2900 "KNSManagerInitDNSEndpoint(www.ncbi.nlm.nih.gov:443)",
2901 KDIAGN_ACCESS_NCBI_HTTPS );
2902 if ( rc == 0 ) {
2903 netNcbiHttp -> next = netNcbiHttps;
2904 }
2905 }
2906 #define FTP "ftp-trace.ncbi.nlm.nih.gov"
2907 if ( rc == 0 ) {
2908 rc = KDiagnoseTestDescMake ( & netNcbiFtp, 3,
2909 "KNSManagerInitDNSEndpoint(" FTP ":443)", KDIAGN_ACCESS_NCBI_FTP );
2910 if ( rc == 0 ) {
2911 netNcbiHttps -> next = netNcbiFtp;
2912 }
2913 }
2914 if ( rc == 0 ) {
2915 rc = KDiagnoseTestDescMake ( & netNcbiVers, 3, "Access to "
2916 "'https://" FTP "/sra/sdk/current/sratoolkit.current.version'",
2917 KDIAGN_ACCESS_NCBI_VERSION );
2918 if ( rc == 0 ) {
2919 netNcbiFtp -> next = netNcbiVers;
2920 }
2921 }
2922 }
2923
2924 if ( rc == 0 ) {
2925 rc = KDiagnoseTestDescMake ( & netHttp, 2, "HTTPS download",
2926 KDIAGN_HTTP );
2927 if ( rc == 0 ) {
2928 netNcbi -> next = netHttp;
2929 // netHttp -> depends = netNcbi;
2930 }
2931 }
2932 {
2933 KDiagnoseTestDesc * netHttpRun = NULL;
2934 KDiagnoseTestDesc * netHttpCgi = NULL;
2935 KDiagnoseTestDesc * netHttpSmall = NULL;
2936 KDiagnoseTestDesc * netVfsSmall = NULL;
2937 if ( rc == 0 ) {
2938 rc = KDiagnoseTestDescMake ( & netHttpRun, 3, "HTTPS access to a run",
2939 KDIAGN_HTTP_RUN );
2940 if ( rc == 0 ) {
2941 netHttp -> child = netHttpRun;
2942 }
2943 }
2944 if ( rc == 0 ) {
2945 rc = KDiagnoseTestDescMake ( & netHttpCgi, 4, "Resolving of HTTPS path",
2946 KDIAGN_HTTP_CGI );
2947 if ( rc == 0 ) {
2948 netHttpRun -> child = netHttpCgi;
2949 }
2950 }
2951 if ( rc == 0 ) {
2952 rc = KDiagnoseTestDescMake ( & netHttpSmall, 4, "Access to a small run",
2953 KDIAGN_HTTP_SMALL_ACCESS );
2954 if ( rc == 0 ) {
2955 netHttpCgi -> next = netHttpSmall;
2956 // netAscp -> depends = netNcbi;
2957 }
2958 }
2959 if ( rc == 0 ) {
2960 rc = KDiagnoseTestDescMake ( & netVfsSmall, 4,
2961 "VFSManagerOpenDirectoryRead(a small run)", KDIAGN_HTTP_SMALL_VFS );
2962 if ( rc == 0 ) {
2963 netHttpSmall -> next = netVfsSmall;
2964 // netAscp -> depends = netNcbi;
2965 }
2966 }
2967 }
2968 if ( rc == 0 ) {
2969 rc = KDiagnoseTestDescMake ( & netAscp, 2, "Aspera download",
2970 KDIAGN_ASCP );
2971 if ( rc == 0 ) {
2972 netHttp -> next = netAscp;
2973 // netAscp -> depends = netNcbi;
2974 }
2975 }
2976 {
2977 KDiagnoseTestDesc * netRun = NULL;
2978 KDiagnoseTestDesc * netCgi = NULL;
2979 KDiagnoseTestDesc * download = NULL;
2980
2981 if ( rc == 0 ) {
2982 rc = KDiagnoseTestDescMake ( & netRun, 3, "Aspera access to a run",
2983 KDIAGN_ASCP_RUN );
2984 if ( rc == 0 ) {
2985 netAscp -> child = netRun;
2986 }
2987 }
2988 if ( rc == 0 ) {
2989 rc = KDiagnoseTestDescMake ( & netCgi, 4, "Resolving of FASP path",
2990 KDIAGN_ASCP_CGI );
2991 if ( rc == 0 ) {
2992 netRun -> child = netCgi;
2993 }
2994 }
2995 if ( rc == 0 ) {
2996 rc = KDiagnoseTestDescMake ( & download, 4, "ascp download test",
2997 KDIAGN_ASCP_DOWNLOAD );
2998 if ( rc == 0 ) {
2999 netCgi -> next = download;
3000 }
3001 }
3002 }
3003
3004 if ( rc == 0 ) {
3005 rc = KDiagnoseTestDescMake ( & netHttpVsAscp, 2,
3006 "HTTP vs ASCP download", KDIAGN_HTTP_VS_ASCP );
3007 if ( rc == 0 ) {
3008 netAscp -> next = netHttpVsAscp;
3009 }
3010 }
3011
3012 if ( rc != 0 )
3013 KDiagnoseTestDescRelease ( root );
3014 else
3015 self -> desc = root;
3016
3017 return rc;
3018 }
3019
3020 static const char DIAGNOSE_CLSNAME [] = "KDiagnose";
3021
KDiagnoseMakeExt(KDiagnose ** test,KConfig * kfg,KNSManager * kmgr,VFSManager * vmgr,rc_t (CC * quitting)(void))3022 LIB_EXPORT rc_t CC KDiagnoseMakeExt ( KDiagnose ** test, KConfig * kfg,
3023 KNSManager * kmgr, VFSManager * vmgr, rc_t (CC *quitting)(void) )
3024 {
3025 rc_t rc = 0;
3026
3027 KDiagnose * p = NULL;
3028
3029 if ( test == NULL )
3030 return RC ( rcRuntime, rcData, rcCreating, rcParam, rcNull );
3031
3032 p = calloc ( 1, sizeof * p );
3033 if ( p == NULL )
3034 return RC ( rcRuntime, rcData, rcAllocating, rcMemory, rcExhausted );
3035
3036 if ( kfg == NULL ) {
3037 rc_t r2 = KConfigMake ( & p -> kfg, NULL );
3038 if ( rc == 0 && r2 != 0 )
3039 rc = r2;
3040 }
3041 else {
3042 rc_t r2 = KConfigAddRef ( kfg );
3043 if ( r2 == 0 )
3044 p -> kfg = kfg;
3045 else if ( rc == 0 )
3046 rc = r2;
3047 }
3048
3049 if ( kmgr == NULL ) {
3050 rc_t r2 = KNSManagerMake ( & p -> kmgr );
3051 if ( rc == 0 && r2 != 0 )
3052 rc = r2;
3053 }
3054 else {
3055 rc_t r2 = KNSManagerAddRef ( kmgr );
3056 if ( r2 == 0 )
3057 p -> kmgr = kmgr;
3058 else if ( rc == 0 )
3059 rc = r2;
3060 }
3061
3062 if ( vmgr == NULL ) {
3063 rc_t r2 = VFSManagerMake ( & p -> vmgr );
3064 if ( rc == 0 && r2 != 0 )
3065 rc = r2;
3066 }
3067 else {
3068 rc_t r2 = VFSManagerAddRef ( vmgr );
3069 if ( r2 == 0 )
3070 p -> vmgr = vmgr;
3071 else if ( rc == 0 )
3072 rc = r2;
3073 }
3074
3075 if ( rc == 0 )
3076 rc = KLockMake ( & p -> lock );
3077 if ( rc == 0 )
3078 rc = KConditionMake ( & p -> condition );
3079
3080 if ( rc == 0 )
3081 rc = KDiagnoseMakeDesc ( p );
3082
3083 if ( rc == 0 ) {
3084 p -> verbosity = KConfig_Verbosity ( p -> kfg );
3085 KRefcountInit ( & p -> refcount, 1, DIAGNOSE_CLSNAME, "init", "" );
3086 p -> quitting = quitting;
3087 AbuseInit ( & p -> report . abuse );
3088 * test = p;
3089 }
3090 else
3091 KDiagnoseRelease ( p );
3092
3093 return rc;
3094 }
3095
KDiagnoseAddRef(const KDiagnose * self)3096 LIB_EXPORT rc_t CC KDiagnoseAddRef ( const KDiagnose * self ) {
3097 if ( self != NULL )
3098 switch ( KRefcountAdd ( & self -> refcount, DIAGNOSE_CLSNAME ) ) {
3099 case krefLimit:
3100 return RC ( rcRuntime,
3101 rcData, rcAttaching, rcRange, rcExcessive );
3102 }
3103
3104 return 0;
3105 }
3106
errorWhack(void * item,void * data)3107 static void CC errorWhack ( void * item, void * data )
3108 { KDiagnoseErrorWhack ( item ); }
testsWhack(void * item,void * data)3109 static void CC testsWhack ( void * item, void * data )
3110 { KDiagnoseTestWhack ( item ); }
3111
KDiagnoseRelease(const KDiagnose * cself)3112 LIB_EXPORT rc_t CC KDiagnoseRelease ( const KDiagnose * cself ) {
3113 rc_t rc = 0;
3114
3115 KDiagnose * self = ( KDiagnose * ) cself;
3116
3117 if ( self != NULL )
3118 switch ( KRefcountDrop ( & self -> refcount, DIAGNOSE_CLSNAME ) ) {
3119 case krefWhack:
3120 RELEASE ( KConfig , self -> kfg );
3121 RELEASE ( KNSManager, self -> kmgr );
3122 RELEASE ( VFSManager, self -> vmgr );
3123 RELEASE ( KLock , self -> lock );
3124 RELEASE ( KCondition, self -> condition );
3125 VectorWhack ( & self -> tests , & testsWhack, NULL );
3126 VectorWhack ( & self -> errors, & errorWhack, NULL );
3127
3128 RELEASE ( KDiagnoseTestDesc, self -> desc );
3129
3130 AbuseFini ( & self -> report . abuse );
3131
3132 free ( self );
3133 break;
3134 case krefNegative:
3135 return RC ( rcRuntime,
3136 rcData, rcReleasing, rcRange, rcExcessive );
3137 }
3138
3139 return rc;
3140 }
3141
_KDiagnoseSetState(KDiagnose * self,enum EState state)3142 static rc_t _KDiagnoseSetState ( KDiagnose * self, enum EState state ) {
3143 rc_t rc = 0;
3144 rc_t r2 = 0;
3145
3146 if ( self == NULL )
3147 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
3148
3149 rc = KLockAcquire ( self -> lock );
3150
3151 if ( rc == 0 ) {
3152 self -> state = state;
3153
3154 rc = KConditionSignal ( self -> condition );
3155 }
3156
3157 r2 = KLockUnlock ( self -> lock );
3158 if ( rc == 0 && r2 != 0 )
3159 rc = r2;
3160
3161 return rc;
3162 }
3163
KDiagnosePause(KDiagnose * self)3164 LIB_EXPORT rc_t CC KDiagnosePause ( KDiagnose * self ) {
3165 return _KDiagnoseSetState ( self, ePaused );
3166 }
3167
KDiagnoseResume(KDiagnose * self)3168 LIB_EXPORT rc_t CC KDiagnoseResume ( KDiagnose * self ) {
3169 return _KDiagnoseSetState ( self, eRunning );
3170 }
3171
KDiagnoseCancel(KDiagnose * self)3172 LIB_EXPORT rc_t CC KDiagnoseCancel ( KDiagnose * self ) {
3173 return _KDiagnoseSetState ( self, eCanceled );
3174 }
3175
KDiagnoseGetDesc(const KDiagnose * self,const KDiagnoseTestDesc ** desc)3176 LIB_EXPORT rc_t CC KDiagnoseGetDesc ( const KDiagnose * self,
3177 const KDiagnoseTestDesc ** desc )
3178 {
3179 if ( desc == NULL )
3180 return RC ( rcRuntime, rcData, rcAccessing, rcParam, rcNull );
3181
3182 * desc = NULL;
3183
3184 if ( self == NULL )
3185 return RC ( rcRuntime, rcData, rcAccessing, rcSelf, rcNull );
3186
3187 * desc = self -> desc;
3188
3189 return 0;
3190 }
3191
STestKNSManagerInitDNSEndpoint(STest * self,uint64_t tests,const String * host,uint16_t port,bool warn)3192 static rc_t STestKNSManagerInitDNSEndpoint ( STest * self, uint64_t tests,
3193 const String * host, uint16_t port, bool warn )
3194 {
3195 rc_t rc = 0;
3196
3197 KEndPoint ep;
3198
3199 assert ( self && self -> dad );
3200
3201 STestStart ( self, false, tests, "KNSManagerInitDNSEndpoint(%S:%hu)",
3202 host, port );
3203 rc = KNSManagerInitDNSEndpoint ( self -> kmgr, & ep, host, port );
3204 if ( rc != 0 ) {
3205 self -> dad -> report . firewall = true;
3206 STestEnd ( self, warn ? eWarning : eEndFAIL, "%R", rc );
3207 }
3208 else {
3209 char endpoint [ 1024 ] = "";
3210 rc_t rx = endpoint_to_string ( endpoint, sizeof endpoint, & ep );
3211 if ( rx == 0 )
3212 STestEndOr ( self, & rx, eEndOK, "= '%s': OK", endpoint );
3213 if ( rx != 0 ) {
3214 if ( _RcCanceled ( rx ) )
3215 STestEnd ( self, eCANCELED, "CANCELED" );
3216 else
3217 STestEnd ( self, eEndFAIL, "CANNOT CONVERT TO STRING: %R", rx );
3218 }
3219 }
3220
3221 return rc;
3222 }
3223
STestCheckNcbiAccess(STest * self,uint64_t tests)3224 static rc_t STestCheckNcbiAccess ( STest * self, uint64_t tests ) {
3225 rc_t rc = 0;
3226
3227 String www;
3228 CONST_STRING ( & www, "www.ncbi.nlm.nih.gov" );
3229
3230 if ( tests & KDIAGN_ACCESS_NCBI_HTTP ) {
3231 rc_t r1 = STestKNSManagerInitDNSEndpoint ( self,
3232 KDIAGN_ACCESS_NCBI_HTTP, & www, 80, false );
3233 if ( rc == 0 && r1 != 0 )
3234 rc = r1;
3235 }
3236
3237 if ( tests & KDIAGN_ACCESS_NCBI_HTTPS ) {
3238 rc_t r1 = STestKNSManagerInitDNSEndpoint ( self,
3239 KDIAGN_ACCESS_NCBI_HTTPS, & www, 443, false );
3240 if ( rc == 0 && r1 != 0 )
3241 rc = r1;
3242 }
3243
3244 if ( tests & KDIAGN_ACCESS_NCBI_FTP ) {
3245 rc_t r1 = 0;
3246 String ftp;
3247 #define FTP "ftp-trace.ncbi.nlm.nih.gov"
3248 CONST_STRING ( & ftp, FTP );
3249 r1 = STestKNSManagerInitDNSEndpoint ( self,
3250 KDIAGN_ACCESS_NCBI_FTP, & ftp, 443, true );
3251 if ( r1 == 0 ) {
3252 Data v;
3253 r1 = DataInit ( & v, self -> vmgr, "https://" FTP
3254 "/sra/sdk/current/sratoolkit.current.version" );
3255 if ( r1 == 0 ) {
3256 uint64_t s = 0;
3257 r1 = STestCheckUrl ( self, tests, KDIAGN_ACCESS_NCBI_VERSION,
3258 0, & v, "", & s, true, 0, 0, NULL );
3259 }
3260 DataFini ( & v );
3261 }
3262 /* ignore result: failure to access current.version is not an error */
3263 }
3264
3265 return rc;
3266 }
3267
STestWritableImpl(const STest * self,const char * path,bool dir)3268 static bool STestWritableImpl ( const STest * self,
3269 const char * path, bool dir )
3270 {
3271 char tmp [ PATH_MAX ] = "";
3272
3273 int i = 0;
3274
3275 if ( path == NULL )
3276 return false;
3277
3278 assert ( self );
3279
3280 if ( ! dir ) {
3281 rc_t rc = 0;
3282 KFile * f = NULL;
3283
3284 if ( KDirectoryPathType ( self -> dir, path ) != kptNotFound ) {
3285 rc = KDirectoryRemove ( self -> dir, false, path );
3286 if ( rc != 0 )
3287 return false;
3288 }
3289
3290 rc = KDirectoryCreateFile ( self -> dir, & f, false,
3291 0775, kcmCreate | kcmParents, path);
3292 if ( rc != 0 )
3293 return false;
3294
3295 RELEASE ( KFile, f );
3296
3297 rc = KDirectoryRemove ( self -> dir, false, path );
3298 return rc == 0;
3299 }
3300
3301 for ( i = 0; i <= 0; ++i ) {
3302 rc_t rc = string_printf ( tmp, sizeof tmp, NULL, "%s/tmp-ncbi-vdb%d",
3303 path, i );
3304 if ( rc != 0 )
3305 return false;
3306
3307 if ( KDirectoryPathType ( self -> dir, tmp ) != kptNotFound )
3308 continue;
3309
3310 rc = KDirectoryCreateDir ( self -> dir,
3311 0775, kcmCreate | kcmParents, tmp );
3312 if ( rc == 0 ) {
3313 rc = KDirectoryRemove ( self -> dir, false, tmp );
3314 return rc == 0;
3315 }
3316 else
3317 return false;
3318 }
3319
3320 return false;
3321 }
3322
STestWritable(const STest * self,const char * path)3323 static bool STestWritable ( const STest * self, const char * path )
3324 { return STestWritableImpl ( self, path, true ); }
3325
STestCanCreate(const STest * self,const char * path)3326 static bool STestCanCreate ( const STest * self, const char * path )
3327 { return STestWritableImpl ( self, path, false ); }
3328
STestCache(const STest * self,const String * acc,char * cache,size_t sCache,const char * suffix)3329 static rc_t STestCache ( const STest * self, const String * acc,
3330 char * cache, size_t sCache, const char * suffix )
3331 {
3332 String rCache;
3333 VPath * path = NULL;
3334 rc_t rc = VFSManagerMakePath ( self -> vmgr, & path, "%S", acc );
3335
3336 const VPath * vcache = NULL;
3337 if ( rc == 0 )
3338 rc = VResolverQuery ( self -> resolver, eProtocolHttps, path,
3339 NULL, NULL, & vcache );
3340 if ( rc == 0 )
3341 rc = VPathGetPath ( vcache, & rCache );
3342 if ( rc == 0 ) {
3343 rc = string_printf ( cache, sCache, NULL, "%S.%s", & rCache, suffix );
3344 RELEASE ( VPath, vcache );
3345 if ( rc != 0 || ! STestCanCreate ( self, cache ) )
3346 cache [ 0 ] = '\0';
3347 }
3348 RELEASE ( VPath, path );
3349
3350 if ( cache [ 0 ] == '\0' ) {
3351 const char * p = getenv ( "TMPDIR" );
3352 while ( cache [ 0 ] == '\0' ) {
3353 if ( STestWritable ( self, p ) )
3354 break;
3355 p = getenv ( "TEMP" );
3356 if ( STestWritable ( self, p ) )
3357 break;
3358 p = getenv ( "TMP" );
3359 if ( STestWritable ( self, p ) )
3360 break;
3361 p = getenv ( "TEMPDIR" );
3362 if ( STestWritable ( self, p ) )
3363 break;
3364 p = NULL;
3365 break;
3366 }
3367 if ( p != NULL ) {
3368 rc = string_printf ( cache, sCache, NULL, "%s/%S.%s",
3369 p, acc, suffix );
3370 if ( rc != 0 )
3371 cache [ 0 ] = '\0';
3372 }
3373 }
3374
3375 if ( cache [ 0 ] == '\0' ) {
3376 String * p = NULL;
3377 rc = KConfigReadString ( self -> kfg,
3378 "/repository/user/default-path", & p );
3379 if ( rc == 0 && STestWritable ( self, p -> addr ) ) {
3380 rc = string_printf ( cache, sCache, NULL, "%S/%S.%s",
3381 p, acc, suffix );
3382 free ( p );
3383 }
3384 if ( rc != 0 )
3385 cache [ 0 ] = '\0';
3386 }
3387
3388 if ( cache [ 0 ] == '\0' ) {
3389 String * p = NULL;
3390 rc = KConfigReadString ( self -> kfg, "NCBI_HOME", & p );
3391 if ( rc == 0 && STestWritable ( self, p -> addr ) ) {
3392 rc = string_printf ( cache, sCache, NULL, "%S/%S.%s",
3393 p, acc, suffix );
3394 free ( p );
3395 }
3396 if ( rc != 0 )
3397 cache [ 0 ] = '\0';
3398 }
3399
3400 if ( cache [ 0 ] == '\0' ) {
3401 String * p = NULL;
3402 rc = KConfigReadString ( self -> kfg, "HOME", & p );
3403 if ( rc == 0 && STestWritable ( self, p -> addr ) ) {
3404 rc = string_printf ( cache, sCache, NULL, "%S/%S.%s",
3405 p, acc, suffix );
3406 free ( p );
3407 }
3408 if ( rc != 0 )
3409 cache [ 0 ] = '\0';
3410 }
3411
3412 if ( cache [ 0 ] == '\0' ) {
3413 rc = string_printf ( cache, sCache, NULL, "%S/%s", acc, suffix );
3414 if ( rc != 0 )
3415 cache [ 0 ] = '\0';
3416 else if ( ! STestWritable ( self, "." ) ) {
3417 cache [ 0 ] = '\0';
3418 rc = RC ( rcRuntime,
3419 rcDirectory, rcAccessing, rcDirectory, rcUnauthorized );
3420 }
3421 }
3422
3423 return rc;
3424 }
3425
STestCheckHttp(STest * self,uint64_t tests,const String * acc,bool print,char * downloaded,size_t sDownloaded,uint64_t * downloadedSize,const char ** exp,size_t esz,bool * tooBig)3426 static rc_t STestCheckHttp ( STest * self, uint64_t tests, const String * acc,
3427 bool print,
3428 char * downloaded, size_t sDownloaded, uint64_t * downloadedSize,
3429 const char ** exp, size_t esz, bool * tooBig )
3430 {
3431 rc_t rc = 0;
3432 char response [ 4096 ] = "";
3433 size_t resp_len = 0;
3434 const char * url = NULL;
3435 bool failed = false;
3436 uint64_t atest = KDIAGN_HTTP_RUN;
3437 STestStart ( self, true, atest,
3438 "HTTPS access to '%S'", acc );
3439 if ( tests & KDIAGN_HTTP_CGI )
3440 rc = STestCallCgi ( self, KDIAGN_HTTP_CGI, acc,
3441 response, sizeof response, & resp_len, & url, true );
3442
3443 if ( rc == 0 ) {
3444 rc = STestCache ( self, acc, downloaded, sDownloaded, "http" );
3445 if ( rc != 0 )
3446 STestFail ( self, rc, 0, "Cannot find cache location" );
3447 }
3448 if ( rc == 0 && url != NULL ) {
3449 char * p = string_chr ( url, resp_len - ( url - response ), '|' );
3450 if ( p == NULL ) {
3451 rc = RC ( rcRuntime,
3452 rcString ,rcParsing, rcString, rcIncorrect );
3453 STestFail ( self, rc, 0, "UNEXPECTED RESOLVER RESPONSE" );
3454 failed = true;
3455 }
3456 else {
3457 Data dt;
3458 * p = '\0';
3459 rc = DataInit ( & dt, self -> vmgr, url );
3460 if ( rc == 0 ) {
3461 rc_t r1 = STestCheckUrl ( self,
3462 tests, KDIAGN_HTTP_SMALL_ACCESS, KDIAGN_HTTP_SMALL_VFS,
3463 & dt, downloaded, downloadedSize, print, exp, esz, tooBig );
3464 if ( rc == 0 && r1 != 0 ) {
3465 assert ( downloaded );
3466 * downloaded = '\0';
3467 rc = r1;
3468 }
3469 }
3470 DataFini ( & dt );
3471 }
3472 }
3473
3474 if ( ! failed ) {
3475 if ( rc == 0 )
3476 rc = STestEnd ( self, eOK, "HTTPS access to '%S'", acc );
3477 else if ( _RcCanceled ( rc ) )
3478 STestEnd ( self, eCANCELED, "HTTPS access to '%S': CANCELED", acc );
3479 else
3480 STestEnd ( self, eFAIL, "HTTPS access to '%S'", acc );
3481 }
3482 return rc;
3483 }
3484
STestCheckFasp(STest * self,uint64_t tests,const String * acc,bool print,char * downloaded,size_t sDownloaded,uint64_t * downloadedSize)3485 static rc_t STestCheckFasp ( STest * self, uint64_t tests, const String * acc,
3486 bool print, char * downloaded, size_t sDownloaded,
3487 uint64_t * downloadedSize )
3488 {
3489 rc_t rc = 0;
3490 char response [ 4096 ] = "";
3491 size_t resp_len = 0;
3492 const char * url = NULL;
3493 bool failed = false;
3494 uint64_t atest = KDIAGN_ASCP_RUN;
3495 STestStart ( self, true, atest, "Aspera access to '%S'", acc );
3496 if ( tests & KDIAGN_ASCP_CGI )
3497 rc = STestCallCgi ( self, KDIAGN_ASCP_CGI, acc,
3498 response, sizeof response, & resp_len, & url, false );
3499
3500 if ( tests & KDIAGN_DOWNLOAD_ASCP ) {
3501 if ( rc == 0 ) {
3502 rc = STestCache ( self, acc, downloaded, sDownloaded, "fasp" );
3503 if ( rc != 0 )
3504 STestFail ( self, rc, 0, "Cannot find cache location" );
3505 }
3506 if ( rc == 0 && url != NULL ) {
3507 char * p = string_chr ( url, resp_len - ( url - response ), '|' );
3508 if ( p == NULL ) {
3509 rc = RC ( rcRuntime,
3510 rcString ,rcParsing, rcString, rcIncorrect );
3511 STestFail ( self, rc, 0, "UNEXPECTED RESOLVER RESPONSE" );
3512 failed = true;
3513 }
3514 else {
3515 Data dt;
3516 * p = '\0';
3517 rc = DataInit ( & dt, self -> vmgr, url );
3518 if ( rc == 0 ) {
3519 rc_t r1 = STestCheckFaspDownload ( self, url, downloaded,
3520 downloadedSize );
3521 if ( rc == 0 && r1 != 0 ) {
3522 assert ( downloaded );
3523 * downloaded = '\0';
3524 rc = r1;
3525 }
3526 }
3527 DataFini ( & dt );
3528 }
3529 }
3530 }
3531
3532 if ( ! failed ) {
3533 if ( rc == 0 )
3534 rc = STestEnd ( self, eOK, "Aspera access to '%S'", acc );
3535 else if ( _RcCanceled ( rc ) )
3536 STestEnd ( self, eCANCELED, "Aspera access to '%S': CANCELED",
3537 acc );
3538 else
3539 STestEnd ( self, eFAIL, "Aspera access to '%S'", acc );
3540 }
3541 return rc;
3542 }
3543
3544 static
STestHttpVsFasp(STest * self,const char * http,uint64_t httpSize,const char * fasp,uint64_t faspSize)3545 rc_t STestHttpVsFasp ( STest * self, const char * http, uint64_t httpSize,
3546 const char * fasp, uint64_t faspSize )
3547 {
3548 rc_t rc = 0;
3549 uint64_t pos = 0;
3550 const KFile * ascpF = NULL;
3551 const KFile * httpF = NULL;
3552 STestStart ( self, false, KDIAGN_HTTP_VS_ASCP, "HTTP vs ASCP download:" );
3553 if ( httpSize != faspSize ) {
3554 rc = RC ( rcRuntime, rcFile, rcComparing, rcSize, rcUnequal );
3555 STestEnd ( self, eEndFAIL, "size does not match: "
3556 "http(%lu)/ascp(%lu)", httpSize, faspSize );
3557 }
3558 else {
3559 rc = KDirectoryOpenFileRead ( self -> dir, & httpF, http );
3560 if ( rc != 0 )
3561 STestEnd ( self, eEndFAIL, "cannot open '%s'; %R", http, rc );
3562 else {
3563 rc = KDirectoryOpenFileRead ( self -> dir, & ascpF, fasp );
3564 if ( rc != 0 )
3565 STestEnd ( self, eEndFAIL, "cannot open '%s'; %R", fasp, rc );
3566 }
3567 }
3568 if ( rc == 0 ) {
3569 char bAscp [ 1024 ] = "";
3570 char bHttp [ 1024 ] = "";
3571 size_t ascp_read = 0;
3572 size_t http_read = 0;
3573 while ( rc == 0 ) {
3574 rc = KFileReadAll ( ascpF, pos, bAscp, sizeof bAscp, & ascp_read );
3575 if ( rc != 0 ) {
3576 STestEnd ( self, eEndFAIL, "cannot read '%s': %R",
3577 fasp, rc );
3578 break;
3579 }
3580 rc = KFileReadAll ( httpF, pos, bHttp, sizeof bHttp, & http_read );
3581 if ( rc != 0 ) {
3582 STestEnd ( self, eEndFAIL, "cannot read '%s': %R",
3583 http, rc );
3584 break;
3585 }
3586 else if ( ascp_read != http_read ) {
3587 rc = RC ( rcRuntime, rcFile, rcComparing, rcSize, rcUnequal );
3588 STestEnd ( self, eEndFAIL,
3589 "cannot read the same amount from files" );
3590 break;
3591 }
3592 else if ( ascp_read == 0 )
3593 break;
3594 else {
3595 pos += ascp_read;
3596 if ( string_cmp ( bAscp, ascp_read,
3597 bHttp, http_read, (uint32_t)ascp_read ) != 0 )
3598 {
3599 rc = RC ( rcRuntime,
3600 rcFile, rcComparing, rcData, rcUnequal );
3601 STestEnd ( self, eEndFAIL, "files are different" );
3602 break;
3603 }
3604 }
3605 }
3606 }
3607 RELEASE ( KFile, ascpF );
3608 RELEASE ( KFile, httpF );
3609 if ( rc == 0 )
3610 rc = STestEnd ( self, eEndOK, "%lu bytes compared: OK", pos );
3611 return rc;
3612 }
3613
StringRelease(String * self)3614 static rc_t StringRelease ( String * self ) {
3615 if ( self != NULL )
3616 free ( self );
3617 return 0;
3618 }
3619
3620 /*static rc_t STestWarning ( STest * self,
3621 const char * msg, const char * fmt, ... )
3622 {
3623 rc_t rc = 0;
3624
3625 va_list args;
3626 va_start ( args, fmt );
3627
3628 rc = STestVStart ( self, false, fmt, args );
3629 STestEnd ( self, eMSG, "WARNING: %s", msg );
3630 if ( CALL_BACK )
3631 CALL_BACK ( eKDTS_Warning, self -> crnt );
3632 rc = STestEnd ( self, eWarning, "" );
3633
3634 va_end ( args );
3635
3636 return rc;
3637 }*/
3638
STestCheckNodeExists(STest * self,uint64_t code,const char * path,const char * msg,const char * fmt,String ** value)3639 static rc_t STestCheckNodeExists ( STest * self, uint64_t code,
3640 const char * path, const char * msg, const char * fmt, String ** value )
3641 {
3642 String * p = NULL;
3643 rc_t rc = KConfigReadString ( self -> kfg, path, & p );
3644
3645 STestStart ( self, false, code, fmt );
3646
3647 if ( rc != 0 ) {
3648 if ( rc != SILENT_RC ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
3649 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, rc );
3650 else {
3651 STestEnd ( self, eWarning, msg );
3652 rc = 0;
3653 }
3654
3655 p = NULL;
3656 }
3657
3658 if ( value != NULL )
3659 * value = p;
3660 else {
3661 STestEnd ( self, eEndOK, "'%S': OK", p );
3662 RELEASE ( String, p );
3663 }
3664
3665 return rc;
3666 }
3667
STestCheckRemoteRepoKfg(STest * self,bool * exists)3668 static rc_t STestCheckRemoteRepoKfg ( STest * self, bool * exists ) {
3669 rc_t rc = 0;
3670 rc_t r1 = 0;
3671 String * p = NULL;
3672 assert ( exists );
3673 * exists = false;
3674 STestStart ( self, true, KDIAGN_REPO_REMOTE, "Remote repository" );
3675 {
3676 bool printed = false;
3677 const char * path = "/repository/remote/disabled";
3678 rc_t r1 = KConfigReadString ( self -> kfg, path, & p );
3679 STestStart ( self, false, 0, "Remote repository disabled:" );
3680 if ( r1 != 0 ) {
3681 if ( r1 !=
3682 SILENT_RC ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
3683 {
3684 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, r1 );
3685 printed = true;
3686 if ( rc == 0 )
3687 rc = r1;
3688 }
3689 }
3690 else {
3691 String sTrue;
3692 CONST_STRING ( & sTrue, "true" );
3693 if ( StringEqual ( p, & sTrue ) ) {
3694 STestEnd ( self, eWarning, "Remote repository is disabled" );
3695 printed = true;
3696 }
3697 RELEASE ( String, p );
3698 }
3699 if ( ! printed )
3700 STestEnd ( self, eEndOK, "false: OK" );
3701 }
3702 {
3703 bool printed = false;
3704 const char * path = "/repository/remote/main/CGI/resolver-cgi";
3705 rc_t r1 = KConfigReadString ( self -> kfg, path, & p );
3706 STestStart ( self, false, 0, "Main resolver-cgi:" );
3707 if ( r1 != 0 ) {
3708 if ( r1 !=
3709 SILENT_RC ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
3710 {
3711 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, r1 );
3712 printed = true;
3713 if ( rc == 0 )
3714 rc = r1;
3715 }
3716 else {
3717 STestEnd ( self, eWarning, "Main resolver-cgi is not set" );
3718 printed = true;
3719 }
3720 }
3721 else {
3722 String c, f, t;
3723 CONST_STRING ( & c,
3724 "https://www.ncbi.nlm.nih.gov/Traces/names/names.cgi" );
3725 CONST_STRING ( & f,
3726 "https://www.ncbi.nlm.nih.gov/Traces/names/names.fcgi" );
3727 CONST_STRING ( & t,
3728 "https://trace.ncbi.nlm.nih.gov/Traces/names/names.fcgi" );
3729 if ( ! StringEqual ( p, & f ) && ! StringEqual ( p, & c ) &&
3730 ! StringEqual ( p, & t ))
3731 {
3732 STestEnd ( self, eWarning,
3733 "Main resolver-cgi is not standard: '%S'", p );
3734 printed = true;
3735 }
3736 RELEASE ( String, p );
3737
3738 * exists = true;
3739 }
3740 if ( ! printed )
3741 STestEnd ( self, eEndOK, "OK" );
3742 }
3743 r1 = STestEnd ( self, rc == 0 ? eOK : eFAIL, "Remote repository" );
3744 if ( rc == 0 && r1 != 0 )
3745 rc = r1;
3746 return rc;
3747 }
3748
STestCheckSiteRepoKfg(STest * self,bool * exists)3749 static rc_t STestCheckSiteRepoKfg ( STest * self, bool * exists ) {
3750 bool printed = false;
3751 bool hasNode = true;
3752 #define SITE "/repository/site"
3753 const char * path = SITE;
3754 const KConfigNode * node = NULL;
3755 String * p = NULL;
3756 rc_t rc = KConfigOpenNodeRead ( self -> kfg, & node, path );
3757 assert ( exists );
3758 * exists = false;
3759 STestStart ( self, false, KDIAGN_REPO_SITE, "Site repository:" );
3760 if ( rc != 0 ) {
3761 if ( rc != SILENT_RC ( rcKFG, rcNode, rcOpening,
3762 rcPath, rcNotFound ) )
3763 {
3764 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, rc );
3765 printed = true;
3766 }
3767 else {
3768 hasNode = false;
3769 rc = 0;
3770 STestEnd ( self, eEndOK, "not found: OK" );
3771 printed = true;
3772 }
3773 }
3774 if ( hasNode ) {
3775 KNamelist * names = NULL;
3776 uint32_t count = 0;
3777 if ( rc == 0 ) {
3778 rc = KConfigNodeListChildren ( node, & names );
3779 if ( rc != 0 ) {
3780 STestEnd ( self, eEndFAIL,
3781 "cannot list children of '%s': %R", path, rc );
3782 printed = true;
3783 }
3784 }
3785 if ( rc == 0 ) {
3786 rc = KNamelistCount ( names, & count );
3787 if ( rc != 0 ) {
3788 STestEnd ( self, eEndFAIL,
3789 "cannot count children of '%s': %R", path, rc );
3790 printed = true;
3791 }
3792 else if ( count > 0 )
3793 * exists = true;
3794 }
3795 if ( rc == 0 ) {
3796 const char * path = SITE "/disabled";
3797 rc = KConfigReadString ( self -> kfg, path, & p );
3798 if ( rc != 0 ) {
3799 if ( rc != SILENT_RC ( rcKFG, rcNode, rcOpening,
3800 rcPath, rcNotFound ) )
3801 {
3802 STestEnd ( self, eEndFAIL, "cannot read '%s': %R",
3803 path, rc );
3804 printed = true;
3805 }
3806 else
3807 rc = 0;
3808 }
3809 else {
3810 String sTrue;
3811 CONST_STRING ( & sTrue, "true" );
3812 if ( StringEqual ( p, & sTrue ) ) {
3813 * exists = false;
3814 if ( count > 1 ) {
3815 STestEnd ( self, eWarning,
3816 "Site repository is disabled" );
3817 printed = true;
3818 }
3819 }
3820 RELEASE ( String, p );
3821 }
3822 }
3823 RELEASE ( KNamelist, names );
3824 }
3825 RELEASE ( KConfigNode, node );
3826 if ( ! printed )
3827 STestEnd ( self, eEndOK, "OK" );
3828 return rc;
3829 }
3830
STestCheckUserRepoKfg(STest * self,bool * exists)3831 static rc_t STestCheckUserRepoKfg ( STest * self, bool * exists ) {
3832 rc_t rc = 0;
3833 rc_t r1 = 0;
3834 String * p = NULL;
3835 assert ( exists );
3836 * exists = false;
3837 STestStart ( self, true, KDIAGN_REPO_USER_PUBLIC,
3838 "Public user repository" );
3839 {
3840 bool printed = false;
3841 const char * path = "/repository/user/cache-disabled";
3842 rc_t r1 = KConfigReadString ( self -> kfg, path, & p );
3843 STestStart ( self, false, 0, "User repository caching:" );
3844 if ( r1 != 0 ) {
3845 if ( r1 !=
3846 SILENT_RC ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
3847 {
3848 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, r1 );
3849 printed = true;
3850 if ( rc == 0 )
3851 rc = r1;
3852 }
3853 }
3854 else {
3855 String sTrue;
3856 CONST_STRING ( & sTrue, "true" );
3857 if ( StringEqual ( p, & sTrue ) ) {
3858 STestEnd ( self, eWarning,
3859 "User repository caching is disabled" );
3860 printed = true;
3861 }
3862 RELEASE ( String, p );
3863 }
3864 if ( ! printed )
3865 STestEnd ( self, eEndOK, "enabled: OK" );
3866 }
3867 {
3868 const char * path = "/repository/user/main/public";
3869 const KConfigNode * node = NULL;
3870 rc_t r1 = KConfigOpenNodeRead ( self -> kfg, & node, path );
3871 if ( r1 == 0 )
3872 * exists = true;
3873 else if ( r1 != SILENT_RC
3874 ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
3875 {
3876 STestFail ( self, r1, 0, "Failed to read '%s'", path );
3877 if ( rc == 0 )
3878 rc = r1;
3879 }
3880 RELEASE ( KConfigNode, node );
3881 }
3882 r1 = STestCheckNodeExists ( self, 0,
3883 "/repository/user/main/public/apps/file/volumes/flat",
3884 "User repository is incomplete", "User repository file app:", NULL );
3885 if ( r1 != 0 && rc == 0 )
3886 rc = r1;
3887
3888 r1 = STestCheckNodeExists ( self, 0,
3889 "/repository/user/main/public/apps/nakmer/volumes/nakmerFlat",
3890 "User repository is incomplete", "User repository nakmer app:", NULL );
3891 if ( r1 != 0 && rc == 0 )
3892 rc = r1;
3893
3894 r1 = STestCheckNodeExists ( self, 0,
3895 "/repository/user/main/public/apps/nannot/volumes/nannotFlat",
3896 "User repository is incomplete", "User repository nannot app:", NULL );
3897 if ( r1 != 0 && rc == 0 )
3898 rc = r1;
3899
3900 {
3901 r1 = STestCheckNodeExists ( self, 0,
3902 "/repository/user/main/public/apps/refseq/volumes/refseq",
3903 "User repository is incomplete", "User repository refseq app:",
3904 & p );
3905 if ( r1 != 0 ) {
3906 if ( rc == 0 )
3907 rc = r1;
3908 }
3909 else if ( p == NULL )
3910 * exists = false;
3911 else
3912 STestEnd ( self, eEndOK, "'%S': OK", p );
3913 RELEASE ( String, p );
3914 }
3915 {
3916 r1 = STestCheckNodeExists ( self, 0,
3917 "/repository/user/main/public/apps/sra/volumes/sraFlat",
3918 "User repository is incomplete", "User repository sra app:", & p );
3919 if ( r1 != 0 ) {
3920 if ( rc == 0 )
3921 rc = r1;
3922 }
3923 else if ( p == NULL )
3924 * exists = false;
3925 else
3926 STestEnd ( self, eEndOK, "'%S': OK", p );
3927 RELEASE ( String, p );
3928 }
3929
3930 r1 = STestCheckNodeExists ( self, 0,
3931 "/repository/user/main/public/apps/wgs/volumes/wgsFlat",
3932 "User repository is incomplete", "User repository wgs app:", NULL );
3933 if ( r1 != 0 && rc == 0 )
3934 rc = r1;
3935
3936 {
3937 bool user = false;
3938 r1 = STestCheckNodeExists ( self, 0,
3939 "/repository/user/main/public/root",
3940 "User repository's root path is not set",
3941 "User repository root path:",
3942 & p );
3943 if ( r1 != 0 ) {
3944 if ( rc == 0 )
3945 rc = r1;
3946 }
3947 else if ( p != NULL ) {
3948 if ( p -> size == 0 )
3949 STestEnd ( self, eWarning,
3950 "User repository's root path is empty" );
3951 else {
3952 KPathType type = kptFirstDefined;
3953 type = KDirectoryPathType ( self -> dir, p -> addr )
3954 & ~ kptAlias;
3955 if ( type == kptNotFound )
3956 STestEnd ( self, eWarning,
3957 "User repository's root path does not exist: '%S'", p );
3958 else if ( type != kptDir )
3959 STestEnd ( self, eWarning,
3960 "User repository's root path is not a directory: '%S'",
3961 p );
3962 else {
3963 STestEnd ( self, eEndOK, "'%S': OK", p );
3964 user = true;
3965 }
3966 }
3967 RELEASE ( String, p );
3968 }
3969 if ( ! user )
3970 * exists = false;
3971 }
3972 r1 = STestEnd ( self, rc == 0 ? eOK : eFAIL, "Public user repository" );
3973 if ( rc == 0 && r1 != 0 )
3974 rc = r1;
3975 return rc;
3976 }
3977
STestCheckNoGapKfg(STest * self,uint64_t tests)3978 static rc_t STestCheckNoGapKfg ( STest * self, uint64_t tests ) {
3979 rc_t rc = 0;
3980 rc_t r1 = 0;
3981 bool rRemote = false;
3982 bool rSite = false;
3983 bool rUser = false;
3984 if ( tests & KDIAGN_REPO_REMOTE ) {
3985 rc_t r1 = STestCheckRemoteRepoKfg ( self, & rRemote );
3986 if ( rc == 0 && r1 != 0 )
3987 rc = r1;
3988 }
3989 if ( tests & KDIAGN_REPO_SITE ) {
3990 rc_t r1 = STestCheckSiteRepoKfg ( self, & rSite );
3991 if ( rc == 0 && r1 != 0 )
3992 rc = r1;
3993 }
3994 if ( tests & KDIAGN_REPO_USER_PUBLIC ) {
3995 rc_t r1 = STestCheckUserRepoKfg ( self, & rUser );
3996 if ( rc == 0 && r1 != 0 )
3997 rc = r1;
3998 }
3999 if ( tests & KDIAGN_KFG_ASCP ) {
4000 r1 = STestCheckNodeExists ( self, KDIAGN_KFG_ASCP,
4001 "/tools/ascp/max_rate",
4002 "ascp max transfer rate is not set", "ascp transfer rate:", NULL );
4003 if ( r1 != 0 && rc == 0 )
4004 rc = r1;
4005 }
4006
4007 if ( ! rRemote && ! rSite && ! rUser ) {
4008 if ( rc == 0 )
4009 rc = RC ( rcRuntime, rcNode, rcValidating, rcNode, rcInsufficient );
4010 STestFail ( self, rc, 0, "No repositories in configuration: " );
4011 }
4012
4013 return rc;
4014 }
4015
STestCheckGapKfg(STest * self,uint64_t tests)4016 static rc_t STestCheckGapKfg ( STest * self, uint64_t tests ) {
4017 rc_t rc = 0;
4018 String * p = NULL;
4019 {
4020 bool printed = false;
4021 const char * path = "/repository/remote/protected/CGI/resolver-cgi";
4022 rc_t r1 = KConfigReadString ( self -> kfg, path, & p );
4023 STestStart ( self, false, 0, "Protected resolver-cgi:" );
4024 if ( r1 != 0 ) {
4025 if ( r1 !=
4026 SILENT_RC ( rcKFG, rcNode, rcOpening, rcPath, rcNotFound ) )
4027 {
4028 STestEnd ( self, eEndFAIL, "cannot read '%s': %R", path, r1 );
4029 printed = true;
4030 if ( rc == 0 )
4031 rc = r1;
4032 }
4033 else {
4034 STestEnd ( self, eEndOK, "not set: OK" );
4035 printed = true;
4036 }
4037 }
4038 else {
4039 String c, f, t;
4040 CONST_STRING ( & c,
4041 "https://www.ncbi.nlm.nih.gov/Traces/names/names.cgi" );
4042 CONST_STRING ( & f,
4043 "https://www.ncbi.nlm.nih.gov/Traces/names/names.fcgi" );
4044 CONST_STRING ( & t,
4045 "https://trace.ncbi.nlm.nih.gov/Traces/names/names.fcgi" );
4046 if ( ! StringEqual ( p, & f ) && ! StringEqual ( p, & c ) &&
4047 ! StringEqual ( p, & t ))
4048 {
4049 STestEnd ( self, eWarning,
4050 "Protected resolver-cgi is not standard: '%S'", p );
4051 printed = true;
4052 }
4053 RELEASE ( String, p );
4054 }
4055 if ( ! printed )
4056 STestEnd ( self, eEndOK, "OK" );
4057 }
4058 {
4059 const char * path = "/repository/user/protected";
4060 const KConfigNode * nProtected = NULL;
4061 rc_t r1 = KConfigOpenNodeRead ( self -> kfg, & nProtected, path );
4062 if ( r1 != 0 ) {
4063 if ( r1 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4064 rcPath, rcNotFound ) )
4065 {
4066 STestFail ( self, r1, 0,
4067 "Protected repositories: failed to read '%s'", path );
4068 if ( rc == 0 )
4069 rc = r1;
4070 }
4071 else {
4072 STestStart ( self, false, 0, "Protected repositories:" );
4073 STestEnd ( self, eEndOK, "not found: OK" );
4074 }
4075 }
4076 else {
4077 bool printed = false;
4078 rc_t r1 = 0;
4079 KNamelist * names = NULL;
4080 uint32_t count = 0;
4081 STestStart ( self, true, 0, "Protected repositories" );
4082 if ( r1 == 0 ) {
4083 r1 = KConfigNodeListChildren ( nProtected, & names );
4084 if ( r1 != 0 ) {
4085 STestEnd ( self, eEndFAIL,
4086 "cannot list children of '%s': %R", path, r1 );
4087 printed = true;
4088 }
4089 }
4090 if ( r1 == 0 ) {
4091 r1 = KNamelistCount ( names, & count );
4092 if ( r1 != 0 ) {
4093 STestEnd ( self, eEndFAIL,
4094 "cannot count children of '%s': %R", path, r1 );
4095 printed = true;
4096 }
4097 }
4098 if ( r1 == 0 ) {
4099 uint32_t i = 0;
4100 for ( i = 0; i < count; ++ i ) {
4101 const KConfigNode * node = NULL;
4102 const char * name = NULL;
4103 r1 = KNamelistGet ( names, i, & name );
4104 if ( r1 != 0 ) {
4105 STestEnd ( self, eEndFAIL,
4106 "cannot get child of '%s': %R", path, r1 );
4107 printed = true;
4108 break;
4109 }
4110 STestStart ( self, true, 0, name );
4111 {
4112 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4113 "%s/%s/apps/file/volumes/flat", path, name );
4114 STestStart ( self, false, 0, "%s file app:", name );
4115 if ( r2 != 0 ) {
4116 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4117 rcPath, rcNotFound ) )
4118 STestEnd ( self, eEndFAIL, "cannot read "
4119 "'%s/%s/apps/file/volumes/flat': %R",
4120 path, name, r2 );
4121 else {
4122 self -> dad -> report . incompleteGapKfg = true;
4123 STestEnd ( self, tests & KDIAGN_TRY_TO_WARN
4124 ? eWarning : eEndFAIL,
4125 "not found" );
4126 }
4127 }
4128 else
4129 STestEnd ( self, eEndOK, "OK" );
4130 RELEASE ( KConfigNode, node );
4131 if ( r2 != 0 && r1 == 0 )
4132 r1 = r2;
4133 }
4134 {
4135 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4136 "%s/%s/apps/sra/volumes/sraFlat", path, name );
4137 STestStart ( self, false, 0, "%s sra app:", name );
4138 if ( r2 != 0 ) {
4139 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4140 rcPath, rcNotFound ) )
4141 STestEnd ( self, eEndFAIL, "cannot read "
4142 "'%s/%s/apps/sra/volumes/sraFlat': %R",
4143 path, name, r2 );
4144 else {
4145 self -> dad -> report . incompleteGapKfg = true;
4146 STestEnd ( self, tests & KDIAGN_TRY_TO_WARN
4147 ? eWarning : eEndFAIL,
4148 "not found" );
4149 }
4150 }
4151 else
4152 STestEnd ( self, eEndOK, "OK" );
4153 RELEASE ( KConfigNode, node );
4154 if ( r2 != 0 && r1 == 0 )
4155 r1 = r2;
4156 }
4157 {
4158 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4159 "%s/%s/cache-enabled", path, name );
4160 STestStart ( self, false, 0, "%s caching:", name );
4161 if ( r2 != 0 ) {
4162 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4163 rcPath, rcNotFound ) )
4164 STestEnd ( self, eEndFAIL, "cannot open "
4165 "'%s/%s/cache-enabled': %R",
4166 path, name, r2 );
4167 else {
4168 STestEnd ( self, eEndOK, "not found: OK" );
4169 r2 = 0;
4170 }
4171 }
4172 else {
4173 String sFalse;
4174 CONST_STRING ( & sFalse, "false" );
4175 r2 = KConfigNodeReadString ( node, & p );
4176 if ( r2 != 0 )
4177 STestEnd ( self, eEndFAIL, "cannot read "
4178 "'%s/%s/cache-enabled': %R",
4179 path, name, r2 );
4180 else if ( StringEqual ( p, & sFalse ) )
4181 STestEnd ( self, eWarning,
4182 "caching is disabled" );
4183 else
4184 STestEnd ( self, eEndOK, "OK" );
4185 RELEASE ( String, p );
4186 }
4187 RELEASE ( KConfigNode, node );
4188 if ( r2 != 0 && r1 == 0 )
4189 r1 = r2;
4190 }
4191 {
4192 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4193 "%s/%s/download-ticket", path, name );
4194 STestStart ( self, false, 0,
4195 "%s download-ticket:", name );
4196 if ( r2 != 0 ) {
4197 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4198 rcPath, rcNotFound ) )
4199 STestEnd ( self, eEndFAIL, "cannot read "
4200 "'%s/%s/download-ticket': %R",
4201 path, name, r2 );
4202 else {
4203 self -> dad -> report . incompleteGapKfg = true;
4204 STestEnd ( self, tests & KDIAGN_TRY_TO_WARN
4205 ? eWarning : eEndFAIL,
4206 "not found" );
4207 }
4208 }
4209 else
4210 STestEnd ( self, eEndOK, "OK" );
4211 RELEASE ( KConfigNode, node );
4212 if ( r2 != 0 && r1 == 0 )
4213 r1 = r2;
4214 }
4215 {
4216 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4217 "%s/%s/encryption-key", path, name );
4218 STestStart ( self, false, 0,
4219 "%s encryption-key:", name );
4220 if ( r2 != 0 ) {
4221 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4222 rcPath, rcNotFound ) )
4223 STestEnd ( self, eEndFAIL, "cannot read "
4224 "'%s/%s/encryption-key': %R",
4225 path, name, r2 );
4226 else {
4227 r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4228 "%s/%s/encryption-key-path", path, name );
4229 if ( r2 != 0 ) {
4230 if ( r2 != SILENT_RC ( rcKFG, rcNode,
4231 rcOpening, rcPath, rcNotFound ) )
4232 {
4233 STestEnd ( self, eEndFAIL,
4234 "cannot read "
4235 "'%s/%s/encryption-key-path': %R",
4236 path, name, r2 );
4237 }
4238 else {
4239 self -> dad -> report . incompleteGapKfg
4240 = true;
4241 STestEnd ( self,
4242 tests & KDIAGN_TRY_TO_WARN
4243 ? eWarning : eEndFAIL,
4244 "not found" );
4245 }
4246 }
4247 }
4248 }
4249 if ( r2 == 0 )
4250 STestEnd ( self, eEndOK, "OK" );
4251 RELEASE ( KConfigNode, node );
4252 if ( r2 != 0 && r1 == 0 )
4253 r1 = r2;
4254 }
4255 {
4256 rc_t r2 = KConfigOpenNodeRead ( self -> kfg, & node,
4257 "%s/%s/root", path, name );
4258 STestStart ( self, false, 0, "%s root:", name );
4259 if ( r2 != 0 ) {
4260 if ( r2 != SILENT_RC ( rcKFG, rcNode, rcOpening,
4261 rcPath, rcNotFound ) )
4262 STestEnd ( self, eEndFAIL,
4263 "cannot open '%s/%s/root': %R",
4264 path, name, r2 );
4265 else
4266 STestEnd ( self, tests & KDIAGN_TRY_TO_WARN
4267 ? eWarning : eEndFAIL,
4268 "not found" );
4269 }
4270 else {
4271 r2 = KConfigNodeReadString ( node, & p );
4272 if ( r2 != 0 )
4273 STestEnd ( self, eEndFAIL,
4274 "cannot read '%s/%s/root': %R",
4275 path, name, r2 );
4276 else if ( p -> size == 0 )
4277 STestEnd ( self, tests & KDIAGN_TRY_TO_WARN
4278 ? eWarning : eEndFAIL,
4279 "'%s' root path is empty", name );
4280 else {
4281 KPathType type = kptFirstDefined;
4282 type = KDirectoryPathType
4283 ( self -> dir, p -> addr ) & ~ kptAlias;
4284 if ( type == kptNotFound )
4285 STestEnd ( self, eWarning, "'%s' root path "
4286 "does not exist: '%S'", name, p );
4287 else if ( type != kptDir )
4288 STestEnd ( self,
4289 tests & KDIAGN_TRY_TO_WARN
4290 ? eWarning : eEndFAIL,
4291 "'%s' root path "
4292 "is not a directory: '%S'", name, p );
4293 else
4294 STestEnd ( self, eEndOK, "'%S': OK", p );
4295 }
4296 RELEASE ( String, p );
4297 RELEASE ( KConfigNode, node );
4298 }
4299 if ( r2 != 0 && r1 == 0 )
4300 r1 = r2;
4301 }
4302 if ( r1 == 0 ) {
4303 rc_t r2 = STestEnd ( self, eOK, name );
4304 if ( r2 != 0 && r1 == 0 )
4305 r1 = r2;
4306 }
4307 else if ( _RcCanceled ( r1 ) )
4308 STestEnd ( self, eCANCELED, name );
4309 else {
4310 self -> dad -> report . incompleteGapKfg = true;
4311 STestEnd ( self, eFAIL, name );
4312 }
4313 }
4314 }
4315 RELEASE ( KNamelist, names );
4316 RELEASE ( KConfigNode, nProtected );
4317 if ( ! printed ) {
4318 printed = true;
4319 if ( r1 == 0 ) {
4320 rc_t r2 = STestEnd ( self, eOK, "Protected repositories" );
4321 if ( r2 != 0 && r1 == 0 )
4322 r1 = r2;
4323 }
4324 else if ( _RcCanceled ( r1 ) )
4325 STestEnd ( self, eCANCELED,
4326 "Protected repositories: CANCELED" );
4327 else
4328 STestEnd ( self, eFAIL, "Protected repositories" );
4329 }
4330 if ( r1 != 0 && rc == 0 )
4331 rc = r1;
4332 }
4333 }
4334 return rc;
4335 }
4336
STestRun(STest * self,uint64_t tests,const KFile * kart,uint32_t numberOfKartItemsToCheck,bool checkHttp,bool checkAspera,bool checkDownload,const char * acc,uint32_t projectId,va_list args)4337 static rc_t CC STestRun ( STest * self, uint64_t tests,
4338 const KFile * kart, uint32_t numberOfKartItemsToCheck,
4339 bool checkHttp, bool checkAspera, bool checkDownload, const char * acc,
4340 uint32_t projectId, va_list args )
4341 {
4342 rc_t rc = 0;
4343
4344 assert ( self );
4345
4346 if ( tests & KDIAGN_CONFIG ) {
4347 rc_t r1 = 0;
4348 STestStart ( self, true, KDIAGN_CONFIG, "Configuration" );
4349 if ( tests & KDIAGN_KFG_NO_GAP && ! _RcCanceled ( r1 ) ) {
4350 rc_t r2 = STestCheckNoGapKfg ( self, tests );
4351 if ( r1 == 0 && r2 != 0 )
4352 r1 = r2;
4353 }
4354 if ( tests & KDIAGN_REPO_GAP && ! _RcCanceled ( r1 ) ) {
4355 rc_t r2 = 0;
4356 STestStart ( self, true, KDIAGN_REPO_GAP, "DbGaP configuration" );
4357 r2 = STestCheckGapKfg ( self, tests );
4358 if ( r2 == 0 )
4359 r2 = STestEnd ( self, eOK, "DbGaP configuration" );
4360 else {
4361 if ( _RcCanceled ( r2 ) )
4362 STestEnd ( self, eCANCELED,
4363 "DbGaP configuration: CANCELED" );
4364 else
4365 STestEnd ( self, eFAIL, "DbGaP configuration" );
4366 }
4367 if ( r1 == 0 && r2 != 0 )
4368 r1 = r2;
4369 }
4370 if ( r1 == 0 )
4371 r1 = STestEnd ( self, eOK, "Configuration" );
4372 else {
4373 if ( _RcCanceled ( r1 ) )
4374 STestEnd ( self, eCANCELED, "Configuration: CANCELED" );
4375 else
4376 STestEnd ( self, eFAIL, "Configuration" );
4377 }
4378 if ( rc == 0 && r1 != 0 )
4379 rc = r1;
4380 }
4381
4382 if ( tests & KDIAGN_NETWORK && ! _RcCanceled ( rc ) ) {
4383 rc_t r1 = 0;
4384 bool tooBig = false;
4385 String run;
4386 char http [ PATH_MAX ] = "";
4387 uint64_t httpSize = 0;
4388 if ( acc != NULL )
4389 StringInitCString ( & run, acc );
4390 else
4391 CONST_STRING ( & run, "SRR029074" );
4392 STestStart ( self, true, KDIAGN_NETWORK, "Network" );
4393 if ( tests & KDIAGN_ACCESS_NCBI && ! _RcCanceled ( r1 ) ) {
4394 rc_t r2 = 0;
4395 STestStart ( self, true, KDIAGN_ACCESS_NCBI, "Access to NCBI" );
4396 r2 = STestCheckNcbiAccess ( self, tests );
4397 if ( r2 == 0 )
4398 r2 = STestEnd ( self, eOK, "Access to NCBI" );
4399 else {
4400 if ( _RcCanceled ( r2 ) )
4401 STestEnd ( self, eCANCELED, "Access to NCBI: CANCELED" );
4402 else {
4403 STestEnd ( self, eFAIL, "Access to NCBI" );
4404 self -> dad -> report . firewall = true;
4405 }
4406 }
4407 if ( r1 == 0 && r2 != 0 )
4408 r1 = r2;
4409 }
4410 if ( tests & KDIAGN_HTTP && ! _RcCanceled ( r1 ) ) {
4411 rc_t r2 = 0;
4412 STestStart ( self, true, KDIAGN_HTTP, "HTTPS download" );
4413 if ( tests & KDIAGN_HTTP_RUN ) {
4414 const char sra [] = "NCBI.sra\210\031\003\005\001\0\0\0";
4415 const char nenc [] = "NCBInenc\210\031\003\005\002\0\0\0";
4416 const char * exp [] = { sra, nenc };
4417 size_t s = sizeof sra - 1;
4418 r2 = STestCheckHttp ( self, tests, & run, false,
4419 http, sizeof http, & httpSize, exp, s, & tooBig );
4420 }
4421 if ( r2 == 0 )
4422 r2 = STestEnd ( self, eOK, "HTTPS download" );
4423 else {
4424 if ( _RcCanceled ( r2 ) )
4425 STestEnd ( self, eCANCELED, "HTTPS download: CANCELED" );
4426 else
4427 STestEnd ( self, eFAIL, "HTTPS download" );
4428 }
4429 if ( r1 == 0 && r2 != 0 )
4430 r1 = r2;
4431 }
4432 if ( tests & KDIAGN_ASCP && ! _RcCanceled ( r1 ) ) {
4433 rc_t r2 = 0;
4434 char fasp [ PATH_MAX ] = "";
4435 uint64_t faspSize = 0;
4436 String smallrun;
4437 const String * frun = & run;
4438 STestStart ( self, true, KDIAGN_ASCP, "Aspera download" );
4439 if ( tooBig ) {
4440 CONST_STRING ( & smallrun, "SRR029074" );
4441 frun = & smallrun;
4442 }
4443
4444 if ( tests & KDIAGN_ASCP_RUN )
4445 r2 = STestCheckFasp ( self, tests,
4446 frun, false, fasp, sizeof fasp, & faspSize );
4447 if ( r2 == 0 )
4448 r2 = STestEnd ( self, eOK, "Aspera download" );
4449 else {
4450 if ( _RcCanceled ( r2 ) )
4451 STestEnd ( self, eCANCELED, "Aspera download: CANCELED" );
4452 else
4453 STestEnd ( self, eFAIL, "Aspera download" );
4454 }
4455 if ( r1 == 0 && r2 != 0 )
4456 r1 = r2;
4457 if ( tests & KDIAGN_HTTP_VS_ASCP && ! tooBig &&
4458 r2 == 0 && httpSize != 0 && faspSize != 0 )
4459 {
4460 r2 = STestHttpVsFasp ( self, http, httpSize, fasp, faspSize );
4461 if ( r1 == 0 && r2 != 0 )
4462 r1 = r2;
4463 }
4464 if ( * fasp != '\0' ) {
4465 rc_t r2 = KDirectoryRemove ( self-> dir, false, fasp );
4466 if ( r2 != 0 ) {
4467 STestFail ( self, r2, 0, "FAILURE: cannot remove '%s': %R",
4468 fasp, r2 );
4469 if ( r1 == 0 && r2 != 0 )
4470 r1 = r2;
4471 }
4472 else
4473 * fasp = '\0';
4474 }
4475 }
4476 if ( * http != '\0' ) {
4477 rc_t r2 = KDirectoryRemove ( self-> dir, false, http );
4478 if ( r2 != 0 ) {
4479 STestFail ( self, r2, 0, "FAILURE: cannot remove '%s': %R",
4480 http, r2 );
4481 if ( r1 == 0 && r2 != 0 )
4482 r1 = r2;
4483 }
4484 else
4485 * http = '\0';
4486 }
4487 if ( r1 == 0)
4488 r1 = STestEnd ( self, eOK, "Network" );
4489 else if ( _RcCanceled ( r1 ) )
4490 STestEnd ( self, eCANCELED, "Network: CANCELED" );
4491 else
4492 STestEnd ( self, eFAIL, "Network" );
4493 if ( rc == 0 && r1 != 0 )
4494 rc = r1;
4495 }
4496
4497 if ( rc == 0 && tests & KDIAGN_FAIL )
4498 rc = 1;
4499
4500 /*if ( rc == 0)
4501 STestEnd ( & t, eOK, "System" );
4502 else if ( _RcCanceled ( rc ) )
4503 STestEnd ( & t, eCANCELED, "System: CANCELED" );
4504 else
4505 STestEnd ( & t, eFAIL, "System" );
4506
4507 STestFini ( & t );
4508 KDiagnoseRelease ( self );*/
4509 return rc;
4510 }
4511
KDiagnoseRunImpl(KDiagnose * self,const char * name,uint64_t tests,const KFile * kart,uint32_t numberOfKartItemsToCheck,bool checkHttp,bool checkAspera,bool checkDownload,const char * acc,uint32_t projectId,...)4512 static rc_t CC KDiagnoseRunImpl ( KDiagnose * self, const char * name,
4513 uint64_t tests, const KFile * kart, uint32_t numberOfKartItemsToCheck,
4514 bool checkHttp, bool checkAspera, bool checkDownload,
4515 const char * acc, uint32_t projectId, ... )
4516 {
4517 rc_t rc = 0;
4518 STest t;
4519 va_list args;
4520 va_start ( args, projectId );
4521 if ( self == NULL )
4522 rc = KDiagnoseMakeExt ( & self, NULL, NULL, NULL, NULL );
4523 else
4524 rc = KDiagnoseAddRef ( self );
4525 if ( rc != 0 )
4526 return rc;
4527
4528 assert ( self );
4529
4530 STestInit ( & t, self );
4531
4532 STestStart ( & t, true, KDIAGN_ALL, name );
4533
4534 rc = STestRun ( & t, tests, kart, numberOfKartItemsToCheck,
4535 checkHttp, checkAspera, checkDownload, acc, projectId, args );
4536 va_end ( args );
4537 if ( rc == 0 && tests & KDIAGN_FAIL )
4538 rc = 1;
4539
4540 if ( rc == 0)
4541 STestEnd ( & t, eOK, name );
4542 else if ( _RcCanceled ( rc ) )
4543 STestEnd ( & t, eCANCELED, "%s: CANCELED", name );
4544 else
4545 STestEnd ( & t, eFAIL, "%s", name );
4546
4547 STestFini ( & t );
4548 KDiagnoseRelease ( self );
4549 return rc;
4550 }
4551
KDiagnoseAll(KDiagnose * self,uint64_t tests)4552 LIB_EXPORT rc_t CC KDiagnoseAll ( KDiagnose * self, uint64_t tests ) {
4553 return KDiagnoseRunImpl ( self, "System", KDIAGN_ALL, NULL, 0,
4554 true, true, true, NULL, 0 );
4555 }
4556
4557 LIB_EXPORT
KDiagnoseAdvanced(KDiagnose * self,uint64_t tests)4558 rc_t CC KDiagnoseAdvanced ( KDiagnose * self, uint64_t tests )
4559 {
4560 return KDiagnoseRunImpl ( self, "System", tests, NULL, 0,
4561 true, true, true, NULL, 0 );
4562 }
4563
KDiagnoseAcc(KDiagnose * self,const char * acc,uint32_t projectId,bool checkHttp,bool checkAspera,bool checkDownload,uint64_t tests)4564 LIB_EXPORT rc_t CC KDiagnoseAcc ( KDiagnose * self, const char * acc,
4565 uint32_t projectId, bool checkHttp, bool checkAspera, bool checkDownload,
4566 uint64_t tests )
4567 {
4568 return KDiagnoseRunImpl ( self, "System", tests, NULL, 0,
4569 checkHttp, checkAspera, checkDownload, acc, 0 );
4570 }
4571
4572 /*DIAGNOSE_EXTERN rc_t CC KDiagnoseDbGap ( KDiagnose * self, uint64_t tests,
4573 uint32_t projectId, ... )
4574 {
4575 rc_t rc = 0;
4576 va_list args;
4577 va_start ( args, projectId );
4578 rc = KDiagnoseRunImpl ( self, tests, NULL, 0, NULL, projectId, args );
4579 va_end ( args );
4580 return rc;
4581 }*/
4582
KDiagnoseKart(KDiagnose * self,const struct KFile * kart,uint32_t numberOfKartItemsToCheck,bool checkHttp,bool checkAspera,uint64_t tests)4583 DIAGNOSE_EXTERN rc_t CC KDiagnoseKart ( KDiagnose * self,
4584 const struct KFile * kart, uint32_t numberOfKartItemsToCheck,
4585 bool checkHttp, bool checkAspera, uint64_t tests )
4586 {
4587 return KDiagnoseRunImpl ( self, "Kart file", KDIAGN_ALL, kart,
4588 numberOfKartItemsToCheck, checkHttp, checkAspera, true, NULL, 0 );
4589 }
4590