/*
 ** author: zhouchao
 ** date: 2019-03-28
 ** version: 1.00
 ** e-mail:  zhouchao@storlead.com  1959353124@qq.com
 ** brief: LM73 driver
 **
*/

#include "./lanTask.h"
#include "bmc_main.h"
#include "bmc_type.h"
#define    BUF_LEN	128

uint8_t REC_BUF[BUF_LEN];
uint8_t	SEND_BUF[BUF_LEN];

//#define IPMI	(REC_BUF[0]==0x06&&REC_BUF[1]==0x00&&REC_BUF[2]==0xff&&(REC_BUF==0x06||REC_BUF==0x07))

int LanTask(void)
{
	int socket=0;
	char **argv;
	int reclan_len=0;
	int i=0;
	unsigned short clientport = 0;
        char clientIP[50] = {0};
	struct sockaddr_in clientAddr;
	socket=udpserver_init(3,argv);
	
	if(socket<0)
	  {
		printf("create socket fial!!!\n");
		return -1;
	  }
	while(1)
	  {
//		printf("start receiver lan fream:\n");
		reclan_len=udp_receiver(socket,REC_BUF,BUF_LEN,&clientAddr);
		clientport = ntohs(clientAddr.sin_port);
		strcpy(clientIP, inet_ntoa(clientAddr.sin_addr));
	  
//	printf("Recv len: %d, from ip %s:%d\n",reclan_len, clientIP, clientport);


//		printf("receiver data leng is %d ,data is :\n",reclan_len);
//		for(i=0;i<reclan_len;i++)
		  {
//		  	if(i%16==0)
//			  printf("\n");
//			printf("%#x  ",REC_BUF[i]);	 
		  }
		if(REC_BUF[0]==0x06&&REC_BUF[1]==0x00&&REC_BUF[2]==0xff)
			switch(REC_BUF[3])
			{
				case 0x06:
					cmd_asf(socket,REC_BUF,reclan_len,&clientAddr);
					break;
		  		case 0x07:
					cmd_ipmi(socket,REC_BUF,reclan_len,&clientAddr);
					break;
		  		default :
					break;

			}	

	  }
	return 0;
}


int cmd_asf(int socket,char * REC_BUF,uint16_t rec_len,struct sockaddr_in * clientAddr)
{
	int i=0;
	ASF_Pong_Message  pong_struct;
	for(i=0;i<rec_len;i++)
	  {
		pong_struct.Data[i]=REC_BUF[i];
	  }
	pong_struct.AST_T.MessageType=0x40;
	pong_struct.AST_T.OEM_IANA[0]  = 0x00;
        pong_struct.AST_T.OEM_IANA[1]  = 0x00;
        pong_struct.AST_T.OEM_IANA[2]  = 0x8e;
        pong_struct.AST_T.OEM_IANA[3]  = 0x71;
	pong_struct.AST_T.Oem_def[0]   = 0x03;
	pong_struct.AST_T.Oem_def[1]   = 0x00;
	pong_struct.AST_T.Oem_def[2]   = 0x00;
	pong_struct.AST_T.Oem_def[3]   = 0x00;
	pong_struct.AST_T.DataLen      = 0x10;
	pong_struct.AST_T.SupportEntities=0x81;
	pong_struct.AST_T.SupportInteractions=0x00;
	pong_struct.AST_T.Reserved3[0] = 0;
	pong_struct.AST_T.Reserved3[1] = 0;
	pong_struct.AST_T.Reserved3[2] = 0;
	pong_struct.AST_T.Reserved3[3] = 0;
	pong_struct.AST_T.Reserved3[4] = 0;
	pong_struct.AST_T.Reserved3[5] = 0;

	if(udp_send(socket,pong_struct.Data,sizeof(pong_struct.Data),clientAddr)<=0)
		printf("send fail!\n");
//	printf("send success !!!\n");
//	printf("\n");
	return 0;
}

int cmd_ipmi(int socket,char * REC_BUF,uint16_t len,struct sockaddr_in * clientAddr)
{
	int i=0,j=0;
	char	Type;
	MsgPkt_T pReq,pRes;
	INT16U clientport;	
	uint32_t	rec_len=len;
	uint32_t	send_len;
	IPMI_Message  IpmiMessage_struct;
        char    SequenceNumber[4]={0x1c,0xb6,0xe8,0xf3};
        char    SessionId[4]={0xfb,0x2d,0xb5,0xff};

	clientport = ntohs(clientAddr->sin_port);
	
	memset(&IpmiMessage_struct,0,sizeof(IPMI_Message));
	Type=GetType(REC_BUF,&rec_len);
	
	//add udp lan message 
	memcpy(IpmiMessage_struct.Data,REC_BUF,rec_len);
	pReq.Channel=1;
	pReq.Param=PARAM_IFC;
        pReq.Privilege=4;
        pReq.ResTimeOut=WAIT_INFINITE;
        pReq.UDPPort=clientport;
	pReq.Socket=socket;
	pReq.Size=IpmiMessage_struct.AST_T.MessageLength;
	
	//send to MsgHndlr.c
	memcpy(pReq.Data,IpmiMessage_struct.AST_T.MessageData,pReq.Size);	
	pReq.NetFnLUN=pReq.Data[1];
	pReq.Cmd=pReq.Data[5];
	strcpy(pReq.SrcQ,OBSM_TASK_Q);
	strcpy(pReq.IPAddr,inet_ntoa(clientAddr->sin_addr));
	PostMsg (&pReq,MSG_HNDLR_Q);	
	
	//receiver from MsgHndlr.c	
	GetMsg (&pRes,OBSM_TASK_Q,WAIT_INFINITE);	
	IpmiMessage_struct.AST_T.MessageLength=pRes.Size;
	memcpy(IpmiMessage_struct.AST_T.MessageData,pRes.Data,pRes.Size);	
	pRes.Data[0]=pReq.Data[3];//source addr
	pRes.Data[1]=((pReq.Data[1]>>2)+1)<<2;//netfn
	pRes.Data[3]=pReq.Data[0];//target addr
	pRes.Data[4]=pReq.Data[4];
	pRes.Data[5]=pReq.Data[5];
	//MD5 add authentication code
	if(Type==MD5)
	  {
		memcpy(IpmiMessage_struct.AST_T.Sequence_Number,SequenceNumber,4);
		IpmiMessage_struct.AST_T.Sequence_Number[0]=IpmiMessage_struct.AST_T.Sequence_Number[0]+SessionSequenceNumberCount;
		memcpy(IpmiMessage_struct.AST_T.Session_ID,SessionId,4);
	  }

	//calculate checksum
	pRes.Data[pRes.Size]=0x00;//checksum is 0	
	CalculateCheckSum2(pRes.Data,pRes.Size+1);
	CalculateCheckSum(pRes.Data,pRes.Size+1);
	pRes.Size=pRes.Size+1;
	IpmiMessage_struct.AST_T.MessageLength=pRes.Size;
	memcpy(IpmiMessage_struct.AST_T.MessageData,pRes.Data,pRes.Size);
	
	//send ipmi response 
	send_len=AddToSendBuf(SEND_BUF,&IpmiMessage_struct);
	if(udp_send(socket,SEND_BUF,send_len,clientAddr)<=0)
                printf("send fail!\n");
	
//        printf("send success !!!\n");
//        printf("\n");
	return 0;
}


char GetType(char *REC_BUF,uint32_t *rec_len)
{
	int i;
        if(REC_BUF[4]==MD5)
	  {
            for(i=13;i<*rec_len-16;i++)
              {
                REC_BUF[i]=REC_BUF[i+16];
              }
	    *rec_len=*rec_len-16;
	  }
	return REC_BUF[4];
}

int AddToSendBuf(char *SEND_BUF,IPMI_Message * IpmiMessage_struct)
{
	char    authent[16]={ 0xfa,0x6f,0x65,0xe4,
                              0xea,0xec,0xaa,0xa0,
                              0x92,0x27,0x95,0xbd,
                              0xf2,0xa9,0x9d,0xcb
			    };
		int i=0;

		if(IpmiMessage_struct->AST_T.MessageType==MD5)
		  {
			memcpy(SEND_BUF,&IpmiMessage_struct->Data[0],13);
			memcpy(&SEND_BUF[13],authent,16);
			SEND_BUF[29]=IpmiMessage_struct->AST_T.MessageLength;
			memcpy(&SEND_BUF[30],&IpmiMessage_struct->AST_T.MessageData[0],IpmiMessage_struct->AST_T.MessageLength);
			return IpmiMessage_struct->AST_T.MessageLength+14+16;
		  }
		else
		  {
			for(i=0;i<IpmiMessage_struct->AST_T.MessageLength+14;i++)
				SEND_BUF[i]=IpmiMessage_struct->Data[i];
			return IpmiMessage_struct->AST_T.MessageLength+14;
		  }
}
	
