diff options
author | Steve Bennett <steveb@workware.net.au> | 2017-09-14 00:07:35 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2017-09-15 12:11:00 +1000 |
commit | 0d3a4d11d6242e482df3896f0b28ca9bbc8f538a (patch) | |
tree | f75900431844a06eeecd1a50e336be62e62b2ef4 | |
parent | e9a9ce8c9eb521f5f0d959996f1378721c586fc7 (diff) | |
download | jimtcl-0d3a4d11d6242e482df3896f0b28ca9bbc8f538a.zip jimtcl-0d3a4d11d6242e482df3896f0b28ca9bbc8f538a.tar.gz jimtcl-0d3a4d11d6242e482df3896f0b28ca9bbc8f538a.tar.bz2 |
aio: Add support for many socket options
Add aio sockopt to get and set various socket options
via setsockopt()/getsockopt()
And remove 'aio tcp_nodelay' in favour of 'aio sockopt tcp_nodelay'
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | jim-aio.c | 115 |
1 files changed, 100 insertions, 15 deletions
@@ -944,22 +944,107 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } #endif -#if defined(TCP_NODELAY) && !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) -static int aio_cmd_tcp_nodelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +#define SOCKOPT_BOOL 0 +#define SOCKOPT_INT 1 +#define SOCKOPT_TIMEVAL 2 /* not currently supported */ + +static const struct sockopt_def { + const char *name; + int level; + int opt; + int type; /* SOCKOPT_xxx */ +} sockopts[] = { +#ifdef SOL_SOCKET +#ifdef SO_BROADCAST + { "broadcast", SOL_SOCKET, SO_BROADCAST }, +#endif +#ifdef SO_DEBUG + { "debug", SOL_SOCKET, SO_DEBUG }, +#endif +#ifdef SO_KEEPALIVE + { "keepalive", SOL_SOCKET, SO_KEEPALIVE }, +#endif +#ifdef SO_NOSIGPIPE + { "nosigpipe", SOL_SOCKET, SO_NOSIGPIPE }, +#endif +#ifdef SO_OOBINLINE + { "oobinline", SOL_SOCKET, SO_OOBINLINE }, +#endif +#ifdef SO_SNDBUF + { "sndbuf", SOL_SOCKET, SO_SNDBUF, SOCKOPT_INT }, +#endif +#ifdef SO_RCVBUF + { "rcvbuf", SOL_SOCKET, SO_RCVBUF, SOCKOPT_INT }, +#endif +#if 0 && defined(SO_SNDTIMEO) + { "sndtimeo", SOL_SOCKET, SO_SNDTIMEO, SOCKOPT_TIMEVAL }, +#endif +#if 0 && defined(SO_RCVTIMEO) + { "rcvtimeo", SOL_SOCKET, SO_RCVTIMEO, SOCKOPT_TIMEVAL }, +#endif +#endif +#ifdef IPPROTO_TCP +#ifdef TCP_NODELAY + { "tcp_nodelay", IPPROTO_TCP, TCP_NODELAY }, +#endif +#endif +}; + +static int aio_cmd_sockopt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); - int on; + int i; - if (Jim_GetBoolean(interp, argv[0], &on) != JIM_OK) { - return JIM_ERR; + if (argc == 0) { + Jim_Obj *dictObjPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < sizeof(sockopts) / sizeof(*sockopts); i++) { + int value = 0; + socklen_t len = sizeof(value); + if (getsockopt(af->fd, sockopts[i].level, sockopts[i].opt, (void *)&value, &len) == 0) { + if (sockopts[i].type == SOCKOPT_BOOL) { + value = !!value; + } + Jim_ListAppendElement(interp, dictObjPtr, Jim_NewStringObj(interp, sockopts[i].name, -1)); + Jim_ListAppendElement(interp, dictObjPtr, Jim_NewIntObj(interp, value)); + } + } + Jim_SetResult(interp, dictObjPtr); + return JIM_OK; + } + if (argc == 1) { + return -1; } - setsockopt(af->fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); - return JIM_OK; + /* Set an option */ + for (i = 0; i < sizeof(sockopts) / sizeof(*sockopts); i++) { + if (strcmp(Jim_String(argv[0]), sockopts[i].name) == 0) { + int on; + if (sockopts[i].type == SOCKOPT_BOOL) { + if (Jim_GetBoolean(interp, argv[1], &on) != JIM_OK) { + return JIM_ERR; + } + } + else { + long longval; + if (Jim_GetLong(interp, argv[1], &longval) != JIM_OK) { + return JIM_ERR; + } + on = longval; + } + if (setsockopt(af->fd, sockopts[i].level, sockopts[i].opt, (void *)&on, sizeof(on)) < 0) { + Jim_SetResultFormatted(interp, "Failed to set %#s: %s", argv[0], strerror(errno)); + return JIM_ERR; + } + return JIM_OK; + } + } + /* Not found */ + Jim_SetResultFormatted(interp, "Unknown sockopt %#s", argv[0]); + return JIM_ERR; } #endif - #ifdef HAVE_FSYNC static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -1392,13 +1477,13 @@ static const jim_subcmd_type aio_command_table[] = { /* Description: Set O_NDELAY (if arg). Returns current/new setting. */ }, #endif -#if defined(TCP_NODELAY) && !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) - { "tcp_nodelay", - "boolean", - aio_cmd_tcp_nodelay, - 1, - 1, - /* Description: Set TCP_NODELAY (Nagle's algorithm) */ +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) + { "sockopt", + "?opt 0|1?", + aio_cmd_sockopt, + 0, + 2, + /* Description: Return a dictionary of sockopts, or set the value of a sockopt */ }, #endif #ifdef HAVE_FSYNC |