Fraxinus  16.5.0-fx-rc1
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxNetworkConnection.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxNetworkConnection.h"
34 
35 #include "cxSender.h"
36 #include "cxTime.h"
37 #include <QThread>
38 
39 #include "cxProtocol.h"
40 #include "cxOpenIGTLinkProtocol.h"
41 #include "cxPlusProtocol.h"
42 #include "cxCustusProtocol.h"
43 #include "cxRASProtocol.h"
44 
45 #include "cxXmlOptionItem.h"
46 #include "cxProfile.h"
47 #include "cxStringProperty.h"
48 #include "cxDoubleProperty.h"
49 #include "vtkImageData.h"
50 
51 #include "cxUtilHelpers.h"
52 #include "cxMesh.h"
53 #include "cxSocket.h"
54 
55 namespace cx
56 {
57 
58 NetworkConnection::NetworkConnection(QString uid, QObject *parent) :
59  SocketConnection(parent),
60  mUid(uid)
61 {
62  qRegisterMetaType<Transform3D>("Transform3D");
63  qRegisterMetaType<ImagePtr>("ImagePtr");
64  qRegisterMetaType<ImagePtr>("MeshPtr");
65  qRegisterMetaType<ProbeDefinitionPtr>("ProbeDefinitionPtr");
66  qRegisterMetaType<VoidFunctionType>("VoidFunctionType");
67 
68 
69  ConnectionInfo info = this->getConnectionInfo();
70 
71  //TODO move to the correct plugin init
72  info.protocol = this->initProtocol(ProtocolPtr(new CustusProtocol()))->getName();
73  this->initProtocol(ProtocolPtr(new PlusProtocol()));
74  this->initProtocol(ProtocolPtr(new OpenIGTLinkProtocol()));
75  this->initProtocol(ProtocolPtr(new RASProtocol()));
76 
78 }
79 
81 {
82 }
83 
84 ProtocolPtr NetworkConnection::initProtocol(ProtocolPtr value)
85 {
86  mAvailableDialects[value->getName()] = value;
87  return value;
88 }
89 
90 void NetworkConnection::invoke(boost::function<void()> func)
91 {
92  QMetaObject::invokeMethod(this,
93  "onInvoke",
94  Qt::QueuedConnection,
95  Q_ARG(VoidFunctionType, func));
96 }
97 
98 void NetworkConnection::onInvoke(VoidFunctionType func)
99 {
100  func();
101 }
102 
104 {
105  QStringList retval;
106  DialectMap::const_iterator it = mAvailableDialects.begin();
107  for( ; it!=mAvailableDialects.end() ; ++it)
108  {
109  retval << it->first;
110  }
111  return retval;
112 }
113 
114 void NetworkConnection::setProtocol(QString protocolname)
115 {
117  if(mProtocol && (protocolname == mProtocol->getName()))
118  return;
119 
120  ProtocolPtr protocol = mAvailableDialects[protocolname];
121  if(!protocol)
122  {
123  CX_LOG_ERROR() << "\"" << protocolname << "\" is an unknown opentigtlink dialect.";
124  return;
125  }
126 
127  if(mProtocol)
128  {
129  disconnect(mProtocol.get(), &Protocol::image, this, &NetworkConnection::image);
130  disconnect(mProtocol.get(), &Protocol::mesh, this, &NetworkConnection::mesh);
131  disconnect(mProtocol.get(), &Protocol::transform, this, &NetworkConnection::transform);
132  disconnect(mProtocol.get(), &Protocol::calibration, this, &NetworkConnection::calibration);
133  disconnect(mProtocol.get(), &Protocol::probedefinition, this, &NetworkConnection::probedefinition);
134  }
135 
136  mProtocol = protocol;
137  connect(protocol.get(), &Protocol::image, this, &NetworkConnection::image);
138  connect(protocol.get(), &Protocol::mesh, this, &NetworkConnection::mesh);
139  connect(protocol.get(), &Protocol::transform, this, &NetworkConnection::transform);
140  connect(protocol.get(), &Protocol::calibration, this, &NetworkConnection::calibration);
141  connect(protocol.get(), &Protocol::probedefinition, this, &NetworkConnection::probedefinition);
142 
143  mProtocol->setSynchronizeRemoteClock(!mConnector->getInfo().isLocalhostConnection());
144  CX_LOG_CHANNEL_SUCCESS(CX_OPENIGTLINK_CHANNEL_NAME) << "Protocol set to " << protocolname;
145 
146 }
147 
148 //namespace
149 //{
150 //void write_send_info(igtl::ImageMessage::Pointer msg)
151 //{
152 // int kb = msg->GetPackSize()/1024;
153 // CX_LOG_CHANNEL_DEBUG("igtl_test") << "Writing image to socket: " << msg->GetDeviceName()
154 // << ", " << kb << " kByte";
155 //}
156 //}
157 
159 {
161 
162  EncodedPackagePtr package = mProtocol->encode(image);
163 
164  int sendSize = package->data()->size/1024;
165  int waitingSize = mSocket->bytesToWrite()/1024;
166  double waitToSendRatio = double(waitingSize)/double(sendSize);
167  double waitToSendRatioThreshold = 0.5;
168 
169  static int sentCounter =0;
170  static int dropCounter =0;
171 // CX_LOG_CHANNEL_DEBUG("igtl_test") << "ratio: " << waitToSendRatio << " ratio";
172 // CX_LOG_CHANNEL_DEBUG("igtl_test") << "GetNumComponents: " << msg->GetNumComponents() << " ";
173 
174 
175  if (waitToSendRatio > waitToSendRatioThreshold)
176  {
177  dropCounter++;
178  CX_LOG_CHANNEL_DEBUG("igtl_test") << QString("dropped stream image: wanted to send %1kB but %2kB already waiting, sent=%3,drop=%4")
179  .arg(sendSize)
180  .arg(waitingSize)
181  .arg(sentCounter)
182  .arg(dropCounter);
183 
184  return;
185  }
186  sentCounter++;
187 
188 // CX_LOG_CHANNEL_DEBUG("igtl_test") << "bytes to write pre write: " << waitingSize << " kbyte";
189 // image->getBaseVtkImageData()->Print(std::cout);
190 
191 // write_send_info(msg);
192 // mSocket->write(reinterpret_cast<char*>(msg->GetPackPointer()), msg->GetPackSize());
193 // CX_LOG_CHANNEL_DEBUG(CX_OPENIGTLINK_CHANNEL_NAME) << "Sent image: " << image->getName();
194 
195  mSocket->write(reinterpret_cast<char*>(package->data()->pointer));
196 }
197 
199 {
201  CX_LOG_CHANNEL_DEBUG(CX_OPENIGTLINK_CHANNEL_NAME) << "Sending image: " << image->getName();
202 
203  EncodedPackagePtr package = mProtocol->encode(image);
204  mSocket->write(package->data()->pointer, package->data()->size);
205 }
206 
208 {
210  CX_LOG_CHANNEL_DEBUG(CX_OPENIGTLINK_CHANNEL_NAME) << "Sending mesh: " << data->getName();
211 
212  EncodedPackagePtr package = mProtocol->encode(data);
213  mSocket->write(package->data()->pointer, package->data()->size);
214 }
215 
216 void NetworkConnection::internalDataAvailable()
217 {
219  //CX_LOG_DEBUG() << "START receive";
220  if(!this->socketIsConnected())
221  return;
222 
223  bool done = false;
224  if(mProtocol->readyToReceiveData())
225  {
226  //CX_LOG_DEBUG() << "A ready to receive data " << mProtocol->readyToReceiveData();
227  EncodedPackagePtr pack = mProtocol->getPack();
228  if(this->socketReceive(pack->data()->pointer, pack->data()->size))
229  {
230  //CX_LOG_DEBUG() << "B";
231  pack->notifyDataArrived();
232  done = true;
233  }
234  }
235  //CX_LOG_DEBUG() << "END receive";
236 
237 }
238 
239 }//namespace cx
virtual void setConnectionInfo(ConnectionInfo info)
thread-safe
void probedefinition(QString devicename, ProbeDefinitionPtr definition)
#define CX_LOG_CHANNEL_SUCCESS(channel)
Definition: cxLogger.h:124
void transform(QString devicename, Transform3D transform, double timestamp)
void image(ImagePtr image)
bool socketReceive(void *packPointer, int packSize) const
void calibration(QString devicename, Transform3D calibration)
void mesh(MeshPtr mesh)
void transform(QString devicename, Transform3D transform, double timestamp)
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
boost::shared_ptr< EncodedPackage > EncodedPackagePtr
void image(ImagePtr image)
virtual void setProtocol(QString protocolname)
ConnectionInfo getConnectionInfo()
thread-safe
void sendMesh(MeshPtr image)
not thread-safe: use invoke
#define CX_LOG_ERROR
Definition: cxLogger.h:114
NetworkConnection(QString uid, QObject *parent=0)
void sendImage(ImagePtr image)
not thread-safe: use invoke
#define CX_LOG_CHANNEL_DEBUG(channel)
Definition: cxLogger.h:122
QStringList getAvailableDialects() const
#define assertRunningInObjectThread()
void streamImage(ImagePtr image)
not thread-safe: use invoke
void calibration(QString devicename, Transform3D calibration)
void probedefinition(QString devicename, ProbeDefinitionPtr definition)
SocketConnectorPtr mConnector
boost::shared_ptr< class Mesh > MeshPtr
The PlusDialect class contains the knowhow on the packages sent from a PlusServer. For this class to function correctly, the Plus configuration file used by the PlusServer needs to set up correctly.
void invoke(boost::function< void()> func)
boost::shared_ptr< Protocol > ProtocolPtr
Definition: cxProtocol.h:87
void mesh(MeshPtr image)