/*******************************************************************
 *                  Light Weight Chord Library 1.0                 *
 *  CopyRight(C) Yoshihide Matsumoto IDEON WorkingGroup 2003,2004  *
 *      matsumoto333@yahoo.co.jp (http://www.matchan.mydns.jp)     *
 *                                                                 *
 * Implementation of chord (Distributed Hash Table)                *
 * This program is distributed under GPL                           *
 * Light Weight Chord Library comes with ABSOLUTELY NO WARRANTY.   *
 * This is free software, and you are welcome to redistribute it   *
 * under certain conditions; read `COPYING' for details.           *
 *******************************************************************/


#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> //gethostbyname
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>


#include "protocol.h"
#include "mchord.h"
#include "misc.h"
#include "define.h"


#define MAX_CONNECT       32
#define CHUNK_DATA_SIZE 1400
#define RECV_BUFF       1024
#define HEADER_SIZE       22

extern  MChord *pMChord;

// *buff include hedder
// *data payload only


Protocol::Protocol(){
  
}


int Protocol::SocketInit(int port){

  int sock;
  int sock_optval = 1;
  struct sockaddr_in sock_addr;

  sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock_optval,
                 sizeof(sock_optval)) == -1){
    fprintf(stderr, "setsockopt error\n");
    close(sock);
    exit(-1);
  }
  
  sock_addr.sin_family = AF_INET;
  sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  sock_addr.sin_port = htons(port);
  
  if ( bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0){
    fprintf(stderr, "bind error\n");
    exit(-1);
  }
  
  return sock;
}



//Call by GUI
void Protocol::RecvPacket(int sock){
  
  int  from_len, n;
  struct sockaddr_in from_addr;
  char buff[RECV_BUFF];
  char ipbuf[32];
  ADDRESS address;
  short int func;
  short int port;
  int  seqno;
  int  packet_len;
  
  //1回で取り出さないとUDPは捨てられる MSG_TRUNC
  n = recvfrom(sock, buff, RECV_BUFF, 0, (sockaddr *)&from_addr, 
	       (socklen_t *)&from_len);

  address.Ip = ntohl(from_addr.sin_addr.s_addr);
  
  //
  memcpy(&func,  &buff[10], 2);
  memcpy(&port,  &buff[12], 2);
  memcpy(&seqno, &buff[14], 4);
  memcpy(&packet_len, &buff[18], 4);

  packet_len = ntohl(packet_len);
  func = ntohs(func);
  address.Port = ntohs(port);
  seqno = ntohl(seqno);

    
  //drop packet
  if (n <= HEADER_SIZE || (packet_len + HEADER_SIZE ) != n){
    log(NOTICE, "receive broken packet! n=%d, packet_len=%d[%d][%d]\n", 
	n, packet_len, errno, EINVAL);
    return;
  }
    
  switch(func){
    
  case M_ACK:
    RecvAck(address, buff);
    break;
    
  case M_ACK_WAIT:
    RecvAckWait(address, buff);
    break;
    
  case M_ACK_RESET:
    RecvAckReset(address, buff);
    break;

  case M_JOIN:
    RecvJoin(address, buff);
    break;

  case M_FILE:
    RecvFile(address, buff);
    break;
    
  case M_JOIN_ACCEPT:
    RecvJoinAccept(address, buff);
    break;
    
  case M_JOIN_REDIRECT:
    RecvJoinRedirect(address, buff);
    break;

  case M_LOOKUP:
    RecvLookup(address, buff);
    break;

  case M_LOOKUP_RESPONSE:
    RecvLookupResponse(address, buff);
    break;

  case M_LEAVE:
    RecvLeave(address, buff);
    break;

  case M_LEAVE_END:
    RecvLeaveEnd(address, buff);
    break;

  case M_MESSAGE:
    RecvMessage(address, buff);
    break;


  default:
    log(NOTICE, "receive unknown type message[%d]\n",func);
    break;

  }


  //JOB LIST
  //session_id timeout func(insert->conn_ok) mcid
  //                        insert->NONE
  
  
  return;
}


void Protocol::SendAck(ADDRESS address, int SeqNo){
  
  char buf[26];//SSID
  short int func_n;
  short int port_n;
  int seqno_n;
  int size_n;


  func_n = htons(M_ACK);
  port_n = htons(pMChord->getPort());
  seqno_n = htonl(SeqNo);
  size_n = htonl(4);

  log(INFORMATION, "Send Ack  seq_no[%d]\n", SeqNo);
 
  memcpy(&buf[0], "MCHORD/1.0", 4);
  memcpy(&buf[10], &func_n,  2);/*func*/
  memcpy(&buf[12], &port_n,  2);/*port*/
  memcpy(&buf[14], &seqno_n, 4);/*sequence*/
  memcpy(&buf[18], &size_n,  4);/*size*/
  memcpy(&buf[HEADER_SIZE],  &seqno_n, 4);/*sequenceno2*/

  // ACKは再送しない
  SendExe(address, buf, HEADER_SIZE + 4);
}


/////////////////////////////////////////////////////////////////////
void Protocol::RecvAck(ADDRESS address, char *data){
 
  //MCHORD/1.0 session_id 200 OK
  int seqno;

  // Send File DOSが来るとfopen数が無限に増えるかも
  memcpy(&seqno, &data[HEADER_SIZE], 4);
  seqno = ntohl(seqno);
  pMChord->RecvAck(address, seqno);
  

}

void Protocol::RecvAckWait(ADDRESS address, char *data){


}


void Protocol::RecvAckReset(ADDRESS address, char *data){


}


/////////////////////////////////////////////////////////////////////
//Call by MChord
void Protocol::SendJoin(ADDRESS address, int sessid, int BeginId, int SeqNo){
  
  //simulation
  //RecvJoin(char *address);

  char buf[HEADER_SIZE + 8];//SSId MCId
  int sessid_n;

  log(INFORMATION, "Send Join sessid=[%d], mcid[%u]\n", sessid, BeginId);
  sessid_n = htonl(sessid);
  BeginId  = htonl(BeginId);
  memcpy(&buf[HEADER_SIZE + 0], &sessid_n, 4);
  memcpy(&buf[HEADER_SIZE + 4], &BeginId,  4);

  SendData(address, buf, HEADER_SIZE + 8, M_JOIN, SeqNo);

  
}


void Protocol::RecvJoin(ADDRESS address, char *buff){  

  //JOIN mcid MCHORD/1.0

  int seq_no;
  int sessid;
  int mcid;

  memcpy(&seq_no, &buff[14], 4);
  memcpy(&sessid, &buff[22], 4);/*0*/
  memcpy(&mcid,   &buff[26], 4);/*4*/

  seq_no = ntohl(seq_no);
  sessid = ntohl(sessid);
  mcid   = ntohl(mcid);

  log(INFORMATION, "Recv Join sessid=[%d], mcid[%u]\n", sessid, mcid);
  
  pMChord->RecvJoin(address, mcid, sessid, seq_no);

}

void Protocol::SendJoinRedirect(ADDRESS address, int sessid, int SeqNo, int ip, int port){
  
  char buf[HEADER_SIZE + 4];//SSId MCId
  int sessid_n;
  
  log(INFORMATION, "Send Join Redirect sessid=[%d]\n", sessid);
  sessid_n = htonl(sessid);
  
  memcpy(&buf[HEADER_SIZE + 0], &sessid_n, 4);
  memcpy(&buf[HEADER_SIZE + 4], &ip,       4);
  memcpy(&buf[HEADER_SIZE + 8], &port,     4);


  SendData(address, buf, HEADER_SIZE + 12, M_JOIN_REDIRECT, SeqNo);
  
}


void Protocol::RecvJoinRedirect(ADDRESS address, char *buff){  

  //JOIN mcid MCHORD/1.0

  int seq_no;
  int sessid;
  int ip;
  int port;

  memcpy(&seq_no, &buff[14], 4);
  memcpy(&sessid, &buff[22], 4);/*0*/
  memcpy(&ip,     &buff[26], 4);/*4*/
  memcpy(&port,   &buff[30], 4);/*8*/

  seq_no = ntohl(seq_no);
  sessid = ntohl(sessid);
  ip     = ntohl(ip);
  port   = ntohl(port);
  
  log(INFORMATION, "Recv Join Redirect sessid=[%d]\n", sessid);
  
  pMChord->RecvJoinRedirect(address, sessid, seq_no, ip, port);
  
}


void Protocol::SendFile(ADDRESS Address, char *Data, int Size, int SeqNo,
			int SessId, int McId, int FileSeqNo, int Flag){

  int sessid_n;
  int mcid_n;
  int fileseqno_n;
  int flag_n;

  if(Size == 0){
    log(WARNING, "SendFileSize = 0\n");
    return;
  }

  sessid_n    = htonl(SessId);
  mcid_n      = htonl(McId);
  fileseqno_n = htonl(FileSeqNo);
  flag_n      = htonl(Flag);

  memcpy(&Data[HEADER_SIZE + 0], &sessid_n,    4);
  memcpy(&Data[HEADER_SIZE + 4], &mcid_n,      4);
  memcpy(&Data[HEADER_SIZE + 8], &fileseqno_n, 4);
  memcpy(&Data[HEADER_SIZE +12], &flag_n,      4);

  SendData(Address, Data, Size , M_FILE, SeqNo);
  
}

void Protocol::RecvFile(ADDRESS address, char *buff){
  
  //JOIN mcid MCHORD/1.0

  int  seq_no;
  int  size;
  int  sessid;
  int  mcid;
  int  fileseqno;
  int  flag;
  
  memcpy(&seq_no,    &buff[14], 4);
  memcpy(&size,      &buff[18], 4);
  memcpy(&sessid,    &buff[HEADER_SIZE + 0], 4);
  memcpy(&mcid,      &buff[HEADER_SIZE + 4], 4);
  memcpy(&fileseqno, &buff[HEADER_SIZE + 8], 4);
  memcpy(&flag,      &buff[HEADER_SIZE +12], 4);

  seq_no    = ntohl(seq_no);
  size      = ntohl(size);
  sessid    = ntohl(sessid);
  mcid      = ntohl(mcid);
  fileseqno = ntohl(fileseqno);
  flag      = ntohl(flag);
  
  
  log(INFORMATION, 
      "Recv File seqno[%d],sessid[%d],mcid[%u],flag[%d],size[%d],fseqno[%d]\n",
      seq_no,sessid, mcid, flag, size + HEADER_SIZE, fileseqno);
  
  pMChord->RecvFile(address, seq_no, size, sessid, mcid, fileseqno, flag,buff);
  
}



//Call by MChord
void Protocol::SendJoinAccept(ADDRESS address, int SessId, ADDRESS next,
			      int EndId, int SeqNo){

  //すべてのファイル転送が完了した場合のみ送信される

  char buf[HEADER_SIZE + 16];//NextIP EndId SessId
  TASKLIST *ptask;
  int sessid;
  int NextIP;
  int NextPort;

  log(INFORMATION, "Send JoinAccept seq_no[%d],sessid[%d],EndId[%d]\n", 
      SeqNo, SessId, EndId);

  sessid   = htonl(SessId);
  NextIP   = htonl(next.Ip);
  NextPort = htonl(next.Port);
  EndId    = htonl(EndId);
  
  memcpy(&buf[HEADER_SIZE + 0], &sessid,   4);
  memcpy(&buf[HEADER_SIZE + 4], &NextIP,   4);
  memcpy(&buf[HEADER_SIZE + 8], &NextPort, 4);
  memcpy(&buf[HEADER_SIZE + 12],&EndId,    4);
  
  SendData(address, buf, HEADER_SIZE + 16, M_JOIN_ACCEPT, SeqNo);

}

 
void Protocol::RecvJoinAccept(ADDRESS address, char *buff){

  //pMChord->RecvJoinAccept(addr, atoi(parse->token[1]));

  int seq_no;
  int sessid;
  int nextip;
  int nextport;
  int endid;
  ADDRESS next;
  
  memcpy(&seq_no,   &buff[14], 4);
  memcpy(&sessid,   &buff[22], 4);/*0*/
  memcpy(&nextip,   &buff[26], 4);/*4*/
  memcpy(&nextport, &buff[30], 4);/*8*/
  memcpy(&endid,    &buff[34], 4);/*12*/

  seq_no    = ntohl(seq_no);
  sessid    = ntohl(sessid);
  next.Ip   = ntohl(nextip);
  next.Port = ntohl(nextport);
  endid     = ntohl(endid);
  
  log(INFORMATION, "Recv Join Accept=[%d]\n", sessid);
  
  
  pMChord->RecvJoinAccept(address, sessid, next, endid, seq_no);
    
}
 
 

void Protocol::SendLookup(ADDRESS address, int sessid, int mcid_to,
			  int mcid_from, int ttl, int SeqNo, 
			  ADDRESS address_src){

  //simulation
  //RecvJoin(char *address);

  char buf[HEADER_SIZE + 24];
  int  mcid_to_n;
  int  mcid_from_n;
  int  sessid_n;

  int  ip_n;
  int  port_n;
  int  ttl_n;
  
  log(INFORMATION, 
      "Send Lookup sess=[%d], port=[%d], mcid to[%u],from[%u],ttl[%d]\n", 
      sessid, address.Port, mcid_to, mcid_from, ttl);
  
  sessid_n    = htonl(sessid);
  mcid_to_n   = htonl(mcid_to);
  mcid_from_n = htonl(mcid_from);
  ip_n        = htonl(address_src.Ip);
  port_n      = htonl(address_src.Port);
  ttl_n       = htonl(ttl);

  memcpy(&buf[HEADER_SIZE + 0], &sessid_n,   4);
  memcpy(&buf[HEADER_SIZE + 4], &mcid_to_n,  4);
  memcpy(&buf[HEADER_SIZE + 8], &mcid_from_n,4);
  memcpy(&buf[HEADER_SIZE +12], &ip_n,       4);
  memcpy(&buf[HEADER_SIZE +16], &port_n,     4);
  memcpy(&buf[HEADER_SIZE +20], &ttl_n,      4);
  
  SendData(address, buf, HEADER_SIZE + 24, M_LOOKUP, SeqNo);
  
}


void Protocol::RecvLookup(ADDRESS address, char *buff){
  

  //pMChord->RecvLookup(addr, atoi(parse->token[1]), atoi(parse->token[2]));
  
  int seq_no;
  int sessid;
  int mcid_to;
  int mcid_from;
  int ttl;
  
  ADDRESS src;
  
  memcpy(&seq_no,    &buff[14], 4);
  memcpy(&sessid,    &buff[22], 4);/*0*/
  memcpy(&mcid_to,   &buff[26], 4);/*4*/
  memcpy(&mcid_from, &buff[30], 4);/*8*/
  memcpy(&src.Ip,    &buff[34], 4);/*12*/
  memcpy(&src.Port,  &buff[38], 4);/*16*/
  memcpy(&ttl,       &buff[42], 4);/*20*/

  seq_no    = ntohl(seq_no);
  sessid    = ntohl(sessid);
  mcid_to   = ntohl(mcid_to);
  mcid_from = ntohl(mcid_from);
  src.Ip    = ntohl(src.Ip);
  src.Port  = ntohl(src.Port);
  ttl       = ntohl(ttl);
  
  log(INFORMATION, 
      "Recv Lookup sess=[%d], mcid to[%u], from[%u], seq_no=%d, ttl=%d\n",
      sessid, mcid_to, mcid_from, seq_no, ttl);
  
  pMChord->RecvLookup(address, sessid, mcid_to, mcid_from, ttl, seq_no, src);
  
}


//Call by MChord
void Protocol::SendLookupResponse(ADDRESS Address, int SessId, int McId, 
				  int SeqNo, int Ttl, int Ans, int mcid2){
  
  char buf[HEADER_SIZE + 20];
  int  mcid_n;
  int  sessid_n;
  int  ans_n;
  int  ttl_n;
  int  mcid2_n;
  log(INFORMATION, 
      "Send LookupResponse sessid=[%d], mcid_to[%u], ttl[%d],mcid2[%d]\n", 
      SessId, McId, Ttl, mcid2);
  
  sessid_n = htonl(SessId);
  mcid_n   = htonl(McId);
  ans_n    = htonl(Ans);
  ttl_n    = htonl(Ttl);
  mcid2_n  = htonl(mcid2);

  memcpy(&buf[HEADER_SIZE + 0], &sessid_n, 4);
  memcpy(&buf[HEADER_SIZE + 4], &mcid_n,   4);
  memcpy(&buf[HEADER_SIZE + 8], &ans_n,    4);
  memcpy(&buf[HEADER_SIZE +12], &ttl_n,    4);
  memcpy(&buf[HEADER_SIZE +16], &mcid2_n,    4);

  
  SendData(Address, buf, HEADER_SIZE + 20, M_LOOKUP_RESPONSE, SeqNo);
  
}

///////////////
//受信したファイルを保存した後どうする?????
void Protocol::RecvLookupResponse(ADDRESS address, char *buff){

  //SendFileと同じにするかも。
  //pMChord->RecvLookupResponse(addr, atoi(parse->token[1]), parse->token[2]); 

  int seq_no;
  int sessid;
  int mcid;
  int ans;
  int ttl;
  int mcid2;
  memcpy(&seq_no, &buff[14], 4);
  memcpy(&sessid, &buff[22], 4);/*0*/
  memcpy(&mcid,   &buff[26], 4);/*4*/
  memcpy(&ans,    &buff[30], 4);/*8*/
  memcpy(&ttl,    &buff[34], 4);/*12*/
  memcpy(&mcid2,  &buff[38], 4);/*16*/

  seq_no = ntohl(seq_no);
  sessid = ntohl(sessid);
  mcid   = ntohl(mcid);
  ans    = ntohl(ans);
  ttl    = ntohl(ttl);
  mcid2    = ntohl(mcid2);


  pMChord->RecvLookupResponse(address, sessid, mcid, seq_no, ans, ttl, mcid2);

}


/////////////////////////////////////////////////////////////////////
//Call by MChord
void Protocol::SendLeave(ADDRESS address, int sessid, ADDRESS next,
			 int BeginId, int EndId, int SeqNo){
  //RecvLookupRes(ADDRESS address);
  char buf[HEADER_SIZE + 20];

  int sessid_n;
  int mcid_n;
  int ip_n;
  int port_n;
  int beginid_n;
  int endid_n;


  log(INFORMATION, 
      "Send Leave sessid=[%d], BeginId[%d], EndId[%d],\n",
      sessid, BeginId, EndId);

  sessid_n  = htonl(sessid);
  ip_n      = htonl(next.Ip);
  port_n    = htonl(next.Port);
  beginid_n = htonl(BeginId);
  endid_n   = htonl(EndId);

  memcpy(&buf[HEADER_SIZE + 0], &sessid_n,  4);
  memcpy(&buf[HEADER_SIZE + 4], &ip_n,      4);
  memcpy(&buf[HEADER_SIZE + 8], &port_n,    4);
  memcpy(&buf[HEADER_SIZE +12], &beginid_n, 4);
  memcpy(&buf[HEADER_SIZE +16], &endid_n,   4);
  
  SendData(address, buf, HEADER_SIZE + 20, M_LEAVE, SeqNo);
  
}


/////////////////////////////////////////////////////////////////////
void Protocol::RecvLeave(ADDRESS address, char *buff){

  //LEAVE mcid MCHORD/1.0
  int seq_no;
  int sessid;
  int beginid;
  int endid;
  int ip;
  int port;
  ADDRESS next;
  
  memcpy(&seq_no,    &buff[14], 4);
  memcpy(&sessid,    &buff[22], 4);/*0*/
  memcpy(&ip,        &buff[26], 4);/*4*/
  memcpy(&port,      &buff[30], 4);/*8*/
  memcpy(&beginid,   &buff[34], 4);/*12*/
  memcpy(&endid,     &buff[38], 4);/*16*/

  seq_no    = ntohl(seq_no);
  sessid    = ntohl(sessid);
  next.Ip   = ntohl(ip);
  next.Port = ntohl(port);
  beginid   = ntohl(beginid);
  endid     = ntohl(endid);
  
  log(INFORMATION, 
      "Recv Leave sessid=[%d], beginid[%d], endid[%d]\n",
      sessid, beginid, endid);
  
  pMChord->RecvLeave(address, sessid, next, beginid, endid, seq_no); 
  
}


/////////////////////////////////////////////////////////////////////
void Protocol::SendLeaveEnd(ADDRESS address, int sessid, int SeqNo){

  char buf[HEADER_SIZE + 4];
  int  sessid_n;
  
  log(INFORMATION, 
      "Send Leave End sessid=[%d], SeqNo=[%d]\n",
      sessid, SeqNo);
  
  sessid_n = htonl(sessid);
  memcpy(&buf[HEADER_SIZE + 0], &sessid_n, 4);
  SendData(address, buf, HEADER_SIZE + 4, M_LEAVE_END, SeqNo);


}

/////////////////////////////////////////////////////////////////////
void Protocol::RecvLeaveEnd(ADDRESS address, char *buff){

  int seq_no;
  int sessid;

  memcpy(&seq_no, &buff[14], 4);
  memcpy(&sessid, &buff[22], 4);/*0*/

  seq_no = ntohl(seq_no);
  sessid = ntohl(sessid);
  
  log(INFORMATION, "Recv Leave End sessid=[%d]\n", sessid);
  pMChord->RecvLeaveEnd(address, sessid, seq_no);
  
}


//Call by MChord
void Protocol::SendInsert(ADDRESS address, char *data, int size, int key, 
			  int SeqNo){
  
  //simulation

  char buf[HEADER_SIZE + 12];//SSId MCId
  int sessid;
  int mcid;
  int sessid_n;

  sessid = get_random();

  log(INFORMATION, "Send Insert sessid=[%d], key(dest)[%d]\n", sessid, key);

  sessid_n = htonl(sessid);
  mcid   = htonl(key);

  memcpy(&buf[0], &sessid_n, 4);
  memcpy(&buf[4], &mcid,     4);
  memcpy(&buf[8], &data,  size);

  SendData(address, buf, HEADER_SIZE + 12 + size, M_INSERT, SeqNo);
  //TimerFunc(sessid);

}

void Protocol::RecvInsert(ADDRESS address, char *buff){

  int seq_no;
  int sessid;
  int mcid;
  int size;
  char *data;

  memcpy(&size,   &buff[18], 4);
  memcpy(&seq_no, &buff[14], 4);
  memcpy(&sessid, &buff[22], 4);/*0*/
  memcpy(&mcid,   &buff[26], 4);/*4*/

  size   = ntohl(size);
  seq_no = ntohl(seq_no);
  sessid = ntohl(sessid);
  mcid   = ntohl(mcid);

  data = (char *)malloc(size);
  memcpy(&data, &buff[30], size - 8);

  log(INFORMATION, "Recv Insert sessid=[%d], mcid[%u]\n", sessid, mcid);

  
  pMChord->RecvInsert(address, data, size, mcid);
  
  
}




//Call by MChord
void Protocol::SendMessage(ADDRESS address, int SeqNo, char *data){
  
  char buf[HEADER_SIZE + 256];//NextIP EndId SessId
  TASKLIST *ptask;

  log(INFORMATION, "Send Message seq_no[%d]\n", data);
  
  memcpy(&buf[HEADER_SIZE + 0], data, 256);
  
  SendData(address, buf, HEADER_SIZE + 256, M_MESSAGE, SeqNo);


}

 
void Protocol::RecvMessage(ADDRESS address, char *buff){

  char buf[256];
  int seq_no;


  memcpy(&seq_no, &buff[14], 4);

  seq_no    = ntohl(seq_no);
  log(INFORMATION, "Recv Message %s\n", &buff[22]);
  pMChord->RecvMessage(address, seq_no, &buff[22]);
  
}
 

//malloc
void Protocol::SendData(ADDRESS Address, char *Data, int Size, int Func, 
			int SeqNo){

  AddHeadder(Data, Size - HEADER_SIZE, Func, SeqNo);

  //send first task
  SendExe(Address, Data, Size);

}



//add header(22byte)
void Protocol::AddHeadder(char *buff, int size, int func, int seqno){

  int func_n;
  int seqno_n;
  int size_n;
  int port_n;

  func_n = htons(func);
  port_n = htons(pMChord->getPort());
  seqno_n = htonl(seqno);
  size_n = htonl(size);

  memcpy(&buff[0],   "MCHORD/1.0", 10);
  memcpy(&buff[10],  &func_n, 2);
  memcpy(&buff[12],  &port_n, 2);
  memcpy(&buff[14],  &seqno_n, 4);
  memcpy(&buff[18],  &size_n, 4);
  
}


//lower layer
void Protocol::SendExe(ADDRESS address, char *buf, int size){
  
  int sock;
  struct hostent *servhost;
  struct sockaddr_in dest_addr;
  char ipbuf[50];
  int len;
  int n;

  ip_to_str(address.Ip, ipbuf);
  if((servhost = gethostbyname(ipbuf)) == NULL){
    u_long addr;
    addr = inet_addr(ipbuf);
    servhost = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
    if (servhost == NULL) {
      log(WARNING, "cannot get dest ip addr\n");
      return ;
    }
  }
  
  if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
    log(ERROR, "socket\n");
    return;
  }
  
  

  memset((char *)&dest_addr, 0, sizeof(dest_addr));
  dest_addr.sin_family = AF_INET;
  dest_addr.sin_port = htons(address.Port);
  memcpy((char *)&dest_addr.sin_addr, servhost->h_addr, servhost->h_length);
  n = sendto(sock, buf, size, 0 ,(sockaddr *)&dest_addr, sizeof(dest_addr));

  close(sock);
  
}

