libvisiontransfer  10.6.0
imagetransfer.cpp
1 /*******************************************************************************
2  * Copyright (c) 2023 Allied Vision Technologies GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #include <cstdio>
16 #include <iostream>
17 #include <cstring>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 #include <mutex>
22 #include "visiontransfer/imagetransfer.h"
23 #include "visiontransfer/exceptions.h"
24 #include "visiontransfer/datablockprotocol.h"
25 #include "visiontransfer/networking.h"
26 
27 using namespace std;
28 using namespace visiontransfer;
29 using namespace visiontransfer::internal;
30 
31 namespace visiontransfer {
32 
33 /*************** Pimpl class containing all private members ***********/
34 
35 class ImageTransfer::Pimpl {
36 public:
37  Pimpl(const char* address, const char* service, ImageProtocol::ProtocolType protType,
38  bool server, int bufferSize, int maxUdpPacketSize);
39  ~Pimpl();
40 
41  // Redeclaration of public members
42  void setRawTransferData(const ImageSet& metaData, const std::vector<unsigned char*>& rawData,
43  int firstTileWidth = 0, int middleTileWidth = 0, int lastTileWidth = 0);
44  void setRawValidBytes(const std::vector<int>& validBytes);
45  void setTransferImageSet(const ImageSet& imageSet);
46  TransferStatus transferData();
47  bool receiveImageSet(ImageSet& imageSet);
48  bool receivePartialImageSet(ImageSet& imageSet, int& validRows, bool& complete);
49  int getNumDroppedFrames() const;
50  bool isConnected() const;
51  void disconnect();
52  std::string getRemoteAddress() const;
53  bool tryAccept();
54 
55  std::string statusReport();
56 private:
57  // Configuration parameters
59  bool isServer;
60  int bufferSize;
61  int maxUdpPacketSize;
62 
63  // Thread synchronization
64  std::recursive_mutex receiveMutex;
65  std::recursive_mutex sendMutex;
66 
67  // Transfer related members
68  SOCKET clientSocket;
69  SOCKET tcpServerSocket;
70  sockaddr_in remoteAddress;
71 
72  // Object for encoding and decoding the network protocol
73  std::unique_ptr<ImageProtocol> protocol;
74 
75  // Outstanding network message that still has to be transferred
76  int currentMsgLen;
77  int currentMsgOffset;
78  const unsigned char* currentMsg;
79 
80  // Socket configuration
81  void setSocketOptions();
82 
83  // Network socket initialization
84  void initTcpServer(const addrinfo* addressInfo);
85  void initTcpClient(const addrinfo* addressInfo);
86  void initUdp(const addrinfo* addressInfo);
87 
88  // Data reception
89  bool receiveNetworkData(bool block);
90 
91  // Data transmission
92  bool sendNetworkMessage(const unsigned char* msg, int length);
93  void sendPendingControlMessages();
94 
95  bool selectSocket(bool read, bool wait);
96 };
97 
98 /******************** Stubs for all public members ********************/
99 
100 ImageTransfer::ImageTransfer(const char* address, const char* service,
101  ImageProtocol::ProtocolType protType, bool server, int bufferSize, int maxUdpPacketSize):
102  pimpl(new Pimpl(address, service, protType, server, bufferSize, maxUdpPacketSize)) {
103  // All initialization in the pimpl class
104 }
105 
106 ImageTransfer::ImageTransfer(const DeviceInfo& device, int bufferSize, int maxUdpPacketSize):
107  pimpl(new Pimpl(device.getIpAddress().c_str(), "7681", static_cast<ImageProtocol::ProtocolType>(device.getNetworkProtocol()),
108  false, bufferSize, maxUdpPacketSize)) {
109  // All initialization in the pimpl class
110 }
111 
112 ImageTransfer::~ImageTransfer() {
113  delete pimpl;
114 }
115 
116 void ImageTransfer::setRawTransferData(const ImageSet& metaData, const std::vector<unsigned char*>& rawData,
117  int firstTileWidth, int middleTileWidth, int lastTileWidth) {
118  pimpl->setRawTransferData(metaData, rawData, firstTileWidth, middleTileWidth, lastTileWidth);
119 }
120 
121 void ImageTransfer::setRawValidBytes(const std::vector<int>& validBytes) {
122  pimpl->setRawValidBytes(validBytes);
123 }
124 
126  pimpl->setTransferImageSet(imageSet);
127 }
128 
130  return pimpl->transferData();
131 }
132 
134  return pimpl->receiveImageSet(imageSet);
135 }
136 
137 bool ImageTransfer::receivePartialImageSet(ImageSet& imageSet, int& validRows, bool& complete) {
138  return pimpl->receivePartialImageSet(imageSet, validRows, complete);
139 }
140 
142  return pimpl->getNumDroppedFrames();
143 }
144 
146  return pimpl->isConnected();
147 }
148 
150  pimpl->disconnect();
151 }
152 
153 std::string ImageTransfer::getRemoteAddress() const {
154  return pimpl->getRemoteAddress();
155 }
156 
158  return pimpl->tryAccept();
159 }
160 
161 /******************** Implementation in pimpl class *******************/
162 ImageTransfer::Pimpl::Pimpl(const char* address, const char* service,
163  ImageProtocol::ProtocolType protType, bool server, int
164  bufferSize, int maxUdpPacketSize)
165  : protType(protType), isServer(server), bufferSize(bufferSize),
166  maxUdpPacketSize(maxUdpPacketSize),
167  clientSocket(INVALID_SOCKET), tcpServerSocket(INVALID_SOCKET),
168  currentMsgLen(0), currentMsgOffset(0), currentMsg(nullptr) {
169 
170  Networking::initNetworking();
171 #ifndef _WIN32
172  // We don't want to be interrupted by the pipe signal
173  signal(SIGPIPE, SIG_IGN);
174 #endif
175 
176  memset(&remoteAddress, 0, sizeof(remoteAddress));
177 
178  // If address is null we use the any address
179  if(address == nullptr || string(address) == "") {
180  address = "0.0.0.0";
181  }
182 
183  addrinfo* addressInfo = Networking::resolveAddress(address, service);
184 
185  try {
186  if(protType == ImageProtocol::PROTOCOL_UDP) {
187  initUdp(addressInfo);
188  } else if(protType == ImageProtocol::PROTOCOL_TCP && isServer) {
189  initTcpServer(addressInfo);
190  } else {
191  initTcpClient(addressInfo);
192  }
193  } catch(...) {
194  freeaddrinfo(addressInfo);
195  throw;
196  }
197 
198  if(addressInfo != nullptr) {
199  freeaddrinfo(addressInfo);
200  }
201 }
202 
203 ImageTransfer::Pimpl::~Pimpl() {
204  if(clientSocket != INVALID_SOCKET) {
205  Networking::closeSocket(clientSocket);
206  }
207  if(tcpServerSocket != INVALID_SOCKET) {
208  Networking::closeSocket(tcpServerSocket);
209  }
210 }
211 
212 void ImageTransfer::Pimpl::initTcpClient(const addrinfo* addressInfo) {
213  protocol.reset(new ImageProtocol(isServer, ImageProtocol::PROTOCOL_TCP));
214  clientSocket = Networking::connectTcpSocket(addressInfo);
215  memcpy(&remoteAddress, addressInfo->ai_addr, sizeof(remoteAddress));
216 
217  // Set special socket options
218  setSocketOptions();
219 }
220 
221 void ImageTransfer::Pimpl::initTcpServer(const addrinfo* addressInfo) {
222  protocol.reset(new ImageProtocol(isServer, ImageProtocol::PROTOCOL_TCP));
223 
224  // Create socket
225  tcpServerSocket = ::socket(addressInfo->ai_family, addressInfo->ai_socktype,
226  addressInfo->ai_protocol);
227  if (tcpServerSocket == INVALID_SOCKET) {
228  TransferException ex("Error opening socket: " + Networking::getLastErrorString());
229  throw ex;
230  }
231 
232  // Enable reuse address
233  Networking::enableReuseAddress(tcpServerSocket, true);
234 
235  // Open a server port
236  Networking::bindSocket(tcpServerSocket, addressInfo);
237  clientSocket = INVALID_SOCKET;
238 
239  // Make the server socket non-blocking
240  Networking::setSocketBlocking(tcpServerSocket, false);
241 
242  // Listen on port
243  listen(tcpServerSocket, 1);
244 }
245 
246 void ImageTransfer::Pimpl::initUdp(const addrinfo* addressInfo) {
247  protocol.reset(new ImageProtocol(isServer, ImageProtocol::PROTOCOL_UDP, maxUdpPacketSize));
248  // Create sockets
249  clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
250  if(clientSocket == INVALID_SOCKET) {
251  TransferException ex("Error creating receive socket: " + Networking::getLastErrorString());
252  throw ex;
253  }
254 
255  // Enable reuse address
256  Networking::enableReuseAddress(clientSocket, true);
257 
258  // Bind socket to port
259  if(isServer && addressInfo != nullptr) {
260  Networking::bindSocket(clientSocket, addressInfo);
261  }
262 
263  if(!isServer) {
264  memcpy(&remoteAddress, addressInfo->ai_addr, sizeof(remoteAddress));
265  }
266 
267  // Set special socket options
268  setSocketOptions();
269 }
270 
271 bool ImageTransfer::Pimpl::tryAccept() {
272  if(protType != ImageProtocol::PROTOCOL_TCP || ! isServer) {
273  throw TransferException("Connections can only be accepted in tcp server mode");
274  }
275 
276  // Accept one connection
277  SOCKET newSocket = Networking::acceptConnection(tcpServerSocket, remoteAddress);
278  if(newSocket == INVALID_SOCKET) {
279  // No connection
280  return false;
281  }
282 
283  // For a new connection we require locks
284  unique_lock<recursive_mutex> recvLock(receiveMutex);
285  unique_lock<recursive_mutex> sendLock(sendMutex);
286 
287  if(clientSocket != INVALID_SOCKET) {
288  Networking::closeSocket(clientSocket);
289  }
290  clientSocket = newSocket;
291 
292  // Set special socket options
293  setSocketOptions();
294 
295  // Reset connection data
296  protocol->resetTransfer();
297  protocol->resetReception();
298  currentMsg = nullptr;
299 
300  return true;
301 }
302 
303 std::string ImageTransfer::Pimpl::getRemoteAddress() const {
304  unique_lock<recursive_mutex> lock(const_cast<recursive_mutex&>(sendMutex)); // either mutex will work
305 
306  if(remoteAddress.sin_family != AF_INET) {
307  return "";
308  }
309 
310  char strPort[11];
311  snprintf(strPort, sizeof(strPort), ":%d", remoteAddress.sin_port);
312 
313  return string(inet_ntoa(remoteAddress.sin_addr)) + strPort;
314 }
315 
316 void ImageTransfer::Pimpl::setSocketOptions() {
317  // Set the socket buffer sizes
318  if(bufferSize > 0) {
319  setsockopt(clientSocket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
320  setsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
321  }
322 
323  Networking::setSocketTimeout(clientSocket, 500);
324  Networking::setSocketBlocking(clientSocket, true);
325 }
326 
327 void ImageTransfer::Pimpl::setRawTransferData(const ImageSet& metaData,
328  const std::vector<unsigned char*>& rawDataVec, int firstTileWidth, int middleTileWidth, int lastTileWidth) {
329  unique_lock<recursive_mutex> sendLock(sendMutex);
330  protocol->setRawTransferData(metaData, rawDataVec, firstTileWidth, middleTileWidth, lastTileWidth);
331  currentMsg = nullptr;
332 }
333 
334 void ImageTransfer::Pimpl::setRawValidBytes(const std::vector<int>& validBytes) {
335  unique_lock<recursive_mutex> sendLock(sendMutex);
336  protocol->setRawValidBytes(validBytes);
337 }
338 
339 void ImageTransfer::Pimpl::setTransferImageSet(const ImageSet& imageSet) {
340  unique_lock<recursive_mutex> sendLock(sendMutex);
341  protocol->setTransferImageSet(imageSet);
342  currentMsg = nullptr;
343 }
344 
345 ImageTransfer::TransferStatus ImageTransfer::Pimpl::transferData() {
346  unique_lock<recursive_mutex> lock(sendMutex);
347 
348  // First receive data in case a control message arrives
349  if(protType == ImageProtocol::PROTOCOL_UDP) {
350  receiveNetworkData(false);
351  }
352 
353  if(remoteAddress.sin_family != AF_INET || !protocol->isConnected()) {
354  return NOT_CONNECTED;
355  }
356 
357 #ifndef _WIN32
358  // Cork TCP to prevent sending of small packets
359  if(protType == ImageProtocol::PROTOCOL_TCP) {
360  int flag = 1;
361  setsockopt(clientSocket, IPPROTO_TCP, TCP_CORK, (char *) &flag, sizeof(int));
362  }
363 #endif
364 
365  // Get first message to transfer
366  if(currentMsg == nullptr) {
367  currentMsgOffset = 0;
368  currentMsg = protocol->getTransferMessage(currentMsgLen);
369 
370  if(currentMsg == nullptr) {
371  if(protocol->transferComplete()) {
372  return ALL_TRANSFERRED;
373  } else {
374  return NO_VALID_DATA;
375  }
376  }
377  }
378 
379  // Try transferring messages
380  bool wouldBlock = false;
381  bool dataTransferred = (currentMsg != nullptr);
382  while(currentMsg != nullptr) {
383  int writing = (int)(currentMsgLen - currentMsgOffset);
384 
385  if(sendNetworkMessage(&currentMsg[currentMsgOffset], writing)) {
386  // Get next message
387  currentMsgOffset = 0;
388  currentMsg = protocol->getTransferMessage(currentMsgLen);
389  } else {
390  // The operation would block
391  wouldBlock = true;
392  break;
393  }
394  }
395 
396  if(dataTransferred && protType == ImageProtocol::PROTOCOL_TCP && protocol->transferComplete()) {
397 #ifndef _WIN32
398  // Uncork - sends the assembled messages
399  int flag = 0;
400  setsockopt(clientSocket, IPPROTO_TCP, TCP_CORK, (char *) &flag, sizeof(int));
401 #else
402  // Force a flush for TCP by turning the nagle algorithm off and on
403  int flag = 1;
404  setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
405  flag = 0;
406  setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
407 #endif
408  }
409 
410  // Also check for control messages at the end
411  if(protType == ImageProtocol::PROTOCOL_UDP) {
412  receiveNetworkData(false);
413  }
414 
415  if(protocol->transferComplete()) {
416  return ALL_TRANSFERRED;
417  } else if(wouldBlock) {
418  return WOULD_BLOCK;
419  } else {
420  return PARTIAL_TRANSFER;
421  }
422 }
423 
424 bool ImageTransfer::Pimpl::receiveImageSet(ImageSet& imageSet) {
425  int validRows = 0;
426  bool complete = false;
427 
428  std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
429  while(!complete) {
430  if(!receivePartialImageSet(imageSet, validRows, complete)) {
431  return false;
432  }
433 
434  unsigned int time = static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::milliseconds>(
435  std::chrono::steady_clock::now() - startTime).count());
436  if(time > 100 && !complete) {
437  return false;
438  }
439  }
440 
441  return true;
442 }
443 
444 bool ImageTransfer::Pimpl::receivePartialImageSet(ImageSet& imageSet,
445  int& validRows, bool& complete) {
446  unique_lock<recursive_mutex> lock(receiveMutex);
447 
448  // Try to receive further image data if needed
449  bool block = true;
450  while(!protocol->imagesReceived() && receiveNetworkData(block)) {
451  block = false;
452  }
453 
454  // Get received image
455  return protocol->getPartiallyReceivedImageSet(imageSet, validRows, complete);
456 }
457 
458 bool ImageTransfer::Pimpl::receiveNetworkData(bool block) {
459  unique_lock<recursive_mutex> lock = block ?
460  unique_lock<recursive_mutex>(receiveMutex) : unique_lock<recursive_mutex>(receiveMutex, std::try_to_lock);
461 
462  if(clientSocket == INVALID_SOCKET) {
463  return false; // Not connected
464  }
465 
466  // First send control messages if necessary
467  sendPendingControlMessages();
468 
469  if(!lock.owns_lock()) {
470  // Waiting for the lock would block this call
471  return false;
472  }
473 
474  // Test if the socket has data available
475  if(!block && !selectSocket(true, false)) {
476  return false;
477  }
478 
479  int maxLength = 0;
480  char* buffer = reinterpret_cast<char*>(protocol->getNextReceiveBuffer(maxLength));
481 
482  // Receive data
483  sockaddr_in fromAddress;
484  socklen_t fromSize = sizeof(fromAddress);
485 
486  int bytesReceived = recvfrom(clientSocket, buffer, maxLength,
487  0, reinterpret_cast<sockaddr*>(&fromAddress), &fromSize);
488 
489  auto err = Networking::getErrno();
490  if(bytesReceived == 0 || (protType == ImageProtocol::PROTOCOL_TCP && bytesReceived < 0 && err == WSAECONNRESET)) {
491  // Connection closed
492  disconnect();
493  } else if(bytesReceived < 0 && err != EWOULDBLOCK && err != EINTR &&
494  err != ETIMEDOUT && err != WSA_IO_PENDING && err != WSAECONNRESET) {
495  TransferException ex("Error reading from socket: " + Networking::getErrorString(err));
496  throw ex;
497  } else if(bytesReceived > 0) {
498  protocol->processReceivedMessage(bytesReceived);
499  if(protocol->newClientConnected()) {
500  // We have just established a new connection
501  memcpy(&remoteAddress, &fromAddress, sizeof(remoteAddress));
502  }
503  }
504 
505  return bytesReceived > 0;
506 }
507 
508 void ImageTransfer::Pimpl::disconnect() {
509  // We just need to forget the remote address in order to
510  // disconnect
511  unique_lock<recursive_mutex> recvLock(receiveMutex);
512  unique_lock<recursive_mutex> sendLock(sendMutex);
513 
514  if(clientSocket != INVALID_SOCKET && protType == ImageProtocol::PROTOCOL_TCP) {
515  Networking::closeSocket(clientSocket);
516  }
517  memset(&remoteAddress, 0, sizeof(remoteAddress));
518 }
519 
520 bool ImageTransfer::Pimpl::isConnected() const {
521  unique_lock<recursive_mutex> lock(const_cast<recursive_mutex&>(sendMutex)); //either mutex will work
522 
523  return remoteAddress.sin_family == AF_INET && protocol->isConnected();
524 }
525 
526 bool ImageTransfer::Pimpl::sendNetworkMessage(const unsigned char* msg, int length) {
527  int written = 0;
528  if(protType == ImageProtocol::PROTOCOL_UDP) {
529  sockaddr_in destAddr;
530  SOCKET destSocket;
531  {
532  unique_lock<recursive_mutex> lock(sendMutex);
533  destAddr = remoteAddress;
534  destSocket = clientSocket;
535  }
536 
537  if(destAddr.sin_family != AF_INET) {
538  return false; // Not connected
539  }
540 
541  written = sendto(destSocket, reinterpret_cast<const char*>(msg), length, 0,
542  reinterpret_cast<sockaddr*>(&destAddr), sizeof(destAddr));
543  } else {
544  SOCKET destSocket;
545  {
546  unique_lock<recursive_mutex> lock(sendMutex);
547  destSocket = clientSocket;
548  }
549  written = send(destSocket, reinterpret_cast<const char*>(msg), length, 0);
550  }
551 
552  auto sendError = Networking::getErrno();
553 
554  if(written < 0) {
555  if(sendError == EAGAIN || sendError == EWOULDBLOCK || sendError == ETIMEDOUT) {
556  // The socket is not yet ready for a new transfer
557  return false;
558  } else if(sendError == EPIPE) {
559  // The connection has been closed
560  disconnect();
561  return false;
562  } else {
563  TransferException ex("Error sending network packet: " + Networking::getErrorString(sendError));
564  throw ex;
565  }
566  } else if(written != length) {
567  if(protType == ImageProtocol::PROTOCOL_UDP) {
568  // The message has been transmitted partially
569  throw TransferException("Unable to transmit complete UDP message");
570  } else {
571  // For TCP we can transmit the remaining data later
572  currentMsgOffset += written;
573  return false;
574  }
575  } else {
576  return true;
577  }
578 }
579 
580 void ImageTransfer::Pimpl::sendPendingControlMessages() {
581  const unsigned char* controlMsgData = nullptr;
582  int controlMsgLen = 0;
583 
584  while(true) {
585  unique_lock<recursive_mutex> lock(sendMutex);
586  if(remoteAddress.sin_family != AF_INET) {
587  return;
588  }
589 
590  controlMsgData = protocol->getNextControlMessage(controlMsgLen);
591 
592  if(controlMsgData != nullptr) {
593  sendNetworkMessage(controlMsgData, controlMsgLen);
594  } else {
595  break;
596  }
597  }
598 }
599 
600 int ImageTransfer::Pimpl::getNumDroppedFrames() const {
601  return protocol->getNumDroppedFrames();
602 }
603 
604 bool ImageTransfer::Pimpl::selectSocket(bool read, bool wait) {
605  SOCKET sock;
606  {
607  unique_lock<recursive_mutex> lock(sendMutex); // Either mutex will do
608  sock = clientSocket;
609  }
610 #ifdef _WIN32
611  fd_set fds;
612  struct timeval tv;
613  FD_ZERO(&fds);
614  FD_SET(sock, &fds);
615  tv.tv_sec = 0;
616  if(wait) {
617  tv.tv_usec = 100000;
618  } else {
619  tv.tv_usec = 0;
620  }
621 
622  if(select(sock+1, (read ? &fds : nullptr), (!read ? &fds : nullptr), nullptr, &tv) <= 0) {
623  // The socket is currently not ready
624  return false;
625  }
626 #else
627  // use poll() on non-Windows platform (glibc select() limitations)
628  constexpr int timeoutMillisec = 100;
629  pollfd pfd;
630  pfd.fd = sock;
631  pfd.events = POLLIN;
632  if (poll(&pfd, 1, wait ? timeoutMillisec: 0) <= 0) {
633  // The socket is currently not ready
634  return false;
635  }
636 #endif
637  // select (or poll) reported an event
638  return true;
639 }
640 
641 std::string ImageTransfer::statusReport() {
642  return pimpl->statusReport();
643 }
644 std::string ImageTransfer::Pimpl::statusReport() {
645  return protocol->statusReport();
646 }
647 
648 } // namespace
649 
visiontransfer::ImageTransfer::setRawValidBytes
void setRawValidBytes(const std::vector< int > &validBytes)
Updates the number of valid bytes in a partial raw transmission.
Definition: imagetransfer.cpp:121
visiontransfer::ImageTransfer::getRemoteAddress
std::string getRemoteAddress() const
Returns the address of the remote host.
Definition: imagetransfer.cpp:153
visiontransfer::ImageTransfer::getNumDroppedFrames
int getNumDroppedFrames() const
Returns the number of frames that have been dropped since connecting to the current remote host.
Definition: imagetransfer.cpp:141
visiontransfer::ImageTransfer::TransferStatus
TransferStatus
The result of a partial image transfer.
Definition: imagetransfer.h:67
visiontransfer::ImageTransfer::tryAccept
bool tryAccept()
Tries to accept a client connection.
Definition: imagetransfer.cpp:157
visiontransfer::ImageTransfer::receivePartialImageSet
bool receivePartialImageSet(ImageSet &imageSet, int &validRows, bool &complete)
Returns the received image set, even if it is not yet complete.
Definition: imagetransfer.cpp:137
visiontransfer::ImageProtocol::PROTOCOL_UDP
@ PROTOCOL_UDP
The connection-less UDP transport protocol.
Definition: imageprotocol.h:84
visiontransfer::DeviceInfo
Aggregates information about a discovered device.
Definition: deviceinfo.h:59
visiontransfer::ImageSet
A set of one to three images, but usually two (the left camera image and the disparity map)....
Definition: imageset.h:50
visiontransfer::ImageTransfer::ImageTransfer
ImageTransfer(const char *address, const char *service="7681", ImageProtocol::ProtocolType protType=ImageProtocol::PROTOCOL_UDP, bool server=false, int bufferSize=16 *1048576, int maxUdpPacketSize=1472)
Creates a new transfer object by manually specifying the target address.
Definition: imagetransfer.cpp:100
visiontransfer::TransferException
Exception class that is used for all transfer exceptions.
Definition: exceptions.h:45
visiontransfer::ImageProtocol::ProtocolType
ProtocolType
Supported network protocols.
Definition: imageprotocol.h:67
visiontransfer::ImageTransfer::disconnect
void disconnect()
Terminates the current connection.
Definition: imagetransfer.cpp:149
visiontransfer::ImageProtocol::PROTOCOL_TCP
@ PROTOCOL_TCP
The connection oriented TCP transport protocol.
Definition: imageprotocol.h:81
visiontransfer::ImageProtocol
A lightweight protocol for transferring image sets.
Definition: imageprotocol.h:52
visiontransfer::ImageTransfer::setTransferImageSet
void setTransferImageSet(const ImageSet &imageSet)
Sets a new image set that shall be transmitted.
Definition: imagetransfer.cpp:125
visiontransfer::ImageTransfer::transferData
TransferStatus transferData()
Performs a partial (or full) image transmission.
Definition: imagetransfer.cpp:129
visiontransfer::ImageTransfer::setRawTransferData
void setRawTransferData(const ImageSet &metaData, const std::vector< unsigned char * > &rawData, int firstTileWidth=0, int middleTileWidth=0, int lastTileWidth=0)
Sets the raw pixel data for a partial image transmission.
Definition: imagetransfer.cpp:116
visiontransfer::ImageTransfer::receiveImageSet
bool receiveImageSet(ImageSet &imageSet)
Waits for and receives a new image set.
Definition: imagetransfer.cpp:133
visiontransfer::ImageTransfer::isConnected
bool isConnected() const
Returns true if a remote connection is established.
Definition: imagetransfer.cpp:145
Allied Vision