Imported Upstream version 0.7.0
[platform/upstream/libsolv.git] / examples / solv / fastestmirror.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <time.h>
6 #include <sys/time.h>
7 #include <sys/socket.h>
8 #include <netdb.h>
9 #include <poll.h>
10 #include <errno.h>
11
12 #include "util.h"
13
14 #include "fastestmirror.h"
15
16 void
17 findfastest(char **urls, int nurls)
18 {
19   int i, j, port;
20   int *socks, qc;
21   struct pollfd *fds;
22   char *p, *p2, *q;
23   char portstr[16];
24   struct addrinfo hints, *result;;
25
26   fds = solv_calloc(nurls, sizeof(*fds));
27   socks = solv_calloc(nurls, sizeof(*socks));
28   for (i = 0; i < nurls; i++)
29     {
30       socks[i] = -1;
31       p = strchr(urls[i], '/');
32       if (!p)
33         continue;
34       if (p[1] != '/')
35         continue;
36       p += 2;
37       q = strchr(p, '/');
38       qc = 0;
39       if (q)
40         {
41           qc = *q;
42           *q = 0;
43         }
44       if ((p2 = strchr(p, '@')) != 0)
45         p = p2 + 1;
46       port = 80;
47       if (!strncmp("https:", urls[i], 6))
48         port = 443;
49       else if (!strncmp("ftp:", urls[i], 4))
50         port = 21;
51       if ((p2 = strrchr(p, ':')) != 0)
52         {
53           port = atoi(p2 + 1);
54           if (q)
55             *q = qc;
56           q = p2;
57           qc = *q;
58           *q = 0;
59         }
60       sprintf(portstr, "%d", port);
61       memset(&hints, 0, sizeof(struct addrinfo));
62       hints.ai_family = AF_UNSPEC;
63       hints.ai_socktype = SOCK_STREAM;
64       hints.ai_flags = AI_NUMERICSERV;
65       result = 0;
66       if (!getaddrinfo(p, portstr, &hints, &result))
67         {
68           socks[i] = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
69           if (socks[i] >= 0)
70             {
71               fcntl(socks[i], F_SETFL, O_NONBLOCK);
72               if (connect(socks[i], result->ai_addr, result->ai_addrlen) == -1)
73                 {
74                   if (errno != EINPROGRESS)
75                     {
76                       close(socks[i]);
77                       socks[i] = -1;
78                     }
79                 }
80             }
81           freeaddrinfo(result);
82         }
83       if (q)
84         *q = qc;
85     }
86   for (;;)
87     {
88       for (i = j = 0; i < nurls; i++)
89         {
90           if (socks[i] < 0)
91             continue;
92           fds[j].fd = socks[i];
93           fds[j].events = POLLOUT;
94           j++;
95         }
96       if (j < 2)
97         {
98           i = j - 1;
99           break;
100         }
101       if (poll(fds, j, 10000) <= 0)
102         {
103           i = -1;       /* something is wrong */
104           break;
105         }
106       for (i = 0; i < j; i++)
107         if ((fds[i].revents & POLLOUT) != 0)
108           {
109             int soe = 0;
110             socklen_t soel = sizeof(int);
111             if (getsockopt(fds[i].fd, SOL_SOCKET, SO_ERROR, &soe, &soel) == -1 || soe != 0)
112               {
113                 /* connect failed, kill socket */
114                 for (j = 0; j < nurls; j++)
115                   if (socks[j] == fds[i].fd)
116                     {
117                       close(socks[j]);
118                       socks[j] = -1;
119                     }
120                 i = j + 1;
121                 break;
122               }
123             break;      /* horray! */
124           }
125       if (i == j + 1)
126         continue;
127       if (i == j)
128         i = -1;         /* something is wrong, no bit was set */
129       break;
130     }
131   /* now i contains the fastest fd index */
132   if (i >= 0)
133     {
134       for (j = 0; j < nurls; j++)
135         if (socks[j] == fds[i].fd)
136           break;
137       if (j != 0)
138         {
139           char *url0 = urls[0];
140           urls[0] = urls[j];
141           urls[j] = url0;
142         }
143     }
144   for (i = j = 0; i < nurls; i++)
145     if (socks[i] >= 0)
146       close(socks[i]);
147   free(socks);
148   free(fds);
149 }