1 #ifndef CONNECT___NCBI_LBOSP__H 2 #define CONNECT___NCBI_LBOSP__H 3 /* 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 * Authors: Dmitriy Elisov 29 * Credits: Denis Vakatov 30 * @file 31 * File Description: 32 * This header was made only because of unit testing application. Please, 33 * include only ncbi_lbos.h. 34 * This file contains only those elements that are absolutely unneeded 35 * if you do not want to dive into internal LBOS client implementation. 36 */ 37 #include "ncbi_servicep.h" 38 #include <connect/ncbi_http_connector.h> 39 #include "ncbi_lbos.h" 40 41 42 #ifdef __cplusplus 43 extern "C" { 44 #endif /*__cplusplus*/ 45 46 #ifndef LBOS_METADATA 47 #define LBOS_METADATA 48 #endif 49 50 /* 51 * Additional HTTP codes: 52 * 450 - LBOS not found 53 * 451 - DNS resolve failed for healthcheck URL 54 * 452 - Invalid arguments provided, request was not sent to LBOS 55 * 453 - Memory allocation error encountered 56 * 454 - LBOS output could not be parsed 57 * 550 - LBOS client is OFF in the current process 58 */ 59 enum ELBOSStatusCodes { 60 eLBOS_Success = 200, /**< HTTP 200 OK */ 61 eLBOS_BadRequest = 400, /**< HTTP 400 Bad Request */ 62 eLBOS_NotFound = 404, /**< HTTP 404 Not Found */ 63 eLBOS_LbosNotFound = 450, /**< Not a HTTP code. LBOS was not found */ 64 eLBOS_DNSResolve = 451, /**< Not a HTTP code. Could not find IP of 65 localhost */ 66 eLBOS_InvalidArgs = 452, /**< Not a HTTP code. Some arguments were 67 invalid */ 68 eLBOS_MemAlloc = 453, /**< Not a HTTP code. Some memory could not be 69 allocated */ 70 eLBOS_Protocol = 454, /**< Not a HTTP code. LBOS response could not 71 be parsed */ 72 eLBOS_Server = 500, /**< HTTP 500 Internal Server Error */ 73 eLBOS_Disabled = 550 /**< Not a HTTP code. LBOS Client functionality 74 is disabled in registry or during 75 initialization (LBOS Client could not 76 establish connection with LBOS) */ 77 }; 78 79 /////////////////////////////////////////////////////////////////////////////// 80 // DATA TYPES // 81 /////////////////////////////////////////////////////////////////////////////// 82 /** @brief Possible values to set primary address where to search for LBOS. 83 * 84 * LBOS can be located in different places, such as: 85 * - localhost, 86 * - home zone server (i.e. LBOS.dev.be-md.ncbi.nlm.nih.gov, if you 87 * are be-md domain on dev machine), 88 * - somewhere else (set in registry with [CONN]LBOS) 89 * You can set priority for the first place to try. If LBOS is not found in 90 * this primary location, then it will be searched for in other places 91 * following default algorithm of going through places (maybe even through 92 * the same place again). */ 93 typedef enum { 94 eLBOSFindMethod_None, /**< do not search. Used to skip 95 "custom host" method */ 96 eLBOS_FindMethod_CustomHost, /**< Use custom address provided by 97 s_SetLBOSaddress() */ 98 eLBOS_FindMethod_Registry, /**< Use value from registry (default) */ 99 eLBOS_FindMethod_Lbosresolve, /**< Use value from /etc/ncbi/lbosresolve*/ 100 } ELBOSFindMethod; 101 102 103 /** Very simple internal structure which stores information about found 104 * servers. */ 105 typedef struct { 106 SSERV_Info* info; /**< Stores only IP and port for now */ 107 } SLBOS_Candidate; 108 109 110 /** All the data required to store state of one request to LBOS between 111 * calls to SERV_GetNextInfo. */ 112 typedef struct { 113 SConnNetInfo* net_info; /**< Connection point */ 114 const char* lbos_addr; /**< LBOS host:port or IP:port. Used if 115 find_method == 116 eLBOS_FindMethod_CustomHost */ 117 SLBOS_Candidate* cand; /**< Array of found server to iterate */ 118 size_t pos_cand; /**< Current candidate */ 119 size_t n_cand; /**< Used space for candidates */ 120 size_t a_cand; /**< Allocated space for candidates */ 121 ELBOSFindMethod find_method; /**< How we find LBOS. Mainly for 122 testing */ 123 } SLBOS_Data; 124 125 126 /** Data structure to use as user_data in HTTP Connector (header is used 127 * only for unit testing) */ 128 typedef struct { 129 int http_response_code; 130 char* http_status_mesage; 131 const char* header; 132 size_t content_length; /**< Value of "Content-length" HTTP header tag. 133 -1 (max value) as no limit */ 134 } SLBOS_UserData; 135 136 137 /** Used for internal storage, so that DeannounceAll() could deannounce 138 * everything that was announced earlier. 139 * @see 140 * DeannounceAll() 141 */ 142 struct SLBOS_AnnounceHandle_Tag 143 { 144 char* service; /**< service name of announced server */ 145 char* version; /**< service version of announced server */ 146 char* host; /**< host of announced server */ 147 unsigned short port; /**< port of announced server */ 148 }; 149 150 151 /** Possible values of parameter for g_LBOS_CheckIterator(), 152 * this enum is used only in assertions 153 * @see 154 * g_LBOS_CheckIterator() */ 155 typedef enum { 156 ELBOSIteratorCheckType_MustHaveData, /**< Iterator MUST have 'data' 157 filled or error will be 158 returned */ 159 ELBOSIteratorCheckType_DataMustBeNULL, /**< Iterator MUST have 'data' 160 NULL or error will be 161 returned */ 162 ELBOSIteratorCheckType_NoCheck /**< No check of 'data' */ 163 } ELBOSIteratorCheckType; 164 165 /////////////////////////////////////////////////////////////////////////////// 166 // MOCK FUNCTION TYPEDEFS // 167 /////////////////////////////////////////////////////////////////////////////// 168 /** Send REST API request to LBOS, read answer and return filled array of 169 * SSERV_INFO, containing info about all found servers. 170 * @param lbos_address[in] 171 * IP:port or host:port where to send request. 172 * @param serviceName[in] 173 * Name of service to ask for. 174 * @param net_info[in] 175 * Connection point. 176 * @return 177 * Array of pointers to SSERV_Info structs, containing all found servers. 178 */ 179 typedef 180 SSERV_Info** FLBOS_ResolveIPPortMethod(const char* lbos_address, 181 const char* serviceName, 182 SConnNetInfo* net_info); 183 184 185 /** Read from connection. Handles buffer itself. 186 * @param conn[in] 187 * Connection handle. 188 * @param buf[in] 189 * Memory buffer to read to. 190 * @param size[in] 191 * Max. # of bytes to read. 192 * @param n_read[out] 193 * Non-NULL, # of actually read bytes. 194 * @param how[in] 195 * Peek/read/persist. 196 * @return 197 * Success or some error code. */ 198 typedef 199 EIO_Status FLBOS_ConnReadMethod(CONN conn, 200 void* buf, 201 size_t size, 202 size_t* n_read, 203 EIO_ReadMethod how); 204 205 206 /** Given just empty data structure and name of service, do all necessary 207 * operations to fill the structure with servers. 208 * @param data[out] 209 * This structure will be filled. 210 * @param service[in] 211 * Name of the service of which we search servers. */ 212 typedef 213 void FLBOS_FillCandidatesMethod(SLBOS_Data* data, 214 const char* service); 215 216 217 /** Destroy data (simulation of destructor as if SLBOS_Data were a class. 218 * Please note that it will be free()'d and no following access is possible, 219 * so setting data to NULL after this method is recommended for avoiding 220 * confusion. 221 * @param data[in] 222 * Structure to be destroyed. 223 * @note 224 * It presumes that s_LBOS_Reset was called previously. 225 * @see 226 * S_LBOS_Reset(), SLBOS_Data */ 227 typedef 228 void FLBOS_DestroyDataMethod(SLBOS_Data* data); 229 230 231 /** Called under the hood of SERV_GetNextInfo and is responsible for 232 * LBOS client. 233 * @param iter[in] 234 * Iterator used to iterate through servers. 235 * @param host_info[out] 236 * Supposed to be set to pointer to info about host on which returned 237 * server resides, but due to limitations of AWS cloud, it is always NULL. 238 * @return 239 * Next server. */ 240 typedef 241 SSERV_Info* FLBOS_GetNextInfoMethod(SERV_ITER iter, 242 HOST_INFO* host_info); 243 244 245 /** For announcement we search for a LBOS which can handle our request. 246 * Search starts with default order of LBOS. 247 * @param service[in] 248 * Name of service as it will appear in ZK. For services this means that 249 * name should start with '/'. 250 * @param version[in] 251 * Any non-NULL valid C-string. 252 * @param [in] host 253 * Optional parameter (NULL to ignore). If provided, tells on which host 254 * the server resides. Can be different from healthcheck host. If set to 255 * NULL, host is taken from healthcheck. 256 * @param port[in] 257 * Port for service. Can differ from healthcheck port. 258 * @param healthcheck_url[in] 259 * Full absolute URL starting with "http://" or "https://". Should include 260 * hostname or IP and port, if necessary. 261 * @param metadata[in] 262 * URL-ready link with additional meta parameters 263 * @param LBOS_answer[out] 264 * This variable will be assigned a pointer to char* with exact answer of 265 * LBOS, or NULL. If it is not NULL, must be free()'d by the caller. If 266 * eLBOS_Success is returned, LBOS answer contains "host:port" 267 * of LBOS that was used for announce. If something else is returned, LBOS 268 * answer contains human-readable error message. 269 * @return 270 * Code of success or some error. 271 * @see 272 * ELBOS_Result */ 273 typedef 274 unsigned short FLBOS_AnnounceMethod(const char* service, 275 const char* version, 276 const char* host, 277 unsigned short port, 278 const char* healthcheck_url, 279 #ifdef LBOS_METADATA 280 const char* metadata, 281 #endif /* LBOS_METADATA */ 282 char** LBOS_answer, 283 char** http_status_message); 284 285 286 /** Deannounce previously announced service. 287 * @param lbos_hostport[in] 288 * Address of the same LBOS that was used for announcement of the service 289 * now being de-announced. 290 * @param service[in] 291 * Name of service to be de-announced. 292 * @param version[in] 293 * Version of service to be de-announced. 294 * @param port[in] 295 * Port of service to be de-announced. 296 * @param[in] 297 * IP or hostname of service to be de-announced. 298 * @return 299 * false - any error, no deannounce was made; 300 * true - success, deannounce was made. */ 301 typedef 302 int/*bool*/ FLBOS_DeannounceMethod(const char* lbos_hostport, 303 const char* service, 304 const char* version, 305 const char* host, 306 unsigned short port, 307 char** lbos_answer, 308 int* http_status_code, 309 char** http_status_message); 310 311 312 /** This function test existence of the application that should always be 313 * found - LBOS itself. If it is not found, we turn client off. */ 314 typedef 315 void FLBOS_InitializeMethod(void); 316 317 318 typedef char* FLBOS_UrlReadAllMethod(SConnNetInfo* net_info, 319 const char* url, 320 int* status_code, 321 char** status_message); 322 323 324 /** Standard parse header function. The only thing considered is that 325 standard "void* data" field is used as int code of HTTP response */ 326 typedef EHTTP_HeaderParse FLBOS_ParseHeader(const char* header, 327 void* /* int* */response_code, 328 int server_error); 329 330 /** Get (and cache for faster follow-up retrievals) the address of 331 * local host. */ 332 typedef unsigned int FLBOS_SOCKGetLocalHostAddressMethod(ESwitch reget); 333 334 /////////////////////////////////////////////////////////////////////////////// 335 // VIRTUAL FUNCTIONS TABLE // 336 /////////////////////////////////////////////////////////////////////////////// 337 typedef struct { 338 FLBOS_ResolveIPPortMethod* ResolveIPPort; 339 FLBOS_ConnReadMethod* Read; 340 FLBOS_FillCandidatesMethod* FillCandidates; 341 FLBOS_DestroyDataMethod* DestroyData; 342 FLBOS_GetNextInfoMethod* GetNextInfo; 343 FLBOS_InitializeMethod* Initialize; 344 FLBOS_UrlReadAllMethod* UrlReadAll; 345 FLBOS_ParseHeader* ParseHeader; 346 FLBOS_SOCKGetLocalHostAddressMethod* LocalHostAddr; 347 FLBOS_AnnounceMethod* AnnounceEx; 348 } SLBOS_Functions; 349 350 351 /////////////////////////////////////////////////////////////////////////////// 352 // GLOBAL FUNCTIONS // 353 /////////////////////////////////////////////////////////////////////////////// 354 /** Get the best possible LBOS address for this platform. 355 * @return 356 * LBOS address that needs to be free()'d by the caller. 357 * @see 358 * g_LBOS_GetLBOSAddressEx() */ 359 NCBI_XCONNECT_EXPORT 360 char* g_LBOS_GetLBOSAddress(void); 361 362 363 /** Get the best possible LBOS addresses for this platform, extended version - 364 * first tries the method of caller's choice. 365 * @param[in] priority_find_method 366 * First method to try. 367 * @param[in] lbos_addr 368 * String with "%hostname%:%port%" or "%IP%:%port%". If priority_find_method 369 * is set to eLBOS_FindMethod_CustomHost, lbos_addr should be non-NULL 370 * (or else the method will be ignored) 371 * @return 372 * LBOS address that needs to be free()'d by the caller. 373 * @see 374 * g_LBOS_GetLBOSAddress() */ 375 NCBI_XCONNECT_EXPORT 376 char* g_LBOS_GetLBOSAddressEx(ELBOSFindMethod priority_find_method, 377 const char* lbos_addr); 378 379 /** Creates iterator and fills it with found servers. 380 * @param[in,out] iter 381 * Pointer to iterator. It is read and rewritten. If nothing found, it is 382 * free()'d and points to unallocated area. 383 * @param[in] net_info 384 * Connection point. 385 * @param[out] info 386 * Always assigned NULL, as not used in this client. 387 * @return 388 * Table of methods if found servers, NULL if not found. 389 * @see 390 * s_Open(), SERV_LOCAL_Open(), SERV_LBSMD_Open(), SERV_DISPD_Open() */ 391 NCBI_XCONNECT_EXPORT 392 const SSERV_VTable* SERV_LBOS_Open(SERV_ITER iter, 393 const SConnNetInfo* net_info, 394 SSERV_Info** info); 395 396 397 /** Checks C-string if it is NULL or is of zero length. 398 * @param[in] str 399 * String to check. 400 * @return 401 * true - string is NULL or empty; 402 * false - string exists and contains elements. */ 403 NCBI_XCONNECT_EXPORT 404 int/*bool*/ g_LBOS_StringIsNullOrEmpty(const char* str); 405 406 407 /** Compose LBOS address from /etc/ncbi/{role, domain}. 408 * @return 409 * LBOS address. Must be free()'d by the caller. */ 410 NCBI_XCONNECT_EXPORT 411 char* g_LBOS_ComposeLBOSAddress(void); 412 413 414 /** Set primary method how to find LBOS. Default is eLBOS_FindMethod_Registry. 415 * @param[in] iter 416 * Iterator that represents current request to LBOS. 417 * @param[in] method 418 * One of methods. 419 * @return f 420 * false - something went wrong, primary method was not changed; 421 * true - success. */ 422 NCBI_XCONNECT_EXPORT 423 int/*bool*/ g_LBOS_UnitTesting_SetLBOSFindMethod(SERV_ITER iter, 424 ELBOSFindMethod method); 425 426 427 /** Set custom host for LBOS. It will be used when method 428 * eLBOS_FindMethod_CustomHost is used. 429 * @param[in] iter 430 * Iterator that represents current request to LBOS. 431 * @param[in] address 432 * IP:port or host:port to use. 433 * @return 434 * false - something went wrong, LBOS address was not changed. 435 * true - success. */ 436 NCBI_XCONNECT_EXPORT 437 int/*bool*/ g_LBOS_UnitTesting_SetLBOSaddress(SERV_ITER iter, 438 char* address); 439 440 441 /** Set custom files to load role and domain from, respectively. 442 * @param lbosresolverFile[in] 443 * To change lbosresolver file path, pass it here. To use current 444 * lbosresolver file path, pass NULL. 445 * @return 446 * false - values not changed; 447 * true - success. */ 448 NCBI_XCONNECT_EXPORT int/*bool*/ 449 g_LBOS_UnitTesting_SetLBOSResolverFile(const char* lbosresolverFile); 450 451 452 /** Checks iterator, fact that iterator belongs to this client, iterator data. 453 * Only debug function. 454 * @param iter[in] 455 * Iterator to check. Not modified in any way. 456 * @param should_have_data[in] 457 * How to check 'data' field of iterator. 458 * @see 459 * ELBOSIteratorCheckType 460 * @return 461 * true - iterator is valid; 462 * false - iterator is invalid. 463 */ 464 NCBI_XCONNECT_EXPORT 465 int/*bool*/ g_LBOS_CheckIterator(SERV_ITER iter, 466 ELBOSIteratorCheckType should_have_data); 467 468 /** Find server among announced and return its position. If not found, 469 * return -1. 470 */ 471 NCBI_XCONNECT_EXPORT 472 int g_LBOS_UnitTesting_FindAnnouncedServer(const char* service, 473 const char* version, 474 unsigned short port, 475 const char* host); 476 477 /** Get LBOS-specific announcement variable from registry 478 */ 479 NCBI_XCONNECT_EXPORT char* g_LBOS_RegGet(const char* section, 480 const char* name, 481 const char* def_value); 482 483 484 485 /** This service can be used to remove service from configuration. Current 486 * version will be empty. Previous version shows deleted version. 487 */ 488 NCBI_XCONNECT_EXPORT 489 unsigned short LBOS_ServiceVersionDelete(const char* service, 490 char** lbos_answer, 491 char** http_status_message); 492 493 494 /** This request can be used to set new version for a service. Current and 495 * previous versions show currently set and previously used service versions. 496 * @param[in] service 497 * Name of service for which the version is going to be changed 498 * @param new_version[out] 499 * Version that will be used by default for specefied service 500 * @param lbos_answer[out] 501 * Variable to be assigned pointer to C-string with LBOS answer 502 * @param http_status_message[out] 503 * Variable to be assigned pointer to C-string with status message from LBOS 504 */ 505 NCBI_XCONNECT_EXPORT 506 unsigned short LBOS_ServiceVersionSet(const char* service, 507 const char* new_version, 508 char** lbos_answer, 509 char** http_status_message); 510 511 512 /** This request will show currently used version for a requested service. 513 * Current and previous version will be the same. 514 * @param service[in] 515 * Name of service for which to ask default version 516 * @param lbos_answer[out] 517 * Variable to be assigned pointer to C-string with LBOS answer 518 * @param http_status_message[out] 519 * Variable to be assigned pointer to C-string with status message from LBOS 520 * @return 521 * Status code returned by LBOS 522 */ 523 NCBI_XCONNECT_EXPORT 524 unsigned short LBOS_ServiceVersionGet(const char* service, 525 char** lbos_answer, 526 char** http_status_message); 527 528 /////////////////////////////////////////////////////////////////////////////// 529 // GLOBAL VARIABLES FOR UNIT TESTS // 530 /////////////////////////////////////////////////////////////////////////////// 531 532 /** Table of all functions to mock, used solely for unit testing purposes. 533 * @see 534 * SLBOS_Functions */ 535 NCBI_XCONNECT_EXPORT 536 SLBOS_Functions* g_LBOS_UnitTesting_GetLBOSFuncs(void); 537 538 539 /** Check whether LBOS client is turned ON or OFF. 540 * @return 541 * address of static variable s_LBOS_TurnedOn. 542 * @see 543 * SERV_LBOS_Open() */ 544 NCBI_XCONNECT_EXPORT 545 int* g_LBOS_UnitTesting_PowerStatus(void); 546 547 548 /** Check whether LBOS client is turned ON or OFF. 549 * @return 550 * address of static variable s_LBOS_TurnedOn. 551 * @see 552 * SERV_LBOS_Open() */ 553 NCBI_XCONNECT_EXPORT 554 int* g_LBOS_UnitTesting_InitStatus(void); 555 556 557 /** List of addresses of LBOS that is maintained in actual state. 558 * @return 559 * address of static variable s_LBOS_InstancesList. 560 * @see 561 * SERV_LBOS_Open(), s_LBOS_FillCandidates() */ 562 NCBI_XCONNECT_EXPORT 563 char** g_LBOS_UnitTesting_Instance(void); 564 565 566 /** List of announced servers that is stored statically 567 * @return 568 * address of static variable s_LBOS_AnnouncedServers */ 569 NCBI_XCONNECT_EXPORT 570 struct SLBOS_AnnounceHandle_Tag** g_LBOS_UnitTesting_GetAnnouncedServers(void); 571 572 573 /** Number of announced servers stored 574 * @return 575 * pointer to s_LBOS_AnnouncedServersNum */ 576 NCBI_XCONNECT_EXPORT 577 int g_LBOS_UnitTesting_GetAnnouncedServersNum(void); 578 579 580 /** Pointer to s_LBOS_Lbosresolver 581 * @return 582 * address of static variable s_LBOS_Lbosresolver. 583 * @see */ 584 NCBI_XCONNECT_EXPORT 585 char** g_LBOS_UnitTesting_Lbosresolver(void); 586 587 588 #ifdef __cplusplus 589 } /* extern "C" */ 590 #endif /*__cplusplus*/ 591 592 #endif /* CONNECT___NCBI_LBOSP__H */ 593