Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkIGTLServer.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkIGTLServer.h"
18 #include <stdio.h>
19 
20 #include <itksys/SystemTools.hxx>
21 #include <itkMutexLockHolder.h>
22 
23 #include <igtlServerSocket.h>
24 #include <igtlTrackingDataMessage.h>
25 #include <igtlImageMessage.h>
26 #include <igtl_status.h>
27 
29 IGTLDevice(ReadFully)
30 {
33 }
34 
36 {
37  m_ReceiveListMutex = nullptr;
38  m_SentListMutex = nullptr;
39 }
40 
42 {
43  if (this->GetState() != Setup)
44  {
46  "Can only try to create a server if in setup mode";
47  return false;
48  }
49 
50  int portNumber = this->GetPortNumber();
51 
52  if (portNumber == -1)
53  {
54  //port number was not correct
55  return false;
56  }
57 
58  //create a new server socket
59  m_Socket = igtl::ServerSocket::New();
60 
61  //try to create the igtl server
62  int response = dynamic_cast<igtl::ServerSocket*>(m_Socket.GetPointer())->
63  CreateServer(portNumber);
64 
65  //check the response
66  if (response != 0)
67  {
69  "The server could not be created. Port: " << portNumber;
70  return false;
71  }
72 
73  // everything is initialized and connected so the communication can be started
74  this->SetState(Ready);
75 
76  return true;
77 }
78 
80 {
81  //remove all registered clients
82  m_SentListMutex->Lock();
83  m_ReceiveListMutex->Lock();
84  SocketListType allRegisteredSockets(m_RegisteredClients);
85  m_SentListMutex->Unlock();
86  m_ReceiveListMutex->Unlock();
87  this->StopCommunicationWithSocket(allRegisteredSockets);
88 
90 }
91 
93 {
94  igtl::Socket::Pointer socket;
95  //check if another igtl device wants to connect to this socket
96  socket =
97  ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(1);
98  //if there is a new connection the socket is not null
99  if (socket.IsNotNull())
100  {
101  //add the new client socket to the list of registered clients
102  m_SentListMutex->Lock();
103  m_ReceiveListMutex->Lock();
104  this->m_RegisteredClients.push_back(socket);
105  m_SentListMutex->Unlock();
106  m_ReceiveListMutex->Unlock();
107  //inform observers about this new client
108  this->InvokeEvent(NewClientConnectionEvent());
109  MITK_INFO("IGTLServer") << "Connected to a new client: " << socket;
110  }
111 }
112 
114 {
115  unsigned int status = IGTL_STATUS_OK;
116  SocketListType socketsToBeRemoved;
117 
118  //the server can be connected with several clients, therefore it has to check
119  //all registered clients
121  m_ReceiveListMutex->Lock();
122  auto it_end = this->m_RegisteredClients.end();
123  for (it = this->m_RegisteredClients.begin(); it != it_end; ++it)
124  {
125  //it is possible that ReceivePrivate detects that the current socket is
126  //already disconnected. Therefore, it is necessary to remove this socket
127  //from the registered clients list
128  status = this->ReceivePrivate(*it);
129  if (status == IGTL_STATUS_NOT_PRESENT)
130  {
131  //remember this socket for later, it is not a good idea to remove it
132  //from the list directly because we iterate over the list at this point
133  socketsToBeRemoved.push_back(*it);
134  MITK_WARN("IGTLServer") << "Lost connection to a client socket. ";
135  }
136  else if (status != 1)
137  {
138  MITK_WARN("IGTLServer") << "IGTL Message with status: " << status;
139  }
140  }
141  m_ReceiveListMutex->Unlock();
142  if (socketsToBeRemoved.size() > 0)
143  {
144  //remove the sockets that are not connected anymore
145  this->StopCommunicationWithSocket(socketsToBeRemoved);
146  //inform observers about loosing the connection to these sockets
147  this->InvokeEvent(LostConnectionEvent());
148  }
149 }
150 
152 {
153  igtl::MessageBase::Pointer curMessage;
154 
155  //get the latest message from the queue
156  curMessage = this->m_MessageQueue->PullSendMessage();
157 
158  // there is no message => return
159  if (curMessage.IsNull())
160  return;
161 
162  //the server can be connected with several clients, therefore it has to check
163  //all registered clients
164  //sending a message to all registered clients might not be the best solution,
165  //it could be better to store the client together with the requested type. Then
166  //the data would be send to the appropriate client and to noone else.
167  //(I know it is no excuse but PLUS is doing exactly the same, they broadcast
168  //everything)
169  m_SentListMutex->Lock();
171  auto it_end =
172  this->m_RegisteredClients.end();
173  for (it = this->m_RegisteredClients.begin(); it != it_end; ++it)
174  {
175  //maybe there should be a check here if the current socket is still active
176  this->SendMessagePrivate(curMessage.GetPointer(), *it);
177  MITK_DEBUG("IGTLServer") << "Sent IGTL Message";
178  }
179  m_SentListMutex->Unlock();
180 }
181 
183  SocketListType& toBeRemovedSockets)
184 {
185  for (auto i = toBeRemovedSockets.begin(); i != toBeRemovedSockets.end(); i++)
186  this->StopCommunicationWithSocket(*i);
187 }
188 
190 {
191  m_SentListMutex->Lock();
192  m_ReceiveListMutex->Lock();
193  auto i = m_RegisteredClients.begin();
194  auto end = m_RegisteredClients.end();
195  while (i != end)
196  {
197  if ((*i) == client)
198  {
199  // //close the socket
200  (*i)->CloseSocket();
201  //and remove it from the list
202  i = this->m_RegisteredClients.erase(i);
203  MITK_INFO("IGTLServer") << "Removed client socket from server client list.";
204  break;
205  }
206  else
207  {
208  ++i;
209  }
210  }
211  m_SentListMutex->Unlock();
212  m_ReceiveListMutex->Unlock();
213 }
214 
216 {
217  return this->m_RegisteredClients.size();
218 }
virtual void Send() override
Call this method to send a message. The message will be read from the queue. So far the message is se...
std::list< igtl::Socket::Pointer > SocketListType
itk::SmartPointer< Self > Pointer
virtual void Connect() override
Call this method to check for other devices that want to connect to this one.
#define MITK_INFO
Definition: mitkLogMacros.h:22
virtual bool OpenConnection() override
Initialize the connection for the IGTLServer.
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
itk::FastMutexLock::Pointer m_ReceiveListMutex
IGTLServer(bool ReadFully)
#define MITK_WARN
Definition: mitkLogMacros.h:23
SocketListType::iterator SocketListIteratorType
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
virtual bool CloseConnection()
Closes the connection to the device.
virtual bool CloseConnection() override
Closes the connection to the device.
virtual void Receive() override
Call this method to receive a message.
itk::FastMutexLock::Pointer m_SentListMutex
Interface for all OpenIGTLink Devices.
#define mitkThrowException(classname)
virtual void StopCommunicationWithSocket(SocketListType &toBeRemovedSockets)
Stops the communication with the given sockets.
virtual unsigned int GetNumberOfConnections() override
Returns the number of client connections of this device.
static void Setup()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.