⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncbi_service_connector.c

📁 ncbi源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_service_connector.c,v $ * PRODUCTION Revision 1000.0  2003/10/29 16:39:51  gouriano * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.60 * PRODUCTION * =========================================================================== *//*  $Id: ncbi_service_connector.c,v 1000.0 2003/10/29 16:39:51 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Anton Lavrentiev * * File Description: *   Implementation of CONNECTOR to a named service * */#include "ncbi_ansi_ext.h"#include "ncbi_comm.h"#include "ncbi_priv.h"#include "ncbi_servicep.h"#include <connect/ncbi_http_connector.h>#include <connect/ncbi_service_connector.h>#include <connect/ncbi_socket_connector.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>typedef struct SServiceConnectorTag {    const char*     name;               /* Verbal connector type             */    const char*     service;            /* Service name (final) to use       */    TSERV_Type      types;              /* Server types, record keeping only */    SConnNetInfo*   net_info;           /* Connection information            */    const char*     user_header;        /* User header currently set         */    SERV_ITER       iter;               /* Dispatcher information            */    SMetaConnector  meta;               /* Low level comm.conn and its VT    */    EIO_Status      status;             /* Status of last op                 */    unsigned int    host;               /* Parsed connection info...         */    unsigned short  port;    ticket_t        ticket;    SSERVICE_Extra  params;    char            args[1];            /* Additional CGI parameters         */} SServiceConnector;/*********************************************************************** *  INTERNAL -- "s_VT_*" functions for the "virt. table" of connector methods ***********************************************************************/#ifdef __cplusplusextern "C" {#endif /* __cplusplus */    static const char* s_VT_GetType (CONNECTOR       connector);    static EIO_Status  s_VT_Open    (CONNECTOR       connector,                                     const STimeout* timeout);    static EIO_Status  s_VT_Status  (CONNECTOR       connector,                                     EIO_Event       dir);    static EIO_Status  s_VT_Close   (CONNECTOR       connector,                                     const STimeout* timeout);    static void        s_Setup      (SMetaConnector* meta,                                     CONNECTOR       connector);    static void        s_Destroy    (CONNECTOR       connector);#ifdef __cplusplus} /* extern "C" */#endif /* __cplusplus */static char* s_GetArgs(const char* client_host){    static const char platform[] = "&platform=";    static const char address[]  = "address=";    size_t nodelen, archlen, buflen;    const char* arch;    unsigned int ip;    char addr[80];    char* p;    buflen = 0;    if (*client_host) {        nodelen = strlen(client_host);        buflen += sizeof(address) - 1 + nodelen;        if (!strchr(client_host, '.')                   &&            (ip = SOCK_gethostbyname(client_host)) != 0 &&            SOCK_ntoa(ip, addr, sizeof(addr))      == 0) {            buflen += strlen(addr) + 2;        } else            *addr = 0;    } else        nodelen = 0;    if ((arch = CORE_GetPlatform()) != 0 && *arch) {        archlen = strlen(arch);        buflen += sizeof(platform) - 1 + archlen;    } else        archlen = 0;    if (!buflen || !(p = (char*) malloc(buflen + 1)))        return 0;    buflen = 0;    if (nodelen) {        strcpy(&p[buflen], address);        buflen += sizeof(address) - 1;        strcpy(&p[buflen], client_host);        buflen += nodelen;        if (*addr)            buflen += sprintf(&p[buflen], "(%s)", addr);    }    if (archlen) {        strcpy(&p[buflen], nodelen ? platform : platform + 1);        buflen += nodelen ? sizeof(platform) - 1 : sizeof(platform) - 2;        strcpy(&p[buflen], arch);        buflen += archlen;    }    return p;}static int/*bool*/ s_OpenDispatcher(SServiceConnector* uuu){    uuu->user_header = 0;    if (!(uuu->iter = SERV_OpenEx(uuu->service, uuu->types,                                  SERV_LOCALHOST, uuu->net_info, 0, 0)))        return 0/*false*/;    return 1/*true*/;}static void s_CloseDispatcher(SServiceConnector* uuu){    if (uuu->user_header) {        free((void*) uuu->user_header);        uuu->user_header = 0;    }    SERV_Close(uuu->iter);    uuu->iter = 0;}/* Reset functions, which are implemented only in transport * connectors, but not in this connector. */static void s_Reset(SMetaConnector *meta){    CONN_SET_METHOD(meta, descr,      0,             0);    CONN_SET_METHOD(meta, wait,       0,             0);    CONN_SET_METHOD(meta, write,      0,             0);    CONN_SET_METHOD(meta, flush,      0,             0);    CONN_SET_METHOD(meta, read,       0,             0);    CONN_SET_METHOD(meta, status,     s_VT_Status,   0);#ifdef IMPLEMENTED__CONN_WaitAsync    CONN_SET_METHOD(meta, wait_async, 0,             0);#endif}#ifdef __cplusplusextern "C" {    static int s_ParseHeader(const char*, void*, int);}#endif /* __cplusplus */static int/*bool*/ s_ParseHeader(const char* header,                                 void*       data,                                 int/*bool*/ server_error){    static const char kStateless[] = "TRY_STATELESS";    SServiceConnector* uuu = (SServiceConnector*) data;    SERV_Update(uuu->iter, header);    if (server_error)        return 1/*parsed okay*/;    while (header && *header) {        if (strncasecmp(header, HTTP_CONNECTION_INFO,                        sizeof(HTTP_CONNECTION_INFO) - 1) == 0) {            unsigned int  i1, i2, i3, i4, ticket;            unsigned char o1, o2, o3, o4;            char ipaddr[32];            header += sizeof(HTTP_CONNECTION_INFO) - 1;            while (*header && isspace((unsigned char)(*header)))                header++;            if (strncasecmp(header, kStateless, sizeof(kStateless) - 1) == 0) {                /* Special keyword for switching into stateless mode */                uuu->host = (unsigned int)(-1);#if defined(_DEBUG) && !defined(NDEBUG)                if (uuu->net_info->debug_printout)                    CORE_LOG(eLOG_Warning,                             "[SERVICE]  Fallback to stateless requested");#endif                break;            }            if (sscanf(header, "%u.%u.%u.%u %hu %x",                       &i1, &i2, &i3, &i4, &uuu->port, &ticket) < 6)                return 0/*failed*/;            o1 = i1; o2 = i2; o3 = i3; o4 = i4;            sprintf(ipaddr, "%u.%u.%u.%u", o1, o2, o3, o4);            uuu->host = SOCK_gethostbyname(ipaddr);            uuu->ticket = SOCK_htonl(ticket);            break;        }        if ((header = strchr(header, '\n')) != 0)            header++;    }    return 1/*success*/;}static char* s_AdjustNetParams(SConnNetInfo*  net_info,                               EReqMethod     req_method,                               const char*    cgi_name,                               const char*    service,                               const char*    args,                               const char*    cgi_args,                               const char*    static_header,                               EMIME_Type     mime_t,                               EMIME_SubType  mime_s,                               EMIME_Encoding mime_e,                               char*          dynamic_header/*will be freed*/){    char content_type[MAX_CONTENT_TYPE_LEN], *retval;    net_info->req_method = req_method;    if (cgi_name)        strncpy0(net_info->path, cgi_name, sizeof(net_info->path) - 1);    if (cgi_args)        strncpy0(net_info->args, cgi_args, sizeof(net_info->args) - 1);    if (service) {        ConnNetInfo_PrependArg(net_info, args, 0);        if (!ConnNetInfo_PreOverrideArg(net_info, "service", service)) {            const char* a = args ? strrchr(args, '&') : 0;            if (!a)                a = args;            while (a) {                ConnNetInfo_DeleteArg(net_info, a + (*a == '&' ? 1 : 0));                if (ConnNetInfo_PreOverrideArg(net_info, "service", service))                    break;                if (a != args) {                    while (a > args) {                        if (*--a == '&')                            break;                    }                } else                    a = 0;            }            if (!a) {                if (dynamic_header)                    free(dynamic_header);                return 0/*failed*/;            }        }    }    if (mime_t == SERV_MIME_TYPE_UNDEFINED    ||        mime_s == SERV_MIME_SUBTYPE_UNDEFINED ||        !MIME_ComposeContentTypeEx(mime_t, mime_s, mime_e,                                   content_type, sizeof(content_type))) {        *content_type = 0;    }    if ((retval = (char*) malloc((static_header ? strlen(static_header) : 0) +                                 strlen(content_type) + 1/*EOL*/ +                                 (dynamic_header? strlen(dynamic_header) : 0)                                 )) != 0) {        strcpy(retval, static_header ? static_header : "");        strcat(retval, content_type);        strcat(retval, dynamic_header ? dynamic_header : "");    }    if (dynamic_header)        free(dynamic_header);    return retval;}static const SSERV_Info* s_GetNextInfo(SServiceConnector* uuu){    if (uuu->params.get_next_info)        return uuu->params.get_next_info(uuu->iter, uuu->params.data);    else        return SERV_GetNextInfo(uuu->iter);}/* Although all additional HTTP tags, which comprise dispatching, have * default values, which in most cases are fine with us, we will use * these tags explicitly to distinguish calls originated from within the * service connector from the calls from a Web browser, for example. * This technique allows the dispatcher to decide whether to use more * expensive dispatching (inlovling loopback connections) in case of browser. */#ifdef __cplusplusextern "C" {    static int s_AdjustNetInfo(SConnNetInfo*, void*, unsigned int);}#endif /* __cplusplus *//* This callback is only for services called via direct HTTP */static int/*bool*/ s_AdjustNetInfo(SConnNetInfo* net_info,                                   void*         data,                                   unsigned int  n){    SServiceConnector* uuu = (SServiceConnector*) data;    const char* user_header = 0;    const SSERV_Info* info;    assert(n != 0); /* paranoid assertion :-) */    if (net_info->firewall && !net_info->stateless)        return 0; /*cannot adjust firewall stateful client*/    for (;;) {        if (!(info = s_GetNextInfo(uuu)))            return 0/*false - not adjusted*/;        /* Skip any 'stateful_capable' entries here, which might         * have left behind a failed stateful dispatching with a         * fallback to stateless HTTP mode */        if (!info->sful)            break;    }    {{        char* iter_header = SERV_Print(uuu->iter);        switch (info->type) {        case fSERV_Ncbid:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -