Browse code

freshclam: try load balance update sessions between available mirrors

git-svn: trunk@3947

Tomasz Kojm authored on 2008/07/15 02:27:10
Showing 4 changed files
... ...
@@ -1,3 +1,8 @@
1
+Mon Jul 14 18:54:01 CEST 2008 (tk)
2
+----------------------------------
3
+  * freshclam: try load balance update sessions between available mirrors
4
+	       (only in IPv6-aware block)
5
+
1 6
 Mon Jul 14 17:26:03 EEST 2008 (edwin)
2 7
 ------------------------------------
3 8
   * libclamav/htmlnorm.c: improve normalization of screnc encoded files(bb #1022)
... ...
@@ -185,8 +185,10 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
185 185
 {
186 186
 	int socketfd, port, ret;
187 187
 #ifdef SUPPORT_IPv6
188
-	struct addrinfo hints, *res = NULL, *rp;
189
-	char port_s[6];
188
+	struct addrinfo hints, *res = NULL, *rp, *loadbal_rp = NULL;
189
+	char port_s[6], loadbal_ipaddr[46];
190
+	uint32_t loadbal = 1, minsucc = 0xffffffff, minfail = 0xffffffff;
191
+	struct mirdat_ip *md;
190 192
 #else
191 193
 	struct sockaddr_in name;
192 194
 	struct hostent *host;
... ...
@@ -250,11 +252,44 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
250 250
 	    return -1;
251 251
 	}
252 252
 
253
-	if((ret = mirman_check(addr, rp->ai_family, mdat))) {
253
+	if((ret = mirman_check(addr, rp->ai_family, mdat, &md))) {
254 254
 	    if(ret == 1)
255 255
 		logg("Ignoring mirror %s (due to previous errors)\n", ipaddr);
256 256
 	    else
257 257
 		logg("Ignoring mirror %s (has connected too many times with an outdated version)\n", ipaddr);
258
+
259
+	    if(!loadbal || rp->ai_next)
260
+		continue;
261
+	}
262
+
263
+	if(loadbal) {
264
+	    if(!ret) {
265
+		if(!md) {
266
+		    loadbal_rp = rp;
267
+		    strncpy(loadbal_ipaddr, ipaddr, sizeof(loadbal_ipaddr));
268
+		} else {
269
+		    if(md->succ < minsucc && md->fail <= minfail) {
270
+			minsucc = md->succ;
271
+			minfail = md->fail;
272
+			loadbal_rp = rp;
273
+			strncpy(loadbal_ipaddr, ipaddr, sizeof(loadbal_ipaddr));
274
+		    }
275
+		    if(rp->ai_next)
276
+			continue;
277
+		}
278
+	    }
279
+
280
+	    if(!loadbal_rp) {
281
+		if(!rp->ai_next) {
282
+		    loadbal = 0;
283
+		    rp = res;
284
+		}
285
+		continue;
286
+	    }
287
+	    rp = loadbal_rp;
288
+	    strncpy(ipaddr, loadbal_ipaddr, sizeof(ipaddr));
289
+
290
+	} else if(loadbal_rp == rp) {
258 291
 	    continue;
259 292
 	}
260 293
 
... ...
@@ -277,6 +312,10 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
277 277
 #endif
278 278
 	    logg("Can't connect to port %d of host %s (IP: %s)\n", port, hostpt, ipaddr);
279 279
 	    closesocket(socketfd);
280
+	    if(loadbal) {
281
+		loadbal = 0;
282
+		rp = res;
283
+	    }
280 284
 	    continue;
281 285
 	} else {
282 286
 	    if(rp->ai_family == AF_INET)
... ...
@@ -302,7 +341,7 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
302 302
 	ia = (unsigned char *) host->h_addr_list[i];
303 303
 	sprintf(ipaddr, "%u.%u.%u.%u", ia[0], ia[1], ia[2], ia[3]);
304 304
 
305
-	if((ret = mirman_check(&((struct in_addr *) ia)->s_addr, AF_INET, mdat))) {
305
+	if((ret = mirman_check(&((struct in_addr *) ia)->s_addr, AF_INET, mdat, NULL))) {
306 306
 	    if(ret == 1)
307 307
 		logg("Ignoring mirror %s (due to previous errors)\n", ipaddr);
308 308
 	    else
... ...
@@ -104,17 +104,26 @@ int mirman_read(const char *file, struct mirdat *mdat, uint8_t active)
104 104
     return 0;
105 105
 }
106 106
 
107
-int mirman_check(uint32_t *ip, int af, struct mirdat *mdat)
107
+int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **md)
108 108
 {
109 109
 	unsigned int i, flevel = cl_retflevel();
110 110
 
111 111
 
112
+    if(md)
113
+	*md = NULL;
114
+
112 115
     if(!mdat->active)
113 116
 	return 0;
114 117
 
115 118
     for(i = 0; i < mdat->num; i++) {
116 119
 
117
-	if(mdat->mirtab[i].atime && ((af == AF_INET && mdat->mirtab[i].ip4 == *ip) || (af == AF_INET6 && !memcmp(mdat->mirtab[i].ip6, ip, 4)))) {
120
+	if(((af == AF_INET && mdat->mirtab[i].ip4 == *ip) || (af == AF_INET6 && !memcmp(mdat->mirtab[i].ip6, ip, 4)))) {
121
+
122
+	    if(!mdat->mirtab[i].atime) {
123
+		if(md)
124
+		    *md = &mdat->mirtab[i];
125
+		return 0;
126
+	    }
118 127
 
119 128
 	    if(mdat->dbflevel && (mdat->dbflevel > flevel) && (mdat->dbflevel - flevel > 3))
120 129
 		if(time(NULL) - mdat->mirtab[i].atime < 4 * 3600)
... ...
@@ -123,11 +132,17 @@ int mirman_check(uint32_t *ip, int af, struct mirdat *mdat)
123 123
 	    if(mdat->mirtab[i].ignore) {
124 124
 		if(time(NULL) - mdat->mirtab[i].atime > IGNTIME) {
125 125
 		    mdat->mirtab[i].ignore = 0;
126
+		    if(md)
127
+			*md = &mdat->mirtab[i];
126 128
 		    return 0;
127 129
 		} else {
128 130
 		    return 1;
129 131
 		}
130 132
 	    }
133
+
134
+	    if(md)
135
+		*md = &mdat->mirtab[i];
136
+	    return 0;
131 137
 	}
132 138
     }
133 139
 
... ...
@@ -41,7 +41,7 @@ struct mirdat {
41 41
 };
42 42
 
43 43
 int mirman_read(const char *file, struct mirdat *mdat, uint8_t active);
44
-int mirman_check(uint32_t *ip, int af, struct mirdat *mdat);
44
+int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **md);
45 45
 int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken);
46 46
 void mirman_list(const struct mirdat *mdat);
47 47
 int mirman_write(const char *file, struct mirdat *mdat);