458 Commits

Author SHA1 Message Date
Azat Khuzhin
4a53c54bf7 http: get fd from be layer during connection reset
Since it can be non -1, and we must close it, otherwise we will have problems.

And after this patch the following tests report fd 2307 instead of 2309 fd leaks:
$ valgrind --leak-check=full --show-reachable=yes --track-fds=yes --error-exitcode=1 regress --no-fork http/cancel..
==10853== FILE DESCRIPTORS: 2307 open at exit.
2016-03-23 12:53:03 +03:00
Azat Khuzhin
d4054928c7 http: make fallback for EVHTTP_CON_READ_ON_WRITE_ERROR more cleaner 2016-03-11 20:59:58 +03:00
Azat Khuzhin
2ff164abac http: fix EVHTTP_CON_READ_ON_WRITE_ERROR when it doesn't supported by OS
For example win32 doesn't accept such things (maybe via overloaded IO, I'm not
sure), also I looked into curl and seems that the behaviour is the same (IOW
like with EVHTTP_CON_READ_ON_WRITE_ERROR on linux/win32).

Fixes: https://ci.appveyor.com/project/nmathewson/libevent/build/2.1.5.216#L499 (win32)
Fixes: 680742e1665b85487f10c0ef3df021e3b8e98634 ("http: read server response
even after server closed the connection")
v2: v0 was just removing that flag, i.e. make it deprecated and set_flags() will return -1
2016-03-11 20:59:58 +03:00
Azat Khuzhin
7c8999956f http: do not do function calls under EVUTIL_ASSERT() to fix NDEBUG builds
Fixes: 2185e639210f072f37e9d19aff7dba382db84529 ("http: assert's that
evbuffer_drain() success on connection reset")
Fixes: http/data_length_constraints
  FAIL ../test/regress_http.c:3775: assert(evhttp_request_get_response_code(req) == HTTP_ENTITYTOOLARGE): 501 vs 413
2016-03-11 20:59:58 +03:00
Azat Khuzhin
8f18a626e6 http: fix leaking of response_code_line
Since now evhttp_parse_response_line() can be called twice because after
"HTTP/1.1 100 Continue" we can have "HTTP/1.1 200"

==29162== 9 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29162==    at 0x4C29C0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29162==    by 0x5CBF0A9: strdup (in /lib/x86_64-linux-gnu/libc-2.21.so)
==29162==    by 0x4AA3AC: event_mm_strdup_ (event.c:3493)
==29162==    by 0x4BD843: evhttp_parse_response_line (http.c:1680)
==29162==    by 0x4BE333: evhttp_parse_firstline_ (http.c:2013)
==29162==    by 0x4BEA4F: evhttp_read_firstline (http.c:2243)
==29162==    by 0x4BC5F8: evhttp_read_cb (http.c:1136)
==29162==    by 0x4993F1: bufferevent_run_readcb_ (bufferevent.c:233)
==29162==    by 0x49FBC0: bufferevent_trigger_nolock_ (bufferevent-internal.h:392)
==29162==    by 0x49FF10: bufferevent_readcb (bufferevent_sock.c:208)
==29162==    by 0x4A474A: event_persist_closure (event.c:1580)
==29162==    by 0x4A49F5: event_process_active_single_queue (event.c:1639)

Fixes: 0b46b39e95ad77951176f09782138305ba34edf3 ("http: fix "Expect:
100-continue" client side")
2016-03-11 20:59:12 +03:00
Azat Khuzhin
0b46b39e95 http: fix "Expect: 100-continue" client side
Instead of sending data always at the beginning of the request wait until the
server will respond with "HTTP/1.1 100 Continue".
Before this patch server do send "HTTP/1.1 100 Continue" but client always send
post data even without waiting server response.

P.S. this patch also touches some not 100% related tab-align issues.

Covered-by: http/data_length_constraints
Covered-by: http/read_on_write_error
2016-03-11 20:58:46 +03:00
Azat Khuzhin
2185e63921 http: assert's that evbuffer_drain() success on connection reset
Since otherwise we can have nasty bugs with part of previous *request* in
current *request* and hence some parsing errors.

And now we have failures:
  http/non_lingering_close: [forking] [err] ../http.c:1326: Assertion !evbuffer_drain(tmp, -1) failed in ../http.c
2016-03-11 18:53:10 +03:00
Azat Khuzhin
ac448a74d0 http: take EVHTTP_CON_LINGERING_CLOSE into account for "Expect: 100-Continue"
Also since after this patch code became more generic, we now respond with
HTTP_ENTITYTOOLARGE even without "Expect: 100-Continue", which is correct by
RFC.

Refs: #321
v2: remove EVHTTP_CON_ABOUT_TO_CLOSE
2016-03-09 18:52:52 +03:00
Azat Khuzhin
9fde5189df http: lingering close (like nginx have) for entity-too-large
By lingering close I mean something what nginx have for this name, by this term
I mean that we need to read all the body even if it's size greater then
`max_body_size`, otherwise browsers on win32 (including chrome) failed read the
http status - entity-too-large (while on linux chrome for instance are good),
and also this includes badly written http clients.

Refs: #321

v2: do this only under EVHTTP_SERVER_LINGERING_CLOSE
2016-03-09 18:52:07 +03:00
Azat Khuzhin
680742e166 http: read server response even after server closed the connection
Otherwise if we will try to write more data than server can accept
(see `evhttp_set_max_body_size()` for libevent server) we will get `EPIPE` and
will not try to read server's response which must contain 400 error for now
(which is not strictly correct though, it must 413).
```
  $ strace regress --no-fork http/data_length_constraints
  ...
  connect(10, {sa_family=AF_INET, sin_port=htons(43988), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
  ...
  writev(10, [{"POST / HTTP/1.1\r\nHost: somehost\r"..., 60}, {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 16324}], 2) = 16384
  epoll_wait(5, [{EPOLLOUT, {u32=10, u64=10}}, {EPOLLIN, {u32=11, u64=11}}], 32, 50000) = 2
  writev(10, [{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 16384}], 1) = 16384
  ioctl(11, FIONREAD, [32768])            = 0
  readv(11, [{"POST / HTTP/1.1\r\nHost: somehost\r"..., 4096}], 1) = 4096
  epoll_ctl(5, EPOLL_CTL_DEL, 11, 0x7fff09d41e50) = 0
  epoll_ctl(5, EPOLL_CTL_ADD, 11, {EPOLLOUT, {u32=11, u64=11}}) = 0
  epoll_wait(5, [{EPOLLOUT, {u32=10, u64=10}}, {EPOLLOUT, {u32=11, u64=11}}], 32, 50000) = 2
  writev(10, [{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 16384}], 1) = 16384
  writev(11, [{"HTTP/1.1 400 Bad Request\r\nConten"..., 129}, {"<HTML><HEAD>\n<TITLE>400 Bad Requ"..., 94}], 2) = 223
  epoll_ctl(5, EPOLL_CTL_DEL, 11, 0x7fff09d42080) = 0
  shutdown(11, SHUT_WR)                   = 0
  close(11)                               = 0
  epoll_wait(5, [{EPOLLOUT|EPOLLERR|EPOLLHUP, {u32=10, u64=10}}], 32, 50000) = 1
  writev(10, [{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 16384}], 1) = -1 EPIPE (Broken pipe)
  --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=13954, si_uid=1000} ---
  epoll_ctl(5, EPOLL_CTL_DEL, 10, 0x7fff09d42010) = 0
  shutdown(10, SHUT_WR)                   = -1 ENOTCONN (Transport endpoint is not connected)
  close(10)                               = 0
  write(1, "\n  FAIL ../test/regress_http.c:3"..., 37
```
Careful reader can ask why it send error even when it didn't read
`evcon->max_body_size`, and the answer will be checks for `evcon->max_body_size
against `Content-Length` header, which contains ~8MB (-2 bytes).

And also if we will not drain the output buffer than we will send buffer that
we didn't send in previous request and instead of sending method via
`evhttp_make_header()`.

Fixes: http/data_length_constraints
Refs: #321

v2: do this only under EVHTTP_CON_READ_ON_WRITE_ERROR flag
2016-03-09 01:12:50 +03:00
Azat Khuzhin
4dc09795c0 http: fix conflicts EVHTTP_CON_AUTOFREE and EVHTTP_CON_REUSE_CONNECTED_ADDR
And we can't make them continuous, since the latest is a public API, and
otherwise we will break binary compatibility.
Also extra check for EVHTTP_CON_PUBLIC_FLAGS_END, in case somebody forgot about
this (implementer I mean).

Refs: #182
2016-02-24 14:22:31 +03:00
Azat Khuzhin
365f181aa3 http: coding style issue 2016-02-24 14:22:27 +03:00
Azat Khuzhin
ab3bc69f47 http: avoid epoll_ctl() on already closed fd (triggers by http/chunk_out)
Before:
$ strace -eepoll_ctl,close regress --verbose --no-fork +http/chunk_out
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
http/chunk_out: epoll_ctl(5, EPOLL_CTL_ADD, 8, {EPOLLIN, {u32=8, u64=8}}) = 0
close(10)                               = 0
close(9)                                = 0
epoll_ctl(5, EPOLL_CTL_ADD, 9, {EPOLLIN, {u32=9, u64=9}}) = 0
epoll_ctl(5, EPOLL_CTL_ADD, 10, {EPOLLOUT, {u32=10, u64=10}}) = 0
epoll_ctl(5, EPOLL_CTL_ADD, 11, {EPOLLIN, {u32=11, u64=11}}) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 10, 7ffffb10b870) = 0
epoll_ctl(5, EPOLL_CTL_ADD, 10, {EPOLLIN, {u32=10, u64=10}}) = 0
close(12)                               = 0
epoll_ctl(5, EPOLL_CTL_MOD, 11, {EPOLLIN|EPOLLOUT, {u32=11, u64=11}}) = 0
epoll_ctl(5, EPOLL_CTL_MOD, 11, {EPOLLIN, {u32=11, u64=11}}) = 0
close(11)                               = 0
epoll_ctl(5, EPOLL_CTL_DEL, 11, 7ffffb10b770) = -1 EBADF (Bad file descriptor)
...

And trace for latest:
close(11)                               = 0
 > regress(evutil_closesocket+0x15) [0xadac4]
 > regress(evhttp_connection_free+0x19d) [0xbada2]
 > regress(evhttp_send_done+0x14d) [0xbde43]
 > regress(evhttp_write_cb+0x4a) [0xba1a1]
 > regress(bufferevent_run_writecb_+0xa2) [0x97bba]
 > regress(bufferevent_trigger_nolock_+0xb1) [0x9e330]
 > regress(bufferevent_writecb+0x2a3) [0x9e91a]
 > regress(event_persist_closure+0x2bb) [0xa2e09]
 > regress(event_process_active_single_queue+0x2a8) [0xa30b4]
 > regress(event_process_active+0x13f) [0xa3696]
 > regress(event_base_loop+0x2ab) [0xa3d97]
 > regress(event_base_dispatch+0x1d) [0xa371e]
 > regress(http_chunk_out_test_impl+0x132) [0x74940]
epoll_ctl(5, EPOLL_CTL_DEL, 11, 7fff09439fe0) = -1 EBADF (Bad file descriptor)
 > regress(epoll_ctl+0x36) [0xb49a3]
 > regress(epoll_apply_one_change+0x14e) [0xb4cd4]
 > regress(epoll_nochangelist_del+0x87) [0xb51e4]
 > regress(evmap_io_del_+0x247) [0xaab04]
 > regress(event_del_nolock_+0x2f7) [0xa6aa8]
 > regress(event_callback_cancel_nolock_+0x6e) [0xa747e]
 > regress(event_callback_finalize_many_+0xeb) [0xa4dd6]
 > regress(bufferevent_decref_and_unlock_+0x21d) [0x98da7]
 > regress(bufferevent_writecb+0x312) [0x9e989]
 > regress(event_persist_closure+0x2bb) [0xa2e09]
 > regress(event_process_active_single_queue+0x2a8) [0xa30b4]
 > regress(event_process_active+0x13f) [0xa3696]
 > regress(event_base_loop+0x2ab) [0xa3d97]
 > regress(event_base_dispatch+0x1d) [0xa371e]
 > regress(http_chunk_out_test_impl+0x132) [0x74940]
 ...
2015-11-20 01:51:39 +03:00
Azat Khuzhin
040000d7a7 http: install timeout for read too during connect for ssl
Since during ssl handshake we can read too, and if something nasty will happens
during this handshake (because of too many events in the loop of something like
this) we can wait forever since there is no read timeout:
  (gdb) p *$2.task.connection.bufev
  $11 = {
    ...
    be_ops = 0x7f78c2864b00 <bufferevent_ops_openssl>,
    ev_read = {
      ...
      ev_ = {
        ev_io = {
          ...
          ev_timeout = { tv_sec = 0, tv_usec = 0 }
        },
        ev_signal = { ... }
      },
      ev_events = 82, ev_res = 2,
      ev_timeout = { tv_sec = 10889976, tv_usec = 418753 }
    },
    ev_write = {
      ...
      ev_ = {
        ev_io = {
          ...
          ev_timeout = { tv_sec = 20, tv_usec = 0 }
        },
        ev_signal = { ... }
      },
      ev_events = 84, ev_res = 4,
      ev_timeout = { tv_sec = 10889977, tv_usec = 598753 }
    },
    ...
    errorcb = 0x7f78c287de70 <evhttp_connection_cb>,
    ...
    timeout_read = { tv_sec = 0, tv_usec = 0 },
    timeout_write = { tv_sec = 20, tv_usec = 0 },
    enabled = 4
  }
  (gdb) bt
  #0  0x00007f78c17c3633 in __epoll_wait_nocancel () at syscall-template.S:81
  #1  0x00007f78c2aaf508 in epoll_dispatch (base=0x18f76d0, tv=<optimized out>) at epoll.c:463
  ...

Found-with: massive crawling
Tested-with: massive crawling
2015-11-18 15:42:22 +03:00
Ed Schouten
c1404b5651 Include <sys/ioctl.h>, <sys/resource.h> and <sys/wait.h> optionally.
Though CloudABI implements a very large part of POSIX, it does not
provide these header files, for the reason that there is no raw device
access, no resource limiting and no access to the global process table
through wait().

It looks like these header files are not actually needed in theory.
There don't seem to be any constructs in these source files that use
these features, but I suspect they might still be required on some
systems.
2015-09-10 12:14:27 +03:00
Azat Khuzhin
b0d3964ff5 http: fix evhttp_request_own() by checking EVHTTP_USER_OWNED in more cases
Suggested-by: @ellzey
Fixes: http/request_own
Fixes: #68
2015-09-09 19:31:12 +03:00
Azat Khuzhin
7ed02ac129 http: fix detecting EOF without write
Before this patch http server don't knows when client disconnected until it
will try to write to it, IOW to detect is client still alive you need to write
something to client socket, however it is not convenient since it requires to
store all clients somewhere and poll them periodically, and I don't see any
regressions if we will leave EV_READ always (like libevhtp do), since we
already reset read callback in evhttp_write_buffer() (see
http/write_during_read).

Also since we don't disable EV_READ anymore we don't need some enable EV_READ,
so we will reduce number of epoll_ctl() calls.

Covered-by: http/terminate_chunked_oneshot
Covered-by: http/write_during_read
Fixes: #78
2015-09-09 18:06:42 +03:00
Azat Khuzhin
dfad1a460a http: eliminate warning about "socklen" in evhttp_connection_connect_() 2015-08-19 23:00:49 +03:00
Azat Khuzhin
a50f5f0ac0 http: reuse connected address only with EVHTTP_CON_REUSE_CONNECTED_ADDR 2015-08-18 20:06:53 +03:00
Azat Khuzhin
54c887d823 http: use IP address that we got before (if any) during retrying
Before this patch every time we are retrying our request we resolve
domain, but we could optimize this (since UDP is slow) by using cached
conn_address value, so do this.
2015-08-18 20:06:52 +03:00
Azat Khuzhin
8bb3842552 bufferevent: move conn_address out from http into bufferevent
In http the only case when when we could store it is when we already
connected, *but* if we are doing request using domain name, then we need
to do request to nameserver to get IP address, and this is handled by
bufferevent.
So when we have IP address (from nameserver) and don't have connection
to this IP address, we could already cache it to avoid extra DNS
requests (since UDP is slow), and we can't do this from http layer, only
from bufferevent.
2015-08-18 20:06:52 +03:00
Azat Khuzhin
22061ac1e9 http: introduce evhttp_request_free_() helper 2015-08-18 11:58:13 +03:00
Azat Khuzhin
6540da3893 http: introduce evhttp_is_request_connection_close() helper 2015-08-18 11:57:54 +03:00
Mark Ellzey
bdeec440f1 Merge pull request #190 from JohnOhl/evhttp-post-fix
evhttp: Fix failure to send all output data for POST/PUT requests
2015-06-17 08:24:52 -07:00
Nick Mathewson
7fd4941465 Merge remote-tracking branch 'origin/pr/182' 2014-11-30 19:26:20 -05:00
John Ohl
24eea0da97 evhttp: Fix failure to send all output data for POST/PUT requests 2014-11-24 02:32:23 -05:00
John Ohl
10fe4ef300 Prevent duplicate event_del on fd 2014-11-16 23:40:16 -05:00
John Ohl
2b9ec4c13c Implement interface that provides the ability to have an outbound evhttp_connection free itself once all requests have completed 2014-10-26 01:25:28 -04:00
Azat Khuzhin
bc79cc5c80 http: reset connection before installing retry timer (fix http retries handling)
This will fix some invalid read/write:
==556== Invalid read of size 8
==556==    at 0x4E4EEC6: event_queue_remove_timeout (minheap-internal.h:178)
==556==    by 0x4E508AA: event_del_nolock_ (event.c:2764)
==556==    by 0x4E53535: event_base_loop (event.c:3088)
==556==    by 0x406FCFA: dispatch (libcrawl.c:271)
==556==    by 0x402863: main (crawler.c:49)
==556==  Address 0x68a3f18 is 152 bytes inside a block of size 400 free'd
==556==    at 0x4C29C97: free (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==556==    by 0x406F140: renew (libcrawl.c:625)
==556==    by 0x4E6CDE9: evhttp_connection_cb_cleanup (http.c:1331)
==556==    by 0x4E6E2B2: evhttp_connection_cb (http.c:1424)
==556==    by 0x4E4DF2D: bufferevent_writecb (bufferevent_sock.c:310)
==556==    by 0x4E52D1D: event_process_active_single_queue (event.c:1584)
==556==    by 0x4E53676: event_base_loop (event.c:1676)
==556==    by 0x406FCFA: dispatch (libcrawl.c:271)
==556==    by 0x402863: main (crawler.c:49)
But this one because of some invalid write before (I guess).

It is 100% reproduced during massive crawling (because this process
has many different servers), but after spending some time for trying to
reproduce this using some simple tests/utils I gave up for a few days (I
have a lot of work to do), but I'm sending this patch as a reminder.

Just in case, I've tried next tests:
- mixing timeouts/retries
- shutdown http server and return it back
- slow dns server for first request
- sleep before accept
- hacking libevent sources to change the behaviour of http layer (so it
  will go into that function which I'm insterested in).
2014-09-30 18:48:15 +04:00
Nick Mathewson
73615a3723 Merge pull request #118 from azat/http-forward-family-to-bufferevent
Add evhttp_connection_set_family() to set addrinfo->family for DNS requests
2014-09-18 11:31:52 -04:00
Azat Khuzhin
12c29b0f6e Add evhttp_connection_set_family() to set addrinfo->family for DNS requests
This is useful if you want to avoid extra dns requests.
2014-03-21 17:32:09 +04:00
Nick Mathewson
e660db6d5f Catch over-large port numbers early in http
Otherwise integer overflow potentially turns the port number into garbage.
2014-03-18 11:39:23 -04:00
Andrew Sweeney
da86dda951 evhttp_request_set_on_complete_cb to be more specific about what the function actually does and usage 2014-01-06 20:36:31 -05:00
Andrew Sweeney
b083ca0551 Provide on request complete callback facility
This patch provides the ability to receive a callback on the completion of a
request.  The callback takes place immediately before the request's resources
are released.
2014-01-05 20:35:46 -05:00
Balint Reczey
b0bd7fe1db Allow registering callback for parsing HTTP headers
Slightly changed version of Espen Jürgensen's
commit 548141e72312126fa6121f6a5f436đ251c7fb1251 for forked-daapd.
2013-11-18 18:24:15 +01:00
Julien BLACHE
8d8decf114 Add a variant of evhttp_send_reply_chunk() with a callback on evhttp_write_buffer()
evhttp_write_buffer() used by evhttp_send_reply_chunk() can take callback
executed when (part of) the buffer has been written. Using this callback to
schedule the next chunk avoids buffering large amounts of data in memory.
2013-11-18 15:39:47 +01:00
Azat Khuzhin
0c7f0405e3 http: implement new evhttp_connection_get_addr() api.
Basically tcp final handshake looks like this:
    (C - client, S - server)
    ACK[C] - FIN/ACK[S] - FIN/ACK[S] - ACK [C]

However there are servers, that didn't close connection like this,
while it is still _considered_ as valid, and using libevent http layer
we can do requests to such servers.

Modified handshake:
    (C - client, S - server)
    ACK[C] - RST/ACK[S] - RST/ACK[S]

And in this case we can't extract IP address from socket, because it is
already closed, and getpeername() will return: "transport endpoint is not connected".
So we need to store address that we are connecting to, after we know it,
and that is what this patch do.

I have reproduced it, however it have some extra packages.
(I will try to fix it)
https://github.com/azat/nfq-examples/blob/master/nfqnl_rst_fin.c
2013-10-14 11:22:29 -04:00
Nick Mathewson
4464bd2396 Tweak indentation 2013-10-10 16:10:50 -04:00
Nicolas Martyanoff
5a5acd9a70 add a http default content type option 2013-09-30 18:11:26 +02:00
Nick Mathewson
b04d13cd72 Merge remote-tracking branch 'origin/patches-2.0' 2013-09-09 12:06:53 -04:00
Nate Rosenblum
5eb178855a Avoid racy bufferevent activation
The evhttp_send_reply method invokes evhttp_write_buffer with a
callback that may release the underlying request object and
bufferevent upon completion. This cleanup callback is invoked by the
underlying bufferevent's write callback. Improperly enabling write
events before referencing the bufferevent could lead to use after free
and memory corruption.
2013-09-09 11:59:00 -04:00
Nick Mathewson
f22049e359 Fix an unlikely but possible error case for http connections
Found by coverity
2013-08-06 19:17:08 -04:00
Maxime Henrion
a7f82a314f Add evhttp_connection_get_server(). 2013-07-31 21:55:13 -04:00
Maxime Henrion
31db8a02bd Fix a double close() bug in evhttp when the underlying bufferevent uses BEV_OPT_CLOSE_ON_FREE. 2013-05-24 11:04:11 -04:00
Azat Khuzhin
7b077194cc Add new error_cb for actual reporting of HTTP request errors.
It is useful to know why you callback called with NULL (i.e. it failed),
for example if you set max_body with evhttp_connection_set_max_body_size()
you must know that it failed because of body was longer than this size.

 (Commit message tweaked by Nick)
2013-04-25 15:11:44 -04:00
Azat Khuzhin
de8101a884 Move prototype of evhttp_decode_uri_internal() to http-internal.h
Make it non static, that can be called from tests
2013-03-01 12:00:24 +04:00
Azat Khuzhin
e1903e3ace uri decode: changed the test for the existence of the next character
Fix for 64b6eceaba1a4

More info here
64b6eceaba (commitcomment-2714685)
2013-02-28 23:10:02 +04:00
Azat Khuzhin
64b6eceaba uri decode: fix for warning "use of uninitialised value"
This patch add check in evhttp_decode_uri_internal() that next 2 symbols
are exists in array of chars for decoding, if don't have two next 2
symbols don't try to decode '%FF'
2013-02-28 17:19:44 +04:00
Nick Mathewson
9709461457 Merge remote-tracking branch 'origin/patches-2.0' 2013-02-14 14:13:11 -05:00
Greg Hazel
b618204216 fix #73 and fix http_connection_fail_test to catch it 2013-02-14 09:54:56 -08:00