/* Copyright (C) 2001 Marc Casaldaliga Albisu ================================================================ This code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Emacs (which is required to make this stuff work); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ================================================================== */ #include "TCPSender.hxx" #include "PeriodicAction.hxx" #include "socket_functions.h" #include #include #include #include #include TCPSender::TCPSender (char * servName_, unsigned int servPort_ ) :retryingTime(3000000),tryingConnect(retryingTime),servPort(servPort_),comMode(false),newReceived(false)//,servName(servName_) { strcpy(servName,servName_); //prepare the name init_sockaddr (&server, servName_, servPort); //this->Reset; } TCPSender::~TCPSender(){ if(comMode){ CloseConnection(); } } void TCPSender::CloseConnection(){ if (comMode){ #ifdef DEBUG cout<<"TCPSender: closing socket to server "<isTrialToConnectSuccesful periodically WHILE this call is NOT returning true, that is is retrying until connection is succesfull. All the threading is done inside PeriodicAction! tryingConnect.DoWhileNot(slot(this, &TCPSender::isTrialToConnectSuccesful) ); // // tryingConnect.FinallyDo(... callback to call when tryingConnect is finished, for example Start reporting periodically (start another PeriodicAction // // supose we have a virtual method WhenConnectionIsEstablished // tryingConnect.FinallyDo(slot(this,&TCPSender::WhenConnectionIsEstablished)); tryingConnect.Start(); } int TCPSender::IODescriptor(){ //returns file descriptor (e.g. to use with IONotifier) return socketItself; } bool TCPSender::isTrialToConnectSuccesful(){ //create the socketItself. After a failed connect call the socket has to be initialized again (?) socketItself = socket (PF_INET, SOCK_STREAM, 0); if ( (socketItself < 0) || (prepare_socket(socketItself) == -1) ) { perror("TCPSender: socket (client)"); exit (EXIT_FAILURE); } #ifdef DEBUG printf("TCPSender: trying to connect\n"); #endif if (0 > connect (socketItself, (struct sockaddr *) &server, sizeof (server))){ int myerrno=errno; perror("TCPSender: connect. Retrying"); comMode=false; close(socketItself); return false; }else{ comMode=true; // fconfigure $socketItself -buffering line #ifdef DEBUG printf("TCPSender: TCPSender: successful connection\n"); #endif return true; } } void TCPSender::Send (char *msg ){ //Syncronous send char buffer[MAXMSG]; strcpy(buffer,msg); unsigned int len=strlen(buffer); buffer[len]='\n'; buffer[len+1]='\0'; #ifdef DEBUG printf("TCPSender: sending %s \n",buffer); #endif if(write(socketItself, buffer, strlen(buffer)) != strlen(buffer)){ int myerrno=errno; } // char * eol="\n"; // if(write(socketItself, eol, strlen(eol)) != strlen(eol)){ // int myerrno=errno; // } // // fsync(readoutSend); } void TCPSender::Receive () { //Syncronous receive. If you are not sure there will be data to read, schedule this receive with IONotifier or something. Otherwise it will block #ifdef DEBUG printf("TCPSender: Receive from TCPSender %d\n", this); #endif int nbytes; nbytes = read (socketItself, receivedStream, MAXMSG); if (nbytes < 0){ /* Read error. */ perror("TCPSender: read"); // this->CloseConnection(); exit (EXIT_FAILURE); }else if (nbytes == 0){ /* End-of-file. */ receivedStream[0]='0'; receivedStream[1]='\0'; this->CloseConnection(); }else{ /* Data read. */ //look for '\n' and chomp, in anycase read doesn't supply the \n so add it if(receivedStream[nbytes-1]=='\n'){ receivedStream[nbytes-1]='\0'; #ifdef DEBUG // printf("TCPSender: %c%c%c chomp\n", receivedStream[nbytes-3],receivedStream[nbytes-2],receivedStream[nbytes-1]); #endif }else{ receivedStream[nbytes]='\0'; } #ifdef DEBUG printf("TCPSender: got message: `%s'\n", receivedStream); #endif this->process(); newReceived=true; } } string TCPSender::ReturnNew () { if (newReceived) { newReceived=false; return string(receivedStream); }else{ return string("0"); } } //this public method should be capitalized for some consistency. Put the change should be propagated. class Make up! void TCPSender::process (){ //to be overriden #ifdef DEBUG printf("TCPSender: message Received [%s] and processed from server %s:%d \n",receivedStream,servName,servPort); #endif }