/*
 * FBA - SocketModule
 *
 * Rel 0.1 - 26/04/2008 - By EvilMaio
 *
 */
#ifdef SOCKET_MODULE

--wontcompile--

#ifdef UNDER_CE
	#include "winsock.h"
#endif


#define SOCKETENGINE_BUFFERSIZE 8192

bool socketEngineInit = false;
bool wannaShutdownSocketEngine = false;
HANDLE socket_thread = 0;

struct myWSABUF {
    u_long      len;     /* the length of the buffer */
    char FAR *  buf;     /* the pointer to the buffer */
};

typedef struct _SOCKETENGINE_MYSOCKET_INFORMATION {
	CHAR Buffer[SOCKETENGINE_BUFFERSIZE];
	myWSABUF DataBuf;
	SOCKET Socket;
	OVERLAPPED Overlapped;
	DWORD SendBytes;
	DWORD RecvBytes;
} SOCKETENGINE_SOCKET_INFORMATION, * SOCKETENGINE_LPSOCKET_INFORMATION;

DWORD socketEngine_TotalSockets = 0;
SOCKETENGINE_LPSOCKET_INFORMATION socketEngine_SocketList[FD_SETSIZE];


//
static DWORD WINAPI RunningThreadSocketEngine(LPVOID param) {

	lua_State *LUA=(lua_State *)param;

	while (!wannaShutdownSocketEngine) {
	} // while (!wannaShutdownSocketEngine) {

	// chiusura del thread
	socketEngineInit = false;
	wannaShutdownSocketEngine = false;

	// libera la dll di winsock
	WSACleanup();

	return 0;
} // RunningThreadSocketEngine

//
int luaInitSocketEngine(lua_State *pL)
{
	if (socketEngineInit)
		return 0;	// niente da fare, engine già aperto

	// setta a null tutti i puntatori dei sockets
	for (int s=0; s < FD_SETSIZE; s++)
		socketEngine_SocketList[s]=NULL;

	// inizializza la dll di winsock
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(2, 0); 
    int err = WSAStartup(wVersionRequested, &wsaData );
	if (err != 0) {
		lua_pushboolean(pL, false);
		return 1;
	}

	// crea thread che processa i messaggi del socket
	PFrogConsole::instance()->addconsole(0, "SOCKET ENGINE INITIALIZATED!");

	socket_thread = CreateThread(NULL, 0, RunningThreadSocketEngine, pL, 0, NULL);
	SetThreadPriority(socket_thread, THREAD_PRIORITY_NORMAL);

	socketEngineInit = true;

	lua_pushboolean(pL, true);
	return 1;
} // int luaInitSocketEngine(lua_State *pL)


//
int luaCloseSocketEngine(lua_State *pL)
{
	if (!socketEngineInit)
		return 0;	// niente da fare, engine già chiuso

	// todo: chiusura di tutti i sockets...

	wannaShutdownSocketEngine=true;

} // int luaCloseSocketEngine(lua_State *pL)


//
// createsocket()
int luaCreateSocket(lua_State *pL)
{	
	SOCKETENGINE_LPSOCKET_INFORMATION SI;

	// cerca un socket libero e allocalo, torna l'indice del socket allocato o false in caso di errore
	int found=-1;
	for (int s=0; s < FD_SETSIZE; s++) {
		if (!socketEngine_SocketList[s]) {
			if ((SI = (SOCKETENGINE_LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKETENGINE_SOCKET_INFORMATION))) == NULL) {
				// non posso allocare
				PFrogConsole::instance()->addconsole(0, "GlobalAlloc() - UNABLE TO ALLOCATE SOCKET INFO");
			} else {
				// socket allocato
				found=s;
				
				// Prepare SocketInfo structure for use.
				SI->Socket = socket(domain, type, protocol);
				SI->SendBytes = 0;
				SI->RecvBytes = 0;
				socketEngine_SocketList[s] = SI;
				socketEngine_TotalSockets++;

				PFrogConsole::instance()->addconsole(0, "SOCKET INFO ALLOCATED %d", s);
			}
			break;
		}
	}
	if (found == -1)
		lua_pushboolean(pL, false);
	else
		lua_pushnumber(pL, found);

	return 1;
} // luaCreateSocket

#endif
