static char sccsid[]="%Z% %M% %I% %E% %U%";
/************************************************/
/*												*/
/*	akamsgroop.c								*/
/*												*/
/*			coded by A.Kobayashi 2010/06/10		*/
/*												*/
/************************************************/
#include "akacommon.h"

extern tdtMsgCtl         tMsgCtl;
extern tdtClassCtlHead   tClassHead;

static char *nullstring = "";

/********************************************************/
/*                                                      */
/********************************************************/
static int _set_recv_msg_com(pPacket,tpInst)
char        *pPacket;
tdtInstance *tpInst;
{
	AKAMSGCOM *tpRcMsg;
	char **cppFilev;
	int iRc;
	tdtCommPackHead   *pHead;

	tpRcMsg = tpInst->recv_msg_com;
	cppFilev = (char **)((char *)tpRcMsg + sizeof(AKAMSGCOM));

	iRc = akb_set_recv_msg(pPacket,tpRcMsg,cppFilev,&tpInst->to_free);
	if (iRc < 0) {
		return iRc;
	}
	pHead = (pCommPackHead)pPacket;
	if (!tpRcMsg->msg_pmsg) tpRcMsg->msg_pmsg = nullstring;
	if (tpRcMsg->msg_mlen > 0)
		*(tpRcMsg->msg_pmsg+tpRcMsg->msg_mlen) = '\0';
	return 0;
}

/********************************************************/
/*                                                      */
/********************************************************/
static int _exec_func(iKind,tpClass,iThread,cpPacket)
int iKind; /* 1/0 = Command/Reply */
tdtClassCtl *tpClass;
int iThread;
char *cpPacket;
{
	int iRc,iHSize,iRc2,iDataSize;
	long lHnd;
	pRcPacketTable  pRc;
	pCommPackHead   pHead;
	tdtInstance    *tpInst;
	char           *p,cver;
	tdtMsgCom      *tpRcMsg;
	ushort          usClassId;
	int (*pFunc)();
/*
printf("_exec_func: iKind=%d\n",iKind);
*/
	tpInst = tpClass->instance;
	if (tpInst->to_free) {
		Free(tpInst->to_free);
		tpInst->to_free = NULL;
	}
	if (iRc=_set_recv_msg_com(cpPacket,tpInst)) {
		ERROROUT1("_exec_func:Recv msg invalid format ret=%d. Can't exec.",iRc);
		return iRc;
	}
	tpInst->kind = iKind;
	if (iKind) {
		pHead = (pCommPackHead)cpPacket;
		AKBGETHSIZE(pHead,iHSize)
		tpInst->used = 1;
		memcpy(tpInst->pack_head,cpPacket,iHSize);
		tpClass->used_count++;
		tClassHead.used_thread_total++;
	}
	pHead = tpInst->pack_head;
	tpRcMsg = tpInst->recv_msg_com;
	tpRcMsg->msg_resv = pHead->cph_sinf.ind_disp;
	lHnd = iThread<<16 | tpClass->class_id;
	pFunc = tpClass->func_name;
	iRc = pFunc(lHnd,tpInst->instance_data,tpInst->recv_msg_com);
	return 0;
}

/********************************************************
 *
 *    aka_get_msg(iWaitTime)
 *
 * ret  >0 のとき、パケットあり。
 *      =0 のとき、パケットなし。
 *      <0 のとき、エラーコード。
 ********************************************************/
int aka_get_msg(iWaitTime)
int  iWaitTime  ;	/* select システムコール時の WaitTime（1/10秒） */
{
	int iRc = 0;
	int iRcW,iRcR,iShutMode;
	int lmtime;
	struct timeval tmtime;
	int iMinWaitTime,iTimerMinWait;

DEBUGOUTL1(AKA_LOG_GROUP|200,"aka_get_msg: Enter iWaitTime=%d",iWaitTime);

	iShutMode = aka_shut_control(AKA_SHUT_GET,NULL);

DEBUGOUTL1(AKA_LOG_GROUP|200,"aka_get_msg: iShutMode=%d",iShutMode);

	tMsgCtl.get_msg_wait_time = iWaitTime*100;

	for (;;) {
		/****************
		 * タイマー処理 *
		 ****************/
		aka_timer_proc();

		/****************
		 * 待ち時間設定 *
		 ****************/
		iMinWaitTime = aka_get_min_wait_time(tMsgCtl.get_msg_wait_time);
		if (iShutMode && iMinWaitTime<0) iMinWaitTime = 0;

		/**********************
		 * パケットＲｅａｄ   *
		 **********************/
		iRc = aka_packet_read(iMinWaitTime);

		/**********************
		 * リターン値の設定  *
		 **********************/
		if (iRc) {
			break;
		}
		else if (iShutMode == 2) {
			iRc = AKB_CMD_FSHUT;
			break;
		}
		else if (iShutMode == 1) {
			iRc = AKB_CMD_SHUT;
			break;
		}
	}

DEBUGOUTL1(AKA_LOG_GROUP|200,"aka_get_msg: Exit iRc=%d",iRc);

	return iRc;
}

/*************************************************************/
/*************************************************************/
int aka_dispatch_msg()
{
	int iRc;

	iRc = aka_dispatch_recv_msg(NULL);
	return iRc;
}

int aka_dispatch_recv_msg(tpRecvIns)
tdtInstance *tpRecvIns;
{
	pRcPacketTable pRcCurrent;
	tdtCommPackHead  *pHead;
	tdtClassCtl *tpClass;
	int iThread,iRc,iMode,iKind;
	char *cpPacket;

	iThread = 1;
	tpClass = NULL;
	cpPacket = NULL;
	/* 受信用テーブル */
	while (pRcCurrent = (pRcPacketTable)akxs_rb_get_n(tMsgCtl.rb_rctl)) {
		cpPacket = pRcCurrent->sp_content;
		pHead = (pCommPackHead)cpPacket;
		tpClass = tClassHead.class;
		if (pHead->cph_sinf.ind_thrd) {
			/* Command Packet */
			iKind = 1;
		}
		else {	/* Return Packet */
			iKind = 0;
		}
		break;
	}
/*
printf("aka_dispatch_recv_msg: iKind=%d pRcCurrent=%08x\n",iKind,pRcCurrent);
*/
	if (pRcCurrent) {
		Free(pRcCurrent);
	}

	if (tpRecvIns && cpPacket) {
/*
akxaxdump("_set_recv_msg_com",cpPacket,32);
*/
		iRc = _set_recv_msg_com(cpPacket,tpRecvIns);
		if (iRc) {
			ERROROUT1("ComObj:Recv msg invalid format ret=%d. Can't exec.",iRc);
			if (cpPacket) Free(cpPacket);
		}
		else {
			iRc = AKB_CMD_RECVMSG;
		}
		return iRc;
	}
	else if (tpClass) {
		_exec_func(iKind,tpClass,iThread,cpPacket);
		if (cpPacket) Free(cpPacket);
		if (tMsgCtl.msg_opt & AKA_MSO_EXEC_NOFREE) {
			if ((iRc=Nofree(0)) >= 0) {
			/*
				PRINTOUTL1(tMsgCtl.rsv2,"aka_dispatch: nofree no=%d",iRc);
				DEBUGOUTL1(tMsgCtl.rsv2,"aka_dispatch: nofree no=%d",iRc);	*/
				PRDBGOUTL1(tMsgCtl.rsv2,"aka_dispatch: nofree no=%d",iRc);
			}
		}
	}
	iMode = aka_shut_control(AKA_SHUT_GET,NULL);
/*
printf("aka_dispatch_recv_msg: iMode=%d Rbget=%08x\n",iMode,akxs_rb_get(tMsgCtl.rb_rctl));
*/
	if (iMode == 2) {	/* FSHUT mode */
		return AKB_CMD_FSHUT;
	}
	else if (iMode == 1 &&	/* SHUT mode */
	   !(akxs_rb_get(tMsgCtl.rb_rctl))) {
		return AKB_CMD_SHUT;
	}
	return 0;
}

/********************************************************/
/*                                                      */
/********************************************************/
int aka_packet_read(iWaitTime)
int iWaitTime;	/* msec */
{
	fd_set readfds;
	struct timeval tval, *ptval;
	int iRc,ret;

	iRc = 0;

	/* set tval for read select() */
	tval.tv_sec  = 0;
	tval.tv_usec = 0;
	if (iWaitTime) {
		if (akxs_rb_get(tMsgCtl.rb_rctl)) tval.tv_usec = 1000;
		else tval.tv_sec = -1;

		if (iWaitTime>0 && tval.tv_sec<0) akxe_timer_set_msec(&tval,iWaitTime);
	}

	ptval = &tval;
	if (ptval->tv_sec < 0) ptval = NULL;
	akb_fd_zero(&readfds);
	ret = select(akb_fd_setsize(),&readfds,NULL,NULL,ptval);
	if (ret < 0) {
		ERROROUTL2(250,"aka_packet_read:select errno=%d [%s]",
		           errno,strerror(errno));
		if (errno == EINTR) {
			akb_fd_zero(&readfds);
			ret = 0;
		}
		else return -18505202 ;
	}
	if (akxs_rb_get(tMsgCtl.rb_rctl)) iRc = 1;

	return iRc;
}
