From aa846a75f692251355458667d28378398fd84b67 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sun, 17 Nov 2013 11:19:08 +0000 Subject: [PATCH] Buffered socket IO wrappers Organization: Straylight/Edgeware From: Richard Kettlewell Includes a nod to win32 API. --- configure.ac | 2 +- lib/Makefile.am | 1 + lib/common.h | 9 +++++ lib/socketio.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/socketio.h | 49 ++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 lib/socketio.c create mode 100644 lib/socketio.h diff --git a/configure.ac b/configure.ac index f0f8a83..c17ad1c 100644 --- a/configure.ac +++ b/configure.ac @@ -663,7 +663,7 @@ if test ! -z "$missing_functions"; then fi # Functions we can take or leave -AC_CHECK_FUNCS([fls getfsstat]) +AC_CHECK_FUNCS([fls getfsstat closesocket]) if test $want_server = yes; then # had better be version 3 or later diff --git a/lib/Makefile.am b/lib/Makefile.am index f2f15f7..c1d927c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -73,6 +73,7 @@ libdisorder_a_SOURCES=charset.c charsetf.c charset.h \ sendmail.c sendmail.h \ signame.c signame.h \ sink.c sink.h \ + socketio.c socketio.h \ speaker-protocol.c speaker-protocol.h \ split.c split.h \ strptime.c strptime.h \ diff --git a/lib/common.h b/lib/common.h index 154338e..9cf3892 100644 --- a/lib/common.h +++ b/lib/common.h @@ -26,6 +26,11 @@ # include #endif +# define SOCKET int +# define INVALID_SOCKET (-1) +# define declspec(x) +# define socket_error() (errno) +# define system_error() (errno) #if HAVE_INTTYPES_H # include #endif @@ -112,6 +117,10 @@ typedef unsigned char uint32_t; # endif #endif +#if !HAVE_CLOSESOCKET +# define closesocket close +#endif + #endif /* COMMENT_H */ /* diff --git a/lib/socketio.c b/lib/socketio.c new file mode 100644 index 0000000..b6528aa --- /dev/null +++ b/lib/socketio.c @@ -0,0 +1,94 @@ +/* + * This file is part of DisOrder + * Copyright (C) 2013 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file lib/socketio.c + * @brief Buffered socket IO + */ +#include "common.h" +#include "socketio.h" +#include "mem.h" + +#include +#include +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif + +void socketio_init(struct socketio *sio, SOCKET sd) { + sio->sd = sd; + sio->inputptr = sio->inputlimit = sio->input; + sio->outputused = 0; + sio->error = 0; +} + +int socketio_write(struct socketio *sio, const void *buffer, size_t n) { + size_t chunk; + while(n > 0) { + chunk = n > sizeof sio->output ? sizeof sio->output : n; + if(chunk) { + memcpy(sio->output + sio->outputused, buffer, chunk); + sio->outputused += chunk; + buffer = (char *)buffer + chunk; + n -= chunk; + } + if(sio->outputused == sizeof sio->output) + if(socketio_flush(sio)) + return -1; + } + return 0; +} + +static int socketio_fill(struct socketio *sio) { + int n = recv(sio->sd, sio->input, sizeof sio->input, 0); + if(n <= 0) { + sio->error = n < 0 ? socket_error() : -1; + return -1; + } + sio->inputptr = sio->input; + sio->inputlimit = sio->input + n; + return 0; +} + +int socketio_getc(struct socketio *sio) { + if(sio->inputptr >= sio->inputlimit) { + if(socketio_fill(sio)) + return EOF; + } + return *sio->inputptr++; +} + +int socketio_flush(struct socketio *sio) { + size_t written = 0; + while(written < sio->outputused) { + int n = send(sio->sd, sio->output + written, sio->outputused - written, 0); + if(n < 0) { + sio->error = socket_error(); + return -1; + } + written += n; + } + sio->outputused = 0; + return 0; +} + +void socketio_close(struct socketio *sio) { + socketio_flush(sio); + closesocket(sio->sd); +} diff --git a/lib/socketio.h b/lib/socketio.h new file mode 100644 index 0000000..22b126b --- /dev/null +++ b/lib/socketio.h @@ -0,0 +1,49 @@ +/* + * This file is part of DisOrder + * Copyright (C) 2013 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file lib/socketio.h + * @brief Buffered socket I/O + */ +#ifndef SOCKETIO_H +# define SOCKETIO_H + +#define SOCKETIO_BUFFER 4096 + +struct socketio { + SOCKET sd; + char *inputptr, *inputlimit; + size_t outputused; + int error; + char input[SOCKETIO_BUFFER]; + char output[SOCKETIO_BUFFER]; +}; + +void socketio_init(struct socketio *sio, SOCKET sd); +int socketio_write(struct socketio *sio, const void *buffer, size_t n); +int socketio_getc(struct socketio *sio); +int socketio_flush(struct socketio *sio); +void socketio_close(struct socketio *sio); + +static inline int socketio_error(struct socketio *sio) { + return sio->error > 0 ? sio->error : 0; +} + +static inline int socketio_eof(struct socketio *sio) { + return sio->error == -1; +} + +#endif -- [mdw]