aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlanfer <lanfer@1faa4e14-9dd3-4be0-9f0e-ffe519881164>2001-11-13 05:49:21 +0000
committerlanfer <lanfer@1faa4e14-9dd3-4be0-9f0e-ffe519881164>2001-11-13 05:49:21 +0000
commit89b3de646698ec703fef9be7b8de4c384ea3e437 (patch)
treef514cdd7f3b949e6b4bba170f61625cd0e864b00
parent38f41659de2f37d3212781200e6faaefc2f66fae (diff)
temp. fix to read bigger data, ignore this file, sc related
git-svn-id: http://svn.cactuscode.org/arrangements/CactusConnect/HTTPD/trunk@140 1faa4e14-9dd3-4be0-9f0e-ffe519881164
-rw-r--r--src/Sockets.c.SC818
1 files changed, 818 insertions, 0 deletions
diff --git a/src/Sockets.c.SC b/src/Sockets.c.SC
new file mode 100644
index 0000000..7c43e02
--- /dev/null
+++ b/src/Sockets.c.SC
@@ -0,0 +1,818 @@
+ /*@@
+ @file Sockets.c
+ @date Wed Sep 13 20:39:15 2000
+ @author Tom Goodale
+ @desc
+ Routines which deal with sockets.
+ These should probably move into thorn Socket at some point if
+ they aren't already there.
+ @enddesc
+ @version $Header: /mnt/data2/cvs2svn/cvs-repositories/arrangements/CactusConnect/HTTPD/src/Sockets.c.SC,v 1.1 2001-11-13 05:49:21 lanfer Exp $
+ @@*/
+
+#include "cctk.h"
+#include "cctk_Parameters.h"
+#include "util_Network.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif /* HAVE_NETDB_H */
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif /* ARPA_INET_H */
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif /* HAVE_WINSOCK2_H */
+#include <errno.h>
+
+#include "util_Network.h"
+
+#include "httpd.h"
+
+static const char *rcsid = "$Header: /mnt/data2/cvs2svn/cvs-repositories/arrangements/CactusConnect/HTTPD/src/Sockets.c.SC,v 1.1 2001-11-13 05:49:21 lanfer Exp $";
+
+CCTK_FILEVERSION(CactusConnect_HTTPD_Sockets_c)
+
+/********************************************************************
+ ********************* Local Data Types ***********************
+ ********************************************************************/
+
+#ifndef HAVE_SOCKET_TYPE
+#define SOCKET int
+#endif
+
+#ifdef SOCKET_ERROR
+#define ERROR_CHECK(a) ((a) == SOCKET_ERROR)
+#else
+#define ERROR_CHECK(a) ((a) < 0)
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#define CLOSESOCKET(a) closesocket(a)
+#else
+#define CLOSESOCKET(a) close(a)
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+/* HTML filename to take the server URL */
+#define SERVER_URL_FILENAME "server_url.html"
+
+#define RECVSIZE 1024
+
+#define HTTP_DEBUG
+
+typedef enum {closed, open} httpSocketState;
+
+typedef struct HTTPSocket
+{
+ struct HTTPSocket *prev;
+ struct HTTPSocket *next;
+ unsigned long filedes;
+ httpSocketState state;
+} httpSocket;
+
+/********************************************************************
+ ********************* Local Routine Prototypes *********************
+ ********************************************************************/
+
+SOCKET HTTP_MakeSocket (unsigned long port, int *hunt);
+
+static httpSocket *SocketCreate(unsigned long int filedes);
+static void SocketDestroy(httpSocket *this);
+static void SocketClose(httpSocket *this);
+
+static int InitialiseTCP(void);
+
+/********************************************************************
+ ********************* Other Routine Prototypes *********************
+ ********************************************************************/
+
+/********************************************************************
+ ********************* Local Data *****************************
+ ********************************************************************/
+
+/* Active file descriptors */
+static fd_set active_fd_set;
+
+/* Main server socket */
+static SOCKET sock;
+static SOCKET minsock;
+static SOCKET maxsock;
+
+static httpSocket *socklist = NULL;
+
+static unsigned long int httpport = 0;
+
+/********************************************************************
+ ********************* External Routines **********************
+ ********************************************************************/
+
+/*@@
+ @routine HTTP_SetupServer
+ @date Wed Sep 13 20:39:15 2000
+ @author Tom Goodale
+ @desc
+ Creates a socket to listen on.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+int HTTP_SetupServer(int which_port, int queue_size, int which_hunt)
+{
+ char hostname[1025];
+ int realport;
+ DECLARE_CCTK_PARAMETERS
+
+
+ /* Some systems need special logic for starting up TCP. */
+ InitialiseTCP();
+
+ /* Create the socket and set it up to accept connections. */
+ sock = HTTP_MakeSocket (which_port, which_hunt ? &realport : NULL);
+
+ if (ERROR_CHECK(listen (sock, queue_size)))
+ {
+ perror ("listen");
+ exit (EXIT_FAILURE);
+ }
+
+
+ Util_GetHostName(hostname, 1024);
+
+ httpport = which_hunt ? realport : which_port;
+
+ printf("Server started on http://%s:%lu/\n", hostname, httpport);
+ if (announce_server_url)
+ {
+ char *filename;
+ FILE *file;
+
+
+ CCTK_CreateDirectory (0755, announce_server_url_outdir);
+ filename = (char *) malloc (strlen (announce_server_url_outdir) + 20);
+ sprintf (filename, "%s/%s", announce_server_url_outdir, SERVER_URL_FILENAME);
+ file = fopen (filename, "w");
+ if (file)
+ {
+ fprintf (file, "HTTPD server started on <A HREF=\"http://%s:%lu\">http://%s:%lu</A>",
+ HTTP_Master (), (unsigned int) HTTP_Port (), HTTP_Master (), (unsigned int) HTTP_Port ());
+ fclose (file);
+ }
+ free (filename);
+ }
+
+ minsock = sock;
+ maxsock = sock;
+
+ /* Initialize the set of active sockets. */
+ FD_ZERO (&active_fd_set);
+ FD_SET (sock, &active_fd_set);
+
+ /* Not all architectures support the MSG_NOSIGNAL flag to send and recv,
+ * so setup to ignore the SIGPIPE via normal signal hadnling as well.
+ */
+
+#ifdef SIGPIPE
+ signal(SIGPIPE,SIG_IGN);
+#endif
+
+ return 0;
+}
+
+ /*@@
+ @routine HTTP_ShutdownServer
+ @date Wed Sep 13 20:39:15 2000
+ @author Tom Goodale
+ @desc
+ Closes all sockets we are interested in.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+int HTTP_ShutdownServer(void)
+{
+ SOCKET i;
+
+ /* Close all sockets in our active set */
+ for(i = maxsock; i >= minsock; i--)
+ {
+ if(FD_ISSET(i, &active_fd_set))
+ {
+ CLOSESOCKET(i);
+ }
+ }
+
+ return 0;
+}
+
+ /*@@
+ @routine HTTP_Poll
+ @date Wed Sep 13 20:39:15 2000
+ @author Tom Goodale
+ @desc
+ Main workhorse routine.
+ Looks for activity on any of the sockets which are open
+ and dispatches work.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+int HTTP_Poll(cGH *cctkGH, long sec, long usec)
+{
+#ifdef HAVE_SOCKLEN_T
+ socklen_t size;
+#else
+ int size;
+#endif
+
+ fd_set read_fd_set;
+
+ struct sockaddr_in clientname;
+ struct timeval timeout;
+ struct timeval *real_timeout;
+
+ httpSocket *this;
+ httpSocket *next;
+
+ if(sec >=0)
+ {
+ timeout.tv_sec = sec;
+ timeout.tv_usec = usec;
+
+ real_timeout = &timeout;
+ }
+ else
+ {
+ real_timeout = NULL;
+ }
+
+ /* Check if any input is available on one or more active sockets. */
+ read_fd_set = active_fd_set;
+
+ if (ERROR_CHECK(select (FD_SETSIZE, &read_fd_set, NULL, NULL, real_timeout)))
+ {
+ perror ("select");
+ CCTK_Abort(cctkGH, EXIT_FAILURE);
+ }
+
+ /* Service all the sockets with input pending. */
+ if (FD_ISSET (sock, &read_fd_set))
+ {
+ /* Connection request on original socket. */
+ SOCKET new;
+ size = sizeof (clientname);
+ new = accept (sock,
+ (struct sockaddr *) &clientname,
+ &size);
+ if (ERROR_CHECK(new))
+ {
+ perror ("accept");
+ /*CCTK_Abort(cctkGH, EXIT_FAILURE);*/
+ }
+ else
+ {
+ fprintf (stderr,
+ "Server: connect from host %s, port %hd.\n",
+ inet_ntoa (clientname.sin_addr),
+ ntohs (clientname.sin_port));
+
+ SocketCreate(new);
+ }
+ }
+
+ for(this = socklist; this; this = next)
+ {
+ next = this->next;
+ if(FD_ISSET (this->filedes, &read_fd_set))
+ {
+ /* Data arriving on an already-connected socket. */
+ if (HTTP_ReadFromClient (cctkGH, this) < 0)
+ {
+ SocketDestroy(this);
+ }
+ }
+ }
+
+
+ return 0;
+}
+
+ /*@@
+ @routine HTTP_Write
+ @date Fri Sep 15 18:47:41 2000
+ @author Tom Goodale
+ @desc
+ Writes part or all of an HTTP reply.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+int HTTP_Write(httpRequest *request, const char *buffer, size_t count)
+{
+ int retval;
+ size_t bytes_sent;
+ size_t halfcount;
+ httpSocket *connection;
+ int done;
+ int tmp;
+ fd_set this_set;
+
+ connection = (httpSocket *)request->connection;
+
+ if(connection->state == open)
+ {
+ FD_ZERO (&this_set);
+ done = 0;
+ bytes_sent = 0;
+ while(!done)
+ {
+ /* Try and send the data. Make sure we don't get a SIGPIPE if the
+ * other end is closed.
+ */
+ retval = send(connection->filedes,
+ buffer+bytes_sent,
+ count-bytes_sent,
+ MSG_NOSIGNAL);
+
+ /* Check for errors */
+ if(ERROR_CHECK(retval))
+ {
+ switch(errno)
+ {
+#ifdef EMSGSIZE
+ case EMSGSIZE : /* The socket requires that message be sent atomically,
+ * and the size of the message to be sent made this
+ * impossible.
+ */
+ /* Split message in two and try again. */
+ halfcount = count/2;
+ retval = HTTP_Write(request, buffer, halfcount);
+ if(retval > -1)
+ {
+ tmp = HTTP_Write(request, buffer+halfcount, count-halfcount);
+ if(tmp > -1)
+ {
+ retval += tmp;
+ }
+ else
+ {
+ retval = tmp;
+ }
+ }
+ break;
+#endif
+
+#ifdef ENOBUFS
+ case ENOBUFS :
+ /* The output queue for a network interface was full. This generally indicates that the interface has
+ * stopped sending, but may be caused by transient congestion. (This cannot occur in Linux, packets are
+ * just silently dropped when a device queue overflows.)
+ */
+ retval = 0;
+ break;
+#endif
+ case EBADF : /* An invalid descriptor was specified. */
+#ifdef ENOTSOCK
+ case ENOTSOCK : /* The filedescriptor is not a socket. */
+#endif
+ case EPIPE : /* The local end has been shut down on a connection oriented socket. In this case the process will also
+ * receive a SIGPIPE unless MSG_NOSIGNAL is set.
+ */
+ SocketClose(connection);
+ break;
+
+ case EINTR : /* A signal occurred.*/
+
+ case ENOMEM : /* No memory available. */
+
+ case EINVAL : /* Invalid argument passed. */
+
+ case EFAULT : /* An invalid user space address was specified for a parameter. */
+ break;
+
+#if 0
+ case EAGAIN :
+ case EWOULDBLOCK :
+ /* The socket is marked non-blocking and the requested operation would block. */
+#endif
+ default :
+ fprintf(stderr, "Error: this should never happen - %s %d", __FILE__, __LINE__);
+ }
+ }
+ else
+ {
+ bytes_sent += retval;
+ }
+
+ if(!(ERROR_CHECK(retval)) && bytes_sent < count)
+ {
+ /* Wait until can write */
+ FD_SET (connection->filedes, &this_set);
+ if (ERROR_CHECK(select (FD_SETSIZE, NULL, &this_set, NULL, NULL)))
+ {
+ perror ("select");
+ CCTK_Abort(NULL, EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ done = 1;
+ }
+ };
+ }
+ else
+ {
+ retval = -1;
+ }
+
+#ifdef HTTP_DEBUG
+ if(retval != -1)
+ {
+ fprintf (stderr, "Wrote: `%s'\n", buffer);
+ }
+ else
+ {
+ fprintf(stderr, "Couldn't write to the socket 8-(\n");
+ }
+#endif
+
+ return retval;
+}
+
+ /*@@
+ @routine HTTP_Read
+ @date Mon Sep 18 10:14:03 2000
+ @author Tom Goodale
+ @desc
+ Reads part or all of an HTTP request.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+int HTTP_Read(httpRequest *request, char *buffer, size_t count)
+{
+ int retval;
+ char tbuffer[RECVSIZE+1];
+
+
+ httpSocket *connection;
+
+ connection = (httpSocket *)request->connection;
+
+ if(connection->state == open)
+ {
+ /* Currently don't do anything fancy. */
+ /* retval = recv(connection->filedes, buffer, count,MSG_NOSIGNAL);*/
+ sprintf(buffer,"%s","");
+ retval = recv(connection->filedes, tbuffer, RECVSIZE, MSG_NOSIGNAL);
+
+#ifdef HTTP_DEBUG
+ printf("HTTP_Read_S: ret %d len %d buff %d\n",
+ retval, strlen(tbuffer), strlen(buffer));
+#endif
+
+ if (retval==RECVSIZE) {
+ while(retval>0)
+ {
+ int timeout;
+ struct timeval tv, now;
+
+ tbuffer[retval]='\0';
+ sprintf(buffer,"%s%s",buffer,tbuffer);
+#ifdef HTTP_DEBUG
+ printf("HTTP_Read: ret %d len %d buff %d\n",retval,
+ strlen(tbuffer), strlen(buffer));
+#endif
+ /** NEED a TIMEOUT **/
+ gettimeofday(&tv,0);
+ for (;;) {
+ gettimeofday(&now,0);
+ if (now.tv_sec-tv.tv_sec>0.5) break;
+ }
+
+ retval = recv(connection->filedes, tbuffer, RECVSIZE, MSG_NOSIGNAL);
+
+ if (retval<RECVSIZE) break;
+ }
+ }
+
+ if (retval>0) {
+ tbuffer[retval]='\0';
+ sprintf(buffer,"%s%s",buffer,tbuffer);
+ }
+ printf("HTTP_Read_E: ret %d len %d buff %d\n",retval,
+ strlen(tbuffer), strlen(buffer));
+
+ retval = strlen(buffer);
+
+
+#ifdef HTTP_DEBUG
+ fprintf (stderr, "Read: `%s'\n", buffer);
+#endif
+ }
+ else
+ {
+ retval = -1;
+ }
+
+ return retval;
+}
+
+ /*@@
+ @routine HTTP_Port
+ @date Tue Oct 3 11:24:40 2000
+ @author Tom Goodale
+ @desc
+ Reports the port the HTTP server is listening on.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+unsigned long int HTTP_Port(void)
+{
+ return httpport;
+}
+
+/********************************************************************
+ ********************* Local Routines *************************
+ ********************************************************************/
+
+ /*@@
+ @routine HTTP_MakeSocket
+ @date Wed Sep 13 20:39:15 2000
+ @author Tom Goodale
+ @desc
+ Creates a socket.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+SOCKET HTTP_MakeSocket (unsigned long port, int *hunt)
+{
+ SOCKET this_sock;
+ struct sockaddr_in name;
+ int opt;
+ int done;
+ int realport;
+ int error;
+
+ /* Create the socket. */
+ this_sock = socket (PF_INET, SOCK_STREAM, 0);
+ if (ERROR_CHECK(sock))
+ {
+ perror ("socket");
+ CCTK_Abort(NULL, EXIT_FAILURE);
+ }
+
+ /* Try to reuse the port if possible */
+#ifdef SO_REUSEADDR
+ opt = 1;
+ setsockopt(this_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+#endif
+
+ done = 0;
+ realport = port;
+
+ while(!done)
+ {
+ /* Give the socket a name. */
+ name.sin_family = AF_INET;
+ name.sin_port = htons (realport);
+ name.sin_addr.s_addr = htonl (INADDR_ANY);
+ if (ERROR_CHECK(error = bind (this_sock, (struct sockaddr *) &name, sizeof (name))))
+ {
+ if(hunt)
+ {
+ /* Hunt for a new port */
+ fprintf(stderr, "Port %u taken, trying %u\n", realport, realport+1);
+ realport++;
+ }
+ else
+ {
+ done = 1;
+ }
+ }
+ else
+ {
+ done = 1;
+ }
+ }
+
+ if(ERROR_CHECK(error))
+ {
+ perror ("bind");
+ CCTK_Abort(NULL,EXIT_FAILURE);
+ }
+ else if(hunt)
+ {
+ *hunt = realport;
+ }
+
+ return this_sock;
+}
+
+ /*@@
+ @routine SocketCreate
+ @date Thu Sep 21 15:03:32 2000
+ @author Tom Goodale
+ @desc
+ Creates an httpSocket structure and links it to the list.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+static httpSocket *SocketCreate(unsigned long int filedes)
+{
+ httpSocket *this;
+
+ this = (httpSocket *)malloc(sizeof (httpSocket));
+
+ if(this)
+ {
+ this->filedes = filedes;
+ this->state = open;
+ this->prev = NULL;
+ this->next = socklist;
+
+ if(socklist)
+ {
+ socklist->prev = this;
+ }
+
+ socklist = this;
+
+ FD_SET (this->filedes, &active_fd_set);
+ }
+
+ return this;
+}
+
+ /*@@
+ @routine SocketDestroy
+ @date Thu Sep 21 15:04:03 2000
+ @author Tom Goodale
+ @desc
+ Destroys an httpSocket structure and removes it from the list.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+static void SocketDestroy(httpSocket *this)
+{
+ if(this)
+ {
+ if(this->state == open)
+ {
+ SocketClose(this);
+ }
+
+ if(this->next)
+ {
+ this->next->prev = this->prev;
+ }
+
+ if(this->prev)
+ {
+ this->prev->next=this->next;
+ }
+ else
+ {
+ socklist = this->next;
+ }
+
+ free(this);
+ }
+}
+
+ /*@@
+ @routine SocketClose
+ @date Thu Sep 21 15:04:27 2000
+ @author Tom Goodale
+ @desc
+ Closes the socket associated with an httpSocket structure.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+static void SocketClose(httpSocket *this)
+{
+ if(this)
+ {
+ if(this->state == open)
+ {
+ CLOSESOCKET(this->filedes);
+ this->state=closed;
+ FD_CLR (this->filedes, &active_fd_set);
+ }
+ }
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
+
+/* Special code for starting up the socket layer. */
+
+#ifdef HAVE_WINSOCK2_H
+#ifndef _M_IX86
+#define _M_IX86 400
+#endif
+
+#include <sys/types.h>
+#include <windows.h>
+#include <stdio.h>
+
+static int InitialiseTCP(void)
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int errnumber;
+
+ wVersionRequested = MAKEWORD( 2, 0 );
+
+ errnumber = WSAStartup( wVersionRequested, &wsaData );
+
+ if (errnumber)
+ {
+ fprintf(stderr, "Couldn't start Windows socket layer\n");
+ }
+ else
+ {
+ printf("Windows socket layer initialized.\n");
+ }
+
+ return errnumber;
+}
+
+#else
+
+static int InitialiseTCP(void)
+{
+ return 0;
+}
+
+#endif /* defined HAVE_WINSOCK2_H */