diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-04-14 07:09:38 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-04-14 07:09:38 -0700 |
commit | 82a11e883049d6578b0301b61603e088dc89773f (patch) | |
tree | 89a15fb1317ab3880a3e2a0289f7bc529d0b816a | |
parent | b25b55d0d935a9b995e3596ec06ab6378ff931e8 (diff) | |
download | txr-82a11e883049d6578b0301b61603e088dc89773f.tar.gz txr-82a11e883049d6578b0301b61603e088dc89773f.tar.bz2 txr-82a11e883049d6578b0301b61603e088dc89773f.zip |
New open-socket-pair function.
* lisplib.c (sock_set_entries): Add open-socket-pair to
autoload list.
* socket.c (sock_mark_connected, socketpair_wrap): New static
functions.
(sock_load_init): Register open-socket-pair intrinsic.
* txr.1: Documented.
-rw-r--r-- | lisplib.c | 1 | ||||
-rw-r--r-- | socket.c | 60 | ||||
-rw-r--r-- | txr.1 | 27 |
3 files changed, 87 insertions, 1 deletions
@@ -292,6 +292,7 @@ static val sock_set_entries(val dlt, val fun) lit("ai-numericserv"), lit("str-inaddr"), lit("str-in6addr"), lit("str-inaddr-net"), lit("str-in6addr-net"), + lit("open-socket-pair"), nil }; set_dlt_entries(dlt, name, fun); @@ -763,6 +763,30 @@ static val sock_connect(val sock, val sockaddr, val timeout) uw_throwf(socket_error_s, lit("sock-connect: cannot connect ~s"), sock, nao); } +static val sock_mark_connected(val sock) +{ + val sfd = stream_fd(sock); + + if (sfd) { + val family = sock_family(sock); + struct sockaddr_storage sa = { 0 }; + socklen_t salen = sizeof sa; + + (void) getpeername(c_num(sfd), coerce(struct sockaddr *, &sa), &salen); + + sock_set_peer(sock, sockaddr_unpack(c_num(family), &sa)); + + if (sock_type(sock) == num_fast(SOCK_DGRAM)) { + struct dgram_stream *d = coerce(struct dgram_stream *, sock->co.handle); + d->sock_connected = 1; + } + + return sock; + } + + return nil; +} + static val sock_listen(val sock, val backlog) { val sfd = stream_fd(sock); @@ -980,6 +1004,40 @@ val open_socket(val family, val type, val mode_str) return open_sockfd(num(fd), family, type, mode_str); } +static val socketpair_wrap(val family, val type, val mode_str) +{ + int sv[2] = { -1, -1 }; + int res = socketpair(c_num(family), c_num(type), 0, sv); + val out = nil; + + uw_simple_catch_begin; + + if (res < 0) + uw_throwf(socket_error_s, lit("sock-pair failed: ~d/~s"), + num(errno), string_utf8(strerror(errno)), nao); + + { + val s0 = open_sockfd(num(sv[0]), family, type, mode_str); + val s1 = open_sockfd(num(sv[1]), family, type, mode_str); + + sock_mark_connected(s0); + sock_mark_connected(s1); + + out = list(s0, s1, nao); + } + + uw_unwind { + if (sv[0] != -1) + close(sv[0]); + if (sv[1] != -1) + close(sv[1]); + } + + uw_catch_end; + + return out; +} + void sock_load_init(void) { sockaddr_in_s = intern(lit("sockaddr-in"), user_package); @@ -1032,7 +1090,7 @@ void sock_load_init(void) reg_fun(intern(lit("sock-listen"), user_package), func_n2o(sock_listen, 1)); reg_fun(intern(lit("sock-accept"), user_package), func_n3o(sock_accept, 1)); reg_fun(intern(lit("sock-shutdown"), user_package), func_n2o(sock_shutdown, 1)); - + reg_fun(intern(lit("open-socket-pair"), user_package), func_n3o(socketpair_wrap, 2)); #if defined SO_SNDTIMEO && defined SO_RCVTIMEO reg_fun(intern(lit("sock-send-timeout"), user_package), func_n2(sock_send_timeout)); reg_fun(intern(lit("sock-recv-timeout"), user_package), func_n2(sock_recv_timeout)); @@ -38283,6 +38283,33 @@ mode in marks a socket as a real-time-stream, and, if it is opened for writing or reading and writing, changes it to use line buffering. +.coNP Function open-socket-pair +.synb +.mets (open-socket-pair < family < type <> [ mode-string ]) +.syne +.desc +The +.code open-socket-pair +function provides an interface to the functionality of the +.code socketpair +C library function. + +If successful, it creates and returns a list of two stream objects, +which are sockets that are connected together. + +Note: the Internet address families +.code af-inet +and +.code af-inet6 +are not supported. + +The +.code mode-string +is applied to each stream. For a description, see +.code open-socket +and +.codn open-file . + .coNP Functions @ sock-family and @ sock-type .synb .mets (sock-family << socket ) |