From 89b3de646698ec703fef9be7b8de4c384ea3e437 Mon Sep 17 00:00:00 2001 From: lanfer Date: Tue, 13 Nov 2001 05:49:21 +0000 Subject: 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 --- src/Sockets.c.SC | 818 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 818 insertions(+) create mode 100644 src/Sockets.c.SC (limited to 'src') 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 +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_SOCKET_H +#include +#endif /* HAVE_SYS_SOCKET_H */ +#ifdef HAVE_NETINET_IN_H +#include +#endif /* HAVE_NETINET_IN_H */ +#ifdef HAVE_NETDB_H +#include +#endif /* HAVE_NETDB_H */ +#ifdef HAVE_ARPA_INET_H +#include +#endif /* ARPA_INET_H */ +#ifdef HAVE_WINSOCK2_H +#include +#endif /* HAVE_WINSOCK2_H */ +#include + +#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 http://%s:%lu", + 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 (retval0) { + 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 +#include +#include + +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 */ -- cgit v1.2.3