diff --git a/src/civetweb.c b/src/civetweb.c index 22aefc35..f40cf53a 100755 --- a/src/civetweb.c +++ b/src/civetweb.c @@ -4891,6 +4891,7 @@ static SOCKET conn2(struct mg_context *ctx /* may be null */, size_t ebuf_len) { union usa sa; + int ip_ver = 0; SOCKET sock = INVALID_SOCKET; memset(&sa, 0, sizeof(sa)); @@ -4931,9 +4932,11 @@ static SOCKET conn2(struct mg_context *ctx /* may be null */, if (mg_inet_pton(AF_INET, host, &sa.sin, sizeof(sa.sin))) { sa.sin.sin_port = htons((uint16_t)port); + ip_ver = 4; #ifdef USE_IPV6 } else if (mg_inet_pton(AF_INET6, host, &sa.sin6, sizeof(sa.sin6))) { sa.sin6.sin6_port = htons((uint16_t)port); + ip_ver = 6; #endif } else { mg_snprintf(NULL, @@ -4945,7 +4948,11 @@ static SOCKET conn2(struct mg_context *ctx /* may be null */, return INVALID_SOCKET; } - sock = socket(PF_INET, SOCK_STREAM, 0); + if (ip_ver == 4) { + sock = socket(PF_INET, SOCK_STREAM, 0); + } else if (ip_ver == 6) { + sock = socket(PF_INET6, SOCK_STREAM, 0); + } if (sock == INVALID_SOCKET) { mg_snprintf(NULL, @@ -4959,21 +4966,29 @@ static SOCKET conn2(struct mg_context *ctx /* may be null */, set_close_on_exec(sock, fc(ctx)); - /* TODO(mid): IPV6 */ - if (connect(sock, (struct sockaddr *)&sa.sin, sizeof(sa.sin)) != 0) { - mg_snprintf(NULL, - NULL, /* No truncation check for ebuf */ - ebuf, - ebuf_len, - "connect(%s:%d): %s", - host, - port, - strerror(ERRNO)); - closesocket(sock); - sock = INVALID_SOCKET; + if ((ip_ver == 4) && + (connect(sock, (struct sockaddr *)&sa.sin, sizeof(sa.sin)) == 0)) { + /* connected with IPv4 */ + return sock; } - return sock; + if ((ip_ver == 6) && + (connect(sock, (struct sockaddr *)&sa.sin6, sizeof(sa.sin6)) == 0)) { + /* connected with IPv6 */ + return sock; + } + + /* Not connected */ + mg_snprintf(NULL, + NULL, /* No truncation check for ebuf */ + ebuf, + ebuf_len, + "connect(%s:%d): %s", + host, + port, + strerror(ERRNO)); + closesocket(sock); + return INVALID_SOCKET; } int mg_url_encode(const char *src, char *dst, size_t dst_len) diff --git a/test/public.c b/test/public.c index 6cf0f09b..0ecd58f1 100644 --- a/test/public.c +++ b/test/public.c @@ -519,7 +519,11 @@ START_TEST(test_request_handlers) char buf[1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 8]; int i; const char *request = "GET /U7 HTTP/1.0\r\n\r\n"; - const char *HTTP_PORT = "8087"; +#ifdef USE_IPV6 + const char *HTTP_PORT = "8084,[::]:8086"; +#else + const char *HTTP_PORT = "8084"; +#endif const char *OPTIONS[8]; /* initializer list here is rejected by CI test */ const char *opt; FILE *f; @@ -595,6 +599,32 @@ START_TEST(test_request_handlers) mg_close_connection(conn); + /* Get data from callback using 127.0.0.1 */ + conn = mg_download( + "127.0.0.1", atoi(HTTP_PORT), 0, ebuf, sizeof(ebuf), "%s", request); + ck_assert(conn != NULL); + ri = mg_get_request_info(conn); + + ck_assert(ri != NULL); + ck_assert_str_eq(ri->uri, "200"); + i = mg_read(conn, buf, sizeof(buf)); + ck_assert_int_eq(i, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10); + mg_close_connection(conn); + + + /* Get data from callback using [::1] */ + conn = mg_download( + "[::1]", atoi(HTTP_PORT), 0, ebuf, sizeof(ebuf), "%s", request); + ck_assert(conn != NULL); + ri = mg_get_request_info(conn); + + ck_assert(ri != NULL); + ck_assert_str_eq(ri->uri, "200"); + i = mg_read(conn, buf, sizeof(buf)); + ck_assert_int_eq(i, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10); + mg_close_connection(conn); + + /* It seems to be impossible to find out what the actual working * directory of the CI test environment is. Before breaking another * dozen of builds by trying blindly with different paths, just @@ -684,6 +714,8 @@ START_TEST(test_request_handlers) ck_assert_str_eq(ri->uri, "401"); /* not authorized */ mg_close_connection(conn); + /* TODO: Test websockets */ + /* Close the server */ g_ctx = NULL; @@ -740,7 +772,7 @@ Suite *make_public_suite(void) return suite; } -#if 0 +#ifdef REPLACE_CHECK_FOR_LOCAL_DEBUGGING /* Used to debug test cases without using the check framework */ void main(void) { @@ -751,7 +783,11 @@ void main(void) void _ck_assert_failed(const char *file, int line, const char *expr, ...) { - fprintf(stderr, "error!\n"); + va_list va; + va_start(va, expr); + fprintf(stderr, "Error: %s, line %i\n", file, line); /* breakpoint here ! */ + vfprintf(stderr, expr, va); + va_end(va); } void _mark_point(const char *file, int line) {}