summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-02-17 20:08:16 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-02-17 20:08:16 -0800
commitc27e986b91fe7db72ae87f731be84fec0e9fab53 (patch)
tree9f500b44c2641c997526b1fd659473f3d9951b85 /ffi.c
parent42e6aaefb83fafc5338c892006f8189937b0667e (diff)
downloadtxr-c27e986b91fe7db72ae87f731be84fec0e9fab53.tar.gz
txr-c27e986b91fe7db72ae87f731be84fec0e9fab53.tar.bz2
txr-c27e986b91fe7db72ae87f731be84fec0e9fab53.zip
ffi: move socket stuff to socket module.
* alloca.h (zalloca): Macro moved here from ffi.c; it's useful to any code that wants to do a zero-filled alloca, and socket.c needs it now. * ffi.c (HAVE_SOCKETS): All includes conditional on HAVE_SOCKETS removed. (zalloca): Macro removed; moved to alloca.h. (ffi_type_struct_checked, ffi_type_lookup): Static functions changed to external linkage. (ffi_type_size, ffi_type_put, ffi_type_get): New functions, used by external module that has incomplete definition of struct txr_ffi_type. (type_by_size): New static array, moved out of ffi_init_extra_types function. (ffi_type_by_size): New function. (ffi_init_extra_types): type_by_size array relocated to file scope. (sock_opt, sock_set_opt): Moved to socket.c, and adjusted to use newly developed external access to needed ffi mechanisms. (ffi_init): Numerous definitions related to sockets removed; these go to socket.c. * ffi.h (struct txr_ffi_type): Declared here now as incomplete type. (ffi_type_struct_checked, ffi_type_size, ffi_type_put, ffi_type_get, ffi_type_lookup, ffi_type_by_size): Declared. * lib.c (init): Call new function sock_init. * socket.c (sock_opt, sock_set_opt): New functions, moved from ffi.c, and slightly adapted to work with external interfaces exposed by ffi.c. (sock_init): New function. This performs unconditional initializations not keyed to the lazy loading lisplib.c mechanism. Here we create the socklen-t FFI type. FFI types lookup doesn't trigger lazy loading, so we do it this way; the alternative would be to introduce lazy load triggering to FFI type lookup, just for this one type. (sock_load_init): All the socket function and variable registrations move here from ffi_init.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c132
1 files changed, 24 insertions, 108 deletions
diff --git a/ffi.c b/ffi.c
index 63fdf45a..8be380b6 100644
--- a/ffi.c
+++ b/ffi.c
@@ -44,11 +44,6 @@
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-#if HAVE_SOCKETS
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#endif
#if HAVE_MMAP
#include <sys/mman.h>
#include <unistd.h>
@@ -75,8 +70,6 @@
#include "ffi.h"
#include "txr.h"
-#define zalloca(size) memset(alloca(size), 0, size)
-
#define alignof(type) offsetof(struct {char x; type y;}, y)
#define pad_retval(size) (!(size) || convert(size_t, size) > sizeof (ffi_arg) \
@@ -239,7 +232,7 @@ static struct txr_ffi_type *ffi_type_struct(val obj)
return coerce(struct txr_ffi_type *, obj->co.handle);
}
-static struct txr_ffi_type *ffi_type_struct_checked(val self, val obj)
+struct txr_ffi_type *ffi_type_struct_checked(val self, val obj)
{
return coerce(struct txr_ffi_type *, cobj_handle(self, obj, ffi_type_cls));
}
@@ -359,6 +352,21 @@ static struct cobj_ops ffi_type_enum_ops =
ffi_enum_type_mark,
cobj_eq_hash_op);
+cnum ffi_type_size(struct txr_ffi_type *tft)
+{
+ return tft->size;
+}
+
+void ffi_type_put(struct txr_ffi_type *tft, val obj, mem_t *dst, val self)
+{
+ tft->put(tft, obj, dst, self);
+}
+
+val ffi_type_get(struct txr_ffi_type *tft, mem_t *src, val self)
+{
+ return tft->get(tft, src, self);
+}
+
#if HAVE_LIBFFI
struct txr_ffi_closure {
@@ -3728,7 +3736,7 @@ static val make_ffi_type_enum(val syntax, val enums,
return type_copy;
}
-static val ffi_type_lookup(val sym)
+val ffi_type_lookup(val sym)
{
return gethash(ffi_typedef_hash, sym);
}
@@ -4640,10 +4648,15 @@ static void ffi_init_types(void)
ffi_typedef(bool_s, ffi_type_compile(cons(bool_s, cons(uchar_s, nil))));
}
-static void ffi_init_extra_types(void)
+static val type_by_size[2][16];
+
+val ffi_type_by_size(int unsig, size_t size)
{
- val type_by_size[2][18] = { { 0 }, { 0 } };
+ return type_by_size[unsig][size];
+}
+static void ffi_init_extra_types(void)
+{
#if HAVE_I64
type_by_size[0][sizeof (i64_t)] = ffi_type_lookup(int64_s);
type_by_size[1][sizeof (i64_t)] = ffi_type_lookup(uint64_s);
@@ -4730,11 +4743,6 @@ static void ffi_init_extra_types(void)
type_by_size[convert(uid_t, -1) > 0][sizeof (uid_t)]);
#endif
-#if HAVE_SOCKETS
- ffi_typedef(intern(lit("socklen-t"), user_package),
- type_by_size[convert(socklen_t, -1) > 0][sizeof (socklen_t)]);
-#endif
-
ffi_typedef(intern(lit("longlong"), user_package),
type_by_size[0][sizeof (long long)]);
ffi_typedef(intern(lit("ulonglong"), user_package),
@@ -6698,65 +6706,6 @@ static val dyn_size(val type, val obj)
return num(tft->dynsize(tft, obj, self));
}
-#if HAVE_SOCKETS
-
-static val sock_opt(val sock, val level, val option, val type_opt)
-{
- val self = lit("sock-opt");
- val sfd = stream_fd(sock);
- int lvl = c_int(level, self);
- int opt = c_int(option, self);
- val type = default_arg(type_opt, ffi_type_lookup(int_s));
- struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
-
- if (!sfd) {
- uw_throwf(socket_error_s, lit("~a: cannot get option on ~s"),
- self, sock, nao);
- } else {
- socklen_t size = convert(socklen_t, tft->size);
- mem_t *data = coerce(mem_t *, zalloca(size));
- if (getsockopt(c_num(sfd, self), lvl, opt, data, &size) != 0)
- uw_ethrowf(socket_error_s, lit("~a failed on ~s: ~d/~s"),
- self, sock, num(errno), errno_to_str(errno), nao);
- /* TODO: Add a separate function to handle options with
- * variable-size values, for example the platform-specific
- * SO_BINDTODEVICE.
- * (Or perhaps add an optional argument following type_opt
- * specifying the requested length of the value, presumably of type
- * carray.) */
- if (size != convert(socklen_t, tft->size))
- uw_throwf(socket_error_s, lit("~a: variable-size option on ~s"),
- self, sock, nao);
- return tft->get(tft, data, self);
- }
-}
-
-static val sock_set_opt(val sock, val level, val option, val value,
- val type_opt)
-{
- val self = lit("sock-set-opt");
- val sfd = stream_fd(sock);
- int lvl = c_int(level, self);
- int opt = c_int(option, self);
- val type = default_arg(type_opt, ffi_type_lookup(int_s));
- struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
-
- if (!sfd) {
- uw_throwf(socket_error_s, lit("~a: cannot set option on ~s"),
- self, sock, nao);
- } else {
- socklen_t size = convert(socklen_t, tft->size);
- mem_t *data = coerce(mem_t *, zalloca(size));
- tft->put(tft, value, data, self);
- if (setsockopt(c_num(sfd, self), lvl, opt, data, size) != 0)
- uw_ethrowf(socket_error_s, lit("~a failed on ~s: ~d/~s"),
- self, sock, num(errno), errno_to_str(errno), nao);
- return value;
- }
-}
-
-#endif
-
void ffi_init(void)
{
prot1(&ffi_typedef_hash);
@@ -6954,39 +6903,6 @@ void ffi_init(void)
reg_fun(intern(lit("get-obj"), user_package), func_n2o(get_obj, 1));
reg_fun(intern(lit("fill-obj"), user_package), func_n3o(fill_obj, 2));
reg_fun(intern(lit("dyn-size"), system_package), func_n2(dyn_size));
-#if HAVE_SOCKETS
- reg_fun(intern(lit("sock-opt"), user_package), func_n4o(sock_opt, 3));
- reg_fun(intern(lit("sock-set-opt"), user_package), func_n5o(sock_set_opt, 4));
- reg_varl(intern(lit("sol-socket"), user_package), num_fast(SOL_SOCKET));
- reg_varl(intern(lit("ipproto-ip"), user_package), num_fast(IPPROTO_IP));
- reg_varl(intern(lit("ipproto-ipv6"), user_package), num_fast(IPPROTO_IPV6));
- reg_varl(intern(lit("ipproto-tcp"), user_package), num_fast(IPPROTO_TCP));
- reg_varl(intern(lit("ipproto-udp"), user_package), num_fast(IPPROTO_UDP));
- reg_varl(intern(lit("so-acceptconn"), user_package), num_fast(SO_ACCEPTCONN));
- reg_varl(intern(lit("so-broadcast"), user_package), num_fast(SO_BROADCAST));
- reg_varl(intern(lit("so-debug"), user_package), num_fast(SO_DEBUG));
- reg_varl(intern(lit("so-dontroute"), user_package), num_fast(SO_DONTROUTE));
- reg_varl(intern(lit("so-error"), user_package), num_fast(SO_ERROR));
- reg_varl(intern(lit("so-keepalive"), user_package), num_fast(SO_KEEPALIVE));
- reg_varl(intern(lit("so-linger"), user_package), num_fast(SO_LINGER));
- reg_varl(intern(lit("so-oobinline"), user_package), num_fast(SO_OOBINLINE));
- reg_varl(intern(lit("so-rcvbuf"), user_package), num_fast(SO_RCVBUF));
- reg_varl(intern(lit("so-rcvlowat"), user_package), num_fast(SO_RCVLOWAT));
- reg_varl(intern(lit("so-rcvtimeo"), user_package), num_fast(SO_RCVTIMEO));
- reg_varl(intern(lit("so-reuseaddr"), user_package), num_fast(SO_REUSEADDR));
- reg_varl(intern(lit("so-sndbuf"), user_package), num_fast(SO_SNDBUF));
- reg_varl(intern(lit("so-sndlowat"), user_package), num_fast(SO_SNDLOWAT));
- reg_varl(intern(lit("so-sndtimeo"), user_package), num_fast(SO_SNDTIMEO));
- reg_varl(intern(lit("so-type"), user_package), num_fast(SO_TYPE));
- reg_varl(intern(lit("ipv6-join-group"), user_package), num_fast(IPV6_JOIN_GROUP));
- reg_varl(intern(lit("ipv6-leave-group"), user_package), num_fast(IPV6_LEAVE_GROUP));
- reg_varl(intern(lit("ipv6-multicast-hops"), user_package), num_fast(IPV6_MULTICAST_HOPS));
- reg_varl(intern(lit("ipv6-multicast-if"), user_package), num_fast(IPV6_MULTICAST_IF));
- reg_varl(intern(lit("ipv6-multicast-loop"), user_package), num_fast(IPV6_MULTICAST_LOOP));
- reg_varl(intern(lit("ipv6-unicast-hops"), user_package), num_fast(IPV6_UNICAST_HOPS));
- reg_varl(intern(lit("ipv6-v6only"), user_package), num_fast(IPV6_V6ONLY));
- reg_varl(intern(lit("tcp-nodelay"), user_package), num_fast(TCP_NODELAY));
-#endif
ffi_typedef_hash = make_hash(hash_weak_none, nil);
ffi_struct_tag_hash = make_hash(hash_weak_none, nil);
ffi_init_types();