//D is a mark for debuging
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include "Packet.h"
#include "common.h"
#include "StopWatch.h"
Packet::Packet()
: packetBytes(0), contBytes(0), contP(NULL),
packetBuff(NULL), headerP(NULL)
{
}
Packet::~Packet()
{
if (packetBuff!=NULL) {
free(packetBuff);
}
}
//
// making a space for a packet
// return a pointer pointing at the top of the packet !!!
void Packet::print()
{
PacketIte *ite = new PacketIte(this);
int ii;
fprintf(stderr,"---Packet contents printing ---------------------\n");
fprintf(stderr,"No of Bytes = %d \n", contBytes);
fprintf(stderr,"No. flag name \n");
for (ii=0;;ii++) {
fprintf(stderr,"%3d %d '%s'\n",
ii, ite->get_flag(), ite->get_name());
if (!ite->pop_entry()) {
break;
}
}
fprintf(stderr,"--------------------------------------------------\n");
}
/////////////////
// RingPacket //
/////////////////
RingPacket::RingPacket()
{
headerBytes=RING_INF_HEADER_BYTES;
trailBytes=RING_INF_TRAIL_BYTES;
headerP=aHeader;
}
//
// making a space for a RING packet
// return a pointer pointing at the top of the contents !!!
// ^^^^^^^^
char * RingPacket::make(short int cont_bytes,short int num_entry)
{
char *pp,*epp;
int nbytes,nnum;
pp = Packet::core_make(cont_bytes,num_entry);
epp = endP;
strncpy(pp,MAGIC_RING_OPEN,MG_CHR_L);
pp += MG_CHR_L;
nbytes = htons(cont_bytes);
nnum = htons(num_entry);
*(short int*)pp=nbytes;
pp +=2 ;
*(short int*)pp=nnum;
strncpy(epp,MAGIC_RING_CLOSE,MG_CHR_L);
return contP;
}
//
// Check Packet header and make space for packet recieving
// Return address for the contents
//
char * RingPacket::checkheader_make()
{
char * pp=aHeader;
int num_entry,cont_bytes;
if (strncmp((char *)pp,MAGIC_RING_OPEN,MG_CHR_L) != 0) {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type mismatch('%s' != %s )\n",
pp,MAGIC_RING_OPEN);
return NULL;
}
pp += MG_CHR_L;
cont_bytes = ntohs(*(unsigned short int*)(pp));
pp += 2;
num_entry = ntohs(*(unsigned short int*)(pp));
pp = make(cont_bytes,num_entry);
memcpy(packetBuff,aHeader,headerBytes);
return pp;
}
//
// Check trailer keyword
// Return 1... OK 0... fail
int RingPacket::checktrailer()
{
if (strncmp(endP,MAGIC_RING_CLOSE,MG_CHR_L) != 0) {
*(endP+MG_CHR_L-1)='\0'; // print safety
fprintf(stderr,"trailer is wrong. ('%s' != '%s')\n",
endP, MAGIC_RING_CLOSE);
return 0;
}
return 1;
}
/////////////////
// HostPacket //
/////////////////
HostPacket::HostPacket()
{
headerBytes=RING_INF_HEADER_BYTES;
trailBytes=RING_INF_TRAIL_BYTES;
headerP=aHeader;
}
char * HostPacket::make(short int cont_bytes,short int num_entry)
{
char *pp,*epp;
int nbytes,nnum;
pp = Packet::core_make(cont_bytes,num_entry);
epp = endP;
strncpy(pp,MAGIC_HOST_OPEN,MG_CHR_L);
pp += MG_CHR_L;
nbytes = htons(cont_bytes);
nnum = htons(num_entry);
*(short int*)pp=nbytes;
pp +=2 ;
*(short int*)pp=nnum;
strncpy(epp,MAGIC_HOST_CLOSE,MG_CHR_L);
return contP;
}
//
// Check Packet header and make space for packet recieving
// Return address for the contents
//
char * HostPacket::checkheader_make()
{
char * pp=aHeader;
int num_entry,cont_bytes;
if (strncmp(pp,MAGIC_HOST_OPEN,MG_CHR_L) != 0) {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type missmatch('%s' != %s )\n",
pp,MAGIC_HOST_OPEN);
return NULL;
}
pp += MG_CHR_L;
cont_bytes = ntohs(*(unsigned short int*)(pp));
pp += 2;
num_entry = ntohs(*(unsigned short int*)(pp));
pp = make(cont_bytes,num_entry);
memcpy(packetBuff,aHeader,headerBytes);
return pp;
}
//
// Check trailer keyword
// Return 1... OK 0... fail
int HostPacket::checktrailer()
{
if (strncmp(endP,MAGIC_HOST_CLOSE,MG_CHR_L) != 0) {
*(endP+MG_CHR_L-1)='\0'; // print safety
fprintf(stderr,"trailer is wrong. ('%s' != '%s')\n",
endP, MAGIC_HOST_CLOSE);
return 0;
}
return 1;
}
/////////////////
// FilePacket //
/////////////////
FilePacket::FilePacket()
{
headerBytes=FILE_INF_HEADER_BYTES;
trailBytes=FILE_INF_TRAIL_BYTES;
headerP=aHeader;
}
//--------------------------//
// Make header for sending //
//--------------------------//
char * FilePacket::make(short int cont_bytes,short int num_entry)
{
char *pp,*epp;
int nbytes,nnum;
pp = Packet::core_make(cont_bytes,num_entry);
epp = endP;
strncpy(pp,MAGIC_FILE_BEGN,MG_CHR_L);
pp += MG_CHR_L;
nbytes = htons(cont_bytes);
nnum = htons(num_entry);
*(short int*)pp=nbytes;
pp +=2 ;
*(short int*)pp=nnum;
strncpy(epp,MAGIC_FILE_END,MG_CHR_L);
return contP;
}
//---------------------------//
// Make header for recieving //
//---------------------------//
//
// Check Packet header and make space for packet recieving
// Return address for the contents
//
char * FilePacket::checkheader_make()
{
int num_entry,cont_bytes;
char * pp=aHeader;
if (strncmp(pp,MAGIC_FILE_BEGN,MG_CHR_L) != 0) {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type missmatch('%s' != %s )\n",
pp,MAGIC_FILE_BEGN);
return NULL;
}
pp += MG_CHR_L;
cont_bytes = ntohs(*(unsigned short int*)(pp));
pp += 2;
num_entry = ntohs(*(unsigned short int*)(pp));
pp = make(cont_bytes,num_entry);
memcpy(packetBuff,aHeader,headerBytes);
return pp;
}
//
// Check trailer keyword
// Return 1... OK 0... fail
int FilePacket::checktrailer()
{
if (strncmp(endP,MAGIC_FILE_END,MG_CHR_L) != 0) {
*(endP+MG_CHR_L-1)='\0'; // print safety
fprintf(stderr,"trailer is wrong. ('%s' != '%s')\n",
endP, MAGIC_FILE_END);
return 0;
}
return 1;
}
//---------------//
// FileNo Packet //
//---------------//
FileNoPacket::FileNoPacket()
{
headerBytes=FILENO_HEADER_BYTES;
trailBytes=FILENO_TRAIL_BYTES;
headerP=aHeader;
}
// For sending
char * FileNoPacket::make(short int dummy1, short int fileno)
{
char *pp = Packet::core_make(0,0);
strncpy(pp,MAGIC_FILENO,MG_CHR_L);
pp+= MG_CHR_L;
*(short int*)pp = 0;
pp+= 2;
fileNo=fileno;
*(short int*)pp = htons(fileNo);
return contP;
}
char * FileNoPacket::checkheader_make()
{
int cont_bytes,type;
char * pp=aHeader;
//D fprintf(stderr,"manabe filenopack header check address =%x \n",pp);
if (strncmp(pp,MAGIC_FILENO,MG_CHR_L) != 0) {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type missmatch('%s' != %s )\n",
pp,MAGIC_FILENO);
return NULL;
}
pp += MG_CHR_L;
contBytes = ntohs(*(unsigned short int*)(pp));
pp += 2;
fileNo = ntohs(*(unsigned short int*)(pp));
DEBPR(printf("========= fileno packet (fileNo=%d) \n",fileNo););
packetBytes = contBytes+headerBytes;
return aHeader;
}
int FileNoPacket::set_fileno(short int fileno)
{
if (packetBuff==NULL) {
fprintf(stderr,
"coding error! FileNoPacket::make() first.(in FileNoPacket::set_fileno(%d) \n"
,fileno);
exit(3);
}
*(unsigned short int*)(packetBuff+MG_CHR_L+2) = htons(fileno);
fileNo=fileno;
return fileno;
}
//------------//
// CMD Packet //
//------------//
CmdPacket::CmdPacket()
:pType(numEntry)
{
headerBytes=CMD_HEADER_BYTES;
trailBytes=CMD_TRAIL_BYTES;
headerP=aHeader;
}
char * CmdPacket::make(short int bytes, short int type)
{
char *pp = Packet::core_make(bytes, type);
// pType=type; aliased
strncpy(pp,MAGIC_COMMAND,MG_CHR_L);
pp+= MG_CHR_L;
*(short int*)pp = htons(bytes);
pp+= 2;
*(short int*)pp = htons(type);
return contP;
}
char * CmdPacket::make_command(int type, long int operand)
{
make(4,(short int)type);
*(int *)contP = htonl(operand);
return contP;
}
char * CmdPacket::make_command(int type, char* message, int size)
{
if (size > MAX_MESSAGE_SIZE) {
fprintf(stderr,
"message size is too big. (max=%d) in CmdPacket:make_command() %s\n",
MAX_MESSAGE_SIZE,getTime());
exit(1);
}
make(size,(short int)type);
memcpy(contP,message,size);
return contP;
}
char * CmdPacket::checkheader_make()
{
int cont_bytes,type;
char * pp=aHeader;
if (strncmp(pp,MAGIC_COMMAND,MG_CHR_L) != 0) {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type missmatch('%s' != %s )\n",
pp,MAGIC_COMMAND);
return NULL;
}
pp += MG_CHR_L;
cont_bytes = ntohs(*(unsigned short int*)(pp));
pp += 2;
type = ntohs(*(unsigned short int*)(pp));
if (cont_bytes > MAX_MESSAGE_SIZE) {
fprintf(stderr,
"exceed message size limit(%d>%d) detect in CmdPacket::checkheader_make()\n"
,cont_bytes,MAX_MESSAGE_SIZE);
return NULL;
}
pp = make(cont_bytes,type);
memcpy(packetBuff,aHeader,headerBytes);
return pp;
}
long int CmdPacket::get_operand()
{
int ret;
if (contP == NULL) {
fprintf(stderr,
"can't recieve cmdpacket before CmdPacket::get_operand() %s.\n",getTime()); exit(3);
} else if (contBytes != 4) {
fprintf(stderr,
"operand in CmdPacket may not be a long integer (sz=%dBytes)."
" detect in CmdPacket::get_operand() %s\n",
contBytes,getTime());
return 0;
}
ret = ntohl(*(int*)contP);
return ret;
}
char * CmdPacket::get_message()
{
if (contP == NULL) {
fprintf(stderr,
"can't recieve cmdpacket before CmdPacket::get_operand(). %s",getTime()); exit(3);
}
*(char *)(contP+contBytes) = '\0'; /* 0 terminate for safety */
return contP;
}
///////////////
// Iterator //
///////////////
PacketIte::PacketIte(Packet *pack)
{
packObj=pack;
packP=packObj->contP;
}
char * PacketIte::get_name()
{
int ret;
ret=name_len_check();
return( packP+FLAG_LEN ); //+1 is flag
}
//
// get the next entry and proceed pointer
// Return 1..Success 0..End of Entry
int PacketIte::pop_entry()
{
int ret;
char * new_p;
ret = name_len_check();
new_p = packP + (ret+FLAG_LEN); //+1 is for flag
if (new_p==packObj->endP) {
return 0;
} else if (new_p < packObj->endP) {
packP = new_p;
return 1; // success
} else {
fprintf(stderr,"something wrong in the packet (0x%x != 0x%x) %s\n",
packP,packObj->endP,getTime());
exit(1);
}
}
//
// search a first encounter entry which has the flag
// Return 1..Success (revised packP) 0..Cannot find (packP preserved)
int PacketIte::search_flag(unsigned char ffff)
{
char *save_p;
while (ffff != get_flag()) {
if (!pop_entry()) {
return 0;
}
}
}
//
// search an entry which has the name
// Return 1..Success (revised packP) 0..Cannot find (packP preserved)
int PacketIte::search_name(char * name)
{
char *save_p;
int len,ii;
if (packObj->numEntry > MAX_PACKET_ENTRY_NO) {
fprintf(stderr,"No of entry in the packet=%d exceed its limit-max.%d\n",
packObj->numEntry,MAX_PACKET_ENTRY_NO);
return(0);
}
for (ii=0;ii<packObj->numEntry;ii++) {
len = get_name_len();
if (strncmp(get_name(),name,len) == 0) {
return 1;
}
if (!pop_entry()) {
return 0;
}
}
fprintf(stderr," PacketIte::pop_entry() cannot detect packet end.\n"
"packetIte::search_name(%s) \n",name);
return 0;
}
//
// retrun length of the name with '\0'
int PacketIte::name_len_check()
{
char *pp,*sp; int ii;
sp=pp=packP+FLAG_LEN; //
for (ii=0;ii< MAX_PACKET_ENTRY_LEN ;ii++,pp++) {
if (*pp=='\0') {
break;
}
}
if (ii==MAX_PACKET_ENTRY_LEN) {
*(packP+10)='\0'; // print safety
fprintf(stderr,"entry is too long. (first 10char is '%s') %s.\n",
sp,getTime());
exit(1);
}
return ii+1; //contains the last \0
}
//////////////////////////////////////////////////////////
// SPacket
// o Packet have continueus memory space which contains
// header, contents and trailer.
// o SPacket has separated memory spaces for its header
// and contents(class Buffer).
/////////////////////////////////////////////////////////
int SPacket::attach(Buffer *buff)
{
pBuff = buff;
contP = buff->get_addr();
contBytes = buff->get_contsize();
return(1);
}
////////////////
// DataPacket //
////////////////
DataPacket::DataPacket()
{
headerBytes=DATA_HEADER_BYTES;
trailBytes=DATA_TRAIL_BYTES;
headerP=aHeader; pBuff=NULL;
}
//
// make pakcket for Recieving
//
char *DataPacket::checkheader_make()
{
// in this case, we dont make anything...
long int cont_bytes,num_entry;
char * pp=aHeader;
//D fprintf(stderr,"datapacket header addr =%x (manabe)\n",pp);
if (strncmp((char *)pp,MAGIC_DATA_SEQ,MG_CHR_L) == 0) {
pBuff->set_eof(B_NORMAL);
} else if (strncmp((char *)pp,MAGIC_DATA_END,MG_CHR_L) == 0) {
pBuff->set_eof(B_EOF);
} else {
pp[MG_CHR_L]=0;
fprintf(stderr,"header type has trouble ('%s' != DATA_HEADER )\n",pp);
return NULL;
}
pp += MG_CHR_L;
contBytes = ntohl(*(unsigned long int*)(pp));
pp += 4;
numEntry = ntohl(*(unsigned long int*)(pp));
pBuff->set_contsize(contBytes);
pBuff->set_seqno(numEntry);
packetBuff = 0;
contP = pBuff->get_addr();
endP = contP+contBytes;
packetBytes = contBytes+headerBytes;
return pp;
}
//
// make packet (just packet header) for sending
//
char * DataPacket::make(short int dummy1, short int dummy2)
{
// All arguments are dummy.
int seqno;
if (pBuff==NULL) {
fprintf(stderr,
"Do not attach buffer yet. SPacket::make_header(): coding error.\n");
exit(3);
}
char *pp=headerP;
seqno = pBuff->get_seqno();
if (pBuff->get_eof()){
strncpy(pp,MAGIC_DATA_END,MG_CHR_L);
} else {
strncpy(pp,MAGIC_DATA_SEQ,MG_CHR_L);
}
contBytes = pBuff->get_contsize();
pp += MG_CHR_L;
*(long int*)pp = htonl(contBytes);
DEBPR(printf("contsize--%d(buff=%d) \n",
contBytes,pBuff->get_contsize()););
pp += 4;
*(long int*)pp = htonl(seqno);
packetBytes=headerBytes+contBytes;
numEntry=0;
packetBuff=0;
contP = pBuff->get_addr();
endP = contP + pBuff->get_size();
return(contP); // is it true?
}
///////////////////////////////////////////////////////////
// Inlines //
///////////////////////////////////////////////////////////
inline
char * Packet::core_make(short int cont_bytes, short int num_entry)
{
if (packetBuff != NULL) {
free(packetBuff);
fprintf(stderr,
"!!!!!!!!!!!!! core_make is called but already packetBuff has value."
" It could be a coding mistake !!!!!!!!\n");
}
packetBytes = cont_bytes+headerBytes+trailBytes;
contBytes = cont_bytes;
numEntry = num_entry;
if ((packetBuff=(char*)malloc(packetBytes)) == NULL) {
perror("Packet::make() malloc()");
fprintf(stderr,"%s\n",getTime());
exit(2);
}
contP = packetBuff+headerBytes;
endP = contP+cont_bytes;
return packetBuff;
}
syntax highlighted by Code2HTML, v. 0.9.1