3 * $Id: net_db.cc,v 1.132 1998/11/12 06:28:17 wessels Exp $
5 * DEBUG: section 38 Network Measurement Database
6 * AUTHOR: Duane Wessels
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
50 static hash_table
*addr_table
= NULL
;
51 static hash_table
*host_table
= NULL
;
53 static struct in_addr
networkFromInaddr(struct in_addr a
);
54 static void netdbRelease(netdbEntry
* n
);
55 static void netdbHashInsert(netdbEntry
* n
, struct in_addr addr
);
56 static void netdbHashDelete(const char *key
);
57 static void netdbHostInsert(netdbEntry
* n
, const char *hostname
);
58 static void netdbHostDelete(const net_db_name
* x
);
59 static void netdbPurgeLRU(void);
60 static netdbEntry
*netdbLookupHost(const char *key
);
61 static net_db_peer
*netdbPeerByName(const netdbEntry
* n
, const char *);
62 static net_db_peer
*netdbPeerAdd(netdbEntry
* n
, peer
* e
);
63 static char *netdbPeerName(const char *name
);
64 static IPH netdbSendPing
;
65 static QS sortPeerByRtt
;
68 static FREE netdbFreeNameEntry
;
69 static FREE netdbFreeNetdbEntry
;
70 static STCB netdbExchangeHandleReply
;
71 static void netdbExchangeDone(void *);
73 /* We have to keep a local list of peer names. The Peers structure
74 * gets freed during a reconfigure. We want this database to
75 * remain persisitent, so _net_db_peer->peername points into this
77 static wordlist
*peer_names
= NULL
;
80 netdbHashInsert(netdbEntry
* n
, struct in_addr addr
)
82 xstrncpy(n
->network
, inet_ntoa(networkFromInaddr(addr
)), 16);
84 assert(hash_lookup(addr_table
, n
->network
) == NULL
);
85 hash_join(addr_table
, (hash_link
*) n
);
89 netdbHashDelete(const char *key
)
91 hash_link
*hptr
= hash_lookup(addr_table
, key
);
93 debug_trap("netdbHashDelete: key not found");
96 hash_remove_link(addr_table
, hptr
);
100 netdbHostInsert(netdbEntry
* n
, const char *hostname
)
102 net_db_name
*x
= memAllocate(MEM_NET_DB_NAME
);
103 x
->name
= xstrdup(hostname
);
107 assert(hash_lookup(host_table
, hostname
) == NULL
);
108 hash_join(host_table
, (hash_link
*) x
);
113 netdbHostDelete(const net_db_name
* x
)
118 assert(x
->net_db_entry
!= NULL
);
121 for (X
= &n
->hosts
; *X
; X
= &(*X
)->next
) {
127 hash_remove_link(host_table
, (hash_link
*) x
);
129 memFree(MEM_NET_DB_NAME
, (void *) x
);
133 netdbLookupHost(const char *key
)
135 net_db_name
*x
= (net_db_name
*) hash_lookup(host_table
, key
);
136 return x
? x
->net_db_entry
: NULL
;
140 netdbRelease(netdbEntry
* n
)
144 for (x
= n
->hosts
; x
; x
= next
) {
152 n
->n_peers_alloc
= 0;
153 if (n
->link_count
== 0) {
154 netdbHashDelete(n
->network
);
155 memFree(MEM_NETDBENTRY
, n
);
160 netdbLRU(const void *A
, const void *B
)
162 const netdbEntry
*const *n1
= A
;
163 const netdbEntry
*const *n2
= B
;
164 if ((*n1
)->last_use_time
> (*n2
)->last_use_time
)
166 if ((*n1
)->last_use_time
< (*n2
)->last_use_time
)
179 list
= xcalloc(memInUse(MEM_NETDBENTRY
), sizeof(netdbEntry
*));
180 hash_first(addr_table
);
181 while ((n
= (netdbEntry
*) hash_next(addr_table
))) {
182 assert(list_count
< memInUse(MEM_NETDBENTRY
));
183 *(list
+ list_count
) = n
;
188 sizeof(netdbEntry
*),
190 for (k
= 0; k
< list_count
; k
++) {
191 if (memInUse(MEM_NETDBENTRY
) < Config
.Netdb
.low
)
193 netdbRelease(*(list
+ k
));
200 netdbLookupAddr(struct in_addr addr
)
203 char *key
= inet_ntoa(networkFromInaddr(addr
));
204 n
= (netdbEntry
*) hash_lookup(addr_table
, key
);
209 netdbAdd(struct in_addr addr
)
212 if (memInUse(MEM_NETDBENTRY
) > Config
.Netdb
.high
)
214 if ((n
= netdbLookupAddr(addr
)) == NULL
) {
215 n
= memAllocate(MEM_NETDBENTRY
);
216 netdbHashInsert(n
, addr
);
222 netdbSendPing(const ipcache_addrs
* ia
, void *data
)
225 char *hostname
= data
;
230 cbdataUnlock(hostname
);
232 cbdataFree(hostname
);
235 addr
= ia
->in_addrs
[ia
->cur
];
236 if ((n
= netdbLookupHost(hostname
)) == NULL
) {
238 netdbHostInsert(n
, hostname
);
239 } else if ((na
= netdbLookupAddr(addr
)) != n
) {
241 *hostname moved from 'network n' to 'network na'!
245 debug(38, 3) ("netdbSendPing: %s moved from %s to %s\n",
246 hostname
, n
->network
, na
->network
);
247 x
= (net_db_name
*) hash_lookup(host_table
, hostname
);
249 debug(38, 1) ("netdbSendPing: net_db_name list bug: %s not found", hostname
);
250 cbdataFree(hostname
);
253 /* remove net_db_name from 'network n' linked list */
254 for (X
= &n
->hosts
; *X
; X
= &(*X
)->next
) {
261 /* point to 'network na' from host entry */
262 x
->net_db_entry
= na
;
263 /* link net_db_name to 'network na' */
269 debug(38, 3) ("netdbSendPing: pinging %s\n", hostname
);
270 icmpDomainPing(addr
, hostname
);
272 n
->next_ping_time
= squid_curtime
+ Config
.Netdb
.period
;
273 n
->last_use_time
= squid_curtime
;
274 cbdataFree(hostname
);
277 static struct in_addr
278 networkFromInaddr(struct in_addr a
)
281 b
.s_addr
= ntohl(a
.s_addr
);
283 if (IN_CLASSC(b
.s_addr
))
284 b
.s_addr
&= IN_CLASSC_NET
;
285 else if (IN_CLASSB(b
.s_addr
))
286 b
.s_addr
&= IN_CLASSB_NET
;
287 else if (IN_CLASSA(b
.s_addr
))
288 b
.s_addr
&= IN_CLASSA_NET
;
290 /* use /24 for everything */
291 b
.s_addr
&= IN_CLASSC_NET
;
293 b
.s_addr
= htonl(b
.s_addr
);
298 sortByRtt(const void *A
, const void *B
)
300 const netdbEntry
*const *n1
= A
;
301 const netdbEntry
*const *n2
= B
;
302 if ((*n1
)->rtt
> (*n2
)->rtt
)
304 else if ((*n1
)->rtt
< (*n2
)->rtt
)
311 netdbPeerByName(const netdbEntry
* n
, const char *peername
)
314 net_db_peer
*p
= n
->peers
;
315 for (i
= 0; i
< n
->n_peers
; i
++, p
++) {
316 if (!strcmp(p
->peername
, peername
))
323 netdbPeerAdd(netdbEntry
* n
, peer
* e
)
329 if (n
->n_peers
== n
->n_peers_alloc
) {
331 osize
= n
->n_peers_alloc
;
332 if (n
->n_peers_alloc
== 0)
333 n
->n_peers_alloc
= 2;
335 n
->n_peers_alloc
<<= 1;
336 debug(38, 3) ("netdbPeerAdd: Growing peer list for '%s' to %d\n",
337 n
->network
, n
->n_peers_alloc
);
338 n
->peers
= xcalloc(n
->n_peers_alloc
, sizeof(net_db_peer
));
339 for (i
= 0; i
< osize
; i
++)
340 *(n
->peers
+ i
) = *(o
+ i
);
345 p
= n
->peers
+ n
->n_peers
;
346 p
->peername
= netdbPeerName(e
->host
);
352 sortPeerByRtt(const void *A
, const void *B
)
354 const net_db_peer
*p1
= A
;
355 const net_db_peer
*p2
= B
;
356 if (p1
->rtt
> p2
->rtt
)
358 else if (p1
->rtt
< p2
->rtt
)
365 netdbSaveState(void *foo
)
367 LOCAL_ARRAY(char, path
, SQUID_MAXPATHLEN
);
371 struct timeval start
= current_time
;
373 snprintf(path
, SQUID_MAXPATHLEN
, "%s/netdb_state", storeSwapDir(0));
374 fp
= fopen(path
, "w");
376 debug(50, 1) ("netdbSaveState: %s: %s\n", path
, xstrerror());
379 hash_first(addr_table
);
380 while ((n
= (netdbEntry
*) hash_next(addr_table
))) {
381 if (n
->pings_recv
== 0)
383 fprintf(fp
, "%s %d %d %10.5f %10.5f %d %d",
389 (int) n
->next_ping_time
,
390 (int) n
->last_use_time
);
391 for (x
= n
->hosts
; x
; x
= x
->next
)
392 fprintf(fp
, " %s", x
->name
);
398 debug(38, 1) ("NETDB state saved; %d entries, %d msec\n",
399 count
, tvSubMsec(start
, current_time
));
400 eventAddIsh("netdbSaveState", netdbSaveState
, NULL
, 3600.0, 1);
404 netdbReloadState(void)
406 LOCAL_ARRAY(char, path
, SQUID_MAXPATHLEN
);
414 struct timeval start
= current_time
;
415 snprintf(path
, SQUID_MAXPATHLEN
, "%s/netdb_state", storeSwapDir(0));
416 fp
= fopen(path
, "r");
419 buf
= memAllocate(MEM_4K_BUF
);
420 while (fgets(buf
, 4095, fp
)) {
421 memset(&N
, '\0', sizeof(netdbEntry
));
422 if ((t
= strtok(buf
, w_space
)) == NULL
)
424 if (!safe_inet_addr(t
, &addr
))
426 if (netdbLookupAddr(addr
) != NULL
) /* no dups! */
428 if ((t
= strtok(NULL
, w_space
)) == NULL
)
430 N
.pings_sent
= atoi(t
);
431 if ((t
= strtok(NULL
, w_space
)) == NULL
)
433 N
.pings_recv
= atoi(t
);
434 if (N
.pings_recv
== 0)
436 /* give this measurement low weight */
439 if ((t
= strtok(NULL
, w_space
)) == NULL
)
442 if ((t
= strtok(NULL
, w_space
)) == NULL
)
445 if ((t
= strtok(NULL
, w_space
)) == NULL
)
447 N
.next_ping_time
= (time_t) atoi(t
);
448 if ((t
= strtok(NULL
, w_space
)) == NULL
)
450 N
.last_use_time
= (time_t) atoi(t
);
451 n
= memAllocate(MEM_NETDBENTRY
);
452 xmemcpy(n
, &N
, sizeof(netdbEntry
));
453 netdbHashInsert(n
, addr
);
454 while ((t
= strtok(NULL
, w_space
)) != NULL
) {
455 if (netdbLookupHost(t
) != NULL
) /* no dups! */
457 netdbHostInsert(n
, t
);
461 memFree(MEM_4K_BUF
, buf
);
464 debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n",
465 count
, tvSubMsec(start
, current_time
));
469 netdbPeerName(const char *name
)
472 for (w
= peer_names
; w
; w
= w
->next
) {
473 if (!strcmp(w
->key
, name
))
476 w
= wordlistAdd(&peer_names
, name
);
481 netdbFreeNetdbEntry(void *data
)
483 netdbEntry
*n
= data
;
485 memFree(MEM_NETDBENTRY
, n
);
489 netdbFreeNameEntry(void *data
)
491 net_db_name
*x
= data
;
493 memFree(MEM_NET_DB_NAME
, x
);
497 netdbExchangeHandleReply(void *data
, char *buf
, ssize_t size
)
499 netdbExchangeState
*ex
= data
;
511 rec_sz
+= 1 + sizeof(addr
.s_addr
);
512 rec_sz
+= 1 + sizeof(int);
513 rec_sz
+= 1 + sizeof(int);
514 ex
->seen
= ex
->used
+ size
;
515 debug(38, 3) ("netdbExchangeHandleReply: %d bytes\n", (int) size
);
516 if (!cbdataValid(ex
->p
)) {
517 debug(38, 3) ("netdbExchangeHandleReply: Peer became invalid\n");
518 netdbExchangeDone(ex
);
521 debug(38, 3) ("netdbExchangeHandleReply: for '%s:%d'\n", ex
->p
->host
, ex
->p
->http_port
);
524 /* skip reply headers */
525 if ((hdr_sz
= headersEnd(p
, size
))) {
526 debug(38, 5) ("netdbExchangeHandleReply: hdr_sz = %d\n", hdr_sz
);
527 rep
= ex
->e
->mem_obj
->reply
;
528 if (0 == rep
->sline
.status
)
529 httpReplyParse(rep
, buf
);
530 debug(38, 3) ("netdbExchangeHandleReply: reply status %d\n",
532 if (HTTP_OK
!= rep
->sline
.status
) {
533 netdbExchangeDone(ex
);
536 assert(size
>= hdr_sz
);
544 debug(38, 5) ("netdbExchangeHandleReply: start parsing loop, size = %d\n",
546 while (size
>= rec_sz
) {
547 debug(38, 5) ("netdbExchangeHandleReply: in parsing loop, size = %d\n",
549 addr
.s_addr
= any_addr
.s_addr
;
551 for (o
= 0; o
< rec_sz
;) {
552 switch ((int) *(p
+ o
)) {
553 case NETDB_EX_NETWORK
:
555 xmemcpy(&addr
.s_addr
, p
+ o
, sizeof(addr
.s_addr
));
556 o
+= sizeof(addr
.s_addr
);
560 xmemcpy(&j
, p
+ o
, sizeof(int));
562 rtt
= (double) ntohl(j
) / 1000.0;
566 xmemcpy(&j
, p
+ o
, sizeof(int));
568 hops
= (double) ntohl(j
) / 1000.0;
572 if (addr
.s_addr
!= any_addr
.s_addr
&& rtt
> 0)
573 netdbExchangeUpdatePeer(addr
, ex
->p
, rtt
, hops
);
579 * This is a fairly cpu-intensive loop, break after adding
585 debug(38, 3) ("netdbExchangeHandleReply: used %d entries, (x %d bytes) == %d bytes total\n",
586 nused
, rec_sz
, nused
* rec_sz
);
587 debug(38, 3) ("netdbExchangeHandleReply: seen %d, used %d\n", ex
->seen
, ex
->used
);
588 if (ex
->e
->store_status
== STORE_ABORTED
) {
589 debug(38, 3) ("netdbExchangeHandleReply: STORE_ABORTED\n");
590 netdbExchangeDone(ex
);
591 } else if (ex
->e
->store_status
== STORE_PENDING
) {
592 debug(38, 3) ("netdbExchangeHandleReply: STORE_PENDING\n");
593 storeClientCopy(ex
->e
, ex
->seen
, ex
->used
, ex
->buf_sz
,
594 ex
->buf
, netdbExchangeHandleReply
, ex
);
595 } else if (ex
->seen
< ex
->e
->mem_obj
->inmem_hi
) {
596 debug(38, 3) ("netdbExchangeHandleReply: ex->e->mem_obj->inmem_hi\n");
597 storeClientCopy(ex
->e
, ex
->seen
, ex
->used
, ex
->buf_sz
,
598 ex
->buf
, netdbExchangeHandleReply
, ex
);
600 debug(38, 3) ("netdbExchangeHandleReply: Done\n");
601 netdbExchangeDone(ex
);
606 netdbExchangeDone(void *data
)
608 netdbExchangeState
*ex
= data
;
609 debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex
->e
));
610 memFree(MEM_4K_BUF
, ex
->buf
);
611 requestUnlink(ex
->r
);
612 storeUnregister(ex
->e
, ex
);
613 storeUnlockObject(ex
->e
);
618 #endif /* USE_ICMP */
620 /* PUBLIC FUNCTIONS */
629 n
= hashPrime(Config
.Netdb
.high
/ 4);
630 addr_table
= hash_create((HASHCMP
*) strcmp
, n
, hash_string
);
631 n
= hashPrime(3 * Config
.Netdb
.high
/ 4);
632 host_table
= hash_create((HASHCMP
*) strcmp
, n
, hash_string
);
633 eventAddIsh("netdbSaveState", netdbSaveState
, NULL
, 3600.0, 1);
635 cachemgrRegister("netdb",
636 "Network Measurement Database",
642 netdbPingSite(const char *hostname
)
647 if ((n
= netdbLookupHost(hostname
)) != NULL
)
648 if (n
->next_ping_time
> squid_curtime
)
650 h
= xstrdup(hostname
);
651 cbdataAdd(h
, MEM_NONE
);
653 ipcache_nbgethostbyname(hostname
, netdbSendPing
, h
);
658 netdbHandlePingReply(const struct sockaddr_in
*from
, int hops
, int rtt
)
663 debug(38, 3) ("netdbHandlePingReply: from %s\n", inet_ntoa(from
->sin_addr
));
664 if ((n
= netdbLookupAddr(from
->sin_addr
)) == NULL
)
669 n
->hops
= ((n
->hops
* (N
- 1)) + hops
) / N
;
670 n
->rtt
= ((n
->rtt
* (N
- 1)) + rtt
) / N
;
671 debug(38, 3) ("netdbHandlePingReply: %s; rtt=%5.1f hops=%4.1f\n",
679 netdbFreeMemory(void)
682 hashFreeItems(addr_table
, netdbFreeNetdbEntry
);
683 hashFreeMemory(addr_table
);
685 hashFreeItems(host_table
, netdbFreeNameEntry
);
686 hashFreeMemory(host_table
);
688 wordlistDestroy(&peer_names
);
694 netdbHops(struct in_addr addr
)
697 netdbEntry
*n
= netdbLookupAddr(addr
);
698 if (n
&& n
->pings_recv
) {
699 n
->last_use_time
= squid_curtime
;
700 return (int) (n
->hops
+ 0.5);
707 netdbDump(StoreEntry
* sentry
)
717 storeAppendPrintf(sentry
, "Network DB Statistics:\n");
718 storeAppendPrintf(sentry
, "%-16.16s %9s %7s %5s %s\n",
724 list
= xcalloc(memInUse(MEM_NETDBENTRY
), sizeof(netdbEntry
*));
726 hash_first(addr_table
);
727 while ((n
= (netdbEntry
*) hash_next(addr_table
)))
729 if (i
!= memInUse(MEM_NETDBENTRY
))
730 debug(38, 0) ("WARNING: netdb_addrs count off, found %d, expected %d\n",
731 i
, memInUse(MEM_NETDBENTRY
));
734 sizeof(netdbEntry
*),
736 for (k
= 0; k
< i
; k
++) {
738 storeAppendPrintf(sentry
, "%-16.16s %4d/%4d %7.1f %5.1f",
744 for (x
= n
->hosts
; x
; x
= x
->next
)
745 storeAppendPrintf(sentry
, " %s", x
->name
);
746 storeAppendPrintf(sentry
, "\n");
748 for (j
= 0; j
< n
->n_peers
; j
++, p
++) {
749 storeAppendPrintf(sentry
, " %-22.22s %7.1f %5.1f\n",
757 storeAppendPrintf(sentry
,
758 "NETDB support not compiled into this Squid cache.\n");
763 netdbHostHops(const char *host
)
766 netdbEntry
*n
= netdbLookupHost(host
);
768 n
->last_use_time
= squid_curtime
;
769 return (int) (n
->hops
+ 0.5);
776 netdbHostRtt(const char *host
)
779 netdbEntry
*n
= netdbLookupHost(host
);
781 n
->last_use_time
= squid_curtime
;
782 return (int) (n
->rtt
+ 0.5);
789 netdbHostData(const char *host
, int *samp
, int *rtt
, int *hops
)
792 netdbEntry
*n
= netdbLookupHost(host
);
795 *samp
= n
->pings_recv
;
796 *rtt
= (int) (n
->rtt
+ 0.5);
797 *hops
= (int) (n
->hops
+ 0.5);
802 netdbHostPeerRtt(const char *host
, peer
* p
)
805 const netdbEntry
*n
= netdbLookupHost(host
);
807 const net_db_peer
*np
= netdbPeerByName(n
, p
->host
);
808 if (np
&& np
->expires
>= squid_curtime
)
809 return (int) (np
->rtt
+ 0.5);
816 netdbUpdatePeer(request_t
* r
, peer
* e
, int irtt
, int ihops
)
820 double rtt
= (double) irtt
;
821 double hops
= (double) ihops
;
823 debug(38, 3) ("netdbUpdatePeer: '%s', %d hops, %d rtt\n", r
->host
, ihops
, irtt
);
824 n
= netdbLookupHost(r
->host
);
826 debug(38, 3) ("netdbUpdatePeer: host '%s' not found\n", r
->host
);
829 if ((p
= netdbPeerByName(n
, e
->host
)) == NULL
)
830 p
= netdbPeerAdd(n
, e
);
833 p
->expires
= squid_curtime
+ 3600;
836 qsort((char *) n
->peers
,
844 netdbExchangeUpdatePeer(struct in_addr addr
, peer
* e
, double rtt
, double hops
)
849 debug(38, 5) ("netdbExchangeUpdatePeer: '%s', %0.1f hops, %0.1f rtt\n",
850 inet_ntoa(addr
), hops
, rtt
);
851 n
= netdbLookupAddr(addr
);
855 if ((p
= netdbPeerByName(n
, e
->host
)) == NULL
)
856 p
= netdbPeerAdd(n
, e
);
859 p
->expires
= squid_curtime
+ 3600; /* XXX ? */
862 qsort((char *) n
->peers
,
870 netdbDeleteAddrNetwork(struct in_addr addr
)
873 netdbEntry
*n
= netdbLookupAddr(addr
);
876 debug(38, 3) ("netdbDeleteAddrNetwork: %s\n", n
->network
);
882 netdbBinaryExchange(StoreEntry
* s
)
884 http_reply
*reply
= s
->mem_obj
->reply
;
893 httpReplyReset(reply
);
894 httpReplySetHeaders(reply
, 1.0, HTTP_OK
, "OK",
895 NULL
, -1, squid_curtime
, -2);
896 httpReplySwapOut(reply
, s
);
898 rec_sz
+= 1 + sizeof(addr
.s_addr
);
899 rec_sz
+= 1 + sizeof(int);
900 rec_sz
+= 1 + sizeof(int);
901 buf
= memAllocate(MEM_4K_BUF
);
903 hash_first(addr_table
);
904 while ((n
= (netdbEntry
*) hash_next(addr_table
))) {
907 if (n
->rtt
> 60000) /* RTT > 1 MIN probably bogus */
909 if (!safe_inet_addr(n
->network
, &addr
))
911 buf
[i
++] = (char) NETDB_EX_NETWORK
;
912 xmemcpy(&buf
[i
], &addr
.s_addr
, sizeof(addr
.s_addr
));
913 i
+= sizeof(addr
.s_addr
);
914 buf
[i
++] = (char) NETDB_EX_RTT
;
915 j
= htonl((int) (n
->rtt
* 1000));
916 xmemcpy(&buf
[i
], &j
, sizeof(int));
918 buf
[i
++] = (char) NETDB_EX_HOPS
;
919 j
= htonl((int) (n
->hops
* 1000));
920 xmemcpy(&buf
[i
], &j
, sizeof(int));
922 if (i
+ rec_sz
> 4096) {
923 storeAppend(s
, buf
, i
);
928 storeAppend(s
, buf
, i
);
933 memFree(MEM_4K_BUF
, buf
);
935 httpReplyReset(reply
);
936 httpReplySetHeaders(reply
, 1.0, HTTP_BAD_REQUEST
, "Bad Request",
937 NULL
, -1, squid_curtime
, -2);
938 storeAppendPrintf(s
, "NETDB support not compiled into this Squid cache.\n");
944 netdbExchangeStart(void *data
)
949 netdbExchangeState
*ex
= xcalloc(1, sizeof(*ex
));
950 cbdataAdd(ex
, MEM_NONE
);
953 uri
= internalRemoteUri(p
->host
, p
->http_port
, "/squid-internal-dynamic/", "netdb");
954 debug(38, 3) ("netdbExchangeStart: Requesting '%s'\n", uri
);
956 ex
->r
= urlParse(METHOD_GET
, uri
);
958 debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri
);
962 assert(NULL
!= ex
->r
);
963 ex
->r
->http_ver
= 1.0;
964 ex
->e
= storeCreateEntry(uri
, uri
, null_request_flags
, METHOD_GET
);
966 ex
->buf
= memAllocate(MEM_4K_BUF
);
967 assert(NULL
!= ex
->e
);
968 storeClientListAdd(ex
->e
, ex
);
969 storeClientCopy(ex
->e
, ex
->seen
, ex
->used
, ex
->buf_sz
,
970 ex
->buf
, netdbExchangeHandleReply
, ex
);
971 ex
->r
->flags
.loopdetect
= 1; /* cheat! -- force direct */
972 fwdStart(-1, ex
->e
, ex
->r
, no_addr
);
977 netdbClosestParent(request_t
* request
)
982 const ipcache_addrs
*ia
;
985 n
= netdbLookupHost(request
->host
);
988 ia
= ipcache_gethostbyname(request
->host
, 0);
990 n
= netdbLookupAddr(ia
->in_addrs
[ia
->cur
]);
997 * Find the parent with the least RTT to the origin server.
998 * Make sure we don't return a parent who is farther away than
999 * we are. Note, the n->peers list is pre-sorted by RTT.
1001 for (i
= 0; i
< n
->n_peers
; i
++) {
1004 if (n
->rtt
< h
->rtt
)
1006 p
= peerFindByName(h
->peername
);
1007 if (NULL
== p
) /* not found */
1009 if (neighborType(p
, request
) != PEER_PARENT
)
1011 if (!peerHTTPOkay(p
, request
)) /* not allowed */