summaryrefslogtreecommitdiffstats
path: root/src/socket_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/socket_io.c')
-rw-r--r--src/socket_io.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/socket_io.c b/src/socket_io.c
new file mode 100644
index 0000000..0475310
--- /dev/null
+++ b/src/socket_io.c
@@ -0,0 +1,239 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * socket.c
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * set/getsockopt and read/write wrappers
+ * ------------------------------------------------------------------- */
+
+#include "headers.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------------------------------------------------
+ * Attempts to reads n bytes from a socket.
+ * Returns number actually read, or -1 on error.
+ * If number read < inLen then we reached EOF.
+ *
+ * from Stevens, 1998, section 3.9
+ * ------------------------------------------------------------------- */
+ssize_t readn (int inSock, void *outBuf, size_t inLen) {
+ size_t nleft;
+ ssize_t nread;
+ char *ptr;
+
+ assert(inSock >= 0);
+ assert(outBuf != NULL);
+ assert(inLen > 0);
+
+ ptr = (char*) outBuf;
+ nleft = inLen;
+
+ while (nleft > 0) {
+ nread = read(inSock, ptr, nleft);
+ if (nread < 0) {
+ if (errno == EINTR)
+ nread = 0; /* interupted, call read again */
+ else
+ return -1; /* error */
+ } else if (nread == 0)
+ break; /* EOF */
+
+ nleft -= nread;
+ ptr += nread;
+ }
+
+ return(inLen - nleft);
+} /* end readn */
+
+/* -------------------------------------------------------------------
+ * Similar to read but supports recv flags
+ * Returns number actually read, or -1 on error.
+ * If number read < inLen then we reached EOF.
+ * from Stevens, 1998, section 3.9
+ * ------------------------------------------------------------------- */
+int recvn (int inSock, char *outBuf, int inLen, int flags) {
+ int nleft;
+ int nread = 0;
+ char *ptr;
+
+ assert(inSock >= 0);
+ assert(outBuf != NULL);
+ assert(inLen > 0);
+
+ ptr = outBuf;
+ nleft = inLen;
+#if (HAVE_DECL_MSG_PEEK)
+ if (flags & MSG_PEEK) {
+ while ((nleft != nread) && !sInterupted) {
+ nread = recv(inSock, ptr, nleft, flags);
+ switch (nread) {
+ case SOCKET_ERROR :
+ // Note: use TCP fatal error codes even for UDP
+ if (FATALTCPREADERR(errno)) {
+ WARN_errno(1, "recvn peek");
+ nread = -1;
+ sInterupted = 1;
+ goto DONE;
+ }
+#ifdef HAVE_THREAD_DEBUG
+ WARN_errno(1, "recvn peek non-fatal");
+#endif
+ break;
+ case 0:
+#ifdef HAVE_THREAD_DEBUG
+ WARN(1, "recvn peek peer close");
+#endif
+ goto DONE;
+ break;
+ default :
+ break;
+ }
+ }
+ } else
+#endif
+ {
+ while ((nleft > 0) && !sInterupted) {
+#if (HAVE_DECL_MSG_WAITALL)
+ nread = recv(inSock, ptr, nleft, MSG_WAITALL);
+#else
+ nread = recv(inSock, ptr, nleft, 0);
+#endif
+ switch (nread) {
+ case SOCKET_ERROR :
+ // Note: use TCP fatal error codes even for UDP
+ if (FATALTCPREADERR(errno)) {
+ WARN_errno(1, "recvn");
+ nread = -1;
+ sInterupted = 1;
+ goto DONE;
+ } else {
+ nread = -2;
+ goto DONE;
+ }
+#ifdef HAVE_THREAD_DEBUG
+ WARN_errno(1, "recvn non-fatal");
+#endif
+ break;
+ case 0:
+#ifdef HAVE_THREAD_DEBUG
+ WARN(1, "recvn peer close");
+#endif
+ nread = inLen - nleft;
+ goto DONE;
+ break;
+ default :
+ nleft -= nread;
+ ptr += nread;
+ break;
+ }
+ nread = inLen - nleft;
+ }
+ }
+ DONE:
+ return(nread);
+} /* end readn */
+
+/* -------------------------------------------------------------------
+ * Attempts to write n bytes to a socket.
+ * returns number actually written, or -1 on error.
+ * number written is always inLen if there is not an error.
+ *
+ * from Stevens, 1998, section 3.9
+ * ------------------------------------------------------------------- */
+
+int writen (int inSock, const void *inBuf, int inLen, int *count) {
+ int nleft;
+ int nwritten;
+ const char *ptr;
+
+ assert(inSock >= 0);
+ assert(inBuf != NULL);
+ assert(inLen > 0);
+ assert(count != NULL);
+
+ ptr = (char*) inBuf;
+ nleft = inLen;
+ nwritten = 0;
+ *count = 0;
+
+ while ((nleft > 0) && !sInterupted) {
+ nwritten = write(inSock, ptr, nleft);
+ (*count)++;
+ switch (nwritten) {
+ case SOCKET_ERROR :
+ // check for a fatal error vs an error that should retry
+ if ((errno != EINTR) && (errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ nwritten = inLen - nleft;
+ fprintf(stdout, "FAIL: writen errno = %d\n", errno);
+ WARN_errno(1, "writen fatal");
+ sInterupted = 1;
+ goto DONE;
+ }
+ break;
+ case 0:
+ // write timeout - retry
+ break;
+ default :
+ nleft -= nwritten;
+ ptr += nwritten;
+ break;
+ }
+ nwritten = inLen - nleft;
+ }
+ DONE:
+ return (nwritten);
+} /* end writen */
+
+
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif