1 | /* Copyright (C) 2001 Marc Casaldaliga Albisu <casaldaliga@ifae.es>
|
---|
2 | ================================================================
|
---|
3 |
|
---|
4 | This code is free software; you can redistribute it and/or modify
|
---|
5 | it under the terms of the GNU General Public License as published by
|
---|
6 | the Free Software Foundation; either version 2 of the License, or
|
---|
7 | (at your option) any later version.
|
---|
8 |
|
---|
9 | This code is distributed in the hope that it will be useful,
|
---|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
12 | GNU General Public License for more details.
|
---|
13 |
|
---|
14 | You should have received a copy of the GNU General Public License
|
---|
15 | along with Emacs (which is required to make this stuff work); if
|
---|
16 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
17 | Cambridge, MA 02139, USA.
|
---|
18 | ==================================================================
|
---|
19 | */
|
---|
20 | #include "TCPSender.hxx"
|
---|
21 | #include "PeriodicAction.hxx"
|
---|
22 | #include "socket_functions.h"
|
---|
23 | #include <iostream>
|
---|
24 | #include <string.h>
|
---|
25 | #include <unistd.h>
|
---|
26 | #include <errno.h>
|
---|
27 | #include <stdio.h>
|
---|
28 |
|
---|
29 | TCPSender::TCPSender (char * servName_, unsigned int servPort_ )
|
---|
30 | :retryingTime(3000000),tryingConnect(retryingTime),servPort(servPort_),comMode(false),newReceived(false)//,servName(servName_)
|
---|
31 | {
|
---|
32 | strcpy(servName,servName_);
|
---|
33 | //prepare the name
|
---|
34 | init_sockaddr (&server, servName_, servPort);
|
---|
35 | //this->Reset;
|
---|
36 |
|
---|
37 |
|
---|
38 | }
|
---|
39 | TCPSender::~TCPSender(){
|
---|
40 | if(comMode){
|
---|
41 | CloseConnection();
|
---|
42 | }
|
---|
43 | }
|
---|
44 |
|
---|
45 | void TCPSender::CloseConnection(){
|
---|
46 | if (comMode){
|
---|
47 | #ifdef DEBUG
|
---|
48 | cout<<"TCPSender: closing socket to server "<<servName<<":"<<servPort<<"\n";
|
---|
49 | #endif
|
---|
50 | close(socketItself);
|
---|
51 | comMode=false;
|
---|
52 | }
|
---|
53 | }
|
---|
54 | void TCPSender::Reset() {
|
---|
55 | if (comMode){
|
---|
56 | CloseConnection();
|
---|
57 | }
|
---|
58 | //Tryingconnect PeriodicAction object DO this->isTrialToConnectSuccesful periodically WHILE this call is NOT returning true, that is is retrying until connection is succesfull. All the threading is done inside PeriodicAction!
|
---|
59 | tryingConnect.DoWhileNot(slot(this, &TCPSender::isTrialToConnectSuccesful) );
|
---|
60 |
|
---|
61 | // // tryingConnect.FinallyDo(... callback to call when tryingConnect is finished, for example Start reporting periodically (start another PeriodicAction
|
---|
62 | // // supose we have a virtual method WhenConnectionIsEstablished
|
---|
63 | // tryingConnect.FinallyDo(slot(this,&TCPSender::WhenConnectionIsEstablished));
|
---|
64 | tryingConnect.Start();
|
---|
65 |
|
---|
66 | }
|
---|
67 |
|
---|
68 | int TCPSender::IODescriptor(){ //returns file descriptor (e.g. to use with IONotifier)
|
---|
69 | return socketItself;
|
---|
70 |
|
---|
71 | }
|
---|
72 |
|
---|
73 | bool TCPSender::isTrialToConnectSuccesful(){
|
---|
74 | //create the socketItself. After a failed connect call the socket has to be initialized again (?)
|
---|
75 | socketItself = socket (PF_INET, SOCK_STREAM, 0);
|
---|
76 | if ( (socketItself < 0) || (prepare_socket(socketItself) == -1) ) {
|
---|
77 | perror("TCPSender: socket (client)");
|
---|
78 | exit (EXIT_FAILURE);
|
---|
79 | }
|
---|
80 | #ifdef DEBUG
|
---|
81 | printf("TCPSender: trying to connect\n");
|
---|
82 | #endif
|
---|
83 | if (0 > connect (socketItself,
|
---|
84 | (struct sockaddr *) &server,
|
---|
85 | sizeof (server))){
|
---|
86 | int myerrno=errno;
|
---|
87 | perror("TCPSender: connect. Retrying");
|
---|
88 | comMode=false;
|
---|
89 | close(socketItself);
|
---|
90 |
|
---|
91 | return false;
|
---|
92 |
|
---|
93 | }else{
|
---|
94 | comMode=true;
|
---|
95 | // fconfigure $socketItself -buffering line
|
---|
96 | #ifdef DEBUG
|
---|
97 | printf("TCPSender: TCPSender: successful connection\n");
|
---|
98 | #endif
|
---|
99 | return true;
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 |
|
---|
104 | void TCPSender::Send (char *msg ){ //Syncronous send
|
---|
105 | char buffer[MAXMSG];
|
---|
106 |
|
---|
107 | strcpy(buffer,msg);
|
---|
108 | unsigned int len=strlen(buffer);
|
---|
109 | buffer[len]='\n';
|
---|
110 | buffer[len+1]='\0';
|
---|
111 | #ifdef DEBUG
|
---|
112 | printf("TCPSender: sending %s \n",buffer);
|
---|
113 | #endif
|
---|
114 |
|
---|
115 | if(write(socketItself, buffer, strlen(buffer)) != strlen(buffer)){
|
---|
116 | int myerrno=errno;
|
---|
117 | }
|
---|
118 | // char * eol="\n";
|
---|
119 | // if(write(socketItself, eol, strlen(eol)) != strlen(eol)){
|
---|
120 | // int myerrno=errno;
|
---|
121 | // }
|
---|
122 | // // fsync(readoutSend);
|
---|
123 | }
|
---|
124 |
|
---|
125 |
|
---|
126 | 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
|
---|
127 | #ifdef DEBUG
|
---|
128 | printf("TCPSender: Receive from TCPSender %d\n", this);
|
---|
129 | #endif
|
---|
130 | int nbytes;
|
---|
131 | nbytes = read (socketItself, receivedStream, MAXMSG);
|
---|
132 | if (nbytes < 0){
|
---|
133 | /* Read error. */
|
---|
134 | perror("TCPSender: read");
|
---|
135 | // this->CloseConnection();
|
---|
136 | exit (EXIT_FAILURE);
|
---|
137 | }else if (nbytes == 0){
|
---|
138 |
|
---|
139 | /* End-of-file. */
|
---|
140 | receivedStream[0]='0';
|
---|
141 | receivedStream[1]='\0';
|
---|
142 | this->CloseConnection();
|
---|
143 | }else{
|
---|
144 | /* Data read. */
|
---|
145 | //look for '\n' and chomp, in anycase read doesn't supply the \n so add it
|
---|
146 | if(receivedStream[nbytes-1]=='\n'){
|
---|
147 | receivedStream[nbytes-1]='\0';
|
---|
148 | #ifdef DEBUG
|
---|
149 | // printf("TCPSender: %c%c%c chomp\n", receivedStream[nbytes-3],receivedStream[nbytes-2],receivedStream[nbytes-1]);
|
---|
150 |
|
---|
151 | #endif
|
---|
152 | }else{
|
---|
153 | receivedStream[nbytes]='\0';
|
---|
154 | }
|
---|
155 | #ifdef DEBUG
|
---|
156 | printf("TCPSender: got message: `%s'\n", receivedStream);
|
---|
157 | #endif
|
---|
158 | this->process();
|
---|
159 | newReceived=true;
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 | string TCPSender::ReturnNew () {
|
---|
164 | if (newReceived) {
|
---|
165 | newReceived=false;
|
---|
166 | return string(receivedStream);
|
---|
167 | }else{
|
---|
168 | return string("0");
|
---|
169 | }
|
---|
170 | }
|
---|
171 |
|
---|
172 | //this public method should be capitalized for some consistency. Put the change should be propagated. class Make up!
|
---|
173 | void TCPSender::process (){
|
---|
174 | //to be overriden
|
---|
175 | #ifdef DEBUG
|
---|
176 | printf("TCPSender: message Received [%s] and processed from server %s:%d \n",receivedStream,servName,servPort);
|
---|
177 | #endif
|
---|
178 | }
|
---|
179 |
|
---|
180 |
|
---|
181 |
|
---|