00001
00002
00003
00004
00005
00006
00007 #include "tcp.hpp"
00008 #include "../tools/errorhandler.hpp"
00009 #include "../tools/toolbox.hpp"
00010 #include <stdio.h>
00011
00012 #include <sys/socket.h>
00013 #include <arpa/inet.h>
00014 #include <string.h>
00015 #include <netdb.h>
00016
00017
00018 Tcp::Tcp()
00019 {
00020 m_beVerbose = false;
00021 m_connectionSocket = -1;
00022
00023 m_readThread.m_threadShouldRun = false;
00024
00025 m_longStringWarningPrinted = false;
00026 m_disconnectFunction = NULL;
00027 m_disconnectFunctionObjPtr = NULL;
00028 m_readFunction = NULL;
00029 m_readFunctionObjPtr = NULL;
00030
00031 }
00032
00033
00034
00035
00036 Tcp::~Tcp(void)
00037 {
00038 close();
00039 }
00040
00041
00042
00043
00044
00045
00046
00047 bool Tcp::write(UINT8* buffer, UINT32 numberOfBytes)
00048 {
00049 INT32 bytesSent;
00050 bool result;
00051 INT32* socketPtr = &m_connectionSocket;
00052
00053
00054 bytesSent = ::send(*socketPtr, buffer, numberOfBytes, 0);
00055
00056 if (bytesSent != (INT32)numberOfBytes)
00057 {
00058 printWarning("Tcp::write: Failed to send data to socket.");
00059 result = false;
00060 }
00061 else
00062 {
00063
00064 printInfoMessage("Tcp::write: Sent " + toString(numberOfBytes) + " bytes to client.", m_beVerbose);
00065 result = true;
00066 }
00067
00068 return result;
00069 }
00070
00071
00072
00073
00074
00075 void Tcp::setDisconnectCallbackFunction(DisconnectFunction discFunction, void* obj)
00076 {
00077 m_disconnectFunction = discFunction;
00078 m_disconnectFunctionObjPtr = obj;
00079 }
00080
00081
00082
00088 bool Tcp::isOpen()
00089 {
00090 if (m_connectionSocket >= 0)
00091 {
00092
00093 return true;
00094 }
00095
00096
00097 return false;
00098 }
00099
00100
00101
00102
00103 void Tcp::setReadCallbackFunction(Tcp::ReadFunction readFunction, void* obj)
00104 {
00105 m_readFunction = readFunction;
00106 m_readFunctionObjPtr = obj;
00107 }
00108
00109
00110
00111
00112 bool Tcp::open(UINT32 ipAddress, UINT16 port, bool enableVerboseDebugOutput)
00113 {
00114 std::string ipAdrStr;
00115
00116 ipAdrStr = ipAdrToString(ipAddress);
00117
00118 bool result = open(ipAdrStr, port, enableVerboseDebugOutput);
00119
00120 return result;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 bool Tcp::open(std::string ipAddress, UINT16 port, bool enableVerboseDebugOutput)
00130 {
00131 INT32 result;
00132 m_beVerbose = enableVerboseDebugOutput;
00133
00134
00135
00136
00137 printInfoMessage("Tcp::open: Opening connection.", m_beVerbose);
00138
00139
00140 m_connectionSocket = -1;
00141 {
00142 ScopedLock lock(&m_socketMutex);
00143 m_connectionSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
00144 }
00145 if (m_connectionSocket < 0)
00146 {
00147 printError("Tcp::open: socket() failed, aborting.");
00148 return false;
00149 }
00150
00151
00152 printInfoMessage("Tcp::open: Connecting. Target address is " + ipAddress + ":" + toString(port) + ".", m_beVerbose);
00153
00154 struct sockaddr_in addr;
00155 struct hostent *server;
00156 server = gethostbyname(ipAddress.c_str());
00157 memset(&addr, 0, sizeof(addr));
00158 addr.sin_family = AF_INET;
00159 bcopy((char *)server->h_addr, (char *)&addr.sin_addr.s_addr, server->h_length);
00160 addr.sin_port = htons(port);
00161 result = connect(m_connectionSocket, (sockaddr*)(&addr), sizeof(addr));
00162 if (result < 0)
00163 {
00164
00165 std::string text = "Tcp::open: Failed to open TCP connection to " + ipAddress + ", aborting.";
00166 printError(text);
00167 return false;
00168 }
00169
00170 printInfoMessage("Tcp::open: Connection established. Now starting read thread.", m_beVerbose);
00171
00172
00173 m_readThread.run(this);
00174
00175 printInfoMessage("Tcp::open: Done, leaving now.", m_beVerbose);
00176
00177 return true;
00178 }
00179
00180
00181
00182
00183
00184 void Tcp::readThreadFunction(bool& endThread, UINT16& waitTimeMs)
00185 {
00186 INT32 result;
00187
00188
00189 result = readInputData();
00190
00191
00192 if (result < 0)
00193 {
00194
00195 if (m_readThread.m_threadShouldRun == true)
00196 {
00197
00198 printInfoMessage("Tcp::readThreadMain: Connection is lost! Read thread terminates now.", m_beVerbose);
00199 }
00200 waitTimeMs = 0;
00201 }
00202 else if (result == 0)
00203 {
00204
00205 waitTimeMs = 1;
00206 }
00207 else
00208 {
00209
00210 waitTimeMs = 0;
00211 }
00212 }
00213
00214
00215
00216
00217 INT32 Tcp::readInputData()
00218 {
00219
00220 const UINT16 max_length = 8192;
00221 UINT8 inBuffer[max_length];
00222 INT32 recvMsgSize = 0;
00223
00224
00225 if (isOpen() == false)
00226 {
00227 printError("Tcp::readInputData: Connection is not open, aborting!");
00228 return -1;
00229 }
00230
00231
00232 recvMsgSize = recv(m_connectionSocket, inBuffer, max_length, 0);
00233 if (recvMsgSize < 0)
00234 {
00235
00236 printError("Tcp::readInputData: Failed to read data from socket, aborting!");
00237 }
00238 else if (recvMsgSize > 0)
00239 {
00240
00241 printInfoMessage("Tcp::readInputData: Read " + toString(recvMsgSize) + " bytes from the connection.", m_beVerbose);
00242
00243
00244
00245 if (m_readFunction != NULL)
00246 {
00247
00248 UINT32 length_uint32 = (UINT32)recvMsgSize;
00249 m_readFunction(m_readFunctionObjPtr, inBuffer, length_uint32);
00250 }
00251 else
00252 {
00253
00254
00255 for (INT32 i = 0; i < recvMsgSize; i++)
00256 {
00257 m_rxBuffer.push_back(inBuffer[i]);
00258 }
00259 }
00260 }
00261 else if (recvMsgSize == 0)
00262 {
00263
00264 printInfoMessage("Tcp::readInputData: Read 0 bytes - connection is lost!", true);
00265
00266
00267 if (m_disconnectFunction != NULL)
00268 {
00269 m_disconnectFunction(m_disconnectFunctionObjPtr);
00270 }
00271
00272
00273 ScopedLock lock(&m_socketMutex);
00274
00275 m_connectionSocket = -1;
00276 }
00277
00278 return recvMsgSize;
00279 }
00280
00281
00282
00283
00284
00285 void Tcp::close()
00286 {
00287 printInfoMessage("Tcp::close: Closing Tcp connection.", m_beVerbose);
00288
00289 if (isOpen() == true)
00290 {
00291
00292 m_readThread.m_threadShouldRun = false;
00293
00294
00295 ::close(m_connectionSocket);
00296
00297
00298 printInfoMessage("Tcp::close: Waiting for the server thread to terminate...", m_beVerbose);
00299
00300
00301 stopReadThread();
00302 }
00303 else
00304 {
00305 printInfoMessage("Tcp::close: Nothing to do - no open connection? Aborting.", m_beVerbose);
00306 }
00307
00308 printInfoMessage("Tcp::close: Done - Connection is now closed.", m_beVerbose);
00309 }
00310
00311
00315 void Tcp::stopReadThread()
00316 {
00317 printInfoMessage("Tcp::stopReadThread: Stopping thread.", m_beVerbose);
00318
00319
00320 m_readThread.join();
00321
00322 printInfoMessage("Tcp::stopReadThread: Done - Read thread is now closed.", m_beVerbose);
00323 }
00324
00325
00326
00332 UINT32 Tcp::getNumReadableBytes()
00333 {
00334 return m_rxBuffer.size();
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 UINT32 Tcp::read(UINT8* buffer, UINT32 bufferLen)
00347 {
00348 UINT32 bytesRead = 0;
00349
00350
00351 while ((getNumReadableBytes() > 0) && (bufferLen > bytesRead))
00352 {
00353 buffer[bytesRead] = m_rxBuffer.front();
00354 m_rxBuffer.pop_front();
00355 bytesRead += 1;
00356 }
00357
00358 return bytesRead;
00359 }
00360
00361
00367 std::string Tcp::readString(UINT8 delimiter)
00368 {
00369 UINT8 c = delimiter;
00370 std::string outString;
00371 const UINT16 maxStringLength = 8192;
00372
00373
00374 while (m_rxBuffer.size() > 0)
00375 {
00376
00377 c = m_rxBuffer.front();
00378 m_rxBuffer.pop_front();
00379 if (c == delimiter)
00380 {
00381
00382 outString = m_rxString;
00383 m_rxString.clear();
00384 break;
00385 }
00386 m_rxString += c;
00387 }
00388
00389
00390 if (m_rxString.length() > maxStringLength)
00391 {
00392 if (m_longStringWarningPrinted == false)
00393 {
00394
00395 printWarning("Receive-String has excessive length (" + toString(m_rxString.length()) +" bytes). Clearing string. On serial devices, incorrect bitrate settings may cause this behaviour.");
00396 m_longStringWarningPrinted = true;
00397 }
00398 else
00399 {
00400
00401 printWarning("Receive-String has excessive length (" + toString(m_rxString.length()) +" bytes). Clearing string.");
00402 }
00403 m_rxString.clear();
00404 }
00405
00406
00407 if ((m_beVerbose == true) && (outString.length() > 0))
00408 {
00409 printInfoMessage("Tcp::readString: Returning string: " + outString, true);
00410 }
00411
00412 return outString;
00413 }
00414
00415