foundation2_fluffos_v1/
foundation2_fluffos_v1/bin/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/ChangeLog.old/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/Win32/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/compat/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/compat/simuls/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/include/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/clone/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/command/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/data/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/etc/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/include/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/inherit/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/inherit/master/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/log/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/compiler/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/efuns/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/operators/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/u/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/tmp/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/windows/
foundation2_fluffos_v1/lib/cfg/
foundation2_fluffos_v1/lib/cmds/adm/
foundation2_fluffos_v1/lib/daemon/save/
foundation2_fluffos_v1/lib/daemon/services/
foundation2_fluffos_v1/lib/daemon/soul/
foundation2_fluffos_v1/lib/doc/build/
foundation2_fluffos_v1/lib/doc/classes/
foundation2_fluffos_v1/lib/doc/driver/
foundation2_fluffos_v1/lib/doc/driver/applies/
foundation2_fluffos_v1/lib/doc/driver/applies/interactive/
foundation2_fluffos_v1/lib/doc/driver/concepts/
foundation2_fluffos_v1/lib/doc/driver/driver/
foundation2_fluffos_v1/lib/doc/driver/efuns/arrays/
foundation2_fluffos_v1/lib/doc/driver/efuns/buffers/
foundation2_fluffos_v1/lib/doc/driver/efuns/calls/
foundation2_fluffos_v1/lib/doc/driver/efuns/compile/
foundation2_fluffos_v1/lib/doc/driver/efuns/filesystem/
foundation2_fluffos_v1/lib/doc/driver/efuns/floats/
foundation2_fluffos_v1/lib/doc/driver/efuns/functions/
foundation2_fluffos_v1/lib/doc/driver/efuns/general/
foundation2_fluffos_v1/lib/doc/driver/efuns/mappings/
foundation2_fluffos_v1/lib/doc/driver/efuns/numbers/
foundation2_fluffos_v1/lib/doc/driver/efuns/parsing/
foundation2_fluffos_v1/lib/doc/driver/lpc/constructs/
foundation2_fluffos_v1/lib/doc/driver/lpc/types/
foundation2_fluffos_v1/lib/doc/driver/platforms/
foundation2_fluffos_v1/lib/doc/efun/
foundation2_fluffos_v1/lib/doc/etc/
foundation2_fluffos_v1/lib/doc/faq/
foundation2_fluffos_v1/lib/doc/help/creator/
foundation2_fluffos_v1/lib/doc/help/player/
foundation2_fluffos_v1/lib/doc/lpc/basic/
foundation2_fluffos_v1/lib/doc/lpc/data_types/
foundation2_fluffos_v1/lib/doc/lpc/etc/
foundation2_fluffos_v1/lib/doc/lpc/intermediate/
foundation2_fluffos_v1/lib/doc/lpc/types/
foundation2_fluffos_v1/lib/doc/mudlib/
foundation2_fluffos_v1/lib/doc/mudlib/Features/
foundation2_fluffos_v1/lib/domains/Examples/armour/
foundation2_fluffos_v1/lib/domains/Examples/etc/
foundation2_fluffos_v1/lib/domains/Examples/npc/
foundation2_fluffos_v1/lib/domains/Examples/room/
foundation2_fluffos_v1/lib/domains/Examples/virtual/
foundation2_fluffos_v1/lib/domains/Examples/virtual/exaA/
foundation2_fluffos_v1/lib/domains/Examples/virtual/exaB/
foundation2_fluffos_v1/lib/domains/Examples/weapon/
foundation2_fluffos_v1/lib/domains/School/doc/
foundation2_fluffos_v1/lib/domains/School/room/
foundation2_fluffos_v1/lib/domains/School/room/Classes/
foundation2_fluffos_v1/lib/domains/School/room/Offices/
foundation2_fluffos_v1/lib/domains/Standard/
foundation2_fluffos_v1/lib/domains/Standard/pools/
foundation2_fluffos_v1/lib/domains/Standard/std/
foundation2_fluffos_v1/lib/domains/Standard/xtra/
foundation2_fluffos_v1/lib/include/
foundation2_fluffos_v1/lib/lib/obj/
foundation2_fluffos_v1/lib/news/
foundation2_fluffos_v1/lib/save/
foundation2_fluffos_v1/lib/secure/cfg/
foundation2_fluffos_v1/lib/secure/cmds/player/
foundation2_fluffos_v1/lib/secure/lib/
foundation2_fluffos_v1/old/
foundation2_fluffos_v1/win32/
/*    /lib/server.c
 *    from the Nightmare IV LPC Library
 *    a TCP server object
 *    created by Descartes of Borg 950429
 */

#include <lib.h>
#include <network.h>
#include "server.h"

inherit LIB_DAEMON;

private static int DestructOnClose;
private static function Read;
private static class server Listen;
private static mapping Sockets;

static void create() {
    daemon::create();
    Sockets = ([]);
}

int eventCreateSocket(int port) {
    int x;

    Listen = new(class server);
    Listen->Blocking = 0; /* servers are not blocking to start */
    x = socket_create(STREAM, "eventServerReadCallback", 
		      "eventServerAbortCallback");
    if( x < 0 ) {
	eventSocketError("Error in socket_create().", x);
	return x;
    }
    Listen->Descriptor = x;
    x = socket_bind(Listen->Descriptor, port);
    if( x != EESUCCESS ) {
	eventClose(Listen);
	eventSocketError("Error in socket_bind().", x);
	return x;
    }
    x = socket_listen(Listen->Descriptor, "eventServerListenCallback");
    if( x != EESUCCESS ) {
	eventClose(Listen);
	eventSocketError("Error in socket_listen().", x);
	return x;
    }
}

static void eventServerListenCallback(int fd) {
    int x;

    x = socket_accept(fd, "eventServerReadCallback", 
		      "eventServerWriteCallback");
    if( x < 0 ) {
	eventSocketError("Error in socket_accept().", x);
	return;
    }
    eventNewConnection(x);
}

static void eventServerAbortCallback(int fd) {
    if( Listen && Listen->Descriptor == fd) eventClose(Listen);
    else if( Sockets[fd] ) eventClose(Sockets[fd]);
}

static void eventServerReadCallback(int fd, string str) {
    if( functionp(Read) ) evaluate(Read, fd, str);
    else eventRead(fd, str);
}

static void eventRead(int fd, string str) { }

static void eventServerWriteCallback(int fd) {
    class server sock;
    int x;

    if( Listen && Listen->Descriptor == fd ) sock = Listen;
    else if( Sockets[fd] ) sock = (class server)Sockets[fd];
    else return;
    sock->Blocking = 0;
    if( !sock->Buffer && sock->Closing ) {
	eventClose(sock);
	return;
    }
    x = EESUCCESS;
    while( sock->Buffer && x == EESUCCESS ) {
	switch( x = socket_write(sock->Descriptor, sock->Buffer[0]) ) {
            case EESUCCESS:
	        break;
	    case EECALLBACK:
		sock->Blocking = 1;
		break;
	    case EEWOULDBLOCK: 
		call_out( (: eventServerWriteCallback :), 0, fd);
		return;
	    case EEALREADY:
		sock->Blocking = 1;
		return;
	    default:
		eventClose(sock);
		eventSocketError("Error in socket_write().", x);
		return;
	}
	if( sizeof(sock->Buffer) == 1 ) {
	    sock->Buffer = 0;
	    if( sock->Closing && !sock->Blocking ) eventClose(sock);
	}
	else sock->Buffer = sock->Buffer[1..];
    }
}

varargs void eventWrite(int fd, string str, int close) {
    class server sock;
    int x;

    if( Listen && Listen->Descriptor == fd ) sock = Listen;
    else if( Sockets[fd] ) sock = (class server)Sockets[fd];
    else return;
    if( sock->Buffer ) sock->Buffer += ({ str });
    else sock->Buffer = ({ str });
    sock->Closing = close;
    if( sock->Blocking ) return;
    else eventServerWriteCallback(sock->Descriptor);
}

static void eventClose(class server sock) {
    if( !sock ) return;
    if( Sockets[sock->Descriptor] ) map_delete(Sockets, sock->Descriptor);
    socket_close(sock->Descriptor);
    eventSocketClosed(sock->Descriptor);
    sock = 0;
    if( DestructOnClose && sock == Listen ) Destruct();
}

static void eventSocketClosed(int fd) { }

int eventDestruct() {
    if( daemon::eventDestruct() ) {
	eventClose(Listen);
	return 1;
    }
    else return 0;
}

static void eventNewConnection(int fd) {
    Sockets[fd] = new(class server);
    ((class server)Sockets[fd])->Descriptor = fd;
    ((class server)Sockets[fd])->Blocking = 0; 
}

static void eventSocketError(string str, int x) { }

function SetRead(function f) { return (Read = f); }

int SetDestructOnClose(int x) { return (DestructOnClose = x); }