|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/connect/ncbi_local.c |
source navigation diff markup identifier search freetext search file search |
1 /* $Id: ncbi_local.c,v 1.15 2008/05/25 01:25:38 kazimird Exp $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Anton Lavrentiev
27 *
28 * File Description:
29 * Low-level API to resolve NCBI service name to the server meta-address
30 * with the use of local registry.
31 *
32 */
33
34 #include "ncbi_ansi_ext.h"
35 #include "ncbi_comm.h"
36 #include "ncbi_lb.h"
37 #include "ncbi_local.h"
38 #include "ncbi_priv.h"
39 #include <stdlib.h>
40
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif /*__cplusplus*/
45 static void s_Reset (SERV_ITER);
46 static SSERV_Info* s_GetNextInfo(SERV_ITER, HOST_INFO*);
47 static void s_Close (SERV_ITER);
48
49 static const SSERV_VTable s_op = {
50 s_Reset, s_GetNextInfo, 0/*Update*/, 0/*Penalize*/, s_Close, "LOCAL"
51 };
52 #ifdef __cplusplus
53 } /* extern "C" */
54 #endif /*__cplusplus*/
55
56
57 struct SLOCAL_Data {
58 SLB_Candidate* cand;
59 size_t i_cand;
60 size_t n_cand;
61 size_t a_cand;
62 int/*bool*/ reset;
63 };
64
65
66 static int/*bool*/ s_AddService(const SSERV_Info* info,
67 struct SLOCAL_Data* data)
68 {
69 if (data->a_cand <= data->n_cand) {
70 size_t n = data->a_cand + 10;
71 SLB_Candidate* temp =
72 (SLB_Candidate*)(data->cand
73 ? realloc(data->cand, n * sizeof(*data->cand))
74 : malloc ( n * sizeof(*data->cand)));
75 if (!temp)
76 return 0/*false*/;
77 data->a_cand = n;
78 data->cand = temp;
79 }
80
81 data->cand[data->n_cand++].info = info;
82 return 1/*true*/;
83 }
84
85
86 static int/*bool*/ s_LoadSingleService(const char* name, SERV_ITER iter)
87 {
88 struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
89 const TSERV_Type type = iter->type & ~fSERV_Firewall;
90 int/*bool*/ ok = 0/*failed*/;
91 SSERV_Info* info;
92 char* buf;
93 int n;
94
95 if (!(buf =
96 (char*) malloc(strlen(name) + sizeof(REG_CONN_LOCAL_SERVER) + 80))) {
97 return 0/*failed*/;
98 }
99
100 info = 0;
101 for (n = 0; n <= 100; n++) {
102 char service[1024];
103 const char* c;
104
105 if (info) {
106 free((void*) info);
107 info = 0;
108 }
109 sprintf(buf, "%s_" REG_CONN_LOCAL_SERVER "_%d", name, n);
110 if (!(c = getenv(buf)) && !(c = getenv(strupr(buf)))) {
111 char* b = buf + strlen(name);
112 size_t len;
113 *b++ = '\0';
114 CORE_REG_GET(buf, b, service, sizeof(service) - 1, 0);
115 len = strlen(service);
116 if (len > 1 && (service[0] == '"' || service[0] == '\'')
117 && service[len - 1] == service[0] && (len -= 2) > 0) {
118 memmove(service, service + 1, len);
119 service[len] = '\0';
120 }
121 if (!len)
122 continue;
123 c = service;
124 }
125 if (!(info = SERV_ReadInfoEx
126 (c, iter->ismask || iter->reverse_dns ? name : ""))) {
127 continue;
128 }
129 if (iter->external && info->locl)
130 continue; /* external mapping for local server not allowed */
131 if (!info->host || (info->locl & 0xF0)) {
132 unsigned int localhost = SOCK_GetLocalHostAddress(eDefault);
133 if (!info->host)
134 info->host = localhost;
135 if ((info->locl & 0xF0) && info->host != localhost)
136 continue; /* private server */
137 }
138 if (!iter->reverse_dns && info->type != fSERV_Dns) {
139 if (type != fSERV_Any && !(type & info->type))
140 continue; /* type doesn't match */
141 if (type == fSERV_Any && info->type == fSERV_Dns)
142 continue; /* DNS entries have to be req'd explicitly */
143 if (iter->stateless && info->sful && !(info->type & fSERV_Http))
144 continue; /* skip stateful only servers */
145 }
146 if (!info->rate)
147 info->rate = LBSM_DEFAULT_RATE;
148 if (!info->time)
149 info->time = LBSM_DEFAULT_TIME;
150
151 if (!s_AddService(info, data))
152 break;
153
154 info = 0;
155 ok = 1/*succeeded*/;
156 }
157 if (info)
158 free((void*) info);
159
160 free(buf);
161 return ok/*whatever*/;
162 }
163
164
165 static int/*bool*/ s_LoadServices(SERV_ITER iter)
166 {
167 int/*bool*/ ok = 0/*false*/;
168 char services[1024];
169 const char* c;
170 char* s;
171
172 if (!iter->ismask) {
173 ok = s_LoadSingleService(iter->name, iter);
174 if (!ok || !iter->reverse_dns)
175 return ok;
176 }
177 if (!(c = ConnNetInfo_GetValue(0, REG_CONN_LOCAL_SERVICES,
178 services, sizeof(services), 0)) || !*c) {
179 return ok;
180 }
181
182 s = services;
183 ok = 0/*false*/;
184 for (s += strspn(s, " \t"); *s; s += strspn(s, " \t")) {
185 size_t len = strcspn(s, " \t");
186 assert(len);
187 if (s[len])
188 s[len++] = '\0';
189 if (!(c = SERV_ServiceName(s)))
190 break;
191 if ((iter->reverse_dns || UTIL_MatchesMask(c, iter->name)) &&
192 s_LoadSingleService(c, iter)) {
193 ok = 1/*succeeded*/;
194 }
195 free((void*) c);
196 s += len;
197 }
198
199 return ok/*whatever*/;
200 }
201
202
203 static int s_Sort(const void* p1, const void* p2)
204 {
205 const SLB_Candidate* c1 = (const SLB_Candidate*) p1;
206 const SLB_Candidate* c2 = (const SLB_Candidate*) p2;
207 if (c1->info->type == fSERV_Dns || c2->info->type == fSERV_Dns) {
208 if (c1->info->type != fSERV_Dns)
209 return -1;
210 if (c2->info->type != fSERV_Dns)
211 return 1;
212 }
213 if ((int) c1->info->type < (int) c2->info->type)
214 return -1;
215 if ((int) c1->info->type > (int) c2->info->type)
216 return 1;
217 return 0;
218 }
219
220
221 static SLB_Candidate* s_GetCandidate(void* user_data, size_t i)
222 {
223 struct SLOCAL_Data* data = (struct SLOCAL_Data*) user_data;
224 return i < data->i_cand ? &data->cand[i] : 0;
225 }
226
227
228 static SSERV_Info* s_GetNextInfo(SERV_ITER iter, HOST_INFO* host_info)
229 {
230 struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
231 const TSERV_Type type = iter->type & ~fSERV_Firewall;
232 int/*bool*/ dns_info_seen = 0/*false*/;
233 SSERV_Info* info;
234 size_t i, n;
235
236 assert(data);
237 if (data->reset) {
238 data->reset = 0/*false*/;
239 if (!s_LoadServices(iter))
240 return 0;
241 if (data->n_cand > 1)
242 qsort(data->cand, data->n_cand, sizeof(*data->cand), s_Sort);
243 }
244
245 i = 0;
246 data->i_cand = 0;
247 while (i < data->n_cand) {
248 /* NB all servers have been loaded in accordance with iter->external */
249 info = (SSERV_Info*) data->cand[i].info;
250 if (info->rate > 0.0 || iter->ok_down) {
251 const char* c = SERV_NameOfInfo(info);
252 for (n = 0; n < iter->n_skip; n++) {
253 const SSERV_Info* skip = iter->skip[n];
254 const char* s = SERV_NameOfInfo(skip);
255 if (*s) {
256 assert(iter->ismask || iter->reverse_dns);
257 if (strcasecmp(s, c) == 0
258 && ((skip->type == fSERV_Dns && !skip->host) ||
259 SERV_EqualInfo(skip, info))) {
260 break;
261 }
262 } else if (SERV_EqualInfo(skip, info))
263 break;
264 if (iter->reverse_dns && skip->type == fSERV_Dns
265 && skip->host == info->host
266 && (!skip->port || skip->port == info->port)) {
267 break;
268 }
269 }
270 } else
271 n = 0;
272 if (!iter->ismask) {
273 if (type == fSERV_Any) {
274 if (iter->reverse_dns && info->type != fSERV_Dns)
275 dns_info_seen = 1/*true*/;
276 } else if ((type & info->type) && info->type == fSERV_Dns)
277 dns_info_seen = 1/*true*/;
278 }
279 if (n < iter->n_skip) {
280 if (i < --data->n_cand) {
281 memmove(data->cand + i, data->cand + i + 1,
282 (data->n_cand - i) * sizeof(*data->cand));
283 }
284 free(info);
285 } else {
286 if (type != fSERV_Any && !(type & info->type))
287 break;
288 if (type == fSERV_Any && info->type == fSERV_Dns)
289 break;
290 data->i_cand++;
291 data->cand[i].status = info->rate < 0.0 ? 0.0 : info->rate;
292 if (iter->ok_down)
293 break;
294 i++;
295 }
296 }
297
298 if (data->i_cand) {
299 n = LB_Select(iter, data, s_GetCandidate, 1.0);
300 info = (SSERV_Info*) data->cand[n].info;
301 if (iter->reverse_dns && info->type != fSERV_Dns) {
302 dns_info_seen = 0/*false*/;
303 for (i = 0; i < data->n_cand; i++) {
304 SSERV_Info* temp = (SSERV_Info*) data->cand[i].info;
305 if (temp->type != fSERV_Dns ||
306 temp->host != info->host || temp->port != info->port) {
307 continue;
308 }
309 if (!iter->ismask)
310 dns_info_seen = 1/*true*/;
311 if (iter->external && temp->locl)
312 continue; /* external mapping req'd; local server */
313 assert(!(temp->locl & 0xF0)); /* no private DNS */
314 if (temp->rate > 0.0 || iter->ok_down) {
315 data->cand[i].status = data->cand[n].status;
316 info = temp;
317 n = i;
318 break;
319 }
320 }
321 if (i >= data->n_cand && dns_info_seen)
322 info = 0;
323 }
324
325 if (info) {
326 info->rate = data->cand[n].status;
327 info->time += iter->time;
328 if (n < --data->n_cand) {
329 memmove(data->cand + n, data->cand + n + 1,
330 (data->n_cand - n) * sizeof(*data->cand));
331 }
332 }
333 } else if (iter->last || iter->n_skip || !dns_info_seen) {
334 info = 0;
335 } else if ((info = SERV_CreateDnsInfo(0)) != 0)
336 info->time = NCBI_TIME_INFINITE;
337
338 if (info && host_info)
339 *host_info = 0;
340 return info;
341 }
342
343
344 static void s_Reset(SERV_ITER iter)
345 {
346 struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
347 if (data && data->cand) {
348 size_t i;
349 assert(data->a_cand);
350 for (i = 0; i < data->n_cand; i++)
351 free((void*) data->cand[i].info);
352 data->n_cand = 0;
353 }
354 data->reset = 1/*true*/;
355 }
356
357
358 static void s_Close(SERV_ITER iter)
359 {
360 struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
361 assert(!data->n_cand && data->reset); /* s_Reset() has been called */
362 if (data->cand) {
363 assert(data->a_cand);
364 data->a_cand = 0;
365 free(data->cand);
366 data->cand = 0;
367 }
368 free(data);
369 iter->data = 0;
370 }
371
372
373 /***********************************************************************
374 * EXTERNAL
375 ***********************************************************************/
376
377 /*ARGSUSED*/
378 const SSERV_VTable* SERV_LOCAL_Open(SERV_ITER iter,
379 SSERV_Info** info, HOST_INFO* u/*unused*/)
380 {
381 struct SLOCAL_Data* data;
382
383 if (!iter->ismask && strpbrk(iter->name, "?*"))
384 return 0/*failed to start unallowed wildcard search*/;
385
386 if (!(data = (struct SLOCAL_Data*) calloc(1, sizeof(*data))))
387 return 0;
388
389 iter->data = data;
390
391 if (g_NCBI_ConnectRandomSeed == 0) {
392 g_NCBI_ConnectRandomSeed = iter->time ^ NCBI_CONNECT_SRAND_ADDEND;
393 srand(g_NCBI_ConnectRandomSeed);
394 }
395
396 if (!s_LoadServices(iter)) {
397 s_Reset(iter);
398 s_Close(iter);
399 return 0;
400 }
401 if (data->n_cand > 1)
402 qsort(data->cand, data->n_cand, sizeof(*data->cand), s_Sort);
403
404 /* call GetNextInfo subsequently if info is actually needed */
405 if (info)
406 *info = 0;
407 return &s_op;
408 }
409 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |