#include <config.h>
#include <stdio.h>
#include <iiimp.h>
#include "IIIMProtocol.hh"
#include "IIIMP_IMState.hh"
#include "IIIMPTrans.hh"

bool
IIIMProtocol::restart(
    IMSocketAddressVec &addrvec
)
{
    if (pimsl) delete pimsl;

    pimsl = new IMSocketListen();
    if (!pimsl) return false;

    return pimsl->listen(addrvec);
}

bool
IIIMProtocol::receive_and_dispatch(
    IMState *pims,
    int flags
)
{
    IIIMP_IMState *pimst = (IIIMP_IMState*) pims; // we should use dynamic_cast.
    IIIMP_message *pmes;

    pmes = pimst->get_iiimptrans()->receive();
    if (pmes) {
	pimst->dispatch(pmes->im_id, pmes->ic_id, pmes);
	iiimp_message_delete(pimst->get_iiimptrans()->get_data_s(), pmes);
	return true;
    }
    if (!pimst->get_iiimptrans()->open_p()) {
	LOG_ERROR("Client shut down the connection owned by im_id(%d).",
		  pims->get_im_id());
	pims->destroy();
	return false;
    }

    return true;  // direct IMScheduler to maintain this IMState.
}

IMState*
IIIMProtocol::accept(
    int flags
)
{
    IIIMPTrans *pimt;
    IIIMP_IMState *pims;

    if (!pimsl) {
	LOG_CRITICAL("I don't have any listening manner.  Immediately exit.");
	exit(255);
    }

    IMSocketTrans *pimst = pimsl->accept();
    if (!pimst) return NULL;
    pimt = new IIIMPTrans(pimst);
    if (!pimt) {
	delete pimst;
	return NULL;
    }
    if (!pimaccept->request_accept(pimt->get_fd())) {
	delete pimt;
	return NULL;
    }
    
    pims = new IIIMP_IMState(this, pimt,
			     iiimp_data_s_get_protocol_version(pimt->get_data_s()));
    // memory error.
    if (!pims) return NULL;
    add_imstate(pims);

    return pims;
}

bool
IIIMProtocol::set_server_listen_address(
    IMSocketAddressVec &addrvec
)
{
    return restart(addrvec);
}


IIIMProtocol::IIIMProtocol(
    IMAccept *pima
) : IMProtocol(pima)
{
    pimsl = NULL;
}

IIIMProtocol::~IIIMProtocol()
{
    if (pimsl) delete pimsl;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
