/*

*/

#include	"trust.h"
#include	"shm.h"
#include	"repeater.h"


int Repeater(void)
{
	struct	repMsg	reqConMsg;
	
	int	ret;
	int	width;
	int	n;
	int	numrcv;
	int	opt;
	int	KeepAliveTimer;
        fd_set  readOk, Mask;
        struct  timeval timeout;

	char	line[20];

        FD_ZERO(&Mask);
        FD_SET(Acc, &Mask);
        FD_SET(0, &Mask);
        width = Acc+1;


	if (login(Acc))
	{
        	//ポート番号の要求 
	        send(Acc, "Port Number: ", 13, 0);
	
      		//ポート番号の受信
	        numrcv = recv(Acc, line, 10, 0);
	      	line[numrcv] = 0x00;
		for (n = 0 ; n < numrcv ; n++)
        	{
                	if (line[n] == 0x0a) line[n] = 0x00;
                	if (line[n] == 0x0d) line[n] = 0x00;
        	}
        	Port = htons(atoi (line));

		logfile = fopen (LOGFILE, "a");
		now = time(NULL);
		fprintf (logfile, "%24.24s Port Number: %d\n", ctime(&now), ntohs(Port));
		fclose (logfile);

		dbSock = socket(AF_INET, SOCK_DGRAM, 0);
        	opt=1;
        	if (setsockopt(dbSock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int)) != 0){
                	perror("setsockopt");
                	exit(-1);
        	}

		memcpy (send_msg.trust_name, TrustName, 16);
		memcpy (send_msg.rep_name, RepeaterCall, 8);
                send_msg.type = RepActive;
                send_msg.protocol = G3;
                dbAddr.sin_family = AF_INET;
                dbAddr.sin_port = dbOutPort;
                dbAddr.sin_addr = dbIP;
                sendto (dbSock, (char *)&send_msg, 
			sizeof (struct shm_form), 0,
                        (struct sockaddr *)&dbAddr, sizeof(dbAddr));
		KeepAliveTimer = 0;

		while(1){
			readOk = Mask;
			timeout.tv_sec = 0;
			timeout.tv_usec = 5000;
			switch (select(width, (fd_set *)&readOk, NULL, NULL, &timeout)){
                        	case    -1:
                                	perror("child select");
                                	break;

                       		case    0:
					for (n = 0 ; n < MAX_SHM ; n++)
					{
						if (shm_msg->shmem[n].mem.type == ReqConnect)
						{ 
							if (memcmp(shm_msg->shmem[n].mem.dstRep, RepeaterCall, 8) == 0) 
							{
								logfile = fopen (LOGFILE, "a");
								now = time(NULL);
								fprintf (logfile, "%24.24s ReqC %2.2x %8.8s %8.8s %8.8s %8.8s\n", ctime(&now),
									shm_msg->shmem[n].mem.type, 
									shm_msg->shmem[n].mem.srcCall, 
									shm_msg->shmem[n].mem.dstCall,
									RepeaterCall,
									shm_msg->shmem[n].mem.dstRep);
								fclose (logfile);
								reqConMsg.reqType = ReqConnect;
								reqConMsg.reqConnect.protocol = shm_msg->shmem[n].mem.protocol;
								reqConMsg.reqConnect.ip = shm_msg->shmem[n].mem.srcIP;
								memcpy (reqConMsg.reqConnect.Rpt2Call, 
									shm_msg->shmem[n].mem.Rep2Call, 32);
                                                                reqConMsg.reqConnect.PacketID[0] = shm_msg->shmem[n].mem.PacketID[0];
                                                                reqConMsg.reqConnect.PacketID[1] = shm_msg->shmem[n].mem.PacketID[1];
								reqConMsg.reqConnect.port = shm_msg->shmem[n].mem.srcPort;
								memcpy (reqConMsg.reqConnect.trustname, TrustName, 16);
								send(Acc, (char *)&reqConMsg, sizeof(reqConMsg), 0);
								shm_msg->shmem[n].mem.type = NoEntry;
							}
						}
                                                else if (shm_msg->shmem[n].mem.type == Ack)
                                                {
                                                        if (memcmp(shm_msg->shmem[n].mem.Rep1Call, RepeaterCall, 8) == 0)
                                                        {
                                                                memcpy (reqConMsg.ackConnect.YourCall,
                                                                        shm_msg->shmem[n].mem.dstCall, 8);
                                                                reqConMsg.ackConnect.ip = shm_msg->shmem[n].mem.srcIP;
                                                                reqConMsg.ackConnect.port = shm_msg->shmem[n].mem.srcPort;
                                                                reqConMsg.reqType = Ack;
								reqConMsg.ackConnect.PacketID[0] = shm_msg->shmem[n].mem.PacketID[0];
								reqConMsg.ackConnect.PacketID[1] = shm_msg->shmem[n].mem.PacketID[1];
								reqConMsg.ackConnect.RespFlags = RespAck;
								logfile = fopen (LOGFILE, "a");
								now = time(NULL);
                                                                fprintf (logfile, "%24.24s Ack %2.2x %8.8s %d %s\n", ctime(&now), reqConMsg.reqType,
                                                                        reqConMsg.ackConnect.YourCall,
									ntohs(reqConMsg.ackConnect.port),
                                                                        inet_ntoa(reqConMsg.ackConnect.ip));
								fclose (logfile);
                                                                memcpy (reqConMsg.ackConnect.trustname, TrustName, 16);
                                                                send (Acc, (char *)&reqConMsg, sizeof(reqConMsg), 0);
                                                                shm_msg->shmem[n].mem.type = NoEntry;
                                                        }
                                                }
						else if (shm_msg->shmem[n].mem.type == Nak)
						{
                                                        if (memcmp(shm_msg->shmem[n].mem.Rep1Call, RepeaterCall, 8) == 0)
                                                        {
                                                                memcpy (reqConMsg.ackConnect.YourCall,
                                                                        shm_msg->shmem[n].mem.dstCall, 8);
                                                                reqConMsg.ackConnect.ip = shm_msg->shmem[n].mem.srcIP;
                                                                reqConMsg.ackConnect.port = shm_msg->shmem[n].mem.srcPort;
                                                                reqConMsg.reqType = Nak;
								reqConMsg.ackConnect.RespFlags = RespBusy;
                                                                reqConMsg.ackConnect.PacketID[0] = shm_msg->shmem[n].mem.PacketID[0];
                                                                reqConMsg.ackConnect.PacketID[1] = shm_msg->shmem[n].mem.PacketID[1];
								logfile = fopen (LOGFILE, "a");
								now = time(NULL);
                                                                fprintf (logfile, "%24.24s Nak %2.2x %8.8s %d %s\n", ctime(&now), reqConMsg.reqType,
                                                                        reqConMsg.ackConnect.YourCall,
                                                                        ntohs(reqConMsg.ackConnect.port),
                                                                        inet_ntoa(reqConMsg.ackConnect.ip));
								fclose (logfile);
                                                                memcpy (reqConMsg.reqConnect.trustname, TrustName, 16);
                                                                send (Acc, (char *)&reqConMsg, sizeof(reqConMsg), 0);
                                                                shm_msg->shmem[n].mem.type = NoEntry;
                                                        }
						}
                                                else if (shm_msg->shmem[n].mem.type == NoRoute)
                                                {
                                                        if (memcmp(shm_msg->shmem[n].mem.Rep1Call, RepeaterCall, 8) == 0)
                                                        {
                                                                memcpy (reqConMsg.ackConnect.YourCall,
                                                                        shm_msg->shmem[n].mem.dstCall, 8);
                                                                reqConMsg.ackConnect.ip = shm_msg->shmem[n].mem.srcIP;
                                                                reqConMsg.ackConnect.port = shm_msg->shmem[n].mem.srcPort;
                                                                reqConMsg.reqType = Nak;
                                                                reqConMsg.ackConnect.RespFlags = RespNoRoute;
								logfile = fopen (LOGFILE, "a");
								now = time(NULL);
                                                                fprintf (logfile, "%24.24s %2.2x %8.8s %d %s\n", ctime(&now), reqConMsg.reqType,
                                                                        reqConMsg.ackConnect.YourCall,
                                                                        ntohs(reqConMsg.ackConnect.port),
                                                                        inet_ntoa(reqConMsg.ackConnect.ip));
								fclose (logfile);
                                                                memcpy (reqConMsg.ackConnect.trustname, TrustName, 16);
                                                                send (Acc, (char *)&reqConMsg, sizeof(reqConMsg), 0);
                                                                shm_msg->shmem[n].mem.type = NoEntry;
                                                        }
                                                }
					}
                        		if (KeepAliveTimer++ > 2000)
                        		{
                                		memcpy (send_msg.trust_name, TrustName, 16);
                                		memcpy (send_msg.rep_name, RepeaterCall, 8);
                                		send_msg.type = RepActive;
                                		send_msg.protocol = G3;
                                		dbAddr.sin_family = AF_INET;
                                		dbAddr.sin_port = dbOutPort;
                                		dbAddr.sin_addr = dbIP;
                                		sendto (dbSock, (char *)&send_msg,
                                        		sizeof (struct shm_form), 0,
                                        		(struct sockaddr *)&dbAddr, sizeof(dbAddr));
                                		KeepAliveTimer = 0;
                        		}
                                	break;

                       	 	default:
                                	if (FD_ISSET(Acc, &readOk)){
						ret = recv(Acc, (char *)&reqConMsg, sizeof(reqConMsg), 0);
						if (ret <= 0) {
							perror("recv");
							goto exit_00;
						}
						if (ret > 0)
						{
							if (DoCommand(reqConMsg) == -1){
								/* end */
								goto exit_00;
							}
						}
					}
			}
		}
	}
exit_00:

	return(0);
}

int DoCommand(struct repMsg com)
{
        int     ret;
	int	n;

	ret = 0;

        if (com.reqType == ReqConnect)
	{
		memcpy (&send_msg.Rep2Call, &com.reqConnect.Rpt2Call, 32);
               	send_msg.srcIP = RepeaterIP;
               	send_msg.srcPort = Port;
		memcpy (&send_msg.dstRep, com.reqConnect.YourCall, 8);
               	send_msg.type = com.reqType;
               	send_msg.protocol = com.reqConnect.protocol;
                dbAddr.sin_family = AF_INET;
                dbAddr.sin_port = dbOutPort;
                dbAddr.sin_addr = dbIP;
		ret = sendto (dbSock, (char *)&send_msg, sizeof (struct shm_form), 0,
				(struct sockaddr *)&dbAddr, sizeof(dbAddr));
        }
	else
	{
		shmdt (shm_msg);
		ret = -1;
	}
        return(ret);
}

