00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00033 #include <assert.h>
00034
00035
00036 #ifdef linux
00037 #include <poll.h>
00038 #include <unistd.h>
00039 #include <errno.h>
00040 #include <sys/types.h>
00041 #include <sys/socket.h>
00042 #include <netinet/in.h>
00043 #include <netinet/tcp.h>
00044 #include <arpa/inet.h>
00045 #include <unistd.h>
00046 #include <netdb.h>
00047 #include <fcntl.h>
00048 #include <time.h>
00049 #endif
00050 #ifdef WIN32
00051 #define WIN32_LEAN_AND_MEAN
00052 #include <windows.h>
00053 #include <winsock2.h>
00054 #include <ws2tcpip.h>
00055 #include <time.h>
00056 #endif
00057
00058 #include "ltkcpp_platform.h"
00059 #include "ltkcpp_base.h"
00060 #include "ltkcpp_frame.h"
00061 #include "ltkcpp_connection.h"
00062
00063
00064 #define LLRP1_TCP_PORT (5084u)
00065
00066
00067 namespace LLRP
00068 {
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #ifdef linux
00083 class CPlatformSocket
00084 {
00085 public:
00086 int m_sock;
00087
00088 CPlatformSocket(int sock);
00089 };
00090
00091 CPlatformSocket::CPlatformSocket (int sock)
00092 {
00093 m_sock = sock;
00094 }
00095
00096 #endif
00097 #ifdef WIN32
00098 class CPlatformSocket
00099 {
00100 public:
00101 SOCKET m_sock;
00102
00103 CPlatformSocket(SOCKET sock);
00104 };
00105
00106 CPlatformSocket::CPlatformSocket (SOCKET sock)
00107 {
00108 m_sock = sock;
00109 }
00110
00111 #endif
00112
00113
00132 CConnection::CConnection (
00133 const CTypeRegistry * pTypeRegistry,
00134 unsigned int nBufferSize)
00135 {
00136
00137
00138
00139 if(0 == nBufferSize)
00140 {
00141 nBufferSize = 128u*1024u;
00142 }
00143
00144
00145
00146
00147
00148
00149 if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
00150 {
00151 throw "Insane buffer size";
00152 }
00153
00154
00155
00156
00157
00158 m_pPlatformSocket = NULL;
00159 m_pTypeRegistry = pTypeRegistry;
00160 m_nBufferSize = nBufferSize;
00161
00162 memset(&m_Recv, 0, sizeof m_Recv);
00163 memset(&m_Send, 0, sizeof m_Send);
00164
00165
00166
00167
00168 m_Recv.pBuffer = new llrp_byte_t[nBufferSize];
00169 m_Send.pBuffer = new llrp_byte_t[nBufferSize];
00170
00171
00172
00173
00174 memset(m_Recv.pBuffer, 0, nBufferSize);
00175 memset(m_Send.pBuffer, 0, nBufferSize);
00176
00177 #ifdef WIN32
00178
00179
00180
00181 {
00182 WSADATA SocketLibraryInitData;
00183 WSAStartup(0xFFFF, &SocketLibraryInitData);
00184 }
00185 #endif
00186
00187
00188
00189
00190 }
00191
00192
00200 CConnection::~CConnection (void)
00201 {
00202
00203
00204
00205 closeConnectionToReader();
00206
00207
00208
00209
00210 for (
00211 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
00212 msg != m_listInputQueue.end();
00213 msg++)
00214 {
00215 delete *msg;
00216 }
00217
00218
00219
00220
00221 delete[] m_Recv.pBuffer;
00222 delete[] m_Send.pBuffer;
00223
00224 #ifdef WIN32
00225
00226
00227
00228 {
00229 WSACleanup();
00230 }
00231 #endif
00232
00233 }
00234
00235
00254 int
00255 CConnection::openConnectionToReader (
00256 const char * pReaderHostName)
00257 {
00258 #ifdef linux
00259 int Sock;
00260 #endif
00261 #ifdef WIN32
00262 SOCKET Sock;
00263 #endif
00264 struct addrinfo aiHints;
00265 struct addrinfo * aiList;
00266 int Flag;
00267 struct sockaddr_in Sin;
00268 int rc;
00269
00270
00271
00272
00273 m_pConnectErrorStr = NULL;
00274
00275
00276
00277
00278 if(NULL != m_pPlatformSocket)
00279 {
00280 m_pConnectErrorStr = "already connected";
00281 return -1;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 memset(&aiHints, 0, sizeof(aiHints));
00291 aiHints.ai_family = AF_INET;
00292 aiList = NULL;
00293
00294 rc = getaddrinfo(pReaderHostName, NULL, &aiHints, &aiList);
00295 if(0 != rc)
00296 {
00297 m_pConnectErrorStr = "host lookup failed";
00298 return -1;
00299 }
00300
00301
00302
00303
00304 memset(&Sin, 0, sizeof Sin);
00305 Sin.sin_family = AF_INET;
00306 Sin.sin_addr = ((struct sockaddr_in *)(aiList->ai_addr))->sin_addr;
00307 Sin.sin_port = htons(LLRP1_TCP_PORT);
00308
00309
00310
00311
00312 freeaddrinfo(aiList);
00313
00314
00315
00316
00317 Sock = socket(AF_INET, SOCK_STREAM, 0);
00318 #ifdef linux
00319 if(0 > Sock)
00320 #endif
00321 #ifdef WIN32
00322 if(NULL == Sock)
00323 #endif
00324 {
00325 m_pConnectErrorStr = "socket() failed";
00326 return -3;
00327 }
00328
00329
00330
00331
00332 rc = connect(Sock, (struct sockaddr *)&Sin, sizeof Sin);
00333 if(0 > rc)
00334 {
00335
00336 m_pConnectErrorStr = "connection failed";
00337 #ifdef linux
00338 close(Sock);
00339 #endif
00340 #ifdef WIN32
00341 closesocket(Sock);
00342 #endif
00343 return -4;
00344 }
00345
00346
00347
00348
00349
00350 Flag = 1;
00351
00352 #ifdef linux
00353 setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (void*)&Flag, sizeof Flag);
00354 #endif
00355 #ifdef WIN32
00356 setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (char*)&Flag, sizeof Flag);
00357 #endif
00358
00359
00360
00361
00362 m_pPlatformSocket = new CPlatformSocket(Sock);
00363
00364
00365
00366
00367 return 0;
00368 }
00369
00370
00381 const char *
00382 CConnection::getConnectError (void)
00383 {
00384 return m_pConnectErrorStr;
00385 }
00386
00387
00398 int
00399 CConnection::closeConnectionToReader (void)
00400 {
00401 if(NULL == m_pPlatformSocket)
00402 {
00403 m_pConnectErrorStr = "not connected";
00404 return -1;
00405 }
00406
00407 #ifdef linux
00408 shutdown(m_pPlatformSocket->m_sock, SHUT_RDWR);
00409 close(m_pPlatformSocket->m_sock);
00410 m_pPlatformSocket->m_sock = -1;
00411 #endif
00412 #ifdef WIN32
00413 closesocket(m_pPlatformSocket->m_sock);
00414 m_pPlatformSocket->m_sock = NULL;
00415 #endif
00416
00417 delete m_pPlatformSocket;
00418 m_pPlatformSocket = NULL;
00419 return 0;
00420 }
00421
00422
00445 CMessage *
00446 CConnection::transact (
00447 CMessage * pSendMessage,
00448 int nMaxMS)
00449 {
00450 const CTypeDescriptor * pResponseType;
00451 EResultCode lrc;
00452 CMessage * pResponseMessage;
00453
00454
00455
00456
00457
00458
00459
00460
00461 pResponseType = pSendMessage->m_pType->m_pResponseType;
00462 if(NULL == pResponseType)
00463 {
00464 CErrorDetails * pError = &m_Send.ErrorDetails;
00465
00466 pError->clear();
00467 pError->resultCodeAndWhatStr(RC_MissingResponseType,
00468 "send message has no response type");
00469 return NULL;
00470 }
00471
00472
00473
00474
00475 lrc = sendMessage(pSendMessage);
00476 if(RC_OK != lrc)
00477 {
00478 return NULL;
00479 }
00480
00481
00482
00483
00484 pResponseMessage = recvResponse(nMaxMS,
00485 pResponseType, pSendMessage->getMessageID());
00486
00487
00488
00489
00490 return pResponseMessage;
00491 }
00492
00493
00508 const CErrorDetails *
00509 CConnection::getTransactError (void)
00510 {
00511 const CErrorDetails * pError;
00512
00513 pError = getSendError();
00514 if(RC_OK == pError->m_eResultCode)
00515 {
00516 pError = getRecvError();
00517 }
00518
00519 return pError;
00520 }
00521
00522
00538 EResultCode
00539 CConnection::sendMessage (
00540 CMessage * pMessage)
00541 {
00542 CErrorDetails * pError = &m_Send.ErrorDetails;
00543 CFrameEncoder * pEncoder;
00544
00545
00546
00547
00548 pError->clear();
00549
00550
00551
00552
00553 if(NULL == m_pPlatformSocket)
00554 {
00555 pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00556 return pError->m_eResultCode;
00557 }
00558
00559
00560
00561
00562
00563 pEncoder = new CFrameEncoder(m_Send.pBuffer, m_nBufferSize);
00564
00565
00566
00567
00568 if(NULL == pEncoder)
00569 {
00570 pError->resultCodeAndWhatStr(RC_MiscError,
00571 "encoder constructor failed");
00572 return pError->m_eResultCode;
00573 }
00574
00575
00576
00577
00578
00579 pEncoder->encodeElement(pMessage);
00580
00581
00582
00583
00584
00585 m_Send.ErrorDetails = pEncoder->m_ErrorDetails;
00586 m_Send.nBuffer = pEncoder->getLength();
00587
00588
00589
00590
00591 delete pEncoder;
00592
00593
00594
00595
00596
00597
00598 if(RC_OK == pError->m_eResultCode)
00599 {
00600 int rc;
00601
00602 rc = send(m_pPlatformSocket->m_sock, (char*)m_Send.pBuffer,
00603 m_Send.nBuffer, 0);
00604 if(rc != (int)m_Send.nBuffer)
00605 {
00606
00607 pError->resultCodeAndWhatStr(RC_SendIOError, "send IO error");
00608 }
00609 }
00610
00611
00612
00613
00614 return pError->m_eResultCode;
00615 }
00616
00617
00627 const CErrorDetails *
00628 CConnection::getSendError (void)
00629 {
00630 return &m_Send.ErrorDetails;
00631 }
00632
00633
00654 CMessage *
00655 CConnection::recvMessage (
00656 int nMaxMS)
00657 {
00658 time_t timeLimit = calculateTimeLimit(nMaxMS);
00659 EResultCode lrc;
00660 CMessage * pMessage;
00661
00662
00663
00664
00665 if(NULL == m_pPlatformSocket)
00666 {
00667 CErrorDetails * pError = &m_Recv.ErrorDetails;
00668
00669 pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00670 return NULL;
00671 }
00672
00673
00674
00675
00676 for(;;)
00677 {
00678
00679
00680
00681
00682 if(!m_listInputQueue.empty())
00683 {
00684 pMessage = m_listInputQueue.front();
00685 m_listInputQueue.pop_front();
00686 return pMessage;
00687 }
00688
00689
00690
00691
00692
00693 lrc = recvAdvance(nMaxMS, timeLimit);
00694 if(lrc != RC_OK)
00695 {
00696 return NULL;
00697 }
00698 }
00699 }
00700
00701
00712 const CErrorDetails *
00713 CConnection::getRecvError (void)
00714 {
00715 return &m_Recv.ErrorDetails;
00716 }
00717
00718
00765 CMessage *
00766 CConnection::recvResponse (
00767 int nMaxMS,
00768 const CTypeDescriptor * pResponseType,
00769 llrp_u32_t ResponseMessageID)
00770 {
00771 time_t timeLimit = calculateTimeLimit(nMaxMS);
00772 const CTypeDescriptor * pErrorMsgType;
00773 EResultCode lrc;
00774 CMessage * pMessage;
00775
00776
00777
00778
00779 if(NULL == m_pPlatformSocket)
00780 {
00781 CErrorDetails * pError = &m_Recv.ErrorDetails;
00782
00783 pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00784 return NULL;
00785 }
00786
00787
00788
00789
00790 pErrorMsgType = m_pTypeRegistry->lookupMessage(100u);
00791
00792
00793
00794
00795 for(;;)
00796 {
00797
00798
00799
00800
00801 for (
00802 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
00803 msg != m_listInputQueue.end();
00804 msg++)
00805 {
00806 pMessage = *msg;
00807
00808
00809
00810
00811 if(NULL != pResponseType)
00812 {
00813
00814
00815
00816
00817 if(pMessage->m_pType != pResponseType &&
00818 pMessage->m_pType != pErrorMsgType)
00819 {
00820
00821 continue;
00822 }
00823 }
00824
00825
00826
00827
00828 if(0 != ResponseMessageID)
00829 {
00830 if(pMessage->getMessageID() != ResponseMessageID)
00831 {
00832
00833 continue;
00834 }
00835 }
00836
00837
00838
00839
00840 m_listInputQueue.remove(pMessage);
00841 return pMessage;
00842 }
00843
00844
00845
00846
00847
00848 lrc = recvAdvance(nMaxMS, timeLimit);
00849 if(lrc != RC_OK)
00850 {
00851 return NULL;
00852 }
00853
00854
00855
00856
00857 }
00858 }
00859
00860
00895 EResultCode
00896 CConnection::recvAdvance (
00897 int nMaxMS,
00898 time_t timeLimit)
00899 {
00900 CErrorDetails * pError = &m_Recv.ErrorDetails;
00901
00902
00903
00904
00905 pError->clear();
00906
00907
00908
00909
00910 for(;;)
00911 {
00912 int rc;
00913
00914
00915
00916
00917
00918
00919 m_Recv.bFrameValid = FALSE;
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 m_Recv.FrameExtract = CFrameExtract(m_Recv.pBuffer, m_Recv.nBuffer);
00940
00941
00942
00943
00944 if(CFrameExtract::FRAME_ERROR == m_Recv.FrameExtract.m_eStatus)
00945 {
00946 pError->resultCodeAndWhatStr(RC_RecvFramingError,
00947 "framing error in message stream");
00948 break;
00949 }
00950
00951
00952
00953
00954
00955 if(CFrameExtract::NEED_MORE == m_Recv.FrameExtract.m_eStatus)
00956 {
00957 unsigned int nRead = m_Recv.FrameExtract.m_nBytesNeeded;
00958 unsigned char * pBufPos = &m_Recv.pBuffer[m_Recv.nBuffer];
00959
00960
00961
00962
00963
00964 if(0 != timeLimit)
00965 {
00966 if(time(NULL) > timeLimit)
00967 {
00968
00969 pError->resultCodeAndWhatStr(RC_RecvTimeout,
00970 "timeout");
00971 break;
00972 }
00973 }
00974
00975
00976
00977
00978
00979 if(m_Recv.nBuffer + nRead > m_nBufferSize)
00980 {
00981 pError->resultCodeAndWhatStr(RC_RecvBufferOverflow,
00982 "buffer overflow");
00983 break;
00984 }
00985
00986
00987
00988
00989
00990 if(nMaxMS >= 0)
00991 {
00992 #ifdef linux
00993 struct pollfd pfd;
00994
00995 pfd.fd = m_pPlatformSocket->m_sock;
00996 pfd.events = POLLIN;
00997 pfd.revents = 0;
00998
00999 rc = poll(&pfd, 1, nMaxMS);
01000 #endif
01001 #ifdef WIN32
01002 fd_set readfds;
01003 struct timeval timeout;
01004
01005 timeout.tv_sec = nMaxMS / 1000u;
01006 timeout.tv_usec = (nMaxMS % 1000u) * 1000u;
01007
01008 FD_ZERO(&readfds);
01009 FD_SET(m_pPlatformSocket->m_sock, &readfds);
01010 rc = select(-1, &readfds, NULL, NULL, &timeout);
01011
01012 #endif
01013 if(0 > rc)
01014 {
01015
01016 pError->resultCodeAndWhatStr(RC_RecvIOError,
01017 "poll failed");
01018 break;
01019 }
01020 if(0 == rc)
01021 {
01022
01023 pError->resultCodeAndWhatStr(RC_RecvTimeout,
01024 "timeout");
01025 break;
01026 }
01027 }
01028
01029
01030
01031
01032 rc = recv(m_pPlatformSocket->m_sock, (char*)pBufPos, nRead, 0);
01033 if(0 > rc)
01034 {
01035
01036
01037
01038
01039
01040
01041 pError->resultCodeAndWhatStr(RC_RecvIOError,
01042 "recv IO error");
01043 break;
01044 }
01045
01046 if(0 == rc)
01047 {
01048
01049 pError->resultCodeAndWhatStr(RC_RecvEOF,
01050 "recv end-of-file");
01051 break;
01052 }
01053
01054
01055
01056
01057
01058
01059 m_Recv.nBuffer += rc;
01060
01061 continue;
01062 }
01063
01064
01065
01066
01067
01068 if(CFrameExtract::READY == m_Recv.FrameExtract.m_eStatus)
01069 {
01070
01071
01072
01073 CFrameDecoder * pDecoder;
01074 CMessage * pMessage;
01075
01076
01077
01078
01079
01080 pDecoder = new CFrameDecoder(m_pTypeRegistry,
01081 m_Recv.pBuffer, m_Recv.nBuffer);
01082
01083
01084
01085
01086 if(pDecoder == NULL)
01087 {
01088
01089 m_Recv.nBuffer = 0;
01090 m_Recv.bFrameValid = FALSE;
01091 pError->resultCodeAndWhatStr(RC_MiscError,
01092 "decoder constructor failed");
01093 break;
01094 }
01095
01096
01097
01098
01099
01100 pMessage = pDecoder->decodeMessage();
01101
01102
01103
01104
01105
01106 m_Recv.ErrorDetails = pDecoder->m_ErrorDetails;
01107
01108
01109
01110
01111 delete pDecoder;
01112
01113
01114
01115
01116
01117 if(NULL == pMessage)
01118 {
01119
01120
01121
01122 if(RC_OK == pError->m_eResultCode)
01123 {
01124 pError->resultCodeAndWhatStr(RC_MiscError,
01125 "NULL message but no error");
01126 }
01127
01128
01129
01130
01131 m_Recv.nBuffer = 0;
01132 m_Recv.bFrameValid = FALSE;
01133
01134 break;
01135 }
01136
01137
01138
01139
01140 m_listInputQueue.push_back(pMessage);
01141
01142
01143
01144
01145
01146
01147 m_Recv.bFrameValid = TRUE;
01148 m_Recv.nBuffer = 0;
01149
01150 break;
01151 }
01152
01153
01154
01155
01156
01157
01158
01159 assert(0);
01160 }
01161
01162 return pError->m_eResultCode;
01163 }
01164
01165
01188 time_t
01189 CConnection::calculateTimeLimit (
01190 int nMaxMS)
01191 {
01192 if(0 == nMaxMS)
01193 {
01194
01195 return time(NULL) + 1;
01196 }
01197 else if(0 < nMaxMS)
01198 {
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 return time(NULL) + ((nMaxMS + 1999u) / 1000u);
01220 }
01221 else
01222 {
01223
01224 return 0;
01225 }
01226 }
01227
01228 };
01229