1 /*
2 HTTP request/response handling
3 Copyright (C) 1999-2004, Joe Orton <joe@manyfish.co.uk>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA
19
20 */
21
22 /* This is the HTTP client request/response implementation.
23 * The goal of this code is to be modular and simple.
24 */
25
26 #include "config.h"
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #ifdef __EMX__
31 #include <sys/select.h>
32 #endif
33
34 #ifdef HAVE_LIMITS_H
35 #include <limits.h> /* for UINT_MAX etc */
36 #endif
37
38 #include <ctype.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #ifdef HAVE_STRING_H
42 #include <string.h>
43 #endif
44 #ifdef HAVE_STRINGS_H
45 #include <strings.h>
46 #endif
47 #ifdef HAVE_STDLIB_H
48 #include <stdlib.h>
49 #endif
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53
54 #include "ne_i18n.h"
55
56 #include "ne_alloc.h"
57 #include "ne_request.h"
58 #include "ne_string.h" /* for ne_buffer */
59 #include "ne_utils.h"
60 #include "ne_socket.h"
61 #include "ne_uri.h"
62
63 #include "ne_private.h"
64
65 #define HTTP_EXPECT_TIMEOUT 15
66 /* 100-continue only used if size > HTTP_EXPECT_MINSIZ */
67 #define HTTP_EXPECT_MINSIZE 1024
68
69 /* with thanks to Jim Blandy; this macro simplified loads of code. */
70 #define HTTP_ERR(x) do { int _ret = (x); if (_ret != NE_OK) return _ret; } while (0)
71
72 #define SOCK_ERR(req, op, msg) do { ssize_t sret = (op); \
73 if (sret < 0) return aborted(req, msg, sret); } while (0)
74
75 /* This is called with each of the headers in the response */
76 struct header_handler {
77 char *name;
78 ne_header_handler handler;
79 void *userdata;
80 struct header_handler *next;
81 };
82
83 /* TODO: could unify these all into a generic callback list */
84
85 struct body_reader {
86 ne_block_reader handler;
87 ne_accept_response accept_response;
88 unsigned int use:1;
89 void *userdata;
90 struct body_reader *next;
91 };
92
93 struct ne_request_s {
94 char *method, *uri; /* method and Request-URI */
95
96 ne_buffer *headers; /* request headers */
97
98 /* Request body. */
99 ne_provide_body body_cb;
100 void *body_ud;
101
102 /* Comes from either an fd or a buffer. */
103 union {
104 int fd;
105 struct {
106 const char *buffer, *pnt;
107 size_t left;
108 } buf;
109 } body;
110
111 size_t body_size, body_progress;
112
113 /* temporary store for response lines. */
114 char respbuf[BUFSIZ];
115
116 /**** Response ***/
117
118 /* The transfer encoding types */
119 struct ne_response {
120 int length; /* Response entity-body content-length */
121 size_t left; /* Bytes left to read */
122 size_t chunk_left; /* Bytes of chunk left to read */
123 size_t total; /* total bytes read so far. */
124 /* how the message length is detemined: */
125 enum {
126 R_TILLEOF = 0, /* read till eof */
127 R_NO_BODY, /* implicitly no body (HEAD, 204, 205, 304) */
128 R_CHUNKED, /* using chunked transfer-encoding */
129 R_CLENGTH /* using given content-length */
130 } mode;
131 } resp;
132
133 /* List of callbacks which are passed response headers */
134 struct header_handler *header_catchers;
135
136 struct hook *private;
137
138 /* We store response header handlers in a hash table. The hash is
139 * derived from the header name in lower case. */
140
141 /* FIXME: this comment is WAY out of date, and no longer in any
142 * way true. */
143
144 /* 53 is magic, of course. For a standard ne_get() (with
145 * redirects), 9 header handlers are defined. Two of these are
146 * for Content-Length (which is a bug, and should be fixed
147 * really). Ignoring that hash clash, the 8 *different* handlers
148 * all hash uniquely into the hash table of size 53. */
149 #define HH_HASHSIZE 53
150
151 struct header_handler *header_handlers[HH_HASHSIZE];
152 /* List of callbacks which are passed response body blocks */
153 struct body_reader *body_readers;
154
155 /*** Miscellaneous ***/
156 unsigned int method_is_head:1;
157 unsigned int use_expect100:1;
158 unsigned int can_persist:1;
159
160 ne_session *session;
161 ne_status status;
162 };
163
164 static int open_connection(ne_request *req);
165
166 /* The iterative step used to produce the hash value. This is DJB's
167 * magic "*33" hash function. Ralf Engelschall has done some amazing
168 * statistical analysis to show that *33 really is a good hash
169 * function: check the new-httpd list archives, or his 'str' library
170 * source code, for the details.
171 *
172 * TODO: due to limited range of characters used in header names,
173 * could maybe get a better hash function to use? */
174
175 #define HH_ITERATE(hash, ch) (((hash)*33 + (ch)) % HH_HASHSIZE);
176
177 /* Returns hash value for header 'name', converting it to lower-case
178 * in-place. */
hash_and_lower(char * name)179 static inline unsigned int hash_and_lower(char *name)
180 {
181 char *pnt;
182 unsigned int hash = 0;
183
184 for (pnt = name; *pnt != '\0'; pnt++) {
185 *pnt = tolower(*pnt);
186 hash = HH_ITERATE(hash,*pnt);
187 }
188
189 return hash;
190 }
191
192 /* Abort a request due to an non-recoverable HTTP protocol error,
193 * whilst doing 'doing'. 'code', if non-zero, is the socket error
194 * code, NE_SOCK_*, or if zero, is ignored. */
aborted(ne_request * req,const char * doing,ssize_t code)195 static int aborted(ne_request *req, const char *doing, ssize_t code)
196 {
197 ne_session *sess = req->session;
198 int ret = NE_ERROR;
199
200 NE_DEBUG(NE_DBG_HTTP, "Aborted request (%" NE_FMT_SSIZE_T "): %s\n",
201 code, doing);
202
203 switch(code) {
204 case NE_SOCK_CLOSED:
205 if (sess->use_proxy) {
206 ne_set_error(sess, _("%s: connection was closed by proxy server."),
207 doing);
208 } else {
209 ne_set_error(sess, _("%s: connection was closed by server."),
210 doing);
211 }
212 break;
213 case NE_SOCK_TIMEOUT:
214 ne_set_error(sess, _("%s: connection timed out."), doing);
215 ret = NE_TIMEOUT;
216 break;
217 case NE_SOCK_ERROR:
218 case NE_SOCK_RESET:
219 case NE_SOCK_TRUNC:
220 ne_set_error(sess, "%s: %s", doing, ne_sock_error(sess->socket));
221 break;
222 case 0:
223 ne_set_error(sess, "%s", doing);
224 break;
225 }
226
227 ne_close_connection(sess);
228 return ret;
229 }
230
notify_status(ne_session * sess,ne_conn_status status,const char * info)231 static void notify_status(ne_session *sess, ne_conn_status status,
232 const char *info)
233 {
234 if (sess->notify_cb) {
235 sess->notify_cb(sess->notify_ud, status, info);
236 }
237 }
238
ne_duplicate_header(void * userdata,const char * value)239 void ne_duplicate_header(void *userdata, const char *value)
240 {
241 char **location = userdata;
242 *location = ne_strdup(value);
243 }
244
ne_handle_numeric_header(void * userdata,const char * value)245 void ne_handle_numeric_header(void *userdata, const char *value)
246 {
247 int *location = userdata;
248 *location = atoi(value);
249 }
250
get_private(const struct hook * hk,const char * id)251 static void *get_private(const struct hook *hk, const char *id)
252 {
253 for (; hk != NULL; hk = hk->next)
254 if (strcmp(hk->id, id) == 0)
255 return hk->userdata;
256 return NULL;
257 }
258
ne_get_request_private(ne_request * req,const char * id)259 void *ne_get_request_private(ne_request *req, const char *id)
260 {
261 return get_private(req->private, id);
262 }
263
ne_get_session_private(ne_session * sess,const char * id)264 void *ne_get_session_private(ne_session *sess, const char *id)
265 {
266 return get_private(sess->private, id);
267 }
268
269 typedef void (*void_fn)(void);
270
271 #define ADD_HOOK(hooks, fn, ud) add_hook(&(hooks), NULL, (void_fn)(fn), (ud))
272
add_hook(struct hook ** hooks,const char * id,void_fn fn,void * ud)273 static void add_hook(struct hook **hooks, const char *id, void_fn fn, void *ud)
274 {
275 struct hook *hk = ne_malloc(sizeof (struct hook)), *pos;
276
277 if (*hooks != NULL) {
278 for (pos = *hooks; pos->next != NULL; pos = pos->next)
279 /* nullop */;
280 pos->next = hk;
281 } else {
282 *hooks = hk;
283 }
284
285 hk->id = id;
286 hk->fn = fn;
287 hk->userdata = ud;
288 hk->next = NULL;
289 }
290
ne_hook_create_request(ne_session * sess,ne_create_request_fn fn,void * userdata)291 void ne_hook_create_request(ne_session *sess,
292 ne_create_request_fn fn, void *userdata)
293 {
294 ADD_HOOK(sess->create_req_hooks, fn, userdata);
295 }
296
ne_hook_pre_send(ne_session * sess,ne_pre_send_fn fn,void * userdata)297 void ne_hook_pre_send(ne_session *sess, ne_pre_send_fn fn, void *userdata)
298 {
299 ADD_HOOK(sess->pre_send_hooks, fn, userdata);
300 }
301
ne_hook_post_send(ne_session * sess,ne_post_send_fn fn,void * userdata)302 void ne_hook_post_send(ne_session *sess, ne_post_send_fn fn, void *userdata)
303 {
304 ADD_HOOK(sess->post_send_hooks, fn, userdata);
305 }
306
ne_hook_destroy_request(ne_session * sess,ne_destroy_req_fn fn,void * userdata)307 void ne_hook_destroy_request(ne_session *sess,
308 ne_destroy_req_fn fn, void *userdata)
309 {
310 ADD_HOOK(sess->destroy_req_hooks, fn, userdata);
311 }
312
ne_hook_destroy_session(ne_session * sess,ne_destroy_sess_fn fn,void * userdata)313 void ne_hook_destroy_session(ne_session *sess,
314 ne_destroy_sess_fn fn, void *userdata)
315 {
316 ADD_HOOK(sess->destroy_sess_hooks, fn, userdata);
317 }
318
319 /* 0.24.x hack to fix ne_compress layer problems */
ne_kill_pre_send(ne_session * sess,ne_pre_send_fn fn,void * userdata)320 void ne_kill_pre_send(ne_session *sess, ne_pre_send_fn fn, void *userdata)
321 {
322 struct hook **last, *hk;
323
324 last = &sess->pre_send_hooks;
325 hk = *last;
326
327 while (hk) {
328 if (hk->fn == (void_fn)fn && hk->userdata == userdata) {
329 *last = hk->next;
330 ne_free(hk);
331 return;
332 }
333 last = &hk->next;
334 hk = *last;
335 }
336 }
337
ne_set_session_private(ne_session * sess,const char * id,void * userdata)338 void ne_set_session_private(ne_session *sess, const char *id, void *userdata)
339 {
340 add_hook(&sess->private, id, NULL, userdata);
341 }
342
ne_set_request_private(ne_request * req,const char * id,void * userdata)343 void ne_set_request_private(ne_request *req, const char *id, void *userdata)
344 {
345 add_hook(&req->private, id, NULL, userdata);
346 }
347
body_string_send(void * userdata,char * buffer,size_t count)348 static ssize_t body_string_send(void *userdata, char *buffer, size_t count)
349 {
350 ne_request *req = userdata;
351
352 if (count == 0) {
353 req->body.buf.left = req->body_size;
354 req->body.buf.pnt = req->body.buf.buffer;
355 } else {
356 /* if body_left == 0 we fall through and return 0. */
357 if (req->body.buf.left < count)
358 count = req->body.buf.left;
359
360 memcpy(buffer, req->body.buf.pnt, count);
361 req->body.buf.pnt += count;
362 req->body.buf.left -= count;
363 }
364
365 return count;
366 }
367
body_fd_send(void * userdata,char * buffer,size_t count)368 static ssize_t body_fd_send(void *userdata, char *buffer, size_t count)
369 {
370 ne_request *req = userdata;
371
372 if (count) {
373 return read(req->body.fd, buffer, count);
374 } else {
375 /* rewind since we may have to send it again */
376 return lseek(req->body.fd, SEEK_SET, 0);
377 }
378 }
379
380 /* Pulls the request body from the source and pushes it to the given
381 * callback. Returns 0 on success, or NE_* code */
ne_pull_request_body(ne_request * req,ne_push_fn fn,void * ud)382 int ne_pull_request_body(ne_request *req, ne_push_fn fn, void *ud)
383 {
384 int ret = 0;
385 char buffer[BUFSIZ];
386 ssize_t bytes;
387
388 /* tell the source to start again from the beginning. */
389 (void) req->body_cb(req->body_ud, NULL, 0);
390
391 /* TODO: should this attempt to pull exactly the number of bytes
392 * they specified were in the body? Currently it just pulls until
393 * they return zero. That makes it possible to extend this to do
394 * chunked request bodies (i.e. indefinitely long, no C-L), so
395 * this is probably a better long-term interface. */
396 while ((bytes = req->body_cb(req->body_ud, buffer, sizeof buffer)) > 0) {
397 ret = fn(ud, buffer, bytes);
398 if (ret < 0)
399 break;
400 NE_DEBUG(NE_DBG_HTTPBODY,
401 "Body block (%" NE_FMT_SSIZE_T " bytes):\n[%.*s]\n",
402 bytes, (int)bytes, buffer);
403 }
404
405 if (bytes < 0) {
406 ne_set_error(req->session, _("Error reading request body."));
407 ret = NE_ERROR;
408 }
409
410 return ret;
411 }
412
send_with_progress(void * userdata,const char * data,size_t n)413 static int send_with_progress(void *userdata, const char *data, size_t n)
414 {
415 ne_request *req = userdata;
416 int ret;
417
418 ret = ne_sock_fullwrite(req->session->socket, data, n);
419 if (ret == 0) {
420 req->body_progress += n;
421 req->session->progress_cb(req->session->progress_ud,
422 req->body_progress, req->body_size);
423 }
424
425 return ret;
426 }
427
428 /* Sends the request body down the socket.
429 * Returns 0 on success, or NE_* code */
send_request_body(ne_request * req)430 static int send_request_body(ne_request *req)
431 {
432 int ret;
433 NE_DEBUG(NE_DBG_HTTP, "Sending request body...\n");
434 if (req->session->progress_cb) {
435 /* with progress callbacks. */
436 req->body_progress = 0;
437 ret = ne_pull_request_body(req, send_with_progress, req);
438 } else {
439 /* without progress callbacks. */
440 ret = ne_pull_request_body(req, (ne_push_fn)ne_sock_fullwrite,
441 req->session->socket);
442 }
443
444 NE_DEBUG(NE_DBG_HTTP, "Request body sent: %s.\n", ret?"failed":"okay");
445 return ret;
446 }
447
448 /* Lob the User-Agent, connection and host headers in to the request
449 * headers */
add_fixed_headers(ne_request * req)450 static void add_fixed_headers(ne_request *req)
451 {
452 if (req->session->user_agent) {
453 ne_buffer_zappend(req->headers, req->session->user_agent);
454 }
455
456 /* Send Connection: Keep-Alive to pre-1.1 origin servers to try
457 * harder to get a persistent connection, except if using a proxy
458 * as per 2068 sec 19.7.1. Always add TE: trailers since those
459 * are understood. */
460 if (!req->session->is_http11 && !req->session->use_proxy) {
461 ne_buffer_zappend(req->headers,
462 "Keep-Alive: " EOL
463 "Connection: TE, Keep-Alive" EOL
464 "TE: trailers" EOL);
465 } else {
466 ne_buffer_zappend(req->headers,
467 "Connection: TE" EOL
468 "TE: trailers" EOL);
469 }
470
471 }
472
ne_accept_always(void * userdata,ne_request * req,const ne_status * st)473 int ne_accept_always(void *userdata, ne_request *req, const ne_status *st)
474 {
475 return 1;
476 }
477
ne_accept_2xx(void * userdata,ne_request * req,const ne_status * st)478 int ne_accept_2xx(void *userdata, ne_request *req, const ne_status *st)
479 {
480 return (st->klass == 2);
481 }
482
483 /* Handler for the "Transfer-Encoding" response header: treat *any*
484 * such header as implying a chunked response, per the "Protocol
485 * Compliance" statement in the manual. */
te_hdr_handler(void * userdata,const char * value)486 static void te_hdr_handler(void *userdata, const char *value)
487 {
488 struct ne_response *resp = userdata;
489
490 resp->mode = R_CHUNKED;
491 }
492
493 /* Handler for the "Connection" response header */
connection_hdr_handler(void * userdata,const char * value)494 static void connection_hdr_handler(void *userdata, const char *value)
495 {
496 ne_request *req = userdata;
497 if (strcasecmp(value, "close") == 0) {
498 req->can_persist = 0;
499 } else if (strcasecmp(value, "Keep-Alive") == 0) {
500 req->can_persist = 1;
501 }
502 }
503
clength_hdr_handler(void * userdata,const char * value)504 static void clength_hdr_handler(void *userdata, const char *value)
505 {
506 struct ne_response *resp = userdata;
507 size_t len = strtoul(value, NULL, 10);
508 if (len != ULONG_MAX && resp->mode == R_TILLEOF) {
509 resp->mode = R_CLENGTH;
510 resp->length = len;
511 }
512 }
513
ne_request_create(ne_session * sess,const char * method,const char * path)514 ne_request *ne_request_create(ne_session *sess,
515 const char *method, const char *path)
516 {
517 ne_request *req = ne_calloc(sizeof *req);
518
519 NE_DEBUG(NE_DBG_HTTP, "Creating request...\n");
520
521 req->session = sess;
522 req->headers = ne_buffer_create();
523
524 /* Add in the fixed headers */
525 add_fixed_headers(req);
526
527 /* Set the standard stuff */
528 req->method = ne_strdup(method);
529 req->method_is_head = (strcmp(method, "HEAD") == 0);
530
531 /* Add in handlers for all the standard HTTP headers. */
532 ne_add_response_header_handler(req, "Content-Length",
533 clength_hdr_handler, &req->resp);
534 ne_add_response_header_handler(req, "Transfer-Encoding",
535 te_hdr_handler, &req->resp);
536 ne_add_response_header_handler(req, "Connection",
537 connection_hdr_handler, req);
538
539 /* Only use an absoluteURI here when absolutely necessary: some
540 * servers can't parse them. */
541 if (req->session->use_proxy && !req->session->use_ssl && path[0] == '/')
542 req->uri = ne_concat(req->session->scheme, "://",
543 req->session->server.hostport, path, NULL);
544 else
545 req->uri = ne_strdup(path);
546
547 {
548 struct hook *hk;
549
550 NE_DEBUG(NE_DBG_HTTP, "Running request create hooks.\n");
551
552 for (hk = sess->create_req_hooks; hk != NULL; hk = hk->next) {
553 ne_create_request_fn fn = (ne_create_request_fn)hk->fn;
554 fn(req, hk->userdata, method, req->uri);
555 }
556 }
557
558 NE_DEBUG(NE_DBG_HTTP, "Request created.\n");
559
560 return req;
561 }
562
set_body_size(ne_request * req,size_t size)563 static void set_body_size(ne_request *req, size_t size)
564 {
565 req->body_size = size;
566 ne_print_request_header(req, "Content-Length", "%" NE_FMT_SIZE_T, size);
567 }
568
ne_set_request_body_buffer(ne_request * req,const char * buffer,size_t size)569 void ne_set_request_body_buffer(ne_request *req, const char *buffer,
570 size_t size)
571 {
572 req->body.buf.buffer = buffer;
573 req->body_cb = body_string_send;
574 req->body_ud = req;
575 set_body_size(req, size);
576 }
577
ne_set_request_body_provider(ne_request * req,size_t bodysize,ne_provide_body provider,void * ud)578 void ne_set_request_body_provider(ne_request *req, size_t bodysize,
579 ne_provide_body provider, void *ud)
580 {
581 req->body_cb = provider;
582 req->body_ud = ud;
583 set_body_size(req, bodysize);
584 }
585
ne_set_request_body_fd(ne_request * req,int fd)586 int ne_set_request_body_fd(ne_request *req, int fd)
587 {
588 struct stat bodyst;
589
590 /* Get file length */
591 if (fstat(fd, &bodyst) < 0) {
592 char err[200];
593 ne_strerror(errno, err, sizeof err);
594 ne_set_error(req->session, _("Could not determine file length: %s"),
595 err);
596 NE_DEBUG(NE_DBG_HTTP, "Stat failed: %s\n", err);
597 return -1;
598 }
599 req->body.fd = fd;
600 req->body_cb = body_fd_send;
601 req->body_ud = req;
602 set_body_size(req, bodyst.st_size);
603 return 0;
604 }
605
ne_add_request_header(ne_request * req,const char * name,const char * value)606 void ne_add_request_header(ne_request *req, const char *name,
607 const char *value)
608 {
609 ne_buffer_concat(req->headers, name, ": ", value, EOL, NULL);
610 }
611
ne_print_request_header(ne_request * req,const char * name,const char * format,...)612 void ne_print_request_header(ne_request *req, const char *name,
613 const char *format, ...)
614 {
615 va_list params;
616 char buf[BUFSIZ];
617
618 va_start(params, format);
619 ne_vsnprintf(buf, sizeof buf, format, params);
620 va_end(params);
621
622 ne_buffer_concat(req->headers, name, ": ", buf, EOL, NULL);
623 }
624
625 void
ne_add_response_header_handler(ne_request * req,const char * name,ne_header_handler hdl,void * userdata)626 ne_add_response_header_handler(ne_request *req, const char *name,
627 ne_header_handler hdl, void *userdata)
628 {
629 struct header_handler *new = ne_calloc(sizeof *new);
630 unsigned int hash;
631 new->name = ne_strdup(name);
632 new->handler = hdl;
633 new->userdata = userdata;
634 hash = hash_and_lower(new->name);
635 new->next = req->header_handlers[hash];
636 req->header_handlers[hash] = new;
637 }
638
ne_add_response_header_catcher(ne_request * req,ne_header_handler hdl,void * userdata)639 void ne_add_response_header_catcher(ne_request *req,
640 ne_header_handler hdl, void *userdata)
641 {
642 struct header_handler *new = ne_calloc(sizeof *new);
643 new->handler = hdl;
644 new->userdata = userdata;
645 new->next = req->header_catchers;
646 req->header_catchers = new;
647 }
648
ne_add_response_body_reader(ne_request * req,ne_accept_response acpt,ne_block_reader rdr,void * userdata)649 void ne_add_response_body_reader(ne_request *req, ne_accept_response acpt,
650 ne_block_reader rdr, void *userdata)
651 {
652 struct body_reader *new = ne_malloc(sizeof *new);
653 new->accept_response = acpt;
654 new->handler = rdr;
655 new->userdata = userdata;
656 new->next = req->body_readers;
657 req->body_readers = new;
658 }
659
ne_request_destroy(ne_request * req)660 void ne_request_destroy(ne_request *req)
661 {
662 struct body_reader *rdr, *next_rdr;
663 struct header_handler *hdlr, *next_hdlr;
664 struct hook *hk, *next_hk;
665 int n;
666
667 ne_free(req->uri);
668 ne_free(req->method);
669
670 for (rdr = req->body_readers; rdr != NULL; rdr = next_rdr) {
671 next_rdr = rdr->next;
672 ne_free(rdr);
673 }
674
675 for (hdlr = req->header_catchers; hdlr != NULL; hdlr = next_hdlr) {
676 next_hdlr = hdlr->next;
677 ne_free(hdlr);
678 }
679
680 for (n = 0; n < HH_HASHSIZE; n++) {
681 for (hdlr = req->header_handlers[n]; hdlr != NULL;
682 hdlr = next_hdlr) {
683 next_hdlr = hdlr->next;
684 ne_free(hdlr->name);
685 ne_free(hdlr);
686 }
687 }
688
689 ne_buffer_destroy(req->headers);
690
691 NE_DEBUG(NE_DBG_HTTP, "Running destroy hooks.\n");
692 for (hk = req->session->destroy_req_hooks; hk; hk = hk->next) {
693 ne_destroy_req_fn fn = (ne_destroy_req_fn)hk->fn;
694 fn(req, hk->userdata);
695 }
696
697 for (hk = req->private; hk; hk = next_hk) {
698 next_hk = hk->next;
699 ne_free(hk);
700 }
701
702 if (req->status.reason_phrase)
703 ne_free(req->status.reason_phrase);
704
705 NE_DEBUG(NE_DBG_HTTP, "Request ends.\n");
706 ne_free(req);
707 }
708
709
710 /* Reads a block of the response into buffer, which is of size buflen.
711 * Returns number of bytes read, 0 on end-of-response, or NE_* on error.
712 * TODO?: only make one actual read() call in here...
713 */
read_response_block(ne_request * req,struct ne_response * resp,char * buffer,size_t * buflen)714 static int read_response_block(ne_request *req, struct ne_response *resp,
715 char *buffer, size_t *buflen)
716 {
717 size_t willread;
718 ssize_t readlen;
719 ne_socket *sock = req->session->socket;
720 switch (resp->mode) {
721 case R_CHUNKED:
722 /* We are doing a chunked transfer-encoding.
723 * It goes: `SIZE CRLF CHUNK CRLF SIZE CRLF CHUNK CRLF ...'
724 * ended by a `CHUNK CRLF 0 CRLF', a 0-sized chunk.
725 * The slight complication is that we have to cope with
726 * partial reads of chunks.
727 * For this reason, resp.chunk_left contains the number of
728 * bytes left to read in the current chunk.
729 */
730 if (resp->chunk_left == 0) {
731 unsigned long int chunk_len;
732 char *ptr;
733 /* We are at the start of a new chunk. */
734 NE_DEBUG(NE_DBG_HTTP, "New chunk.\n");
735 SOCK_ERR(req, ne_sock_readline(sock, buffer, *buflen),
736 _("Could not read chunk size"));
737 NE_DEBUG(NE_DBG_HTTP, "[Chunk Size] < %s", buffer);
738 chunk_len = strtoul(buffer, &ptr, 16);
739 /* limit chunk size to <= UINT_MAX, so it will probably
740 * fit in a size_t. */
741 if (ptr == buffer ||
742 chunk_len == ULONG_MAX || chunk_len > UINT_MAX) {
743 return aborted(req, _("Could not parse chunk size"), 0);
744 }
745 NE_DEBUG(NE_DBG_HTTP, "Got chunk size: %lu\n", chunk_len);
746 if (chunk_len == 0) {
747 /* Zero-size chunk == end of response. */
748 NE_DEBUG(NE_DBG_HTTP, "Zero-size chunk.\n");
749 *buflen = 0;
750 return NE_OK;
751 }
752 resp->chunk_left = chunk_len;
753 }
754 willread = resp->chunk_left;
755 break;
756 case R_CLENGTH:
757 willread = resp->left;
758 break;
759 case R_TILLEOF:
760 willread = *buflen;
761 break;
762 case R_NO_BODY:
763 default:
764 willread = 0;
765 break;
766 }
767 if (willread > *buflen) willread = *buflen;
768 else if (willread == 0) {
769 *buflen = 0;
770 return 0;
771 }
772 NE_DEBUG(NE_DBG_HTTP,
773 "Reading %" NE_FMT_SIZE_T " bytes of response body.\n", willread);
774 readlen = ne_sock_read(sock, buffer, willread);
775
776 /* EOF is only valid when response body is delimited by it.
777 * Strictly, an SSL truncation should not be treated as an EOF in
778 * any case, but SSL servers are just too buggy. */
779 if (resp->mode == R_TILLEOF &&
780 (readlen == NE_SOCK_CLOSED || readlen == NE_SOCK_TRUNC)) {
781 NE_DEBUG(NE_DBG_HTTP, "Got EOF.\n");
782 req->can_persist = 0;
783 readlen = 0;
784 } else if (readlen < 0) {
785 return aborted(req, _("Could not read response body"), readlen);
786 } else {
787 NE_DEBUG(NE_DBG_HTTP, "Got %" NE_FMT_SSIZE_T " bytes.\n", readlen);
788 }
789 /* safe to cast: readlen guaranteed to be >= 0 above */
790 *buflen = (size_t)readlen;
791 NE_DEBUG(NE_DBG_HTTPBODY,
792 "Read block (%" NE_FMT_SSIZE_T " bytes):\n[%.*s]\n",
793 readlen, (int)readlen, buffer);
794 if (resp->mode == R_CHUNKED) {
795 resp->chunk_left -= readlen;
796 if (resp->chunk_left == 0) {
797 char crlfbuf[2];
798 /* If we've read a whole chunk, read a CRLF */
799 readlen = ne_sock_fullread(sock, crlfbuf, 2);
800 if (readlen < 0)
801 return aborted(req, _("Could not read chunk delimiter"),
802 readlen);
803 else if (crlfbuf[0] != '\r' || crlfbuf[1] != '\n')
804 return aborted(req, _("Chunk delimiter was invalid"), 0);
805 }
806 } else if (resp->mode == R_CLENGTH) {
807 resp->left -= readlen;
808 }
809 return NE_OK;
810 }
811
ne_read_response_block(ne_request * req,char * buffer,size_t buflen)812 ssize_t ne_read_response_block(ne_request *req, char *buffer, size_t buflen)
813 {
814 struct body_reader *rdr;
815 size_t readlen = buflen;
816
817 if (read_response_block(req, &req->resp, buffer, &readlen))
818 return -1;
819
820 req->resp.total += readlen;
821
822 if (req->session->progress_cb) {
823 req->session->progress_cb(req->session->progress_ud, req->resp.total,
824 (req->resp.mode==R_CLENGTH)?req->resp.length:-1);
825 }
826
827 /* TODO: call the readers when this fails too. */
828 for (rdr = req->body_readers; rdr!=NULL; rdr=rdr->next) {
829 if (rdr->use) rdr->handler(rdr->userdata, buffer, readlen);
830 }
831
832 return readlen;
833 }
834
835 /* Build the request string, returning the buffer. */
build_request(ne_request * req)836 static ne_buffer *build_request(ne_request *req)
837 {
838 struct hook *hk;
839 ne_buffer *buf = ne_buffer_create();
840
841 /* Add Request-Line and Host header: */
842 ne_buffer_concat(buf, req->method, " ", req->uri, " HTTP/1.1" EOL,
843 "Host: ", req->session->server.hostport, EOL, NULL);
844
845 /* Add custom headers: */
846 ne_buffer_append(buf, req->headers->data, ne_buffer_size(req->headers));
847
848 #define E100 "Expect: 100-continue" EOL
849 if (req->use_expect100)
850 ne_buffer_append(buf, E100, strlen(E100));
851
852 NE_DEBUG(NE_DBG_HTTP, "Running pre_send hooks\n");
853 for (hk = req->session->pre_send_hooks; hk!=NULL; hk = hk->next) {
854 ne_pre_send_fn fn = (ne_pre_send_fn)hk->fn;
855 fn(req, hk->userdata, buf);
856 }
857
858 ne_buffer_append(buf, "\r\n", 2);
859 return buf;
860 }
861
862 #ifdef NE_DEBUGGING
863 #define DEBUG_DUMP_REQUEST(x) dump_request(x)
864
dump_request(const char * request)865 static void dump_request(const char *request)
866 {
867 if ((NE_DBG_HTTPPLAIN&ne_debug_mask) == NE_DBG_HTTPPLAIN) {
868 /* Display everything mode */
869 NE_DEBUG(NE_DBG_HTTP, "Sending request headers:\n%s", request);
870 } else {
871 /* Blank out the Authorization paramaters */
872 char *reqdebug = ne_strdup(request), *pnt = reqdebug;
873 while ((pnt = strstr(pnt, "Authorization: ")) != NULL) {
874 for (pnt += 15; *pnt != '\r' && *pnt != '\0'; pnt++) {
875 *pnt = 'x';
876 }
877 }
878 NE_DEBUG(NE_DBG_HTTP, "Sending request headers:\n%s", reqdebug);
879 ne_free(reqdebug);
880 }
881 }
882
883 #else
884 #define DEBUG_DUMP_REQUEST(x)
885 #endif /* DEBUGGING */
886
887 /* remove trailing EOL from 'buf', where strlen(buf) == *len. *len is
888 * adjusted in accordance with any changes made to the string to
889 * remain equal to strlen(buf). */
strip_eol(char * buf,ssize_t * len)890 static inline void strip_eol(char *buf, ssize_t *len)
891 {
892 char *pnt = &buf[*len-1];
893 while (pnt >= buf && (*pnt == '\r' || *pnt == '\n')) {
894 *pnt-- = '\0';
895 (*len)--;
896 }
897 }
898
899 /* For accurate persistent connection handling, for any write() or
900 * read() operation for a new request on an already-open connection,
901 * an EOF or RST error MUST be treated as a persistent connection
902 * timeout, and the request retried on a new connection. Once a
903 * read() operation has succeeded, any subsequent error MUST be
904 * treated as fatal. A 'retry' flag is used; retry=1 represents the
905 * first case, retry=0 the latter. */
906
907 /* RETRY_RET() crafts a function return value given the 'retry' flag,
908 * the socket error 'code', and the return value 'acode' from the
909 * aborted() function. */
910 #define RETRY_RET(retry, code, acode) \
911 ((((code) == NE_SOCK_CLOSED || (code) == NE_SOCK_RESET || \
912 (code) == NE_SOCK_TRUNC) && retry) ? NE_RETRY : (acode))
913
914 /* Read and parse response status-line into 'status'. 'retry' is non-zero
915 * if an NE_RETRY should be returned if an EOF is received. */
read_status_line(ne_request * req,ne_status * status,int retry)916 static int read_status_line(ne_request *req, ne_status *status, int retry)
917 {
918 char *buffer = req->respbuf;
919 ssize_t ret;
920
921 ret = ne_sock_readline(req->session->socket, buffer, sizeof req->respbuf);
922 if (ret <= 0) {
923 int aret = aborted(req, _("Could not read status line"), ret);
924 return RETRY_RET(retry, ret, aret);
925 }
926
927 NE_DEBUG(NE_DBG_HTTP, "[status-line] < %s", buffer);
928 strip_eol(buffer, &ret);
929
930 if (status->reason_phrase) ne_free(status->reason_phrase);
931 memset(status, 0, sizeof *status);
932
933 if (ne_parse_statusline(buffer, status))
934 return aborted(req, _("Could not parse response status line."), 0);
935
936 return 0;
937 }
938
939 /* Discard a set of message headers. */
discard_headers(ne_request * req)940 static int discard_headers(ne_request *req)
941 {
942 do {
943 SOCK_ERR(req, ne_sock_readline(req->session->socket, req->respbuf,
944 sizeof req->respbuf),
945 _("Could not read interim response headers"));
946 NE_DEBUG(NE_DBG_HTTP, "[discard] < %s", req->respbuf);
947 } while (strcmp(req->respbuf, EOL) != 0);
948 return NE_OK;
949 }
950
951 /* Send the request, and read the response Status-Line. Returns:
952 * NE_RETRY connection closed by server; persistent connection
953 * timeout
954 * NE_OK success
955 * NE_* error
956 * On NE_RETRY and NE_* responses, the connection will have been
957 * closed already.
958 */
send_request(ne_request * req,const ne_buffer * request)959 static int send_request(ne_request *req, const ne_buffer *request)
960 {
961 ne_session *sess = req->session;
962 ssize_t ret = NE_OK;
963 int sentbody = 0; /* zero until body has been sent. */
964 int retry; /* non-zero whilst the request should be retried */
965 ne_status *status = &req->status;
966
967 /* Send the Request-Line and headers */
968 NE_DEBUG(NE_DBG_HTTP, "Sending request-line and headers:\n");
969 /* Open the connection if necessary */
970 HTTP_ERR(open_connection(req));
971
972 /* Allow retry if a persistent connection has been used. */
973 retry = sess->persisted;
974
975 ret = ne_sock_fullwrite(req->session->socket, request->data,
976 ne_buffer_size(request));
977 if (ret < 0) {
978 int aret = aborted(req, _("Could not send request"), ret);
979 return RETRY_RET(retry, ret, aret);
980 }
981
982 if (!req->use_expect100 && req->body_size > 0) {
983 /* Send request body, if not using 100-continue. */
984 ret = send_request_body(req);
985 if (ret < 0) {
986 int aret = aborted(req, _("Could not send request body"), ret);
987 return RETRY_RET(sess, ret, aret);
988 }
989 }
990
991 NE_DEBUG(NE_DBG_HTTP, "Request sent; retry is %d.\n", retry);
992
993 /* Loop eating interim 1xx responses (RFC2616 says these MAY be
994 * sent by the server, even if 100-continue is not used). */
995 while ((ret = read_status_line(req, status, retry)) == NE_OK
996 && status->klass == 1) {
997 NE_DEBUG(NE_DBG_HTTP, "Interim %d response.\n", status->code);
998 retry = 0; /* successful read() => never retry now. */
999 /* Discard headers with the interim response. */
1000 if ((ret = discard_headers(req)) != NE_OK) break;
1001
1002 if (req->use_expect100 && (status->code == 100) && !sentbody) {
1003 /* Send the body after receiving the first 100 Continue */
1004 if ((ret = send_request_body(req)) != NE_OK) break;
1005 sentbody = 1;
1006 }
1007 }
1008
1009 return ret;
1010 }
1011
1012 /* Read a message header from sock into buf, which has size 'buflen'.
1013 *
1014 * Returns:
1015 * NE_RETRY: Success, read a header into buf.
1016 * NE_OK: End of headers reached.
1017 * NE_ERROR: Error (session error is set).
1018 */
read_message_header(ne_request * req,char * buf,size_t buflen)1019 static int read_message_header(ne_request *req, char *buf, size_t buflen)
1020 {
1021 ssize_t n;
1022 ne_socket *sock = req->session->socket;
1023
1024 n = ne_sock_readline(sock, buf, buflen);
1025 if (n <= 0)
1026 return aborted(req, _("Error reading response headers"), n);
1027 NE_DEBUG(NE_DBG_HTTP, "[hdr] %s", buf);
1028
1029 strip_eol(buf, &n);
1030
1031 if (n == 0) {
1032 NE_DEBUG(NE_DBG_HTTP, "End of headers.\n");
1033 return NE_OK;
1034 }
1035
1036 buf += n;
1037 buflen -= n;
1038
1039 while (buflen > 0) {
1040 char ch;
1041
1042 /* Collect any extra lines into buffer */
1043 SOCK_ERR(req, ne_sock_peek(sock, &ch, 1),
1044 _("Error reading response headers"));
1045
1046 if (ch != ' ' && ch != '\t') {
1047 /* No continuation of this header: stop reading. */
1048 return NE_RETRY;
1049 }
1050
1051 /* Otherwise, read the next line onto the end of 'buf'. */
1052 n = ne_sock_readline(sock, buf, buflen);
1053 if (n <= 0) {
1054 return aborted(req, _("Error reading response headers"), n);
1055 }
1056
1057 NE_DEBUG(NE_DBG_HTTP, "[cont] %s", buf);
1058
1059 strip_eol(buf, &n);
1060
1061 /* assert(buf[0] == ch), which implies len(buf) > 0.
1062 * Otherwise the TCP stack is lying, but we'll be paranoid.
1063 * This might be a \t, so replace it with a space to be
1064 * friendly to applications (2616 says we MAY do this). */
1065 if (n) buf[0] = ' ';
1066
1067 /* ready for the next header. */
1068 buf += n;
1069 buflen -= n;
1070 }
1071
1072 ne_set_error(req->session, _("Response header too long"));
1073 return NE_ERROR;
1074 }
1075
1076 /* Apache's default is 100, seems reasonable. */
1077 #define MAX_HEADER_FIELDS 100
1078
1079 /* Read response headers. Returns NE_* code, sets session error. */
read_response_headers(ne_request * req)1080 static int read_response_headers(ne_request *req)
1081 {
1082 char hdr[8192]; /* max header length */
1083 int ret, count = 0;
1084
1085 while ((ret = read_message_header(req, hdr, sizeof hdr)) == NE_RETRY
1086 && ++count < MAX_HEADER_FIELDS) {
1087 struct header_handler *hdl;
1088 char *pnt;
1089 unsigned int hash = 0;
1090
1091 for (hdl = req->header_catchers; hdl != NULL; hdl = hdl->next)
1092 hdl->handler(hdl->userdata, hdr);
1093
1094 /* Strip any trailing whitespace */
1095 pnt = hdr + strlen(hdr) - 1;
1096 while (pnt > hdr && (*pnt == ' ' || *pnt == '\t'))
1097 *pnt-- = '\0';
1098
1099 /* Convert the header name to lower case and hash it. */
1100 for (pnt = hdr; (*pnt != '\0' && *pnt != ':' &&
1101 *pnt != ' ' && *pnt != '\t'); pnt++) {
1102 *pnt = tolower(*pnt);
1103 hash = HH_ITERATE(hash,*pnt);
1104 }
1105
1106 /* Skip over any whitespace before the colon. */
1107 while (*pnt == ' ' || *pnt == '\t')
1108 *pnt++ = '\0';
1109
1110 /* ignore header lines which lack a ':'. */
1111 if (*pnt != ':')
1112 continue;
1113
1114 /* NUL-terminate at the colon (when no whitespace before) */
1115 *pnt++ = '\0';
1116
1117 /* Skip any whitespace after the colon... */
1118 while (*pnt == ' ' || *pnt == '\t')
1119 pnt++;
1120
1121 /* pnt now points to the header value. */
1122 NE_DEBUG(NE_DBG_HTTP, "Header Name: [%s], Value: [%s]\n", hdr, pnt);
1123
1124 /* Iterate through the header handlers */
1125 for (hdl = req->header_handlers[hash]; hdl != NULL; hdl = hdl->next) {
1126 if (strcmp(hdr, hdl->name) == 0)
1127 hdl->handler(hdl->userdata, pnt);
1128 }
1129 }
1130
1131 if (count == MAX_HEADER_FIELDS)
1132 ret = aborted(
1133 req, _("Response exceeded maximum number of header fields."), 0);
1134
1135 return ret;
1136 }
1137
lookup_host(ne_session * sess,struct host_info * info)1138 static int lookup_host(ne_session *sess, struct host_info *info)
1139 {
1140 NE_DEBUG(NE_DBG_HTTP, "Doing DNS lookup on %s...\n", info->hostname);
1141 if (sess->notify_cb)
1142 sess->notify_cb(sess->notify_ud, ne_conn_namelookup, info->hostname);
1143 info->address = ne_addr_resolve(info->hostname, 0);
1144 if (ne_addr_result(info->address)) {
1145 char buf[256];
1146 ne_set_error(sess, _("Could not resolve hostname `%s': %s"),
1147 info->hostname,
1148 ne_addr_error(info->address, buf, sizeof buf));
1149 ne_addr_destroy(info->address);
1150 info->address = NULL;
1151 return NE_LOOKUP;
1152 } else {
1153 return NE_OK;
1154 }
1155 }
1156
ne_begin_request(ne_request * req)1157 int ne_begin_request(ne_request *req)
1158 {
1159 struct body_reader *rdr;
1160 struct host_info *host;
1161 ne_buffer *data;
1162 const ne_status *const st = &req->status;
1163 int ret;
1164
1165 /* Resolve hostname if necessary. */
1166 host = req->session->use_proxy?&req->session->proxy:&req->session->server;
1167 if (host->address == NULL)
1168 HTTP_ERR(lookup_host(req->session, host));
1169
1170 req->resp.mode = R_TILLEOF;
1171
1172 /* FIXME: Determine whether to use the Expect: 100-continue header. */
1173 req->use_expect100 = (req->session->expect100_works > -1) &&
1174 (req->body_size > HTTP_EXPECT_MINSIZE) && req->session->is_http11;
1175
1176 /* Build the request string, and send it */
1177 data = build_request(req);
1178 DEBUG_DUMP_REQUEST(data->data);
1179 ret = send_request(req, data);
1180 /* Retry this once after a persistent connection timeout. */
1181 if (ret == NE_RETRY && !req->session->no_persist) {
1182 NE_DEBUG(NE_DBG_HTTP, "Persistent connection timed out, retrying.\n");
1183 ret = send_request(req, data);
1184 }
1185 ne_buffer_destroy(data);
1186 if (ret != NE_OK) return ret;
1187
1188 /* Determine whether server claims HTTP/1.1 compliance. */
1189 req->session->is_http11 = (st->major_version == 1 &&
1190 st->minor_version > 0) || st->major_version > 1;
1191
1192 /* Persistent connections supported implicitly in HTTP/1.1 */
1193 if (req->session->is_http11) req->can_persist = 1;
1194
1195 ne_set_error(req->session, "%d %s", st->code, st->reason_phrase);
1196
1197 /* Read the headers */
1198 HTTP_ERR(read_response_headers(req));
1199
1200 #ifdef NEON_SSL
1201 /* Special case for CONNECT handling: the response has no body,
1202 * and the connection can persist. */
1203 if (req->session->in_connect && st->klass == 2) {
1204 req->resp.mode = R_NO_BODY;
1205 req->can_persist = 1;
1206 }
1207 #endif
1208
1209 /* HEAD requests and 204, 205, 304 responses have no response body,
1210 * regardless of what headers are present. */
1211 if (req->method_is_head || st->code==204 || st->code==205 || st->code==304)
1212 req->resp.mode = R_NO_BODY;
1213
1214 /* Prepare for reading the response entity-body. Call each of the
1215 * body readers and ask them whether they want to accept this
1216 * response or not. */
1217 for (rdr = req->body_readers; rdr != NULL; rdr=rdr->next) {
1218 rdr->use = rdr->accept_response(rdr->userdata, req, st);
1219 }
1220
1221 req->resp.left = req->resp.length;
1222 req->resp.chunk_left = 0;
1223
1224 return NE_OK;
1225 }
1226
ne_end_request(ne_request * req)1227 int ne_end_request(ne_request *req)
1228 {
1229 struct hook *hk;
1230 int ret = NE_OK;
1231
1232 /* Read headers in chunked trailers */
1233 if (req->resp.mode == R_CHUNKED)
1234 HTTP_ERR(read_response_headers(req));
1235
1236 NE_DEBUG(NE_DBG_HTTP, "Running post_send hooks\n");
1237 for (hk = req->session->post_send_hooks;
1238 ret == NE_OK && hk != NULL; hk = hk->next) {
1239 ne_post_send_fn fn = (ne_post_send_fn)hk->fn;
1240 ret = fn(req, hk->userdata, &req->status);
1241 }
1242
1243 /* Close the connection if persistent connections are disabled or
1244 * not supported by the server. */
1245 if (req->session->no_persist || !req->can_persist)
1246 ne_close_connection(req->session);
1247 else
1248 req->session->persisted = 1;
1249
1250 return ret;
1251 }
1252
ne_request_dispatch(ne_request * req)1253 int ne_request_dispatch(ne_request *req)
1254 {
1255 int ret;
1256
1257 /* Loop sending the request:
1258 * Retry whilst authentication fails and we supply it. */
1259
1260 do {
1261 ssize_t len;
1262
1263 HTTP_ERR(ne_begin_request(req));
1264
1265 do {
1266 len = ne_read_response_block(req, req->respbuf,
1267 sizeof req->respbuf);
1268 } while (len > 0);
1269
1270 if (len < 0) {
1271 return NE_ERROR;
1272 }
1273
1274 ret = ne_end_request(req);
1275
1276 } while (ret == NE_RETRY);
1277
1278 NE_DEBUG(NE_DBG_HTTP | NE_DBG_FLUSH,
1279 "Request ends, status %d class %dxx, error line:\n%s\n",
1280 req->status.code, req->status.klass, req->session->error);
1281
1282 return ret;
1283 }
1284
ne_get_status(const ne_request * req)1285 const ne_status *ne_get_status(const ne_request *req)
1286 {
1287 return &req->status;
1288 }
1289
ne_get_session(const ne_request * req)1290 ne_session *ne_get_session(const ne_request *req)
1291 {
1292 return req->session;
1293 }
1294
1295 #ifdef NEON_SSL
1296 /* Create a CONNECT tunnel through the proxy server.
1297 * Returns HTTP_* */
proxy_tunnel(ne_session * sess)1298 static int proxy_tunnel(ne_session *sess)
1299 {
1300 /* Hack up an HTTP CONNECT request... */
1301 ne_request *req;
1302 int ret = NE_OK;
1303 char ruri[200];
1304
1305 /* Can't use server.hostport here; Request-URI must include `:port' */
1306 ne_snprintf(ruri, sizeof ruri, "%s:%u", sess->server.hostname,
1307 sess->server.port);
1308 req = ne_request_create(sess, "CONNECT", ruri);
1309
1310 sess->in_connect = 1;
1311 ret = ne_request_dispatch(req);
1312 sess->in_connect = 0;
1313
1314 sess->persisted = 0; /* don't treat this is a persistent connection. */
1315
1316 if (ret != NE_OK || !sess->connected || req->status.klass != 2) {
1317 ne_set_error
1318 (sess, _("Could not create SSL connection through proxy server"));
1319 ret = NE_ERROR;
1320 }
1321
1322 ne_request_destroy(req);
1323 return ret;
1324 }
1325 #endif
1326
1327 /* Make new TCP connection to server at 'host' of type 'name'. Note
1328 * that once a connection to a particular network address has
1329 * succeeded, that address will be used first for the next attempt to
1330 * connect. */
1331 /* TODO: an alternate implementation could always cycle through the
1332 * addresses: this could ease server load, but could hurt SSL session
1333 * caching for SSL sessions, which would increase server load. */
do_connect(ne_request * req,struct host_info * host,const char * err)1334 static int do_connect(ne_request *req, struct host_info *host, const char *err)
1335 {
1336 ne_session *const sess = req->session;
1337 int ret;
1338
1339 if ((sess->socket = ne_sock_create()) == NULL) {
1340 ne_set_error(sess, _("Could not create socket"));
1341 return NE_ERROR;
1342 }
1343
1344 if (host->current == NULL)
1345 host->current = ne_addr_first(host->address);
1346
1347 do {
1348 notify_status(sess, ne_conn_connecting, host->hostport);
1349 #ifdef NE_DEBUGGING
1350 if (ne_debug_mask & NE_DBG_HTTP) {
1351 char buf[150];
1352 NE_DEBUG(NE_DBG_HTTP, "Connecting to %s\n",
1353 ne_iaddr_print(host->current, buf, sizeof buf));
1354 }
1355 #endif
1356 ret = ne_sock_connect(sess->socket, host->current, host->port);
1357 } while (ret && /* try the next address... */
1358 (host->current = ne_addr_next(host->address)) != NULL);
1359
1360 if (ret) {
1361 ne_set_error(sess, "%s: %s", err, ne_sock_error(sess->socket));
1362 ne_sock_close(sess->socket);
1363 return NE_CONNECT;
1364 }
1365
1366 notify_status(sess, ne_conn_connected, sess->proxy.hostport);
1367
1368 if (sess->rdtimeout)
1369 ne_sock_read_timeout(sess->socket, sess->rdtimeout);
1370
1371 sess->connected = 1;
1372 /* clear persistent connection flag. */
1373 sess->persisted = 0;
1374 return NE_OK;
1375 }
1376
open_connection(ne_request * req)1377 static int open_connection(ne_request *req)
1378 {
1379 ne_session *sess = req->session;
1380 int ret;
1381
1382 if (sess->connected) return NE_OK;
1383
1384 if (!sess->use_proxy)
1385 ret = do_connect(req, &sess->server, _("Could not connect to server"));
1386 else
1387 ret = do_connect(req, &sess->proxy,
1388 _("Could not connect to proxy server"));
1389
1390 if (ret != NE_OK) return ret;
1391
1392 #ifdef NEON_SSL
1393 /* Negotiate SSL layer if required. */
1394 if (sess->use_ssl && !sess->in_connect) {
1395 /* CONNECT tunnel */
1396 if (req->session->use_proxy)
1397 ret = proxy_tunnel(sess);
1398
1399 if (ret == NE_OK)
1400 ret = ne_negotiate_ssl(req);
1401
1402 /* This is probably only really needed for ne_negotiate_ssl
1403 * failures as proxy_tunnel will fail via aborted(). */
1404 if (ret != NE_OK)
1405 ne_close_connection(sess);
1406 }
1407 #endif
1408
1409 return ret;
1410 }
1411