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