diff --git a/http/socket.c b/http/socket.c
index 2810973..a733470 100644
--- a/http/socket.c
+++ b/http/socket.c
@@ -11,10 +11,10 @@
* THIS SOFTWARE.
*/
#include <errno.h>
-#include <netdb.h>
-#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
#include <unistd.h>
#include <libkc3/kc3.h>
#include "socket.h"
@@ -49,65 +49,112 @@ p_socket socket_init_accept (p_socket s, p_socket listening)
return s;
}
-p_socket socket_init_listen (p_socket s, const s_str *host, u16 port)
+p_socket socket_init_connect (p_socket s, const s_str *host,
+ const s_str *service)
{
- struct sockaddr *addr;
- struct sockaddr_in *addr_inet;
- struct sockaddr_in6 *addr_inet6;
- socklen_t addr_len;
- struct sockaddr_storage addr_storage;
- sw e;
- struct hostent *hostent;
+ struct addrinfo hints = {0};
+ struct addrinfo *res;
+ struct addrinfo *res0;
+ s32 e;
+ const char *error_reason;
t_socket tmp;
assert(s);
assert(host);
- hostent = gethostbyname2(host->ptr.pchar, AF_INET);
- if (! hostent)
- hostent = gethostbyname2(host->ptr.pchar, AF_INET6);
- if (! hostent) {
- e = errno;
- err_write_1("socket_init_listen: gethostbyname2: ");
- err_puts(strerror(e));
- assert(! "socket_init_listen: gethostbyname2");
+ hints.ai_family = AF_INET;
+ e = getaddrinfo(host->ptr.pchar, service->ptr.pchar, &hints, &res0);
+ if (e) {
+ err_write_1("socket_init_connect(");
+ err_write_1(host->ptr.pchar);
+ err_write_1(", ");
+ err_write_1(service->ptr.pchar);
+ err_write_1("): getaddrinfo: ");
+ err_puts(gai_strerror(e));
+ assert(! "socket_init_connect: getaddrinfo");
return NULL;
}
- addr = (struct sockaddr *) &addr_storage;
- addr_len = hostent->h_length;
- memcpy(addr, hostent->h_addr_list[0], addr_len);
- switch (addr->sa_family) {
- case AF_INET:
- addr_inet = (struct sockaddr_in *) addr;
- addr_inet->sin_port = htons(port);
- break;
- case AF_INET6:
- addr_inet6 = (struct sockaddr_in6 *) addr;
- addr_inet6->sin6_port = htons(port);
- break;
- default:
- err_puts("socket_init_listen: unknown address family");
- assert(! "socket_init_listen: unknown address family");
- return NULL;
+ e = 0;
+ tmp = -1;
+ res = res0;
+ while (res) {
+ tmp = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
+ if (tmp < 0) {
+ e = errno;
+ error_reason = "socket_init_connect: socket: ";
+ goto next;
+ }
+ if (connect(tmp, res->ai_addr, res->ai_addrlen) < 0) {
+ e = errno;
+ error_reason = "socket_init_connect: connect: ";
+ goto next;
+ }
+ next:
+ res = res->ai_next;
}
- tmp = socket(addr->sa_family, SOCK_STREAM, 0);
if (tmp < 0) {
- e = errno;
- err_write_1("socket_init_listen: socket: ");
+ err_write_1(error_reason);
err_puts(strerror(e));
- assert(! "socket_init_listen: socket");
+ assert(! "socket_init_connect");
return NULL;
}
- if (bind(tmp, addr, addr_len) < 0) {
- e = errno;
- err_write_1("socket_init_listen: bind: ");
- err_puts(strerror(e));
- assert(! "socket_init_listen: bind");
+ *s = tmp;
+ return s;
+}
+
+p_socket socket_init_listen (p_socket s, const s_str *host,
+ const s_str *service)
+{
+ struct addrinfo hints = {0};
+ struct addrinfo *res;
+ struct addrinfo *res0;
+ s32 e;
+ const char *error_reason;
+ t_socket tmp;
+ assert(s);
+ assert(host);
+ hints.ai_family = AF_INET;
+ e = getaddrinfo(host->ptr.pchar, service->ptr.pchar, &hints, &res0);
+ if (e) {
+ err_write_1("socket_init_listen(");
+ err_write_1(host->ptr.pchar);
+ err_write_1(", ");
+ err_write_1(service->ptr.pchar);
+ err_write_1("): getaddrinfo: ");
+ err_puts(gai_strerror(e));
+ assert(! "socket_init_listen: getaddrinfo");
return NULL;
}
- if (listen(tmp, SOMAXCONN) < 0) {
- e = errno;
- err_write_1("socket_init_listen: listen: ");
+ e = 0;
+ tmp = -1;
+ res = res0;
+ while (res) {
+ tmp = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
+ if (tmp < 0) {
+ e = errno;
+ error_reason = "socket_init_listen: socket: ";
+ goto next;
+ }
+ if (setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &(int) {1},
+ sizeof(int)) < 0) {
+ error_reason = "setsockopt(SO_REUSEADDR)";
+ goto next;
+ }
+ if (bind(tmp, res->ai_addr, res->ai_addrlen) < 0) {
+ e = errno;
+ error_reason = "socket_init_listen: bind: ";
+ goto next;
+ }
+ if (listen(tmp, SOMAXCONN) < 0) {
+ e = errno;
+ error_reason = "socket_init_listen: listen: ";
+ goto next;
+ }
+ next:
+ res = res->ai_next;
+ }
+ if (tmp < 0) {
+ err_write_1(error_reason);
err_puts(strerror(e));
- assert(! "socket_init_listen: listen");
+ assert(! "socket_init_listen");
return NULL;
}
*s = tmp;
diff --git a/http/socket.h b/http/socket.h
index 26a03fc..09b7311 100644
--- a/http/socket.h
+++ b/http/socket.h
@@ -17,7 +17,8 @@
/* Stack-allocation compatible functions. */
p_socket socket_init_accept (p_socket s, p_socket listening);
-p_socket socket_init_listen (p_socket s, const s_str *host, u16 port);
+p_socket socket_init_listen (p_socket s, const s_str *host,
+ const s_str *service);
/* Operators. */
void socket_close (p_socket s);
diff --git a/lib/kc3/0.1/http.kc3 b/lib/kc3/0.1/http.kc3
deleted file mode 100644
index cfdd4b2..0000000
--- a/lib/kc3/0.1/http.kc3
+++ /dev/null
@@ -1,14 +0,0 @@
-defmodule Socket do
-
- defstruct [fd: (S32) 0]
-
- dlopen(__DIR__ + "http.so")
-
- def accept = cfn Socket "socket_init_accept" (Result, Socket)
-
- def close = cfn Void "socket_close" (Socket)
-
- # listen(host, port)
- def listen = cfn Socket "socket_init_listen" (Result, Str, U16)
-
-end
diff --git a/lib/kc3/0.1/socket.kc3 b/lib/kc3/0.1/socket.kc3
index ad3a0c2..c380af3 100644
--- a/lib/kc3/0.1/socket.kc3
+++ b/lib/kc3/0.1/socket.kc3
@@ -8,6 +8,8 @@ defmodule Socket do
def close = cfn Void "socket_close" (Socket)
- def listen = cfn Socket "socket_init_listen" (Result, Str, U16)
+ def connect = cfn Socket "socket_init_connect" (Result, Str, Str)
+
+ def listen = cfn Socket "socket_init_listen" (Result, Str, Str)
end
diff --git a/libkc3/cfn.c b/libkc3/cfn.c
index 8022e03..8205ccb 100644
--- a/libkc3/cfn.c
+++ b/libkc3/cfn.c
@@ -56,14 +56,20 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
if (cfn->cif.rtype == &ffi_type_pointer) {
/* make result point to result_pointer */
if (! tag_to_ffi_pointer(&tmp, cfn->result_type,
- (void **) &result_pointer))
+ (void **) &result_pointer)) {
+ err_puts("cfn_apply: tag_to_ffi_pointer 1");
+ assert(! "cfn_apply: tag_to_ffi_pointer 1");
return NULL;
+ }
result = &result_pointer;
}
else {
/* make result point to tmp value */
- if (! tag_to_ffi_pointer(&tmp, cfn->result_type, &result))
+ if (! tag_to_ffi_pointer(&tmp, cfn->result_type, &result)) {
+ err_puts("cfn_apply: tag_to_ffi_pointer 2");
+ assert(! "cfn_apply: tag_to_ffi_pointer 2");
return NULL;
+ }
}
if (cfn->arity) {
arg_pointers = alloc((cfn->arity + 1) * sizeof(void *));
@@ -81,22 +87,32 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
if (cfn_arg_types->tag.data.sym == &g_sym_Result) {
assert(cfn->cif.rtype == &ffi_type_pointer);
cfn_tag_init(&tmp2, cfn->result_type);
- if (! tag_to_ffi_pointer(&tmp2, cfn->result_type, arg_pointers + i))
+ if (! tag_to_ffi_pointer(&tmp2, cfn->result_type,
+ arg_pointers + i)) {
+ err_puts("cfn_apply: tag_to_ffi_pointer 3");
+ assert(! "cfn_apply: tag_to_ffi_pointer 3");
goto ko;
+ }
arg_values[i] = &arg_pointers[i];
arg_pointer_result = arg_pointers[i];
}
else {
if (cfn->cif.arg_types[i] == &ffi_type_pointer) {
if (! tag_to_ffi_pointer(&a->tag, cfn_arg_types->tag.data.sym,
- arg_pointers + i))
+ arg_pointers + i)) {
+ err_puts("cfn_apply: tag_to_ffi_pointer 4");
+ assert(! "cfn_apply: tag_to_ffi_pointer 4");
goto ko;
+ }
arg_values[i] = &arg_pointers[i];
}
else
if (! tag_to_ffi_pointer(&a->tag, cfn_arg_types->tag.data.sym,
- arg_values + i))
+ arg_values + i)) {
+ err_puts("cfn_apply: tag_to_ffi_pointer 5");
+ assert(! "cfn_apply: tag_to_ffi_pointer 5");
goto ko;
+ }
a = list_next(a);
}
cfn_arg_types = list_next(cfn_arg_types);
diff --git a/test/Makefile b/test/Makefile
index 3b81cb5..a0ee8c0 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -74,7 +74,7 @@ gdb_test_ekc3:
cd ekc3 && gdb ../../kc3s/.libs/kc3s_debug
gdb_test_http:
- cd http && gdb ../../kc3s/.libs/kc3s_debug
+ cd http && gdb ../../ikc3/.libs/ikc3_debug
lldb_test: debug
if [ -f libkc3_test_debug.core ]; then lldb .libs/libkc3_test_debug libkc3_test_debug.core; else lldb .libs/libkc3_test_debug; fi
diff --git a/test/http/.ikc3_history b/test/http/.ikc3_history
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/http/.ikc3_history
diff --git a/test/http/server.kc3 b/test/http/server.kc3
index bc658e1..4c7599a 100644
--- a/test/http/server.kc3
+++ b/test/http/server.kc3
@@ -1,2 +1,12 @@
-server = Socket.listen("localhost", 8000)
-client = Socket.accept(server)
+quote server = Socket.listen("localhost", "8000")
+server = Socket.listen("localhost", "8000")
+quote client = Socket.connect("localhost", "8000")
+client = Socket.connect("localhost", "8000")
+quote server_client = Socket.accept(server)
+server_client = Socket.accept(server)
+quote Socket.close(client)
+Socket.close(client)
+quote Socket.close(server_client)
+Socket.close(server_client)
+quote Socket.close(server)
+Socket.close(server)
diff --git a/test/http/server.out.expected b/test/http/server.out.expected
index e69de29..d7cff23 100644
--- a/test/http/server.out.expected
+++ b/test/http/server.out.expected
@@ -0,0 +1,12 @@
+server = Socket.listen("localhost", "8000")
+%Socket{fd: 4}
+client = Socket.connect("localhost", "8000")
+%Socket{fd: 5}
+server_client = Socket.accept(server)
+%Socket{fd: 6}
+Socket.close(client)
+void
+Socket.close(server_client)
+void
+Socket.close(server)
+void
diff --git a/test/http/server.ret b/test/http/server.ret
index 897bdc8..573541a 100644
--- a/test/http/server.ret
+++ b/test/http/server.ret
@@ -1 +1 @@
-139
+0
diff --git a/test/http_test b/test/http_test
index 64f0d53..2254924 100755
--- a/test/http_test
+++ b/test/http_test
@@ -29,10 +29,10 @@ test_ok() {
}
if [ $# = 0 ]; then
- if [ "x${EKC3_TEST_TARGETS}" = "x" ]; then
+ if [ "x${HTTP_TEST}" = "x" ]; then
TARGETS="$(ls -1 *.kc3 | sed -e 's/[.]kc3$//')"
else
- TARGETS="${EKC3_TEST_TARGETS}"
+ TARGETS="${HTTP_TEST}"
fi
else
TARGETS="$@"