/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	HTTPListener.cpp
 *
 *****************************************************************************/


#include <sol\Stdio.h>
#include <sol\SocketSelector.h>

#include "HTTPListener.h"
#include "HTTPCommunicator.h"



HTTPListener::HTTPListener(SolWebServer* viewer)
	:Thread(),
	webServer(viewer)
{
	Printf("HTTPListener::HTTPListener()\r\n");

	looping = False;
	unsigned short port = webServer ->getPort();
	listener = createListenSocket(port);
	if (listener) {
		looping = True;
	}
}


HTTPListener::~HTTPListener() 
{
	Printf("HTTPListener::~HTTPListener()\r\n");
	delete listener;
}


SocketStream* HTTPListener::createListenSocket(unsigned short port)	
{
	SocketStream* listener = new SocketStream(AF_INET, 0);

	if (listener == null) {
		return null;
	}

	// 1999.08.25
	int option = 1;
	listener -> setOption(SO_REUSEADDR, (char*)&option, sizeof(option));
	
	InetAddress addr(port, INADDR_ANY);

	if (listener -> bind(addr) != 0) {
		webServer -> append("Bind failed.\r\n");
		delete listener;
		return null;
	}

	if (listener -> listen(5) !=0) {
		webServer -> append("Listen failed.\r\n");
		delete listener;
		return null;
	}
	return listener;	
}	


void  HTTPListener::run()
{
	if (listener == null) {
		webServer -> append("HTTPListener terminated.\r\n");
		return;
	}

    listener -> nonBlocking();

    SocketSelector selector;

    selector.setTimeout(0, 100);

    while (looping) {   
        selector.clearAll();
        selector.setReadable(listener);
 
		if (looping == False) break;

        if (selector.select() != SOCKET_ERROR) {
			if (looping == False) break;
            if (selector.isReadable(listener)) {
				InetAddress addr;
	            SocketStream* socket = listener -> accept(addr);
	            if (socket == NULL) {
		            webServer -> append("Accept failed\r\n");
                    break;
                } else {
                    HTTPCommunicator* comm = new HTTPCommunicator(socket, webServer);
                    comm -> start();
                }
            }
        } else {
            break;
        }
    }
}


void HTTPListener::stop()
{
    looping = False;

	if (listener) {	
		listener -> shutdown(2);
	}
}
