Add support for Win32 and Winsock to main.c and sock.c code
This commit is contained in:
+66
-3
@@ -10,6 +10,7 @@
|
|||||||
* 2001, Rene Wagner
|
* 2001, Rene Wagner
|
||||||
* 2002, Mike Patnode
|
* 2002, Mike Patnode
|
||||||
* 2002, Guillaume Filion
|
* 2002, Guillaume Filion
|
||||||
|
* 2003, Benjamin Tse (Win32 support)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Contains main(), plus signal callback functions and a help screen.
|
* Contains main(), plus signal callback functions and a help screen.
|
||||||
@@ -31,20 +32,25 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifndef WIN32
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#else
|
||||||
|
#include "getopt.h"
|
||||||
|
#endif
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
/* TODO: fill in what to include otherwise */
|
/* TODO: fill in what to include otherwise */
|
||||||
|
|
||||||
|
/* REVISIT: externs should be provided by a header */
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind, optopt, opterr;
|
extern int optind, optopt, opterr;
|
||||||
|
|
||||||
@@ -79,6 +85,10 @@ extern int optind, optopt, opterr;
|
|||||||
#define DEFAULT_SCREEN_DURATION 32
|
#define DEFAULT_SCREEN_DURATION 32
|
||||||
#define DEFAULT_HEARTBEAT HEARTBEAT_ON
|
#define DEFAULT_HEARTBEAT HEARTBEAT_ON
|
||||||
|
|
||||||
|
/* All variables are set to 'unset' values*/
|
||||||
|
#define UNSET_INT -1
|
||||||
|
#define UNSET_STR "\01"
|
||||||
|
|
||||||
/* Socket to bind to...
|
/* Socket to bind to...
|
||||||
|
|
||||||
Using loopback is much more secure; it means that this port is
|
Using loopback is much more secure; it means that this port is
|
||||||
@@ -221,7 +231,7 @@ main (int argc, char **argv)
|
|||||||
/* Only catch SIGHUP if not in foreground mode */
|
/* Only catch SIGHUP if not in foreground mode */
|
||||||
|
|
||||||
/* Startup the subparts of the server */
|
/* Startup the subparts of the server */
|
||||||
CHAIN( e, sock_init() );
|
CHAIN( e, sock_init(bind_addr, bind_port) );
|
||||||
CHAIN( e, screenlist_init() );
|
CHAIN( e, screenlist_init() );
|
||||||
CHAIN( e, init_drivers() );
|
CHAIN( e, init_drivers() );
|
||||||
CHAIN( e, clients_init() );
|
CHAIN( e, clients_init() );
|
||||||
@@ -514,6 +524,7 @@ set_default_settings()
|
|||||||
void
|
void
|
||||||
install_signal_handlers (int allow_reload)
|
install_signal_handlers (int allow_reload)
|
||||||
{
|
{
|
||||||
|
#ifndef WIN32
|
||||||
/* Installs signal handlers so that the program does clean exit and
|
/* Installs signal handlers so that the program does clean exit and
|
||||||
* can also receive a reload signal.
|
* can also receive a reload signal.
|
||||||
* sigaction() is favoured over signal() */
|
* sigaction() is favoured over signal() */
|
||||||
@@ -537,6 +548,14 @@ install_signal_handlers (int allow_reload)
|
|||||||
/* Treat this signal just like INT and TERM */
|
/* Treat this signal just like INT and TERM */
|
||||||
}
|
}
|
||||||
sigaction (SIGHUP, &sa, NULL);
|
sigaction (SIGHUP, &sa, NULL);
|
||||||
|
#else
|
||||||
|
/* Win32 does not support POSIX signals i.e. sigaction(). However, it does
|
||||||
|
* support ANSI signals in mingw. */
|
||||||
|
signal (SIGINT, exit_program); /* Ctrl-C will cause a clean exit...*/
|
||||||
|
signal (SIGTERM, exit_program); /* and "kill"...*/
|
||||||
|
|
||||||
|
/* REVISIT: implement SIGHUP on windows */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -554,6 +573,13 @@ child_ok_func (int signal) {
|
|||||||
pid_t
|
pid_t
|
||||||
daemonize()
|
daemonize()
|
||||||
{
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
/* WIN32 does not support fork() - CreateProcess() does not even have
|
||||||
|
* similar functionality. Instead don't daemonize on WIN32.
|
||||||
|
*/
|
||||||
|
pid_t parent;
|
||||||
|
parent = getpid();
|
||||||
|
#else
|
||||||
pid_t child;
|
pid_t child;
|
||||||
pid_t parent;
|
pid_t parent;
|
||||||
int child_status;
|
int child_status;
|
||||||
@@ -605,6 +631,7 @@ daemonize()
|
|||||||
|
|
||||||
setsid(); /* Create a new session because otherwise we'll
|
setsid(); /* Create a new session because otherwise we'll
|
||||||
* catch a SIGHUP when the shell is closed. */
|
* catch a SIGHUP when the shell is closed. */
|
||||||
|
#endif
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
@@ -613,9 +640,11 @@ daemonize()
|
|||||||
int
|
int
|
||||||
wave_to_parent (pid_t parent_pid)
|
wave_to_parent (pid_t parent_pid)
|
||||||
{
|
{
|
||||||
|
#ifndef WIN32
|
||||||
debug( RPT_DEBUG, "%s( parent_pid=%d )", __FUNCTION__, parent_pid );
|
debug( RPT_DEBUG, "%s( parent_pid=%d )", __FUNCTION__, parent_pid );
|
||||||
|
|
||||||
kill( parent_pid, SIGUSR1 );
|
kill( parent_pid, SIGUSR1 );
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -664,6 +693,7 @@ init_drivers()
|
|||||||
|
|
||||||
int drop_privs(char *user)
|
int drop_privs(char *user)
|
||||||
{
|
{
|
||||||
|
#ifndef WIN32
|
||||||
struct passwd *pwent;
|
struct passwd *pwent;
|
||||||
|
|
||||||
debug( RPT_DEBUG, "%s( user=\"%.40s\" )", __FUNCTION__, user );
|
debug( RPT_DEBUG, "%s( user=\"%.40s\" )", __FUNCTION__, user );
|
||||||
@@ -679,6 +709,10 @@ int drop_privs(char *user)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/* Don't alter privileges in WIN32 */
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,8 +774,14 @@ void
|
|||||||
do_mainloop ()
|
do_mainloop ()
|
||||||
{
|
{
|
||||||
Screen * s;
|
Screen * s;
|
||||||
|
#ifndef WIN32
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
struct timeval last_t;
|
struct timeval last_t;
|
||||||
|
#else
|
||||||
|
LARGE_INTEGER t;
|
||||||
|
LARGE_INTEGER last_t;
|
||||||
|
LARGE_INTEGER perf_freq; /* frequency of high perf counter (cycles per usec) */
|
||||||
|
#endif
|
||||||
int sleeptime;
|
int sleeptime;
|
||||||
long int process_lag = 0;
|
long int process_lag = 0;
|
||||||
long int render_lag = 0;
|
long int render_lag = 0;
|
||||||
@@ -749,14 +789,31 @@ do_mainloop ()
|
|||||||
|
|
||||||
debug( RPT_DEBUG, "%s()", __FUNCTION__ );
|
debug( RPT_DEBUG, "%s()", __FUNCTION__ );
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
gettimeofday (&t, NULL); /* Get initial time */
|
gettimeofday (&t, NULL); /* Get initial time */
|
||||||
|
#else
|
||||||
|
QueryPerformanceFrequency(&perf_freq);
|
||||||
|
/* scale perf_freq to number of cycles per micro-sec */
|
||||||
|
/* REVISIT: this causes rounding errors below but is more efficient */
|
||||||
|
perf_freq.QuadPart /= 1e6;
|
||||||
|
QueryPerformanceCounter(&t);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Get current time */
|
/* Get current time */
|
||||||
last_t = t;
|
last_t = t;
|
||||||
|
#ifndef WIN32
|
||||||
gettimeofday (&t, NULL);
|
gettimeofday (&t, NULL);
|
||||||
t_diff = ((t.tv_sec - last_t.tv_sec) * 1e6 + (t.tv_usec - last_t.tv_usec));
|
t_diff = ((t.tv_sec - last_t.tv_sec) * 1e6 + (t.tv_usec - last_t.tv_usec));
|
||||||
|
#else
|
||||||
|
QueryPerformanceCounter(&t);
|
||||||
|
/*t_diff.HighPart = t.HighPart - last_t.HighPart;
|
||||||
|
t_diff.LowPart = t.LowPart - last_t.LowPart;
|
||||||
|
*/
|
||||||
|
t_diff = t.QuadPart - last_t.QuadPart;
|
||||||
|
t_diff /= perf_freq.QuadPart; /* scale to microseconds */
|
||||||
|
/* REVISIT: assumes fits into long */
|
||||||
|
#endif
|
||||||
process_lag += t_diff;
|
process_lag += t_diff;
|
||||||
if (process_lag > 0) {
|
if (process_lag > 0) {
|
||||||
/* Time for a processing stroke */
|
/* Time for a processing stroke */
|
||||||
@@ -796,7 +853,12 @@ do_mainloop ()
|
|||||||
/* Sleep just as long as needed */
|
/* Sleep just as long as needed */
|
||||||
sleeptime = min (0-process_lag, 0-render_lag);
|
sleeptime = min (0-process_lag, 0-render_lag);
|
||||||
if( sleeptime > 0 ) {
|
if( sleeptime > 0 ) {
|
||||||
|
#ifndef WIN32
|
||||||
usleep (sleeptime);
|
usleep (sleeptime);
|
||||||
|
#else
|
||||||
|
/* Sleep in Windows takes milliseconds argument */
|
||||||
|
Sleep(sleeptime / 1000);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a SIGHUP has been caught */
|
/* Check if a SIGHUP has been caught */
|
||||||
@@ -848,6 +910,7 @@ exit_program (int val)
|
|||||||
menuscreens_shutdown ();
|
menuscreens_shutdown ();
|
||||||
screenlist_shutdown (); /* shutdown screens (must come after client_shutdown) */
|
screenlist_shutdown (); /* shutdown screens (must come after client_shutdown) */
|
||||||
input_shutdown (); /* shutdown key input part */
|
input_shutdown (); /* shutdown key input part */
|
||||||
|
sock_shutdown(); /* shutdown the sockets server */
|
||||||
|
|
||||||
report( RPT_INFO, "Exiting." );
|
report( RPT_INFO, "Exiting." );
|
||||||
_exit (0);
|
_exit (0);
|
||||||
|
|||||||
+232
-56
@@ -6,33 +6,36 @@
|
|||||||
* COPYING file distributed with this package.
|
* COPYING file distributed with this package.
|
||||||
*
|
*
|
||||||
* Copyright (c) 1999, William Ferrell, Scott Scriven
|
* Copyright (c) 1999, William Ferrell, Scott Scriven
|
||||||
*
|
* 2003, Benjamin Tse (blt@ieee.org) - Winsock port
|
||||||
*
|
*
|
||||||
* LCDproc sockets code...
|
* LCDproc sockets code...
|
||||||
*
|
*
|
||||||
* This is messy, and needs to be finished.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef WINSOCK2
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#endif /* WINSOCK */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "clients.h"
|
#include "clients.h"
|
||||||
@@ -41,26 +44,97 @@
|
|||||||
#include "screenlist.h"
|
#include "screenlist.h"
|
||||||
|
|
||||||
|
|
||||||
fd_set active_fd_set, read_fd_set;
|
/****************************************************************************/
|
||||||
int listening_fd;
|
static fd_set active_fd_set, read_fd_set;
|
||||||
|
static int listening_fd;
|
||||||
|
|
||||||
|
/* For efficiency we maintain a list of open sockets. Nodes in this list
|
||||||
|
* are obtained from a pre-allocated pool - this removes heap operations
|
||||||
|
* from the polling loop. A list of open sockets is also required under WINSOCK
|
||||||
|
* as sockets can be arbitrary values instead of low value integers. */
|
||||||
|
static LinkedList* openSocketList = NULL;
|
||||||
|
static LinkedList* freeClientSocketList = NULL;
|
||||||
|
|
||||||
|
struct ClientSocketMap
|
||||||
|
{
|
||||||
|
int socket;
|
||||||
|
Client* client;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The memory referenced from clientSocketPoolList is obtained from the
|
||||||
|
* clientSocketPool array. */
|
||||||
|
struct ClientSocketMap* freeClientSocketPool;
|
||||||
|
|
||||||
/* Length of longest transmission allowed at once...*/
|
/* Length of longest transmission allowed at once...*/
|
||||||
#define MAXMSG 8192
|
#define MAXMSG 8192
|
||||||
|
|
||||||
int sock_read_from_client (int filedes);
|
/**** Internal function declarations ****************************************/
|
||||||
|
int sock_read_from_client(struct ClientSocketMap* clientSocketMap);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
int
|
int
|
||||||
sock_init ()
|
sock_init(char* bind_addr, int bind_port)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef WINSOCK2
|
||||||
|
/* Initialize the Winsock dll */
|
||||||
|
WSADATA wsaData;
|
||||||
|
int startup = WSAStartup( MAKEWORD(2, 2), &wsaData );
|
||||||
|
if (startup != 0)
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Could not start Winsock library - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
|
}
|
||||||
|
/* REVISIT: call WSACleanup(); */
|
||||||
|
#endif
|
||||||
|
|
||||||
debug (RPT_DEBUG, "%s( bind_addr=\"%s\", port=%d )", __FUNCTION__, bind_addr, bind_port);
|
debug (RPT_DEBUG, "%s( bind_addr=\"%s\", port=%d )", __FUNCTION__, bind_addr, bind_port);
|
||||||
|
|
||||||
/* Create the socket and set it up to accept connections. */
|
/* Create the socket and set it up to accept connections. */
|
||||||
listening_fd = sock_create_inet_socket (bind_addr, bind_port);
|
listening_fd = sock_create_inet_socket (bind_addr, bind_port);
|
||||||
if (listening_fd < 0) {
|
if (listening_fd < 0) {
|
||||||
report (RPT_ERR, "%s: Error creating socket", __FUNCTION__);
|
report (RPT_ERR, "%s: Error creating socket - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the socket -> Client mapping pool */
|
||||||
|
/* How large can FD_SETSIZE be? Even if it is ~2000 this only uses a
|
||||||
|
few kilobytes of memory. Let's trade size for speed! */
|
||||||
|
freeClientSocketPool = (struct ClientSocketMap*)
|
||||||
|
malloc(sizeof(struct ClientSocketMap) * FD_SETSIZE);
|
||||||
|
if (!freeClientSocketPool)
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Error allocating memory for client sockets.",
|
||||||
|
__FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeClientSocketList = LL_new();
|
||||||
|
for (i = 0; i < FD_SETSIZE; ++i)
|
||||||
|
{
|
||||||
|
LL_AddNode(freeClientSocketList, (void*) &freeClientSocketPool[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and initialize the open socket list with the server socket */
|
||||||
|
openSocketList = LL_new();
|
||||||
|
if (!openSocketList)
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Error allocating memory for the open socket "
|
||||||
|
"list.", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
struct ClientSocketMap* entry;
|
||||||
|
|
||||||
|
/* LL_DeleteNode removes an entry from the list and returns it */
|
||||||
|
entry = (struct ClientSocketMap*) LL_Pop(freeClientSocketList);
|
||||||
|
entry->socket = listening_fd;
|
||||||
|
entry->client = NULL;
|
||||||
|
LL_AddNode(openSocketList, (void*) entry);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,12 +158,46 @@ This code gets the send and receive buffer sizes.
|
|||||||
int
|
int
|
||||||
sock_shutdown ()
|
sock_shutdown ()
|
||||||
{
|
{
|
||||||
|
int retVal = 0;
|
||||||
|
|
||||||
debug( RPT_DEBUG, "%s()", __FUNCTION__ );
|
debug( RPT_DEBUG, "%s()", __FUNCTION__ );
|
||||||
|
|
||||||
|
/*struct ClientSocketMap* clientIt;*/
|
||||||
|
|
||||||
|
/* delete all clients */
|
||||||
|
/* This should be done by calling clients_shutdown */
|
||||||
|
/*
|
||||||
|
LL_Rewind(openSocketList);
|
||||||
|
for (clientIt = (struct ClientSocketMap*) LL_Get(openSocketList);
|
||||||
|
clientIt;
|
||||||
|
clientIt = LL_GetNext(openSocketList))
|
||||||
|
{
|
||||||
|
if (clientIt->client)
|
||||||
|
{
|
||||||
|
/* destroying a client also closes its socket */
|
||||||
|
/* client_destroy(clientIt->client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LL_Destroy(openSocketList);
|
||||||
|
*/
|
||||||
close( listening_fd );
|
close( listening_fd );
|
||||||
|
LL_Destroy(freeClientSocketList);
|
||||||
|
free(freeClientSocketPool);
|
||||||
|
|
||||||
|
#ifdef WINSOCK2
|
||||||
|
if (WSACleanup() != 0)
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Error closing Winsock library - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
|
retVal = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
/* Creates a socket in internet space */
|
/* Creates a socket in internet space */
|
||||||
int
|
int
|
||||||
sock_create_inet_socket (char * addr, unsigned int port)
|
sock_create_inet_socket (char * addr, unsigned int port)
|
||||||
@@ -101,13 +209,20 @@ sock_create_inet_socket (char * addr, unsigned int port)
|
|||||||
|
|
||||||
/* Create the socket. */
|
/* Create the socket. */
|
||||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||||
if (sock < 0) {
|
#ifdef WINSOCK2
|
||||||
report(RPT_ERR, "%s: Could not create socket", __FUNCTION__);
|
if (sock == INVALID_SOCKET)
|
||||||
|
#else
|
||||||
|
if (sock < 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Could not create socket - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Set the socket so we can re-use it*/
|
/* Set the socket so we can re-use it*/
|
||||||
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&sockopt,sizeof(sockopt)) < 0) {
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) < 0) {
|
||||||
report(RPT_ERR, "%s: Error setting socket option SO_REUSEADDR", __FUNCTION__);
|
report(RPT_ERR, "%s: Error setting socket option SO_REUSEADDR - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,17 +230,26 @@ sock_create_inet_socket (char * addr, unsigned int port)
|
|||||||
memset (&name, 0, sizeof (name));
|
memset (&name, 0, sizeof (name));
|
||||||
name.sin_family = AF_INET;
|
name.sin_family = AF_INET;
|
||||||
name.sin_port = htons (port);
|
name.sin_port = htons (port);
|
||||||
|
#ifndef WINSOCK2
|
||||||
|
/* REVISIT: can probably use the same code as under winsock */
|
||||||
inet_aton(addr, &name.sin_addr);
|
inet_aton(addr, &name.sin_addr);
|
||||||
|
#else
|
||||||
|
name.sin_addr.S_un.S_addr = inet_addr(addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
|
if (bind(sock, (struct sockaddr *) &name, sizeof (name)) < 0)
|
||||||
report(RPT_ERR, "Could not bind to port %d", port);
|
{
|
||||||
|
report(RPT_ERR, "%s: Could not bind to port %d at address %s - %s",
|
||||||
|
__FUNCTION__, port, addr, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
report(RPT_NOTICE, "Listening for queries on %s:%d", addr, port);
|
report(RPT_NOTICE, "Listening for queries on %s:%d", addr, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen (sock, 1) < 0) {
|
if (listen (sock, 1) < 0) {
|
||||||
report(RPT_ERR, "%s: error in attempting to listen to port", __FUNCTION__);
|
report(RPT_ERR, "%s: error in attempting to listen to port "
|
||||||
|
"%d at %s - %s",
|
||||||
|
__FUNCTION__, port, addr, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,12 +265,10 @@ sock_create_inet_socket (char * addr, unsigned int port)
|
|||||||
int
|
int
|
||||||
sock_poll_clients ()
|
sock_poll_clients ()
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int err;
|
int err;
|
||||||
struct sockaddr_in clientname;
|
struct sockaddr_in clientname;
|
||||||
size_t size;
|
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
Client * c;
|
struct ClientSocketMap* clientSocket;
|
||||||
|
|
||||||
debug (RPT_DEBUG, "%s()", __FUNCTION__);
|
debug (RPT_DEBUG, "%s()", __FUNCTION__);
|
||||||
|
|
||||||
@@ -157,35 +279,73 @@ sock_poll_clients ()
|
|||||||
read_fd_set = active_fd_set;
|
read_fd_set = active_fd_set;
|
||||||
|
|
||||||
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, &t) < 0) {
|
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, &t) < 0) {
|
||||||
report (RPT_ERR, "%s: Select error", __FUNCTION__);
|
report(RPT_ERR, "%s: Select error - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Service all the sockets with input pending. */
|
/* Service all the sockets with input pending. */
|
||||||
for (i = 0; i < FD_SETSIZE; ++i) {
|
LL_Rewind(openSocketList);
|
||||||
if (FD_ISSET (i, &read_fd_set)) {
|
for (clientSocket = (struct ClientSocketMap*) LL_Get(openSocketList);
|
||||||
if (i == listening_fd) {
|
clientSocket;
|
||||||
|
clientSocket = LL_GetNext(openSocketList))
|
||||||
|
{
|
||||||
|
if (FD_ISSET(clientSocket->socket, &read_fd_set))
|
||||||
|
{
|
||||||
|
if (clientSocket->socket == listening_fd)
|
||||||
|
{
|
||||||
/* Connection request on original socket. */
|
/* Connection request on original socket. */
|
||||||
|
Client* c;
|
||||||
int new_sock;
|
int new_sock;
|
||||||
size = sizeof (clientname);
|
size_t size = sizeof(clientname);
|
||||||
new_sock = accept (listening_fd, (struct sockaddr *) &clientname, &size);
|
new_sock = accept (listening_fd, (struct sockaddr *) &clientname, &size);
|
||||||
if (new_sock < 0) {
|
#ifdef WINSOCK2
|
||||||
report (RPT_ERR, "%s: Accept error", __FUNCTION__);
|
if (new_sock == INVALID_SOCKET)
|
||||||
|
#else
|
||||||
|
if (new_sock < 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
report(RPT_ERR, "%s: Accept error - %s",
|
||||||
|
__FUNCTION__, sock_geterror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
report (RPT_NOTICE, "Connect from host %s:%hd on socket %i",
|
report (RPT_NOTICE, "Connect from host %s:%hd on socket %i",
|
||||||
inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port), new_sock);
|
inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port), new_sock);
|
||||||
FD_SET (new_sock, &active_fd_set);
|
FD_SET (new_sock, &active_fd_set);
|
||||||
|
|
||||||
|
#ifdef WINSOCK2
|
||||||
|
{
|
||||||
|
unsigned long tmp;
|
||||||
|
ioctlsocket(new_sock, FIONBIO, &tmp);
|
||||||
|
}
|
||||||
|
#else
|
||||||
fcntl(new_sock, F_SETFL, O_NONBLOCK);
|
fcntl(new_sock, F_SETFL, O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create new client */
|
/* Create new client */
|
||||||
if ((c = client_create (new_sock)) == NULL) {
|
if ((c = client_create (new_sock)) == NULL) {
|
||||||
report( RPT_ERR, "%s: Error creating client on socket %i", __FUNCTION__, i);
|
report( RPT_ERR, "%s: Error creating client on socket %i - %s",
|
||||||
|
__FUNCTION__, clientSocket->socket, sock_geterror());
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
/* add new_sock */
|
||||||
|
struct ClientSocketMap* newClientSocket;
|
||||||
|
newClientSocket = (struct ClientSocketMap*) LL_Pop(freeClientSocketList);
|
||||||
|
if (newClientSocket)
|
||||||
|
{
|
||||||
|
newClientSocket->socket = new_sock;
|
||||||
|
newClientSocket->client = c;
|
||||||
|
LL_InsertNode(openSocketList, (void*) newClientSocket);
|
||||||
|
/* advance past the new node - check it on the next pass */
|
||||||
|
LL_Next(openSocketList);
|
||||||
|
} else {
|
||||||
|
report(RPT_ERR, "%s: Error - free client socket list exhausted - %d clients.",
|
||||||
|
__FUNCTION__, FD_SETSIZE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (clients_add_client (c) != 0) {
|
if (clients_add_client (c) != 0) {
|
||||||
report( RPT_ERR, "%s: Could not add client on socket %i", __FUNCTION__, i);
|
report( RPT_ERR, "%s: Could not add client on socket %i", __FUNCTION__, clientSocket->socket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -193,20 +353,29 @@ sock_poll_clients ()
|
|||||||
err = 0;
|
err = 0;
|
||||||
do {
|
do {
|
||||||
debug (RPT_DEBUG, "%s: reading...", __FUNCTION__);
|
debug (RPT_DEBUG, "%s: reading...", __FUNCTION__);
|
||||||
err = sock_read_from_client (i);
|
err = sock_read_from_client(clientSocket);
|
||||||
debug (RPT_DEBUG, "%s: ...done", __FUNCTION__);
|
debug (RPT_DEBUG, "%s: ...done", __FUNCTION__);
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
|
{
|
||||||
/* Client disconnected, destroy client data */
|
/* Client disconnected, destroy client data */
|
||||||
c = clients_find_client_by_sock (i);
|
/* c = clients_find_client_by_sock(); - Deprecated by clientsocketmap*/
|
||||||
if (c) {
|
if (clientSocket->client)
|
||||||
|
{
|
||||||
|
struct ClientSocketMap* entry;
|
||||||
|
|
||||||
/*sock_send_string(i, "bye\n");*/
|
/*sock_send_string(i, "bye\n");*/
|
||||||
report (RPT_NOTICE, "Client on socket %i disconnected", i);
|
report (RPT_NOTICE, "Client on socket %i disconnected",
|
||||||
client_destroy (c);
|
clientSocket->socket);
|
||||||
clients_remove_client (c);
|
client_destroy(clientSocket->client);
|
||||||
close (i);
|
clients_remove_client(clientSocket->client);
|
||||||
FD_CLR (i, &active_fd_set);
|
FD_CLR(clientSocket->socket, &active_fd_set);
|
||||||
|
close(clientSocket->socket);
|
||||||
|
|
||||||
|
entry = (struct ClientSocketMap*) LL_DeleteNode(openSocketList);
|
||||||
|
LL_Push(freeClientSocketList, (void*) entry);
|
||||||
} else {
|
} else {
|
||||||
report (RPT_ERR, "%s: Can't find client of socket %i", __FUNCTION__, i);
|
report (RPT_ERR, "%s: Can't find client of socket %i",
|
||||||
|
__FUNCTION__, clientSocket->socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (err > 0);
|
} while (err > 0);
|
||||||
@@ -217,25 +386,29 @@ sock_poll_clients ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sock_read_from_client (int filedes)
|
sock_read_from_client(struct ClientSocketMap* clientSocketMap)
|
||||||
{
|
{
|
||||||
char buffer[MAXMSG];
|
char buffer[MAXMSG];
|
||||||
int nbytes, i;
|
int nbytes, i;
|
||||||
Client * c;
|
|
||||||
|
|
||||||
debug (RPT_DEBUG, "%s()", __FUNCTION__);
|
debug (RPT_DEBUG, "%s()", __FUNCTION__);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if ((nbytes = sock_recv (filedes, buffer, MAXMSG)) < 0) {
|
nbytes = sock_recv(clientSocketMap->socket, buffer, MAXMSG);
|
||||||
|
if (nbytes < 0)
|
||||||
|
{
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
report (RPT_DEBUG, "%s: Error on socket %d: %s", __FUNCTION__, filedes, strerror(errno));
|
report(RPT_DEBUG, "%s: Error on socket %d - %s",
|
||||||
|
__FUNCTION__, clientSocketMap->socket, sock_geterror());
|
||||||
return 0;
|
return 0;
|
||||||
} else if (nbytes == 0) /* EOF*/
|
} else if (nbytes == 0) /* EOF*/
|
||||||
return -1;
|
|
||||||
else if (nbytes > (MAXMSG - (MAXMSG / 8))) /* Very noisy client...*/
|
|
||||||
{
|
{
|
||||||
sock_send_string (filedes, "huh? Too much data received... quiet down!\n");
|
return -1;
|
||||||
report (RPT_WARNING, "%s: Too much data received on socket %d", __FUNCTION__, filedes);
|
} else if (nbytes > (MAXMSG - (MAXMSG / 8))) /* Very noisy client...*/
|
||||||
|
{
|
||||||
|
sock_send_string(clientSocketMap->socket, "huh? Too much data received... quiet down!\n");
|
||||||
|
report(RPT_WARNING, "%s: Too much data received on socket %d",
|
||||||
|
__FUNCTION__, clientSocketMap->socket);
|
||||||
return -1;
|
return -1;
|
||||||
} else /* Data Read*/
|
} else /* Data Read*/
|
||||||
{
|
{
|
||||||
@@ -245,13 +418,16 @@ sock_read_from_client (int filedes)
|
|||||||
if (buffer[i] == 0)
|
if (buffer[i] == 0)
|
||||||
buffer[i] = '\n';
|
buffer[i] = '\n';
|
||||||
/* Enqueue a "client message" here...*/
|
/* Enqueue a "client message" here...*/
|
||||||
c = clients_find_client_by_sock (filedes);
|
/* c = clients_find_client_by_sock (filedes); - Deprecated by clientsocketmap*/
|
||||||
if (c) {
|
if (clientSocketMap->client) {
|
||||||
client_add_message (c, buffer);
|
client_add_message(clientSocketMap->client, buffer);
|
||||||
} else
|
} else {
|
||||||
report (RPT_DEBUG, "%s: Can't find client %d", __FUNCTION__, filedes);
|
report(RPT_DEBUG, "%s: Can't find client %d",
|
||||||
|
__FUNCTION__, clientSocketMap->socket);
|
||||||
|
}
|
||||||
|
|
||||||
report (RPT_DEBUG, "%s: got message from client %d: \"%s\"", __FUNCTION__, filedes, buffer);
|
report(RPT_DEBUG, "%s: got message from client %d: \"%s\"",
|
||||||
|
__FUNCTION__, clientSocketMap->socket, buffer);
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
return nbytes;
|
return nbytes;
|
||||||
|
|||||||
+2
-2
@@ -17,9 +17,9 @@
|
|||||||
typedef struct sockaddr_in sockaddr_in;
|
typedef struct sockaddr_in sockaddr_in;
|
||||||
|
|
||||||
/* Server functions...*/
|
/* Server functions...*/
|
||||||
int sock_init ();
|
int sock_init(char* bind_addr, int bind_port);
|
||||||
int sock_shutdown();
|
int sock_shutdown();
|
||||||
int sock_create_inet_socket (char * addr, unsigned int port);
|
int sock_create_inet_socket(char* bind_addr, unsigned int port);
|
||||||
int sock_poll_clients();
|
int sock_poll_clients();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user