~ubuntu-branches/ubuntu/feisty/ncbi-tools6/feisty

« back to all changes in this revision

Viewing changes to connect/ncbi_service_connector.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2006-07-19 23:28:07 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060719232807-et3cdmcjgmnyleyx
Tags: 6.1.20060507-3ubuntu1
Re-merge with Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  $Id: ncbi_service_connector.c,v 6.64 2005/10/26 14:44:59 lavr Exp $
 
1
/*  $Id: ncbi_service_connector.c,v 6.72 2006/04/23 18:27:54 lavr Exp $
2
2
 * ===========================================================================
3
3
 *
4
4
 *                            PUBLIC DOMAIN NOTICE
43
43
 
44
44
typedef struct SServiceConnectorTag {
45
45
    const char*     name;               /* Verbal connector type             */
46
 
    const char*     service;            /* Service name (final) to use       */
47
46
    TSERV_Type      types;              /* Server types, record keeping only */
48
47
    SConnNetInfo*   net_info;           /* Connection information            */
49
48
    const char*     user_header;        /* User header currently set         */
54
53
    unsigned short  port;
55
54
    ticket_t        ticket;
56
55
    SSERVICE_Extra  params;
57
 
    char            args[1];            /* Additional CGI parameters         */
 
56
    const char*     x_service;          /* Translated service name, if stored*/
 
57
    char            service[1];         /* Untranslated service name         */
58
58
} SServiceConnector;
59
59
 
60
60
 
80
80
#endif /* __cplusplus */
81
81
 
82
82
 
83
 
static char* s_GetArgs(const char* client_host)
84
 
{
85
 
    static const char platform[] = "&platform=";
86
 
    static const char address[]  = "address=";
87
 
    size_t nodelen, archlen, buflen;
88
 
    const char* arch;
89
 
    unsigned int ip;
90
 
    char addr[80];
91
 
    char* p;
92
 
 
93
 
    buflen = 0;
94
 
    if (*client_host) {
95
 
        nodelen = strlen(client_host);
96
 
        buflen += sizeof(address) - 1 + nodelen;
97
 
        if (!strchr(client_host, '.')                   &&
98
 
            (ip = SOCK_gethostbyname(client_host)) != 0 &&
99
 
            SOCK_ntoa(ip, addr, sizeof(addr))      == 0) {
100
 
            buflen += strlen(addr) + 2;
101
 
        } else
102
 
            *addr = 0;
103
 
    } else
104
 
        nodelen = 0;
105
 
    if ((arch = CORE_GetPlatform()) != 0 && *arch) {
106
 
        archlen = strlen(arch);
107
 
        buflen += sizeof(platform) - 1 + archlen;
108
 
    } else
109
 
        archlen = 0;
110
 
    if (!buflen || !(p = (char*) malloc(buflen + 1)))
111
 
        return 0;
112
 
    buflen = 0;
113
 
    if (nodelen) {
114
 
        strcpy(&p[buflen], address);
115
 
        buflen += sizeof(address) - 1;
116
 
        strcpy(&p[buflen], client_host);
117
 
        buflen += nodelen;
118
 
        if (*addr)
119
 
            buflen += sprintf(&p[buflen], "(%s)", addr);
120
 
    }
121
 
    if (archlen) {
122
 
        strcpy(&p[buflen], nodelen ? platform : platform + 1);
123
 
        buflen += nodelen ? sizeof(platform) - 1 : sizeof(platform) - 2;
124
 
        strcpy(&p[buflen], arch);
125
 
        buflen += archlen;
126
 
    }
127
 
    return p;
128
 
}
129
 
 
130
 
 
131
83
static int/*bool*/ s_OpenDispatcher(SServiceConnector* uuu)
132
84
{
133
 
    uuu->user_header = 0;
134
85
    if (!(uuu->iter = SERV_OpenEx(uuu->service, uuu->types,
135
 
                                  SERV_LOCALHOST, uuu->net_info, 0, 0)))
 
86
                                  SERV_LOCALHOST, uuu->net_info, 0, 0))) {
136
87
        return 0/*false*/;
 
88
    }
137
89
    return 1/*true*/;
138
90
}
139
91
 
140
92
 
141
93
static void s_CloseDispatcher(SServiceConnector* uuu)
142
94
{
143
 
    if (uuu->user_header) {
144
 
        free((void*) uuu->user_header);
145
 
        uuu->user_header = 0;
146
 
    }
147
95
    SERV_Close(uuu->iter);
148
96
    uuu->iter = 0;
149
97
}
154
102
 */
155
103
static void s_Reset(SMetaConnector *meta)
156
104
{
157
 
    CONN_SET_METHOD(meta, descr,      0,             0);
158
 
    CONN_SET_METHOD(meta, wait,       0,             0);
159
 
    CONN_SET_METHOD(meta, write,      0,             0);
160
 
    CONN_SET_METHOD(meta, flush,      0,             0);
161
 
    CONN_SET_METHOD(meta, read,       0,             0);
162
 
    CONN_SET_METHOD(meta, status,     s_VT_Status,   0);
 
105
    CONN_SET_METHOD(meta, descr,      0,           0);
 
106
    CONN_SET_METHOD(meta, wait,       0,           0);
 
107
    CONN_SET_METHOD(meta, write,      0,           0);
 
108
    CONN_SET_METHOD(meta, flush,      0,           0);
 
109
    CONN_SET_METHOD(meta, read,       0,           0);
 
110
    CONN_SET_METHOD(meta, status,     s_VT_Status, 0);
163
111
#ifdef IMPLEMENTED__CONN_WaitAsync
164
 
    CONN_SET_METHOD(meta, wait_async, 0,             0);
 
112
    CONN_SET_METHOD(meta, wait_async, 0,           0);
165
113
#endif
166
114
}
167
115
 
179
127
    static const char kStateless[] = "TRY_STATELESS";
180
128
    SServiceConnector* uuu = (SServiceConnector*) data;
181
129
 
182
 
    SERV_Update(uuu->iter, header);
 
130
    SERV_Update(uuu->iter, header, server_error);
183
131
    if (server_error)
184
132
        return 1/*parsed okay*/;
185
133
 
190
138
            unsigned char o1, o2, o3, o4;
191
139
            char ipaddr[32];
192
140
 
 
141
            if (uuu->host)
 
142
                break/*failed - duplicate connection info*/;
193
143
            header += sizeof(HTTP_CONNECTION_INFO) - 1;
194
144
            while (*header && isspace((unsigned char)(*header)))
195
145
                header++;
197
147
                /* Special keyword for switching into stateless mode */
198
148
                uuu->host = (unsigned int)(-1);
199
149
#if defined(_DEBUG) && !defined(NDEBUG)
200
 
                if (uuu->net_info->debug_printout)
201
 
                    CORE_LOG(eLOG_Warning,
 
150
                if (uuu->net_info->debug_printout) {
 
151
                    CORE_LOG(eLOG_Note,
202
152
                             "[SERVICE]  Fallback to stateless requested");
 
153
                }
203
154
#endif
204
 
                break;
 
155
            } else {
 
156
                if (sscanf(header, "%u.%u.%u.%u %hu %x",
 
157
                           &i1, &i2, &i3, &i4, &uuu->port, &ticket) < 6) {
 
158
                    break/*failed - unreadable connection info*/;
 
159
                }
 
160
                o1 = i1; o2 = i2; o3 = i3; o4 = i4;
 
161
                sprintf(ipaddr, "%u.%u.%u.%u", o1, o2, o3, o4);
 
162
                if (!(uuu->host = SOCK_gethostbyname(ipaddr)) || !uuu->port)
 
163
                    break/*failed - bad host:port in connection info*/;
 
164
                uuu->ticket = SOCK_HostToNetLong(ticket);
205
165
            }
206
 
            if (sscanf(header, "%u.%u.%u.%u %hu %x",
207
 
                       &i1, &i2, &i3, &i4, &uuu->port, &ticket) < 6)
208
 
                return 0/*failed*/;
209
 
            o1 = i1; o2 = i2; o3 = i3; o4 = i4;
210
 
            sprintf(ipaddr, "%u.%u.%u.%u", o1, o2, o3, o4);
211
 
            uuu->host = SOCK_gethostbyname(ipaddr);
212
 
            uuu->ticket = SOCK_htonl(ticket);
213
 
            break;
214
166
        }
215
167
        if ((header = strchr(header, '\n')) != 0)
216
168
            header++;
217
169
    }
218
 
 
219
 
    return 1/*success*/;
 
170
    if (!header || !*header)
 
171
        return 1/*success*/;
 
172
 
 
173
    uuu->host = 0;
 
174
    return 0/*failure*/;
 
175
}
 
176
 
 
177
 
 
178
static int/*bool*/ s_ContentTypeDefined(const SConnNetInfo* net_info,
 
179
                                        EMIME_Type          mime_t,
 
180
                                        EMIME_SubType       mime_s,
 
181
                                        EMIME_Encoding      mime_e)
 
182
{
 
183
    const char* s;
 
184
 
 
185
    assert(net_info);
 
186
    for (s = net_info->http_user_header; s; s = strchr(s, '\n')) {
 
187
        if (s != net_info->http_user_header)
 
188
            s++;
 
189
        if (!*s)
 
190
            break;
 
191
        if (strncasecmp(s, "content-type: ", 14) == 0) {
 
192
#if defined(_DEBUG) && !defined(NDEBUG)
 
193
            EMIME_Type     m_t;
 
194
            EMIME_SubType  m_s;
 
195
            EMIME_Encoding m_e;
 
196
            char           c_t[MAX_CONTENT_TYPE_LEN];
 
197
            if (net_info->debug_printout                      &&
 
198
                mime_t != SERV_MIME_TYPE_UNDEFINED            &&
 
199
                mime_t != eMIME_T_Unknown                     &&
 
200
                MIME_ParseContentTypeEx(s, &m_t, &m_s, &m_e)  &&
 
201
                (mime_t != m_t
 
202
                 ||  (mime_s != SERV_MIME_SUBTYPE_UNDEFINED &&
 
203
                      mime_s != eMIME_Unknown &&
 
204
                      m_s != eMIME_Unknown && mime_s != m_s)
 
205
                 ||  (mime_e != eENCOD_None &&
 
206
                      m_e != eENCOD_None && mime_e != m_e))) {
 
207
                const char* c;
 
208
                size_t len;
 
209
                char* t;
 
210
                for (s += 15; *s; s++) {
 
211
                    if (!isspace((unsigned char)(*s)))
 
212
                        break;
 
213
                }
 
214
                if (!(c = strchr(s, '\n')))
 
215
                    c = s + strlen(s);
 
216
                if (c > s && c[-1] == '\r')
 
217
                    c--;
 
218
                len = (size_t)(c - s);
 
219
                if ((t = (char*) malloc(len + 1)) != 0) {
 
220
                    memcpy(t, s, len);
 
221
                    t[len] = '\0';
 
222
                }
 
223
                if (!MIME_ComposeContentTypeEx(mime_t, mime_s, mime_e,
 
224
                                               c_t, sizeof(c_t))) {
 
225
                    *c_t = '\0';
 
226
                }
 
227
                CORE_LOGF(eLOG_Warning,
 
228
                          ("[SERVICE]  Content-Type mismatch for \"%s\" "
 
229
                           "%s%s%s%s%s", net_info->service,
 
230
                           t && *t         ? "specified="  : "",
 
231
                           t && *t         ? t             : "",
 
232
                           t && *t && *c_t ? ", "          : "",
 
233
                           *c_t            ? "configured=" : "",
 
234
                           *c_t            ? c_t           : ""));
 
235
                if (t)
 
236
                    free(t);
 
237
            }
 
238
#endif
 
239
            return 1/*true*/;
 
240
        }
 
241
    }
 
242
    return 0/*false*/;
220
243
}
221
244
 
222
245
 
223
246
static char* s_AdjustNetParams(SConnNetInfo*  net_info,
224
247
                               EReqMethod     req_method,
225
 
                               const char*    cgi_name,
226
 
                               const char*    service,
 
248
                               const char*    cgi_path,
 
249
                               const char*    cgi_args,
227
250
                               const char*    args,
228
 
                               const char*    cgi_args,
229
251
                               const char*    static_header,
230
252
                               EMIME_Type     mime_t,
231
253
                               EMIME_SubType  mime_s,
232
254
                               EMIME_Encoding mime_e,
233
255
                               char*          dynamic_header/*will be freed*/)
234
256
{
235
 
    char content_type[MAX_CONTENT_TYPE_LEN], *retval;
 
257
    char c_t[MAX_CONTENT_TYPE_LEN], *retval;
 
258
    size_t sh_len, dh_len, ct_len;
236
259
 
237
260
    net_info->req_method = req_method;
238
261
 
239
 
    if (cgi_name)
240
 
        strncpy0(net_info->path, cgi_name, sizeof(net_info->path) - 1);
241
 
 
242
 
    if (cgi_args)
243
 
        strncpy0(net_info->args, cgi_args, sizeof(net_info->args) - 1);
244
 
 
245
 
    if (service) {
246
 
        if (!args) {
247
 
            ConnNetInfo_AppendArg(net_info, "service", service);
248
 
        } else {
249
 
            ConnNetInfo_PrependArg(net_info, args, 0);
250
 
            if (!ConnNetInfo_PreOverrideArg(net_info, "service", service)) {
251
 
                const char* a = args ? strrchr(args, '&') : 0;
252
 
                if (!a)
253
 
                    a = args;
254
 
                while (a) {
255
 
                    ConnNetInfo_DeleteArg(net_info, a + (*a == '&' ? 1 : 0));
256
 
                    if (ConnNetInfo_PreOverrideArg(net_info,"service",service))
257
 
                        break;
258
 
                    if (a != args) {
259
 
                        while (a > args) {
260
 
                            if (*--a == '&')
261
 
                                break;
262
 
                        }
263
 
                    } else
264
 
                        a = 0;
265
 
                }
266
 
                if (!a) {
267
 
                    if (dynamic_header)
268
 
                        free(dynamic_header);
269
 
                    return 0/*failed*/;
270
 
                }
271
 
            }
272
 
        }
273
 
    }
274
 
 
275
 
    if (mime_t == SERV_MIME_TYPE_UNDEFINED    ||
276
 
        mime_s == SERV_MIME_SUBTYPE_UNDEFINED ||
277
 
        !MIME_ComposeContentTypeEx(mime_t, mime_s, mime_e,
278
 
                                   content_type, sizeof(content_type))) {
279
 
        *content_type = 0;
280
 
    }
281
 
    if ((retval = (char*) malloc((static_header ? strlen(static_header) : 0) +
282
 
                                 strlen(content_type) + 1/*EOL*/ +
283
 
                                 (dynamic_header? strlen(dynamic_header) : 0)
284
 
                                 )) != 0) {
285
 
        strcpy(retval, static_header ? static_header : "");
286
 
        strcat(retval, content_type);
287
 
        strcat(retval, dynamic_header ? dynamic_header : "");
 
262
    if (cgi_path)
 
263
        strncpy0(net_info->path, cgi_path, sizeof(net_info->path) - 1);
 
264
 
 
265
    if (args)
 
266
        strncpy0(net_info->args, args, sizeof(net_info->args) - 1);
 
267
    ConnNetInfo_DeleteAllArgs(net_info, cgi_args);
 
268
    if (!ConnNetInfo_PrependArg(net_info, cgi_args, 0)) {
 
269
        if (dynamic_header)
 
270
            free(dynamic_header);
 
271
        return 0/*failed*/;
 
272
    }
 
273
 
 
274
    sh_len = static_header  ? strlen(static_header)  : 0;
 
275
    dh_len = dynamic_header ? strlen(dynamic_header) : 0;
 
276
    if (s_ContentTypeDefined(net_info, mime_t, mime_s, mime_e)  ||
 
277
        mime_t == SERV_MIME_TYPE_UNDEFINED                      ||
 
278
        mime_s == SERV_MIME_SUBTYPE_UNDEFINED                   ||
 
279
        !MIME_ComposeContentTypeEx(mime_t, mime_s, mime_e, c_t, sizeof(c_t))) {
 
280
        c_t[0] = '\0';
 
281
        ct_len = 0;
 
282
    } else
 
283
        ct_len = strlen(c_t);
 
284
    if ((retval = (char*) malloc(sh_len + dh_len +ct_len + 1/*EOL*/)) != 0) {
 
285
        strcpy(retval,                   static_header  ? static_header  : "");
 
286
        strcpy(retval + sh_len,          dynamic_header ? dynamic_header : "");
 
287
        strcpy(retval + sh_len + dh_len, c_t);
288
288
    }
289
289
    if (dynamic_header)
290
290
        free(dynamic_header);
322
322
                                   unsigned int  n)
323
323
{
324
324
    SServiceConnector* uuu = (SServiceConnector*) data;
325
 
    const char* user_header = 0;
 
325
    const char* user_header;
326
326
    const SSERV_Info* info;
327
327
 
328
328
    assert(n != 0); /* paranoid assertion :-) */
329
 
    if (net_info->firewall && !net_info->stateless)
 
329
    if (uuu->net_info->firewall && !uuu->net_info->stateless)
330
330
        return 0; /*cannot adjust firewall stateful client*/
331
331
 
332
332
    for (;;) {
333
333
        if (!(info = s_GetNextInfo(uuu)))
334
334
            return 0/*false - not adjusted*/;
335
 
        /* Skip any 'stateful_capable' entries here, which might
336
 
         * have left behind a failed stateful dispatching with a
337
 
         * fallback to stateless HTTP mode */
338
 
        if (!info->sful)
 
335
        /* Skip any 'stateful_capable' or unconnectable entries here,
 
336
         * which might have left behind by either a failed stateful
 
337
         * dispatching with a fallback to stateless HTTP mode or
 
338
         * a too relaxed server type selection */
 
339
        if (!info->sful  &&  info->type != fSERV_Dns)
339
340
            break;
340
341
    }
341
342
 
346
347
            user_header = "Connection-Mode: STATELESS\r\n"; /*default*/
347
348
            user_header = s_AdjustNetParams(net_info, eReqMethod_Post,
348
349
                                            NCBID_WEBPATH,
349
 
                                            uuu->service, uuu->args,
350
350
                                            SERV_NCBID_ARGS(&info->u.ncbid),
 
351
                                            uuu->net_info->args,
351
352
                                            user_header, info->mime_t,
352
353
                                            info->mime_s, info->mime_e,
353
354
                                            iter_header);
363
364
                                               ? eReqMethod_Post
364
365
                                               : eReqMethod_Any),
365
366
                                            SERV_HTTP_PATH(&info->u.http),
366
 
                                            uuu->service, 0,
367
367
                                            SERV_HTTP_ARGS(&info->u.http),
 
368
                                            uuu->net_info->args,
368
369
                                            user_header, info->mime_t,
369
370
                                            info->mime_s, info->mime_e,
370
371
                                            iter_header);
373
374
        case fSERV_Firewall:
374
375
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
375
376
            user_header = s_AdjustNetParams(net_info, eReqMethod_Post,
376
 
                                            uuu->net_info->path,
377
 
                                            uuu->service, uuu->args,
 
377
                                            uuu->net_info->path, 0,
378
378
                                            uuu->net_info->args,
379
379
                                            user_header, info->mime_t,
380
380
                                            info->mime_s, info->mime_e,
381
381
                                            iter_header);
382
382
            break;
383
383
        default:
384
 
            assert(0);
385
384
            if (iter_header)
386
385
                free(iter_header);
 
386
            user_header = 0;
387
387
            break;
388
388
        }
389
389
    }}
398
398
    if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
399
399
        return 0/*false - not adjusted*/;
400
400
 
401
 
    if (info->type == fSERV_Ncbid || (info->type & fSERV_Http) != 0) {
 
401
    if (info->type == fSERV_Ncbid || (info->type & fSERV_Http)) {
402
402
        SOCK_ntoa(info->host, net_info->host, sizeof(net_info->host));
403
403
        net_info->port = info->port;
404
404
    } else {
419
419
                        SConnNetInfo*      net_info,
420
420
                        int/*bool*/        second_try)
421
421
{
422
 
    const char* user_header = 0; /*may assign "", or be non-empty dynamic str*/
 
422
    const char* user_header; /* either "" or non-empty dynamic string */
 
423
    char*       iter_header;
423
424
    EReqMethod  req_method;
424
425
 
425
426
    if (info && info->type != fSERV_Firewall) {
426
427
        /* Not a firewall/relay connection here */
427
 
        assert(!net_info->firewall && !second_try);
 
428
        assert(!second_try);
428
429
        /* We know the connection point, let's try to use it! */
429
430
        SOCK_ntoa(info->host, net_info->host, sizeof(net_info->host));
430
431
        net_info->port = info->port;
435
436
            if (net_info->stateless) {
436
437
                /* Connection request with data */
437
438
                user_header = "Connection-Mode: STATELESS\r\n"; /*default*/
438
 
                req_method = eReqMethod_Post;
 
439
                req_method  = eReqMethod_Post;
439
440
            } else {
440
441
                /* We will wait for conn-info back */
441
442
                user_header = "Connection-Mode: STATEFUL\r\n";
442
 
                req_method = eReqMethod_Get;
 
443
                req_method  = eReqMethod_Get;
443
444
            }
444
445
            user_header = s_AdjustNetParams(net_info, req_method,
445
446
                                            NCBID_WEBPATH,
446
 
                                            uuu->service, uuu->args,
447
447
                                            SERV_NCBID_ARGS(&info->u.ncbid),
448
 
                                            user_header, info->mime_t,
 
448
                                            0, user_header, info->mime_t,
449
449
                                            info->mime_s, info->mime_e, 0);
450
 
            if (!user_header)
451
 
                return 0;
452
450
            break;
453
451
        case fSERV_Http:
454
452
        case fSERV_HttpGet:
455
453
        case fSERV_HttpPost:
456
454
            /* Connection directly to CGI */
457
 
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
458
 
            req_method = info->type == fSERV_HttpGet
 
455
            req_method  = info->type == fSERV_HttpGet
459
456
                ? eReqMethod_Get : (info->type == fSERV_HttpPost
460
457
                                    ? eReqMethod_Post : eReqMethod_Any);
 
458
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
461
459
            user_header = s_AdjustNetParams(net_info, req_method,
462
460
                                            SERV_HTTP_PATH(&info->u.http),
463
 
                                            uuu->service, 0,
464
461
                                            SERV_HTTP_ARGS(&info->u.http),
465
 
                                            user_header, info->mime_t,
 
462
                                            0, user_header, info->mime_t,
466
463
                                            info->mime_s, info->mime_e, 0);
467
 
            if (!user_header)
468
 
                return 0;
469
464
            break;
470
465
        case fSERV_Standalone:
471
 
            if (net_info->stateless) {
472
 
                /* This will be a pass-thru connection, socket otherwise */
473
 
                user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
474
 
                user_header = s_AdjustNetParams(net_info, eReqMethod_Post, 0,
475
 
                                                uuu->service, uuu->args,
476
 
                                                0, user_header, info->mime_t,
477
 
                                                info->mime_s, info->mime_e, 0);
478
 
                if (!user_header)
479
 
                    return 0;
 
466
            if (!net_info->stateless) {
 
467
                /* We create SOCKET connector here */
 
468
                return SOCK_CreateConnectorEx(net_info->host,
 
469
                                              net_info->port,
 
470
                                              1/*max.try*/,
 
471
                                              0/*init.data*/,
 
472
                                              0/*data.size*/,
 
473
                                              net_info->debug_printout ==
 
474
                                              eDebugPrintout_Data
 
475
                                              ? eSCC_DebugPrintout : 0);
480
476
            }
 
477
            /* Otherwise, this will be a pass-thru connection */
 
478
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
 
479
            user_header = s_AdjustNetParams(net_info, eReqMethod_Post, 0, 0,
 
480
                                            0, user_header, info->mime_t,
 
481
                                            info->mime_s, info->mime_e, 0);
481
482
            break;
482
483
        default:
483
 
            assert(0);
484
 
            return 0;
 
484
            user_header = 0;
 
485
            break;
485
486
        }
486
487
    } else {
487
488
        EMIME_Type     mime_t;
511
512
        user_header = net_info->stateless
512
513
            ? "Client-Mode: STATELESS_ONLY\r\n" /*default*/
513
514
            : "Client-Mode: STATEFUL_CAPABLE\r\n";
514
 
        user_header = s_AdjustNetParams(net_info, req_method, 0,
515
 
                                        second_try ? 0 : uuu->service,
516
 
                                        second_try ? 0 : uuu->args,
517
 
                                        0, user_header,
 
515
        user_header = s_AdjustNetParams(net_info, req_method,
 
516
                                        0, 0, 0, user_header,
518
517
                                        mime_t, mime_s, mime_e, 0);
519
 
        if (!user_header)
520
 
            return 0;
521
518
    }
 
519
    if (!user_header)
 
520
        return 0;
522
521
 
523
 
    if (user_header) {
524
 
        /* We create HTTP connector here */
525
 
        char* iter_header = SERV_Print(uuu->iter, uuu->net_info);
526
 
        size_t n;
527
 
        if (iter_header /*NB: <CR><LF>-terminated*/) {
528
 
            if ((n = strlen(user_header)) > 0) {
529
 
                if ((iter_header = (char*)
530
 
                     realloc(iter_header, strlen(iter_header) + n + 1)) != 0)
531
 
                    strcat(iter_header, user_header);
532
 
                free((char*) user_header);
 
522
    if ((iter_header = SERV_Print(uuu->iter, uuu->net_info)) != 0) {
 
523
        size_t uh_len;
 
524
        if ((uh_len = strlen(user_header)) > 0) {
 
525
            char*  ih;
 
526
            size_t ih_len = strlen(iter_header);
 
527
            if ((ih = (char*) realloc(iter_header, ih_len + uh_len + 1)) != 0){
 
528
                strcpy(ih + ih_len, user_header);
 
529
                iter_header = ih;
533
530
            }
534
 
            user_header = iter_header;
535
 
        } else if (!*user_header)
536
 
            user_header = 0; /* special case of assignment of literal "" */
537
 
        if (uuu->user_header) {
538
 
            ConnNetInfo_DeleteUserHeader(net_info, uuu->user_header);
539
 
            free((void*) uuu->user_header);
 
531
            free((char*) user_header);
540
532
        }
541
 
        uuu->user_header = user_header;
542
 
        if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
543
 
            return 0;
544
 
 
545
 
        if (!second_try) {
546
 
            ConnNetInfo_ExtendUserHeader
547
 
                (net_info, "User-Agent: NCBIServiceConnector/"
548
 
                 DISP_PROTOCOL_VERSION
 
533
        user_header = iter_header;
 
534
    } else if (!*user_header)
 
535
        user_header = 0; /* special case of assignment of literal "" */
 
536
 
 
537
    if (uuu->user_header) {
 
538
        ConnNetInfo_DeleteUserHeader(net_info, uuu->user_header);
 
539
        free((void*) uuu->user_header);
 
540
    }
 
541
    uuu->user_header = user_header;
 
542
    if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
 
543
        return 0;
 
544
 
 
545
    if (!second_try) {
 
546
        ConnNetInfo_ExtendUserHeader
 
547
            (net_info, "User-Agent: NCBIServiceConnector/"
 
548
             DISP_PROTOCOL_VERSION
549
549
#ifdef NCBI_CXX_TOOLKIT
550
 
                 " (C++ Toolkit)"
 
550
             " (C++ Toolkit)"
551
551
#else
552
 
                 " (C Toolkit)"
 
552
             " (C Toolkit)"
553
553
#endif
554
 
                 "\r\n");
555
 
        }
556
 
 
557
 
        if (!net_info->stateless && (!info                        ||
558
 
                                     info->type == fSERV_Firewall ||
559
 
                                     info->type == fSERV_Ncbid)) {
560
 
            /* HTTP connector is auxiliary only */
561
 
            CONNECTOR conn;
562
 
            CONN c;
563
 
 
564
 
            /* Clear connection info */
565
 
            uuu->host = 0;
566
 
            uuu->port = 0;
567
 
            uuu->ticket = 0;
568
 
            net_info->max_try = 1;
569
 
            conn = HTTP_CreateConnectorEx(net_info,
570
 
                                          (uuu->params.flags & fHCC_Flushable)
571
 
                                          | fHCC_SureFlush/*flags*/,
572
 
                                          s_ParseHeader, 0/*adj.info*/,
573
 
                                          uuu/*adj.data*/, 0/*cleanup.data*/);
574
 
            /* Wait for connection info back (error-transparent by DISPD.CGI)*/
575
 
            if (conn && CONN_Create(conn, &c) == eIO_Success) {
576
 
                CONN_SetTimeout(c, eIO_Open,      timeout);
577
 
                CONN_SetTimeout(c, eIO_ReadWrite, timeout);
578
 
                CONN_SetTimeout(c, eIO_Close,     timeout);
579
 
                CONN_Flush(c);
580
 
                /* This also triggers parse header callback */
581
 
                CONN_Close(c);
582
 
            } else {
583
 
                CORE_LOGF(eLOG_Error, ("[SERVICE]  Unable to create aux. %s",
584
 
                                       conn ? "connection" : "connector"));
585
 
                assert(0);
586
 
            }
587
 
            if (!uuu->host)
588
 
                return 0/*failed, no connection info returned*/;
589
 
            if (uuu->host == (unsigned int)(-1)) {
590
 
                /* Firewall mode only in stateful mode, fallback requested */
591
 
                assert((!info || info->type == fSERV_Firewall) && !second_try);
592
 
                /* Try to use stateless mode instead */
593
 
                net_info->stateless = 1/*true*/;
594
 
                return s_Open(uuu, timeout, info, net_info, 1/*second try*/);
595
 
            }
596
 
            if (net_info->firewall && *net_info->proxy_host)
597
 
                strcpy(net_info->host, net_info->proxy_host);
598
 
            else
599
 
                SOCK_ntoa(uuu->host, net_info->host, sizeof(net_info->host));
600
 
            net_info->port = uuu->port;
601
 
            /* Build and return target SOCKET connector */
602
 
            return SOCK_CreateConnectorEx(net_info->host, net_info->port,
603
 
                                          1/*max.try*/,
604
 
                                          &uuu->ticket, sizeof(uuu->ticket),
605
 
                                          net_info->debug_printout ==
606
 
                                          eDebugPrintout_Data
607
 
                                          ? eSCC_DebugPrintout : 0);
608
 
        }
609
 
        net_info->max_try = uuu->net_info->max_try;
610
 
        return HTTP_CreateConnectorEx(net_info,
 
554
             "\r\n");
 
555
    }
 
556
 
 
557
    if (!net_info->stateless && (!info                        ||
 
558
                                 info->type == fSERV_Firewall ||
 
559
                                 info->type == fSERV_Ncbid)) {
 
560
        /* HTTP connector is auxiliary only */
 
561
        CONNECTOR conn;
 
562
        CONN c;
 
563
 
 
564
        /* Clear connection info */
 
565
        uuu->host = 0;
 
566
        uuu->port = 0;
 
567
        uuu->ticket = 0;
 
568
        net_info->max_try = 1;
 
569
        conn = HTTP_CreateConnectorEx(net_info,
611
570
                                      (uuu->params.flags & fHCC_Flushable)
612
 
                                      | fHCC_AutoReconnect/*flags*/,
613
 
                                      s_ParseHeader, s_AdjustNetInfo,
 
571
                                      | fHCC_SureFlush/*flags*/,
 
572
                                      s_ParseHeader, 0/*adj.info*/,
614
573
                                      uuu/*adj.data*/, 0/*cleanup.data*/);
 
574
        /* Wait for connection info back (error-transparent by DISPD.CGI) */
 
575
        if (conn && CONN_Create(conn, &c) == eIO_Success) {
 
576
            CONN_SetTimeout(c, eIO_Open,      timeout);
 
577
            CONN_SetTimeout(c, eIO_ReadWrite, timeout);
 
578
            CONN_SetTimeout(c, eIO_Close,     timeout);
 
579
            CONN_Flush(c);
 
580
            /* This also triggers parse header callback */
 
581
            CONN_Close(c);
 
582
        } else {
 
583
            CORE_LOGF(eLOG_Error, ("[SERVICE]  Unable to create aux. %s",
 
584
                                   conn ? "connection" : "connector"));
 
585
            assert(0);
 
586
        }
 
587
        if (!uuu->host)
 
588
            return 0/*failed, no connection info returned*/;
 
589
        if (uuu->host == (unsigned int)(-1)) {
 
590
            /* Firewall mode only in stateful mode, fallback requested */
 
591
            assert((!info || info->type == fSERV_Firewall) && !second_try);
 
592
            /* Try to use stateless mode instead */
 
593
            net_info->stateless = 1/*true*/;
 
594
            return s_Open(uuu, timeout, info, net_info, 1/*second try*/);
 
595
        }
 
596
        if (net_info->firewall && *net_info->proxy_host)
 
597
            strcpy(net_info->host, net_info->proxy_host);
 
598
        else
 
599
            SOCK_ntoa(uuu->host, net_info->host, sizeof(net_info->host));
 
600
        net_info->port = uuu->port;
 
601
        /* Build and return target SOCKET connector */
 
602
        return SOCK_CreateConnectorEx(net_info->host,
 
603
                                      net_info->port,
 
604
                                      1/*max.try*/,
 
605
                                      &uuu->ticket,
 
606
                                      sizeof(uuu->ticket),
 
607
                                      net_info->debug_printout ==
 
608
                                      eDebugPrintout_Data
 
609
                                      ? eSCC_DebugPrintout : 0);
615
610
    }
616
 
    /* We create SOCKET connector here */
617
 
    return SOCK_CreateConnectorEx(net_info->host, net_info->port,
618
 
                                  1/*max.try*/, 0/*init.data*/, 0/*data.size*/,
619
 
                                  net_info->debug_printout ==
620
 
                                  eDebugPrintout_Data ? eSCC_DebugPrintout :0);
 
611
    return HTTP_CreateConnectorEx(net_info,
 
612
                                  (uuu->params.flags & fHCC_Flushable)
 
613
                                  | fHCC_AutoReconnect/*flags*/,
 
614
                                  s_ParseHeader, s_AdjustNetInfo,
 
615
                                  uuu/*adj.data*/, 0/*cleanup.data*/);
621
616
}
622
617
 
623
618
 
637
632
    }
638
633
 
639
634
    if (close_dispatcher) {
640
 
        s_CloseDispatcher(uuu);
 
635
        if (uuu->user_header) {
 
636
            free((void*) uuu->user_header);
 
637
            uuu->user_header = 0;
 
638
        }
641
639
        if (uuu->params.reset)
642
640
            uuu->params.reset(uuu->params.data);
 
641
        s_CloseDispatcher(uuu);
643
642
    }
644
643
 
645
644
    if (uuu->meta.list) {
686
685
        if (!(net_info = ConnNetInfo_Clone(uuu->net_info)))
687
686
            break;
688
687
 
689
 
        conn = s_Open(uuu, timeout, info, net_info, 0/*second_try - false*/);
 
688
        conn = s_Open(uuu, timeout, info, net_info, 0/*!second_try*/);
690
689
 
691
690
        ConnNetInfo_Destroy(net_info);
692
691
 
733
732
        if (status == eIO_Success)
734
733
            break;
735
734
 
736
 
        s_Close(connector, timeout, 0/*don't close dispatcher!*/);
 
735
        s_Close(connector, timeout, 0/*don't close dispatcher yet!*/);
737
736
    }
738
737
 
739
738
    uuu->status = status;
771
770
{
772
771
    SServiceConnector* uuu = (SServiceConnector*) connector->handle;
773
772
 
774
 
    s_CloseDispatcher(uuu);
 
773
    if (uuu->iter)
 
774
        s_CloseDispatcher(uuu);
775
775
    if (uuu->params.cleanup)
776
776
        uuu->params.cleanup(uuu->params.data);
777
777
    ConnNetInfo_Destroy(uuu->net_info);
778
778
    if (uuu->name)
779
779
        free((void*) uuu->name);
780
 
    free((void*) uuu->service);
 
780
    if (uuu->x_service)
 
781
        free((void*) uuu->x_service);
781
782
    free(uuu);
782
783
    connector->handle = 0;
783
784
    free(connector);
796
797
{
797
798
    CONNECTOR          ccc;
798
799
    SServiceConnector* xxx;
799
 
    char*              x_args;
800
 
    SConnNetInfo*      x_net_info;
801
800
 
802
801
    if (!service || !*service)
803
802
        return 0;
804
803
 
805
 
    x_net_info =
806
 
        net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(service);
807
 
    x_args     = s_GetArgs(x_net_info->client_host);
808
 
    ccc        = (SConnector*)        malloc(sizeof(SConnector));
809
 
    xxx        = (SServiceConnector*) malloc(sizeof(SServiceConnector) +
810
 
                                             (x_args ? strlen(x_args) : 0));
811
 
    xxx->name     = 0;
812
 
    xxx->service  = SERV_ServiceName(service);
813
 
    xxx->net_info = x_net_info;
814
 
    if (types & fSERV_StatelessOnly)
 
804
    ccc = (SConnector*)        malloc(sizeof(SConnector));
 
805
    xxx = (SServiceConnector*) calloc(1, sizeof(*xxx) + strlen(service));
 
806
 
 
807
    /* initialize connector structures */
 
808
    ccc->handle   = xxx;
 
809
    ccc->next     = 0;
 
810
    ccc->meta     = 0;
 
811
    ccc->setup    = s_Setup;
 
812
    ccc->destroy  = s_Destroy;
 
813
 
 
814
    xxx->types    = types;
 
815
    xxx->net_info = (net_info
 
816
                     ? ConnNetInfo_Clone(net_info)
 
817
                     : ConnNetInfo_Create(service));
 
818
    if (net_info  &&  xxx->net_info) {
 
819
        xxx->x_service = SERV_ServiceName(service);
 
820
        xxx->net_info->service = xxx->x_service;/*SetupStandardArgs() expects*/
 
821
    }
 
822
    if (!ConnNetInfo_SetupStandardArgs(xxx->net_info)) {
 
823
        s_Destroy(ccc);
 
824
        return 0;
 
825
    }
 
826
 
 
827
    /* now get ready for first probe dispatching */
 
828
    if (types & fSERV_Stateless)
815
829
        xxx->net_info->stateless = 1/*true*/;
816
830
    if (types & fSERV_Firewall)
817
831
        xxx->net_info->firewall = 1/*true*/;
818
 
    xxx->status   = eIO_Success;
819
 
    xxx->types    = types;
820
 
    xxx->iter     = 0;
821
 
    memset(&xxx->params, 0, sizeof(xxx->params));
822
 
    memset(&xxx->meta,   0, sizeof(xxx->meta));
823
 
 
824
 
    if (x_args) {
825
 
        strcpy(xxx->args, x_args);
826
 
        free(x_args);
827
 
    } else
828
 
        xxx->args[0] = '\0';
829
 
 
830
 
    /* initialize connector structure */
831
 
    ccc->handle  = xxx;
832
 
    ccc->next    = 0;
833
 
    ccc->meta    = 0;
834
 
    ccc->setup   = s_Setup;
835
 
    ccc->destroy = s_Destroy;
836
 
 
837
 
    /* now make the first probe dispatching */
 
832
    strcpy(xxx->service, service);
838
833
    if (!s_OpenDispatcher(xxx)) {
839
 
        s_CloseDispatcher(xxx);
840
834
        s_Destroy(ccc);
841
835
        return 0;
842
836
    }
854
848
/*
855
849
 * --------------------------------------------------------------------------
856
850
 * $Log: ncbi_service_connector.c,v $
 
851
 * Revision 6.72  2006/04/23 18:27:54  lavr
 
852
 * BUGFIX:  typo in SServiceConnector allocation caused memory corruption
 
853
 *
 
854
 * Revision 6.71  2006/04/20 14:00:59  lavr
 
855
 * Keep original service name and use it for service mappers
 
856
 *
 
857
 * Revision 6.70  2006/01/27 17:10:24  lavr
 
858
 * Replace obsolete call names with current ones
 
859
 *
 
860
 * Revision 6.69  2006/01/17 20:28:21  lavr
 
861
 * Do not override user-provided Content-Type
 
862
 *
 
863
 * Revision 6.68  2006/01/12 18:12:46  lavr
 
864
 * Fix erroneous use of non-translated service name
 
865
 * Stricter checks on uniqueness of returned Connection-Info:
 
866
 *
 
867
 * Revision 6.67  2006/01/11 20:28:47  lavr
 
868
 * Take advantage of ConnNetInfo_SetupStandardArgs();  other changes to
 
869
 * allow to pass user-supplied parameters to services (where feasible)
 
870
 *
 
871
 * Revision 6.66  2006/01/11 16:28:28  lavr
 
872
 * Simplify code (mostly, by factoring out)
 
873
 *
 
874
 * Revision 6.65  2005/12/23 18:12:32  lavr
 
875
 * fSERV_StatelessOnly -> fSERV_Stateless
 
876
 *
857
877
 * Revision 6.64  2005/10/26 14:44:59  lavr
858
878
 * Insure service name appears in URLs for HTTP services
859
879
 *