/[axel]/branches/2.x/conn.c
ViewVC logotype

Contents of /branches/2.x/conn.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations) (download)
Mon Dec 29 13:10:12 2008 UTC (4 years, 4 months ago) by phihag-guest
File MIME type: text/plain
File size: 8720 byte(s)
Synchronize trunk and 2.x branch: Backport UA

1 /********************************************************************\
2 * Axel -- A lighter download accelerator for Linux and other Unices. *
3 * *
4 * Copyright 2001 Wilmer van der Gaast *
5 \********************************************************************/
6
7 /* Connection stuff */
8
9 /*
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License with
21 the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
22 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23 Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include "axel.h"
27
28 char string[MAX_STRING];
29
30 /* Convert an URL to a conn_t structure */
31 int conn_set( conn_t *conn, char *set_url )
32 {
33 char url[MAX_STRING];
34 char *i, *j;
35
36 /* protocol:// */
37 if( ( i = strstr( set_url, "://" ) ) == NULL )
38 {
39 conn->proto = PROTO_DEFAULT;
40 strncpy( url, set_url, MAX_STRING );
41 }
42 else
43 {
44 if( set_url[0] == 'f' )
45 conn->proto = PROTO_FTP;
46 else if( set_url[0] == 'h' )
47 conn->proto = PROTO_HTTP;
48 else
49 {
50 return( 0 );
51 }
52 strncpy( url, i + 3, MAX_STRING );
53 }
54
55 /* Split */
56 if( ( i = strchr( url, '/' ) ) == NULL )
57 {
58 strcpy( conn->dir, "/" );
59 }
60 else
61 {
62 *i = 0;
63 snprintf( conn->dir, MAX_STRING, "/%s", i + 1 );
64 if( conn->proto == PROTO_HTTP )
65 http_encode( conn->dir );
66 }
67 strncpy( conn->host, url, MAX_STRING );
68 j = strchr( conn->dir, '?' );
69 if( j != NULL )
70 *j = 0;
71 i = strrchr( conn->dir, '/' );
72 *i = 0;
73 if( j != NULL )
74 *j = '?';
75 if( i == NULL )
76 {
77 strncpy( conn->file, conn->dir, MAX_STRING );
78 strcpy( conn->dir, "/" );
79 }
80 else
81 {
82 strncpy( conn->file, i + 1, MAX_STRING );
83 strcat( conn->dir, "/" );
84 }
85
86 /* Check for username in host field */
87 if( strrchr( conn->host, '@' ) != NULL )
88 {
89 strncpy( conn->user, conn->host, MAX_STRING );
90 i = strrchr( conn->user, '@' );
91 *i = 0;
92 strncpy( conn->host, i + 1, MAX_STRING );
93 *conn->pass = 0;
94 }
95 /* If not: Fill in defaults */
96 else
97 {
98 if( conn->proto == PROTO_FTP )
99 {
100 /* Dash the password: Save traffic by trying
101 to avoid multi-line responses */
102 strcpy( conn->user, "anonymous" );
103 strcpy( conn->pass, "mailto:axel-devel@lists.alioth.debian.org" );
104 }
105 else
106 {
107 *conn->user = *conn->pass = 0;
108 }
109 }
110
111 /* Password? */
112 if( ( i = strchr( conn->user, ':' ) ) != NULL )
113 {
114 *i = 0;
115 strncpy( conn->pass, i + 1, MAX_STRING );
116 }
117 /* Port number? */
118 if( ( i = strchr( conn->host, ':' ) ) != NULL )
119 {
120 *i = 0;
121 sscanf( i + 1, "%i", &conn->port );
122 }
123 /* Take default port numbers from /etc/services */
124 else
125 {
126 #ifndef DARWIN
127 struct servent *serv;
128
129 if( conn->proto == PROTO_FTP )
130 serv = getservbyname( "ftp", "tcp" );
131 else
132 serv = getservbyname( "www", "tcp" );
133
134 if( serv )
135 conn->port = ntohs( serv->s_port );
136 else
137 #endif
138 if( conn->proto == PROTO_HTTP )
139 conn->port = 80;
140 else
141 conn->port = 21;
142 }
143
144 return( conn->port > 0 );
145 }
146
147 /* Generate a nice URL string. */
148 char *conn_url( conn_t *conn )
149 {
150 if( conn->proto == PROTO_FTP )
151 strcpy( string, "ftp://" );
152 else
153 strcpy( string, "http://" );
154
155 if( *conn->user != 0 && strcmp( conn->user, "anonymous" ) != 0 )
156 sprintf( string + strlen( string ), "%s:%s@",
157 conn->user, conn->pass );
158
159 sprintf( string + strlen( string ), "%s:%i%s%s",
160 conn->host, conn->port, conn->dir, conn->file );
161
162 return( string );
163 }
164
165 /* Simple... */
166 void conn_disconnect( conn_t *conn )
167 {
168 if( conn->proto == PROTO_FTP && !conn->proxy )
169 ftp_disconnect( conn->ftp );
170 else
171 http_disconnect( conn->http );
172 conn->fd = -1;
173 }
174
175 int conn_init( conn_t *conn )
176 {
177 char *proxy = conn->conf->http_proxy, *host = conn->conf->no_proxy;
178 int i;
179
180 if( *conn->conf->http_proxy == 0 )
181 {
182 proxy = NULL;
183 }
184 else if( *conn->conf->no_proxy != 0 )
185 {
186 for( i = 0; ; i ++ )
187 if( conn->conf->no_proxy[i] == 0 )
188 {
189 if( strstr( conn->host, host ) != NULL )
190 proxy = NULL;
191 host = &conn->conf->no_proxy[i+1];
192 if( conn->conf->no_proxy[i+1] == 0 )
193 break;
194 }
195 }
196
197 conn->proxy = proxy != NULL;
198
199 if( conn->proto == PROTO_FTP && !conn->proxy )
200 {
201 conn->ftp->local_if = conn->local_if;
202 conn->ftp->ftp_mode = FTP_PASSIVE;
203 if( !ftp_connect( conn->ftp, conn->host, conn->port, conn->user, conn->pass ) )
204 {
205 conn->message = conn->ftp->message;
206 conn_disconnect( conn );
207 return( 0 );
208 }
209 conn->message = conn->ftp->message;
210 if( !ftp_cwd( conn->ftp, conn->dir ) )
211 {
212 conn_disconnect( conn );
213 return( 0 );
214 }
215 }
216 else
217 {
218 conn->http->local_if = conn->local_if;
219 if( !http_connect( conn->http, conn->proto, proxy, conn->host, conn->port, conn->user, conn->pass ) )
220 {
221 conn->message = conn->http->headers;
222 conn_disconnect( conn );
223 return( 0 );
224 }
225 conn->message = conn->http->headers;
226 conn->fd = conn->http->fd;
227 }
228 return( 1 );
229 }
230
231 int conn_setup( conn_t *conn )
232 {
233 if( conn->ftp->fd <= 0 && conn->http->fd <= 0 )
234 if( !conn_init( conn ) )
235 return( 0 );
236
237 if( conn->proto == PROTO_FTP && !conn->proxy )
238 {
239 if( !ftp_data( conn->ftp ) ) /* Set up data connnection */
240 return( 0 );
241 conn->fd = conn->ftp->data_fd;
242
243 if( conn->currentbyte )
244 {
245 ftp_command( conn->ftp, "REST %lld", conn->currentbyte );
246 if( ftp_wait( conn->ftp ) / 100 != 3 &&
247 conn->ftp->status / 100 != 2 )
248 return( 0 );
249 }
250 }
251 else
252 {
253 char s[MAX_STRING];
254 int i;
255
256 snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file );
257 conn->http->firstbyte = conn->currentbyte;
258 conn->http->lastbyte = conn->lastbyte;
259 http_get( conn->http, s );
260 http_addheader( conn->http, "User-Agent: %s", conn->conf->user_agent );
261 for( i = 0; i < conn->conf->add_header_count; i++)
262 http_addheader( conn->http, "%s", conn->conf->add_header[i] );
263 }
264 return( 1 );
265 }
266
267 int conn_exec( conn_t *conn )
268 {
269 if( conn->proto == PROTO_FTP && !conn->proxy )
270 {
271 if( !ftp_command( conn->ftp, "RETR %s", conn->file ) )
272 return( 0 );
273 return( ftp_wait( conn->ftp ) / 100 == 1 );
274 }
275 else
276 {
277 if( !http_exec( conn->http ) )
278 return( 0 );
279 return( conn->http->status / 100 == 2 );
280 }
281 }
282
283 /* Get file size and other information */
284 int conn_info( conn_t *conn )
285 {
286 /* It's all a bit messed up.. But it works. */
287 if( conn->proto == PROTO_FTP && !conn->proxy )
288 {
289 ftp_command( conn->ftp, "REST %lld", 1 );
290 if( ftp_wait( conn->ftp ) / 100 == 3 ||
291 conn->ftp->status / 100 == 2 )
292 {
293 conn->supported = 1;
294 ftp_command( conn->ftp, "REST %lld", 0 );
295 ftp_wait( conn->ftp );
296 }
297 else
298 {
299 conn->supported = 0;
300 }
301
302 if( !ftp_cwd( conn->ftp, conn->dir ) )
303 return( 0 );
304 conn->size = ftp_size( conn->ftp, conn->file, MAX_REDIR );
305 if( conn->size < 0 )
306 conn->supported = 0;
307 if( conn->size == -1 )
308 return( 0 );
309 else if( conn->size == -2 )
310 conn->size = INT_MAX;
311 }
312 else
313 {
314 char s[MAX_STRING], *t;
315 long long int i = 0;
316
317 do
318 {
319 conn->currentbyte = 1;
320 if( !conn_setup( conn ) )
321 return( 0 );
322 conn_exec( conn );
323 conn_disconnect( conn );
324 /* Code 3xx == redirect */
325 if( conn->http->status / 100 != 3 )
326 break;
327 if( ( t = http_header( conn->http, "location:" ) ) == NULL )
328 return( 0 );
329 sscanf( t, "%255s", s );
330 if( strstr( s, "://" ) == NULL)
331 {
332 sprintf( conn->http->headers, "%s%s",
333 conn_url( conn ), s );
334 strncpy( s, conn->http->headers, MAX_STRING );
335 }
336 else if( s[0] == '/' )
337 {
338 sprintf( conn->http->headers, "http://%s:%i%s",
339 conn->host, conn->port, s );
340 strncpy( s, conn->http->headers, MAX_STRING );
341 }
342 conn_set( conn, s );
343 i ++;
344 }
345 while( conn->http->status / 100 == 3 && i < MAX_REDIR );
346
347 if( i == MAX_REDIR )
348 {
349 sprintf( conn->message, _("Too many redirects.\n") );
350 return( 0 );
351 }
352
353 conn->size = http_size( conn->http );
354 if( conn->http->status == 206 && conn->size >= 0 )
355 {
356 conn->supported = 1;
357 conn->size ++;
358 }
359 else if( conn->http->status == 200 || conn->http->status == 206 )
360 {
361 conn->supported = 0;
362 conn->size = INT_MAX;
363 }
364 else
365 {
366 t = strchr( conn->message, '\n' );
367 if( t == NULL )
368 sprintf( conn->message, _("Unknown HTTP error.\n") );
369 else
370 *t = 0;
371 return( 0 );
372 }
373 }
374
375 return( 1 );
376 }

  ViewVC Help
Powered by ViewVC 1.1.5