#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "net.h"
#include "Net.h"
#include "Packet.h"
#include "Disk.h"
#include "StopWatch.h"
#define MAXRETRY 3
bool flag_v=false, flag_d=false, flag_bind=true;
bool flag_unblock_write = true;
//these names contain '/0'
char * serverName;
char * myName;
char * nextName;
bool isNextServer;
PacketIte *hostIte;
PacketIte *fileIte;
DataOut *dataout=NULL;
DataIn *datain=NULL;
CntlIn *cntlin=NULL;
CntlOut *cntlout=NULL;
CntlOut *repout=NULL;
void data_transfer();
void exception_reciever(NetRecv *net );
//FILE *ty_err=NULL;
/*************************
* BuildRing *
*************************/
DataOut *find_next_and_newnet( PacketIte *ite )
// Return: Success(Dataout), Fail(NULL)
//
{
DataOut *net;
if (!ite->pop_entry()) {
if (isNextServer) {
fprintf(stderr,"the next host is dolly server. so you"
" don't have any option for the next host.\n");
return(NULL); }
isNextServer=true;
fprintf(stderr,"Server(%s) was selected for the next adjacent host.\n",
serverName);
net = new DataOut(serverName);
}else{ // find the next in the list
ite->set_flag(CALL_HOST);
if (flag_v) {
fprintf(stderr,"Try sending RING packet to %s\n",ite->get_name()); }
net = new DataOut(ite->get_name());
}
return net;
}
/////////////////
// buildring() //
/////////////////
void buildring()
{
int ret,retry;
Net::ret_value retn;
Net::sr_retval srret;
//--------------------------------------------------
//****** 1st Step: recieve a RING packet **********
//--------------------------------------------------
datain = new DataIn();
cntlin = new CntlIn();
cntlin->open();
datain->register_exception(cntlin,exception_reciever);
if(datain->open_accept()!=Net::SUCCESS){
fprintf(stderr,"fail to accept connection in reciving RING packet.\n");
exit(2);
}
RingPacket *ring_packet=new RingPacket();
srret=datain->recv_packet(ring_packet);
if (srret!=Net::SR_success) {
fprintf(stderr,"Ring packet cannot be recieved (timeout)\n");
exit(1); }
hostIte=new PacketIte(ring_packet);
ret = hostIte->get_name_len();
serverName = new char[ret+1];
strncpy(serverName,hostIte->get_name(),ret);
serverName[ret]='\0';
if (!hostIte->search_flag(CALL_HOST)) {
fprintf(stderr,"cannot find myhost name in RING packet"
"(Client.cpp)\n"); exit(1); }
ret= hostIte->get_name_len();
myName = new char [ret+1];
strncpy(myName,hostIte->get_name(),ret);
myName[ret]='\0';
hostIte->set_flag(AVAIL_HOST);
if (flag_v) {
fprintf(stderr," Server name is %s, my name is %s.(%s)\n",
serverName,myName,getTime()); }
//-------------------------------------------------------
//****** 2nd Step: Send the RingPacket to the nexthost;
//-------------------------------------------------------
isNextServer=false; //initial value
dataout = find_next_and_newnet(hostIte);
if (dataout == NULL) {
fprintf(stderr,"cannot find the next host in 1st RingPacket"
" sending.(1)\n"); exit(1);
}
// connection to the adjacent host. upto MAXRETRY hosts are tried if fail.
for (retry=0;retry<MAXRETRY;retry++) {
retn = dataout->open_connect();
if (retn != Net::SUCCESS) {
if (!isNextServer) {
hostIte->set_flag(NOAVIL_HOST);
}else{ // next is Server
fprintf(stderr,
"cannot connect to server(%s) in the ring creation step.\n"
,serverName); exit(1);
}
dataout->close_sock();
delete dataout;
dataout=find_next_and_newnet(hostIte);
if(dataout == NULL) {
fprintf(stderr,"cannot fine the next host in 1st "
"RingPacket sending.(2)\n"); exit(1); }
continue; //<-----------continue to retry open_connect
} // if open fail
srret=dataout->send_packet(ring_packet);
if (srret == Net::SR_success) /* send packet success */ {
break; //<----------- success then break retry loop
}else if (srret==Net::SR_connectionlost)
/* packet sending timeout or EPIPE */ {
fprintf(stderr," fail to send to %s,",hostIte->get_name());
if (!isNextServer) {
hostIte->set_flag(NOAVIL_HOST);
}
dataout=find_next_and_newnet(hostIte);
if (dataout==NULL) {
fprintf(stderr,"cannot fine the next host in 1st "
"RingPacket sending.(2)\n"); exit(2); }
}else /* send packet error*/ {
fprintf(stderr,"Client.cpp:1st ring packet sending.\n");
exit(1);
} /* send packet result if */
} /* ring retry loop */
if (retry==MAXRETRY) {
int retn;
char message[100];
CmdPacket rep_pack;
fprintf(stderr,"send retry failed. (%d times tried)\n",retry);
repout = new CntlOut(serverName);
retn =repout->open_connect();
if (retn != Net::SUCCESS) {
fprintf(stderr,"cannot report RETRY overrun to %s(1).\n",serverName);
exit(2);
}
sprintf(message,"(<%s): Stop to sending RingPacket(retry=%d).",
myName,retry);
retn = strlen(message);
rep_pack.make_command(TYPE_REPORT,message,retn);
if (repout->send_packet(&rep_pack) != Net::SR_success ) {
fprintf(stderr,"cannot report RETRY overrun to %s(2).\n",serverName);
exit(2);
}
fprintf(stderr,"Report to server(%s) is succeeded.\n",serverName);
exit(1); }
if (flag_v) {
fprintf(stderr,"RING packet recieved/sent.\n"); }
ret = hostIte->get_name_len();
nextName = new char[ret+1]; // +1 = '\0'
strncpy(nextName,hostIte->get_name(),ret);
nextName[ret]='\0';
delete hostIte;
//-------------------------------------------------
//****** 3rd Step: Recieving a Host list Packet *
//-------------------------------------------------
HostPacket *host_packet=new HostPacket();
srret=datain->recv_packet(host_packet);
if ( srret != Net::SR_success ) {
fprintf(stderr,"Host packet cannot be recieved (ret=%d)\n",srret);
exit(1); }
//------------------------------------------------------------
//****** 4th Step: Host List Packet sending to the nexthost *
//------------------------------------------------------------
srret=dataout->send_packet(host_packet);
if (srret != Net::SR_success) {
fprintf(stderr,"fail to send Hostpacket to '%s'(ret=%d). \n",
nextName,srret);
exit(1); }
if (flag_v) {
fprintf(stderr,"HOST packet recieved/sent \n");
host_packet->print(); }
/* Setting Host iterator again */
hostIte=new PacketIte(host_packet);
if (!hostIte->search_name(nextName)){ // reconfirmation
fprintf(stderr,"cannot find the next adjacent host name in HOST "
"packet(Client.cpp).\n"); exit(1); }
datain->register_exception(0,NULL);
cntlin->close_sock();
delete cntlin;
}
void file_info()
{
Net::sr_retval srret;
//----------------------------------------------
//****** 5th Step: recieve a File List Packet *
//----------------------------------------------
FilePacket *file_packet=new FilePacket();
srret=datain->recv_packet(file_packet);
if (srret != Net::SR_success) {
fprintf(stderr,"File packet cannot be recieved. (ret=%d)\n",srret);
exit(1); }
//-----------------------------------------------------------
//****** 6th Step: the FilePacket sending to the nexthost *
//-----------------------------------------------------------
srret=dataout->send_packet(file_packet);
if (srret!=Net::SR_success) {
fprintf(stderr,"fail to send file packet to '%s'.", nextName);
exit(1); }
if (flag_v) {
fprintf(stderr,"File packet recieved/sent.\n");
file_packet->print(); }
fileIte = new PacketIte(file_packet); // set file list iterator
}
//**********************
//* Main ROUTINE **
//**********************
void usage(char * progname)
{
fprintf(stderr,
" %s [-v] [-d] [-b] [-t device]\n" ,progname);
fprintf(stderr,
" :-v verbose -d dummy \n"
" :-p pingfile ping mode \n");
fprintf(stderr,
" :-B switch off binding of writenet() and readnet().\n"
" With this option, you may get faster transfer "
"and less avility \n"
" for recovery \n");
fprintf(stderr,
" :-L switch off unblocking write mode in sending network"
" packet.\n"
" With this option, you may get faster transfer "
"and less avility\n"
" for recovery \n");
}
int main(int argc, char** argv)
{
int c;
bool flag_p=false;
/* Parse arguments */
while(1) {
c = getopt(argc, argv, "vdpbBL");
if (c == -1) break;
switch(c) {
case 'v':
/* Verbose */
flag_v = true;
break;
case 'p':
/* ping mode */
flag_p = true;
break;
case 'd':
/* Dummy disk read/write for debugging */
flag_d = true;
break;
case 'B':
/* netread() and netwrite() off-binding */
fprintf(stderr,"unbind mode. \n");
flag_bind = false;
break;
case 'L':
/* stop unblocking write in Net.cpp:send_packet() */
fprintf(stderr,"nonblock write mode. \n");
flag_unblock_write = false;
break;
default:
fprintf(stderr, "Unknown option '%c'.\n", c);
usage(argv[0]);
exit(1);
}
}
if (flag_d) {
fprintf(stderr,
"Dolly will send dummy data and never stop \n"); }
if (!flag_p) /* normal mode */ {
signal(SIGPIPE, SIG_IGN);
if (flag_v) {
fprintf(stderr, "Trying to build ring... %s.\n",getTime()); }
buildring();
file_info();
data_transfer();
if (flag_v) {
fprintf(stderr, "Going into multiThread mode... %s\n",getTime()); }
} else /* ping mode .... this is actually not dolly */ {
const char *filename;
Net::sr_retval srret;
FilePacket *filepacket = new FilePacket();
NetRecv *repin = new NetRecv(REPORT);
FromDisk *afile = new FromDisk();
Buffer *buff = new Buffer();
DataPacket *pack = new DataPacket();
pack->attach(buff);
while (1) {
if ( repin->open_accept()!=Net::SUCCESS ) {
fprintf(stderr,"fail to accept connection in ping mode.\n");
exit(2);
}
if ((srret=repin->recv_packet(filepacket)) != Net::SR_success ) {
fprintf(stderr,"File name packet recieve failure.(ret=%d)\n",srret);
exit(2);
}
fileIte = new PacketIte(filepacket);
filename = fileIte->get_name();
if (!afile->open(filename)) {
fprintf(stderr,"file open error in ping mode.\n");
exit(2);
}
afile->read_tobuff(buff);
pack->make(0,0);
srret=repin->send_packet(pack);
if (srret !=Net::SR_success) {
fprintf(stderr,"data send error \n");
}
repin->close_sock();
} /* infinete loop */
} /* ping mode */
/* Default exit value of 0 */
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1