//D is a mark for debugging
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <fcntl.h>
#include "common.h"
#include "Net.h"
#include "StopWatch.h"
/////////////////////////
/////////////////////////
bool CntlIn::exist = false;
bool CntlOut::exist = false;
bool DataIn::exist = false;
bool DataOut::exist = false;
//////////////////////////////////
// just a writter's memo
//
// struct sockaddr {
// u_short sa_family; :
// char sa_data[14]; : depends on the protocol
// }
//
// IPv4's case !!
// struct sockaddr_in {
// short sin_family; : AF_INET
// u_short sin_port; : 16bit port number with network byte order
// struct in_addr sin_addr; :32bin netid ex.192.168.197.11
// : with network byte order
// char sin_zero[8]; : just a pad 8=14-2-4
// }
// struct in_addr {
// u_long s_addr; : 32bint netid(IP address), networkbyte order
// }
//////////////////////////////////
// Net //
//////////////////////////////////
Net::Net()
: sockDesc(-1), closedYes(false),
writeTimeout(SENDTIMEOUT), readTimeout(RECVTIMEOUT) {
}
Net::~Net()
{
if (!closedYes) {
close(sockDesc);
}
}
int Net::flag_v = 0;
///////////////////////////////////////////////
// Net for Active connection //
///////////////////////////////////////////////
NetSend::NetSend(const char *host, const int port)
: exceptionNet(NULL), exceptionFunction(NULL)
{
int ret;
portNo=port;
if (host == NULL) {
hostName = NULL;
}else{
ret=strlen(host)+1;
if (ret>MAX_HOST_NAME_LEN) {
fprintf(stderr,"hostname is too long. (%s) NetSend::new \n",
host); exit(1); }
hostName = new char[ret];
strncpy(hostName,host,ret);
//D fprintf(stderr,"Netsend hostname=%s (manabe)\n",hostName);
}
// Net(); //manabe test
}
NetSend::~NetSend()
{
delete hostName;
}
int NetSend::flag_nonblock_write=1;
//**********************************************//
// Active open a network for sending to a host //
// Return: Success(0) Error(-1) Fatal(-2) //
//**********************************************//
Net::ret_value NetSend::open_connect()
{
struct hostent *hent;
struct sockaddr_in addrdata, addrctrl;
int ret,dataok,no_try;
unsigned long inaddr;
int option,optlen;
//D fprintf(stderr,"start Connection %d (manabe)\n",flag_v);
//hostName is IP address or a real name ?
if ( (inaddr = inet_addr(hostName)) != INADDR_NONE) {
// addrdata for the later connect() call
if (flag_v) fprintf(stderr,"use IP number address %s\n",hostName);
bcopy((char*)&inaddr, (char *)&addrdata.sin_addr,sizeof(inaddr));
} else {
if (flag_v) fprintf(stderr,"use hostname '%s'\n",hostName);
if ((hent=gethostbyname(hostName))==NULL) {
fprintf(stderr,"hostname=%s..\n",hostName);
herror("gethostbyname@Net.cpp");
return(FATAL);
}
if (hent->h_addrtype != AF_INET) {
fprintf(stderr, "Expected h_addrtype of AF_INET, got %d\n",
hent->h_addrtype);
return(FATAL); }
bcopy(hent->h_addr, &addrdata.sin_addr, hent->h_length);
}
addrdata.sin_family = AF_INET;
addrdata.sin_port = htons(portNo);
/* Setup data port */
if (flag_v) {
fprintf(stderr, "Connecting to %s...",hostName);
fflush(stderr);
}
/* Wait until we connected to everything... */
no_try = 0; dataok=0;
while (no_try<=MAX_CONNECT_TRY) {
if ((sockDesc = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("Opening output data socket"); return(FATAL); }
ret=connect(sockDesc,(struct sockaddr *)&addrdata,
sizeof(addrdata));
if ((ret == -1) &&
( errno==ECONNREFUSED || errno==ENETUNREACH ||
errno==EHOSTUNREACH ) ) {
close(sockDesc);
} else if(ret == -1) {
fprintf(stderr,"errno=%d \n",errno);
perror("connect at NetSend::open_connect() "); return(FATAL);
} else {
if (flag_v) {
fprintf(stderr, "..(host=%s::%d)",hostName,portNo);
fprintf(stderr, "\n");
}
///manabe added for test, manabetest
// optlen = sizeof(option);
// option = 1;
// if ( setsockopt(sockDesc, SOL_IP, IP_RECVERR, &option,
// (socklen_t)optlen) < 0 ) {
// perror("setsockopt");
// exit(1);
// }
// if ( getsockopt(sockDesc, SOL_IP, IP_RECVERR, &option,
// (socklen_t*)&optlen) < 0 ) {
// perror("getsockopt");
// exit(1);
// }
// printf("==========================\n");
// printf("option=%d length=%d \n",option,optlen);
// printf("==========================\n");
if (flag_nonblock_write) {
if (fcntl(sockDesc,F_SETFL,O_NONBLOCK)<0) {
fprintf(stderr,"fail to set NOBLOCK mode in open_connect()\n");
perror("fcntl");
}
if (flag_v) {
fprintf(stderr,"setting NOBLOCK mode in open_connect()\n");
}
}
////////////////////////
return(SUCCESS); // <--- normal return //
////////////////////////
}
sleep(1);
no_try++;
} // connect loop
fprintf(stderr,"Connection to %s is faild."
"(#_try>%d)\n",hostName,no_try);
return(ERROR);
}
void NetSend::close_sock()
{
close(sockDesc);
closedYes=true;
}
//***************************************************//
// Send a packet //
// return: normal(1), timeout or EPIPE(0), error(-1) //
//***************************************************//
Net::sr_retval NetSend::send_packet(Packet *pack)
{
using namespace NetSendRecv;
fd_set save_rset, save_wset;
int maxsetnr; int rest_bytes;
int exp_sock;
const char *pp;
if (sockDesc == (-1)) {
fprintf(stderr,"coding error! call NetSend::open_connect() first"
" NetSend::send_packet(pack) \n"); exit(3);
}
FD_ZERO(&save_wset); FD_ZERO(&save_rset);
FD_SET(sockDesc,&save_wset);
if (exceptionFunction != NULL ) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>sockDesc)?exp_sock:sockDesc;
} else {
maxsetnr=sockDesc;
}
maxsetnr++;
pp = pack->get_addr();
rest_bytes=pack->get_size();
int ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, sockDesc,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
return(SR_success);
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to send packet NetSend::send_packet()\n");
return(SR_error);
}
}
////////////////////////////////////////////////////////
// Send a Spacket //
// return: normal(1), timeout or EPIPE(0), error(-1) //
////////////////////////////////////////////////////////
Net::sr_retval NetSend::send_packet(SPacket *pack)
{
using namespace NetSendRecv;
fd_set save_rset, save_wset;
int maxsetnr; int rest_bytes;
int exp_sock;
const char *pp;
if (sockDesc==(-1)){
fprintf(stderr,"coding error! call NetSend::open_connect() first"
" in NetSend::send_packet(SPacket)\n"); exit(3);
}
FD_ZERO(&save_wset); FD_ZERO(&save_rset);
FD_SET(sockDesc,&save_wset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>sockDesc)?exp_sock:sockDesc;
} else {
maxsetnr=sockDesc;
}
maxsetnr++;
pp = pack->get_haddr();
rest_bytes=pack->get_headersize();
int ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, sockDesc,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to send packet header "
"NetSend::send_packet(spacket)\n");
return(SR_error);
}
pp=pack->get_contaddr();
rest_bytes=pack->get_contsize();
ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, sockDesc,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else{
fprintf(stderr,"fail to send data packet(contents)"
"NetSend::send_packet(spacket)\n");
return(SR_error);
}
return(SR_success);
}
//********************************************//
// recieving a packet //
// return: normal(1), timeout(0), error(-1) //
//********************************************//
Net::sr_retval NetSend::recv_packet(Packet *pack)
{
using namespace NetSendRecv;
char *pp;
fd_set save_rset;
int exp_sock, maxsetnr, rest_bytes;
if (sockDesc==(-1)) {
fprintf(stderr,"coding error! Call open() first."
" in NetSend::recv_packet() \n"); exit(3);
}
FD_ZERO(&save_rset);
FD_SET(sockDesc,&save_rset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>sockDesc)?exp_sock:sockDesc;
} else {
maxsetnr= sockDesc;
}
maxsetnr++;
pp=pack->get_haddr();
rest_bytes = pack->get_headersize();
if (rest_bytes>HEADER_MAXLEN) {
fprintf(stderr," exceed header size limit."
" (NetSend::recv_packet(packet) coding error). %s\n", getTime());
exit(3);
}
int ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,
readTimeout,sockDesc,exp_sock,exceptionNet,exceptionFunction);
if (ret == r_OK) {
// do continue
} else if (ret == r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetSend::recv_packet()(1)\n");
return(SR_error);
}
if ((pp=pack->checkheader_make())==NULL) {
fprintf(stderr,"recived data header mismatch "
"NetSend::recv_packet(pack) %s\n",getTime());
exit(3); }
rest_bytes=pack->get_contsize()+pack->get_trailersize();
ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,
readTimeout,sockDesc,exp_sock,exceptionNet,exceptionFunction);
if (ret == r_OK) {
// do continue
} else if (ret == r_TIMEOUT ) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetSend::recv_packet()(2)\n");
return(SR_error);
}
if (!pack->checktrailer()) {
fprintf(stderr,"checktrailer() fail NetSend::recv_packet()\n");
pack->print();
return(SR_error);
}
return(SR_success);
}
////////////////////////////////////////////////
// recieving a Spacket //
// return: normal(1), timeout(0), error(-1) //
////////////////////////////////////////////////
Net::sr_retval NetSend::recv_packet(SPacket *pack)
{
using namespace NetSendRecv;
char *pp;
fd_set save_rset;
int maxsetnr; int rest_bytes;
int exp_sock;
if (sockDesc==(-1)) {
fprintf(stderr,"coding error! Call open() first"
" in NetSend::recv_packet(SPacket) \n");
exit(3);
}
FD_ZERO(&save_rset);
FD_SET(sockDesc,&save_rset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>sockDesc)?exp_sock:sockDesc;
} else {
maxsetnr= sockDesc;
}
maxsetnr++;
pp=pack->get_haddr();
rest_bytes = pack->get_headersize();
if (rest_bytes>HEADER_MAXLEN) {
fprintf(stderr," exceed header size limit."
" (NetRecv::recv_packet(SPacket) coding error) \n"); exit(3);
}
int ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,
readTimeout,sockDesc,exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
//do continue
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetSend::recv_packet(spacket)(3)\n");
return(SR_error);
}
if (pack->checkheader_make()==NULL) {
fprintf(stderr,"recieved data header mismatch "
"NetSend::recv_packet(SPacket) \n");
return(SR_error);
}
rest_bytes = pack->get_contsize();
pp=(char *)pack->get_contaddr();
ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,readTimeout,
sockDesc,exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to recieve SPacket NetSend::recv_packet(SP)\n");
return(SR_error);
}
return(SR_success);
}
//
// Registrate a function which will be called when
// a packet is sent from control port
// If function is NULL, catching exceptional access is disabled.
NetRecv::T_FUNC
NetSend::register_exception(NetRecv *net, void function(NetRecv *))
{
exceptionFunction = function;
exceptionNet=net;
return(exceptionFunction);
}
/////////////////////////////////////////////
//// Net for Passive Connection //
/////////////////////////////////////////////
NetRecv::NetRecv(const int port)
: exceptionNet(NULL), exceptionFunction(NULL),
accptSock(-1)
{
int ret;
hostName = FROM_ANY; //from any interface. hostName is not a right name
portNo=port;
}
NetRecv::~NetRecv()
{
if (!closedYes) {
close(sockDesc);
if (accptSock!=(-1))
close(accptSock);
}
delete hostName;
}
void NetRecv::close_sock()
{
closedYes = true;
close(sockDesc);
if(accptSock != (-1)) {
close(accptSock);
}
}
////////////////////////////////////////////////////////
// Passive Open network for recieving from any hosts //
////////////////////////////////////////////////////////
Net::ret_value NetRecv::open_accept()
{
struct sockaddr_in addr;
int optval,size=0;
struct hostent *hent;
int acptret;
sockDesc = socket(PF_INET, SOCK_STREAM, 0);
if (sockDesc==-1) {
perror("Opening input data socket"); return(FATAL); }
optval = 1;
if (setsockopt(sockDesc,SOL_SOCKET,SO_REUSEADDR,
&optval, sizeof(int)) == -1) {
perror("setsockopt on dataSock"); return(FATAL); }
addr.sin_family = AF_INET;
addr.sin_port = htons(portNo);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // from any interface
if (bind(sockDesc,(struct sockaddr *)&addr,sizeof(addr))==-1) {
perror("binding input data socket"); return(FATAL); }
if (listen(sockDesc,2)==-1) { /* queue is 2...Manabe */
perror("listen input data socket"); return(FATAL); }
if (exceptionFunction == NULL) {
fprintf(stderr,"Accepting port(%d).....",portNo);
fflush(stderr);
accptSock = ::accept(sockDesc,NULL,(socklen_t*)&size);
if (accptSock<0) {
perror("Acception error");
return(FATAL);
}
} else {
fd_set use_rset,rset; struct timeval timeout;
timeout.tv_sec=timeout.tv_usec=0;
int selret;
int exp_sock,maxsetnr;
fprintf(stderr,"Accepting port(%d).....",portNo);
fflush(stderr);
FD_ZERO(&rset); FD_SET(sockDesc,&rset);
exp_sock= exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&rset);
maxsetnr = (exp_sock>sockDesc)?exp_sock:sockDesc;
maxsetnr++;
while(1) {
use_rset = rset;
selret=select(sockDesc+1,&use_rset,NULL,NULL,NULL);
if(selret>0) {
if (FD_ISSET(sockDesc,&use_rset)) {
break;
} else { // must be exception access
exceptionFunction(exceptionNet);
}
} else /*select error*/ {
perror("Net::open_accept() select()");
return(FATAL);
}
} // while(1) loop
accptSock = ::accept(sockDesc,NULL,(socklen_t*)&size);
if (accptSock<0) {
perror("Acception error");
return(FATAL);
}
} // is exceptionFunction set ?
return(SUCCESS);
}
//
// Separated routines
//
void NetRecv::open()
{
struct sockaddr_in addr;
int optval;
struct hostent *hent;
sockDesc = socket(PF_INET, SOCK_STREAM, 0);
if (sockDesc==(-1)) {
perror("Opening input data socket");
fprintf(stderr,"%s\n",getTime());
exit(2); }
optval = 1;
if (setsockopt(sockDesc,SOL_SOCKET,SO_REUSEADDR,
&optval,sizeof(int))==(-1)) {
perror("setsockopt on dataSock");
fprintf(stderr,"%s\n",getTime());exit(2); }
addr.sin_family = AF_INET;
addr.sin_port = htons(portNo);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // from any interface
if (bind(sockDesc,(struct sockaddr *)&addr,sizeof(addr))==-1) {
perror("binding input data socket");
fprintf(stderr,"%s\n",getTime());exit(2); }
if (listen(sockDesc,2)==-1) { /* queue is 2...Manabe */
perror("listen input data socket");
fprintf(stderr,"%s\n",getTime());exit(2); }
}
//
// Return ... Fail(0) .. Accepted(1)
Net::ret_value NetRecv::nonblock_accept()
{
socklen_t size=0;
struct sockaddr_in peer_sin;
struct hostent *peer_host;
fcntl(sockDesc,F_SETFL,O_NONBLOCK);
fprintf(stderr,"Nonblock Accept from port(%d) ...\n",portNo);
if ((accptSock = ::accept(sockDesc,NULL,(socklen_t*)&size)) < 0 ){
if (errno==EAGAIN) {
return(ERROR);
} else {
perror("Net::noblock_accept()");
return(FATAL);
}
}
if (flag_v) {
fprintf(stderr," peer host is ..");
size = sizeof peer_sin;
if (getpeername(accptSock,(struct sockaddr*)&peer_sin,&size) == -1) {
perror("fail getpeername()");
return(ERROR);
}
if ((peer_host=gethostbyaddr((char*)&peer_sin.sin_addr,
sizeof peer_sin.sin_addr, AF_INET)) == NULL) {
perror("fail gethostbyaddr()");
return(ERROR);
}
fprintf(stderr,"%s\n",peer_host->h_name);
}
return(SUCCESS);
}
// accept wait without exception handling
// Return ... Fail(0) .. Accepted(1)
Net::ret_value NetRecv::accept()
{
socklen_t size=0;
struct sockaddr_in peer_sin;
struct hostent *peer_host;
fprintf(stderr,"Wait for some one access at port(%d) ...\n",portNo);
if ((accptSock = ::accept(sockDesc,NULL,(socklen_t*)&size)) < 0 ){
if (errno==EAGAIN) {
return(ERROR);
} else {
perror("Net::noblock_accept()");
return(FATAL);
}
}
if (flag_v) {
fprintf(stderr," peer host is ..");
size = sizeof peer_sin;
if (getpeername(accptSock,(struct sockaddr*)&peer_sin,&size) == -1) {
perror("fail getpeername()");
return(ERROR);
}
if ((peer_host=gethostbyaddr((char*)&peer_sin.sin_addr,
sizeof peer_sin.sin_addr, AF_INET)) == NULL) {
perror("fail gethostbyaddr()");
return(ERROR);
}
fprintf(stderr,"%s\n",peer_host->h_name);
}
return(SUCCESS);
}
//
// Registrate a function which will be called when
// a packet is sent from control port
//
NetRecv::T_FUNC
NetRecv::register_exception(NetRecv *net, void function(NetRecv *))
{
exceptionFunction = function;
exceptionNet = net;
return(exceptionFunction);
}
//********************************************//
// recieving a packet //
// return: normal(1), timeout(0), error(-1) //
//********************************************//
Net::sr_retval NetRecv::recv_packet(Packet *pack)
{
using namespace NetSendRecv;
char *pp;
fd_set save_rset;
int exp_sock, maxsetnr, rest_bytes;
//D fprintf(stderr,"NetRecv::Recv_pacekt(Packet) (manabe) \n");
if (accptSock==(-1)) {
fprintf(stderr,"coding error! you try recv_packet() but did not call "
"open() first in NetRecv::recv_packet() (port=%d)\n",portNo);
// return(-1); for debug
exit(3);
}
FD_ZERO(&save_rset);
FD_SET(accptSock,&save_rset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>accptSock)?exp_sock:accptSock;
} else {
maxsetnr= accptSock;
}
maxsetnr++;
//D char * mm;
pp=pack->get_haddr();
//D fprintf(stderr,"NetRecv::Recv_pacekt(Packet) header add=%x(manabe) \n",pp);
//Dmm=pp;
rest_bytes = pack->get_headersize();
if( rest_bytes > HEADER_MAXLEN ) {
fprintf(stderr," exceed header size limit."
" (NetRecv::recv_packet(packet) coding error) \n"); exit(3);
}
int ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,
readTimeout,accptSock,exp_sock,exceptionNet,exceptionFunction);
if (ret == r_OK) {
//do continue
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetRecv::recv_packet()(1)\n");
return(SR_error);
}
//D fprintf(stderr,"packet header is %c %c %c (manabe)\n",*mm,*(mm+1),*(mm+2));
if ((pp=pack->checkheader_make())==NULL) {
fprintf(stderr,"recived data header mismatch Net::recv_packet() %s\n",
getTime()); exit(3); }
rest_bytes = pack->get_contsize() + pack->get_trailersize();
ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,readTimeout,
accptSock,exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
//do continue
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetRecv::recv_packet()(2)\n");
return(SR_error);
}
//D fprintf(stderr,"pack->checkheder_make addr=%x(manabe)\n",pp);
if (!pack->checktrailer()) {
fprintf(stderr,"checktrailer() fail in NetRecv::recv_packet()\n");
pack->print();
return(SR_error);
}
return(SR_success);
}
////////////////////////////////////////////////
// recieving a Spacket //
// return: normal(1), timeout(0), error(-1) //
////////////////////////////////////////////////
Net::sr_retval NetRecv::recv_packet(SPacket *pack)
{
using namespace NetSendRecv;
char *pp;
fd_set save_rset;
int maxsetnr; int rest_bytes;
int exp_sock;
if (accptSock==(-1)) {
fprintf(stderr,"coding error! Call open() first"
" in NetRecv::recv_packet(SPacket) \n");
exit(3);
}
FD_ZERO(&save_rset);
FD_SET(accptSock,&save_rset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>accptSock)?exp_sock:accptSock;
} else {
maxsetnr= accptSock;
}
maxsetnr++;
pp=pack->get_haddr();
rest_bytes = pack->get_headersize();
if (rest_bytes>HEADER_MAXLEN) {
fprintf(stderr," exceed header size limit."
" (NetRecv::recv_packet(SPacket) coding error) \n"); exit(3);
}
int ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,
readTimeout,accptSock,exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
//do continue
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to reciev packet NetRecv::recv_packet()(3)\n");
return(SR_error);
}
if (pack->checkheader_make()==NULL) {
fprintf(stderr,"recieved data header mismatch "
"NetRecv::recv_packet(SPacket) \n");
return(SR_error);
}
rest_bytes = pack->get_contsize();
pp=(char *)pack->get_contaddr();
ret=NetSendRecv::recving(save_rset,maxsetnr,pp,rest_bytes,readTimeout,
accptSock,exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to recieve SPacket NetRecv::recv_packet(SP)\n");
return(SR_error);
}
return(SR_success);
}
//***************************************************//
// Send a packet //
// return: normal(1), timeout or EPIPE(0), error(-1) //
//***************************************************//
Net::sr_retval NetRecv::send_packet(Packet *pack)
{
using namespace NetSendRecv;
fd_set save_rset, save_wset;
int maxsetnr; int rest_bytes;
int exp_sock;
const char *pp;
if (accptSock==(-1)) {
fprintf(stderr,"coding error! call NetRecv::open_accpt() first in"
" NetRecv::send_packet(pack) \n"); exit(3);
}
FD_ZERO(&save_wset); FD_ZERO(&save_rset);
FD_SET(accptSock,&save_wset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>accptSock)?exp_sock:accptSock;
} else {
maxsetnr= accptSock;
}
maxsetnr++;
pp = pack->get_addr();
rest_bytes=pack->get_size();
int ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, accptSock,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to send packet NetRecv::send_packet()\n");
return(SR_error);
}
return(SR_success);
}
////////////////////////////////////////////////////////
// Send a Spacket //
// return: normal(1), timeout or EPIPE(0), error(-1) //
////////////////////////////////////////////////////////
Net::sr_retval NetRecv::send_packet(SPacket *pack)
{
using namespace NetSendRecv;
fd_set save_rset, save_wset;
int maxsetnr; int rest_bytes;
int exp_sock;
const char *pp;
if (sockDesc==(-1)){
fprintf(stderr,"coding error! call NetRecv::open_accpt() first"
" in NetRecv::send_packet(SPacket)\n"); exit(3);
}
FD_ZERO(&save_wset); FD_ZERO(&save_rset);
FD_SET(accptSock,&save_wset);
if (exceptionFunction != NULL) {
exp_sock = exceptionNet->get_accept_sock();
if (exp_sock==(-1)) {
exp_sock = exceptionNet->get_sock();
}
FD_SET(exp_sock,&save_rset);
maxsetnr= (exp_sock>accptSock)?exp_sock:accptSock;
} else {
maxsetnr=accptSock;
}
maxsetnr++;
pp = pack->get_haddr();
rest_bytes=pack->get_headersize();
int ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, accptSock,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
//do continue;
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else {
fprintf(stderr,"fail to send packet header "
"NetRecv::send_packet(spacket)\n");
return(SR_error);
}
pp=pack->get_contaddr();
rest_bytes=pack->get_contsize();
ret=NetSendRecv::sending(save_rset,save_wset,maxsetnr,
pp,rest_bytes, writeTimeout, accptSock,
exp_sock,exceptionNet,exceptionFunction);
if (ret==r_OK) {
} else if (ret==r_TIMEOUT || ret==r_EPIPE) {
return(SR_connectionlost);
} else{
fprintf(stderr,"fail to send data packet(contents)"
"NetRecv::send_packet(spacket)\n");
return(SR_error);
}
return(SR_success);
}
//****************************************************//
// Inline's //
//****************************************************//
namespace NetSendRecv {
/// return -1=(error) 0=(timeout or pipebroken) 1=(normal)
/// return r_ERROR(-1),r_OK(0),r_TIMEOUT(1),r_UEOF(2)
inline ret_srecving sending(
const fd_set &rset, const fd_set &wset,
const int &maxnr,
const char *addr, const int &bytes, int timelimit,
const int &sock,
const int &ex_sock, NetRecv *& ex_net, void (*func)(NetRecv *))
{
const char *pp=addr;
int r_bytes=bytes,ret,selret;
fd_set use_rset,use_wset; struct timeval timeout;
for (;r_bytes>0;r_bytes-=ret,pp+=ret) {
use_wset=wset;
timeout.tv_sec=timelimit; timeout.tv_usec=0;
ret=0;
// Linux rule! see select(2)
if (func!=NULL) {
use_rset=rset;
selret=select(maxnr,&use_rset,&use_wset,NULL,&timeout);
} else {
selret=select(maxnr,NULL,&use_wset,NULL,&timeout);
}
if (selret>0) { // normal result
if (FD_ISSET(sock,&use_wset)) {
write_again:
DEBPR(printf("write..%dbytes add=%d>>\n",r_bytes,pp););
ret = write(sock,(char *)pp,r_bytes);
DEBPR(printf("done..ret=%dbytes<<\n",ret););
if (ret<=0) {
// 2001.8.2 modified
// if (errno==EPIPE) /* pipe broken*/ {
//return(r_TIMEOUT);
// }else{
// perror("::write() in Net::sending()");
// return(r_ERROR);
// }
if (errno==EBADF || errno==EINVAL || errno==EFAULT ||
errno==ENOSPC || errno==EIO ) {
perror("unrecoverable error ::write() in Net::sending()");
return(r_ERROR);
} else if (errno==EAGAIN) {
sleep(1);
DEBPR(printf("EAGAIN\n"););
goto write_again;
}else{
DEBPR(printf("TIMEOUT\n"););
if (Net::is_verbose()) {
printf("write TIMEOUT happned (%d)\n",errno);
perror("reason");
}
return(r_TIMEOUT);
}
} /* write error */
DEBPR(printf("writeend\n"););
}
if (func!=NULL && FD_ISSET(ex_sock,&use_rset)) {
func(ex_net);
}
} else if (selret==0) { // timeout
return(r_TIMEOUT);
}else{
perror("Net::send_packet select()");
return(r_ERROR);
}
DEBPR(printf("next\n"););
}//write loop
return(r_OK);
}
/// return r_ERROR(-1),r_OK(0),r_TIMEOUT(1),r_UEOF(2)
inline ret_srecving recving(
const fd_set &rset, const int &maxnr,
char * addr, const int &bytes, int timelimit,
const int &sock,
const int &ex_sock, NetRecv *&ex_net, void (*func)(NetRecv *))
{
char *pp=addr;
int ret,selret;
fd_set use_rset,save_rset;
struct timeval timeout;
int r_bytes=bytes;
save_rset=rset;
for (; r_bytes>0; r_bytes-=ret,pp+=ret) {
use_rset=save_rset;
timeout.tv_sec=timelimit; timeout.tv_usec=0;
ret=0;
DEBPR(printf("recving select=%o \n",use_rset););
selret=select(maxnr,&use_rset,NULL,NULL,&timeout);
DEBPR(printf("recving select ret=%d \n",selret););
if (selret>0) { // normal result
if (FD_ISSET(sock,&use_rset)) {
if ((ret=read(sock,pp,r_bytes))<0){
perror("Net(h)::recving read(header)");
return(r_ERROR);
} else if (ret==0) /* EOF read*/ {
struct hostent *peer_host;
struct sockaddr_in peer_sin;
socklen_t size=sizeof peer_sin;
int ret_r;
ret_r=getpeername(sock,(struct sockaddr*)&peer_sin,&size);
fprintf(stderr,"unexpected EOF in Net::recving read() %s"
"(restbytes=%d)",getTime(),r_bytes);
if(ret_r != -1) {
peer_host=gethostbyaddr((char*)&peer_sin.sin_addr,
sizeof peer_sin.sin_addr, AF_INET);
if (peer_host != NULL) {
fprintf(stderr,"from host=%s(port=%d)",peer_host->h_name,
ntohs(peer_sin.sin_port));
}
}
fprintf(stderr,"\n");
// return(-1); 2001.5.1.15
if (r_bytes == bytes) {
fprintf(stderr,"detect 'exception' port closing.\n");
FD_CLR(sock,&save_rset);
continue;
} else {
fprintf(stderr,"Stop data reading!! Only wait for exception port"
" access. %s\n",getTime());
FD_CLR(sock,&save_rset);
continue;
}
} /* read/EOF */
} /* sock ISSET? */
if (func!=NULL && FD_ISSET(ex_sock,&use_rset)) {
func(ex_net);
}
} else if (selret==0) { // timeout
return(r_TIMEOUT);
} else {
perror("Net::recv_packet select()");
fprintf(stderr,"%d = select() \n",selret);
return(r_ERROR);
} //select result if
} //read loop
return(r_OK);
}
}
/*
int CntlOut::send_packet(Packet *pack) {
struct sockaddr_in peer_sin;
socklen_t size = sizeof peer_sin;
struct hostent *peer_host;
getpeername(sockDesc,(struct sockaddr*)&peer_sin,&size);
peer_host=gethostbyaddr((char*)&peer_sin.sin_addr,sizeof peer_sin.sin_addr,AF_INET);
printf("ctlout------ sock=%d port=%d host=%s(%s) \n",sockDesc,portNo,hostName,peer_host->h_name);
return NetSend::send_packet(pack);
}
int DataOut::send_packet(SPacket *pack) {
struct sockaddr_in peer_sin;
socklen_t size = sizeof peer_sin;
struct hostent *peer_host;
getpeername(sockDesc,(struct sockaddr*)&peer_sin,&size);
peer_host=gethostbyaddr((char*)&peer_sin.sin_addr,sizeof peer_sin.sin_addr,AF_INET);
printf("dataout-S------------- sock=%d port=%d host=%s(%s) \n",sockDesc,portNo,hostName,peer_host->h_name);
return NetSend::send_packet(pack);
}
*/
syntax highlighted by Code2HTML, v. 0.9.1