diff --git a/CMakeExternals/OpenIGTLink-92bc3d7b.patch b/CMakeExternals/OpenIGTLink-92bc3d7b.patch deleted file mode 100644 index 314b33090e..0000000000 --- a/CMakeExternals/OpenIGTLink-92bc3d7b.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- OpenIGTLink/Source/CMakeLists.txt.original 2017-06-28 12:28:12.000000000 +0200 -+++ OpenIGTLink/Source/CMakeLists.txt 2019-03-31 04:04:46.392945177 +0200 -@@ -71,12 +71,11 @@ - igtlTransformMessage.cxx - ) - --SET(OpenIGTLink_INCLUDE_FILES) --IF( MSVC OR ${CMAKE_GENERATOR} MATCHES "Xcode" ) -- LIST(APPEND OpenIGTLink_INCLUDE_FILES -+SET(OpenIGTLink_INCLUDE_FILES - igtlutil/igtl_header.h - igtlutil/igtl_image.h - igtlutil/igtl_position.h -+ igtlutil/igtl_status.h - igtlutil/igtl_transform.h - igtlutil/igtl_types.h - igtlutil/igtl_util.h -@@ -117,7 +116,6 @@ - igtlWindows.h - igtlCommon.h - ) --ENDIF() - - # Add support for OpenIGTLink version 2 - IF (${OpenIGTLink_PROTOCOL_VERSION} GREATER "1" ) -@@ -150,7 +148,7 @@ - igtlBindMessage.cxx - igtlNDArrayMessage.cxx - ) -- IF( MSVC OR ${CMAKE_GENERATOR} MATCHES "Xcode" ) -+ - LIST(APPEND OpenIGTLink_INCLUDE_FILES - igtlutil/igtl_colortable.h - igtlutil/igtl_imgmeta.h -@@ -180,7 +178,6 @@ - igtlBindMessage.h - igtlNDArrayMessage.h - ) -- ENDIF() - ENDIF() - - # Add support for OpenIGTLink version 3 -@@ -191,14 +188,13 @@ - igtlutil/igtl_command.c - igtlutil/igtl_query.c - ) -- IF( MSVC OR ${CMAKE_GENERATOR} MATCHES "Xcode" ) -+ - LIST(APPEND OpenIGTLink_INCLUDE_FILES - igtlCommandMessage.h - igtlQueryMessage.h - igtlutil/igtl_command.h - igtlutil/igtl_query.h - ) -- ENDIF() - ENDIF() - - ADD_LIBRARY(OpenIGTLink ${OpenIGTLink_SOURCES} ${OpenIGTLink_INCLUDE_FILES}) -@@ -227,4 +223,4 @@ - INSTALL(TARGETS OpenIGTLink EXPORT OpenIGTLink - RUNTIME DESTINATION ${OpenIGTLink_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries - LIBRARY DESTINATION ${OpenIGTLink_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries -- ARCHIVE DESTINATION ${OpenIGTLink_INSTALL_LIB_DIR} COMPONENT Development) -\ No newline at end of file -+ ARCHIVE DESTINATION ${OpenIGTLink_INSTALL_LIB_DIR} COMPONENT Development) diff --git a/CMakeExternals/OpenIGTLink.cmake b/CMakeExternals/OpenIGTLink.cmake index 62611eafa8..086f2ccce7 100644 --- a/CMakeExternals/OpenIGTLink.cmake +++ b/CMakeExternals/OpenIGTLink.cmake @@ -1,58 +1,57 @@ #----------------------------------------------------------------------------- # OpenIGTLink #----------------------------------------------------------------------------- if(MITK_USE_OpenIGTLink) # Sanity checks if(DEFINED OpenIGTLink_DIR AND NOT EXISTS ${OpenIGTLink_DIR}) message(FATAL_ERROR "OpenIGTLink_DIR variable is defined but corresponds to non-existing directory") endif() set(proj OpenIGTLink) set(proj_DEPENDENCIES ) set(${proj}_DEPENDS ${proj}) if(NOT DEFINED OpenIGTLink_DIR) set(additional_cmake_args ) if(CTEST_USE_LAUNCHERS) set(additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() mitk_query_custom_ep_vars() ExternalProject_Add(${proj} - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenIGTLink-release-3.0.tar.gz - URL_MD5 0a759655da037f6df2087dd2690d1ae2 - PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/OpenIGTLink-92bc3d7b.patch + GIT_REPOSITORY https://github.com/openigtlink/OpenIGTLink.git + GIT_TAG d4eaae93 CMAKE_GENERATOR ${gen} CMAKE_GENERATOR_PLATFORM ${gen_platform} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_EXAMPLES:BOOL=OFF -DOpenIGTLink_PROTOCOL_VERSION_2:BOOL=ON -DOpenIGTLink_INSTALL_LIB_DIR:STRING=lib -DOpenIGTLink_INSTALL_PACKAGE_DIR:STRING=lib/cmake/OpenIGTLink -DOpenIGTLink_INSTALL_NO_DOCUMENTATION:BOOL=ON ${${proj}_CUSTOM_CMAKE_ARGS} CMAKE_CACHE_ARGS ${ep_common_cache_args} ${${proj}_CUSTOM_CMAKE_CACHE_ARGS} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} ${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS} DEPENDS ${proj_DEPENDENCIES} ) set(OpenIGTLink_DIR "${ep_prefix}/lib/cmake/OpenIGTLink") else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/Modules/OpenIGTLink/mitkIGTLClient.cpp b/Modules/OpenIGTLink/mitkIGTLClient.cpp index 649c6a808d..ea192cbbec 100644 --- a/Modules/OpenIGTLink/mitkIGTLClient.cpp +++ b/Modules/OpenIGTLink/mitkIGTLClient.cpp @@ -1,117 +1,117 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkIGTLClient.h" //#include "mitkIGTTimeStamp.h" //#include "mitkIGTHardwareException.h" #include "igtlTrackingDataMessage.h" #include #include #include -#include +#include mitk::IGTLClient::IGTLClient(bool ReadFully) : IGTLDevice(ReadFully) { } mitk::IGTLClient::~IGTLClient() { } bool mitk::IGTLClient::OpenConnection() { if (this->GetState() != Setup) { mitkThrowException(mitk::Exception) << "Can only try to open the connection if in setup mode. State was " << this->GetState(); return false; } std::string hostname = this->GetHostname(); int portNumber = this->GetPortNumber(); if (portNumber == -1 || hostname.size() <= 0) { //port number or hostname was not correct MITK_WARN << "Port number or hostname was not correct"; return false; } //create a new client socket m_Socket = igtl::ClientSocket::New(); //try to connect to the igtl server int response = dynamic_cast(m_Socket.GetPointer())-> ConnectToServer(hostname.c_str(), portNumber); //check the response if (response != 0) { MITK_ERROR << "The client could not connect to " << hostname << " port: " << portNumber; return false; } // everything is initialized and connected so the communication can be started this->SetState(Ready); //inform observers about this new client this->InvokeEvent(NewClientConnectionEvent()); return true; } void mitk::IGTLClient::Receive() { //MITK_INFO << "Trying to receive message"; //try to receive a message, if the socket is not present anymore stop the //communication unsigned int status = this->ReceivePrivate(this->m_Socket); if (status == IGTL_STATUS_NOT_PRESENT) { this->StopCommunicationWithSocket(this->m_Socket); //inform observers about loosing the connection to this socket this->InvokeEvent(LostConnectionEvent()); MITK_WARN("IGTLClient") << "Lost connection to server socket."; } } void mitk::IGTLClient::Send() { mitk::IGTLMessage::Pointer mitkMessage; //get the latest message from the queue mitkMessage = this->m_MessageQueue->PullSendMessage(); // there is no message => return if (mitkMessage.IsNull()) return; if (!this->SendMessagePrivate(mitkMessage, this->m_Socket)) { MITK_WARN("IGTLDevice") << "Could not send the message."; } } void mitk::IGTLClient::StopCommunicationWithSocket(igtl::Socket* /*socket*/) { m_StopCommunicationMutex.lock(); m_StopCommunication = true; m_StopCommunicationMutex.unlock(); } unsigned int mitk::IGTLClient::GetNumberOfConnections() { return this->m_Socket->GetConnected(); } diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index 8d531d085d..bad9c5bd65 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,496 +1,497 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkIGTLDevice.h" //#include "mitkIGTException.h" //#include "mitkIGTTimeStamp.h" #include #include #include #include #include #include -#include +#include //remove later #include namespace mitk { itkEventMacroDefinition(MessageSentEvent, itk::AnyEvent); itkEventMacroDefinition(MessageReceivedEvent, itk::AnyEvent); itkEventMacroDefinition(CommandReceivedEvent, itk::AnyEvent); itkEventMacroDefinition(NewClientConnectionEvent, itk::AnyEvent); itkEventMacroDefinition(LostConnectionEvent, itk::AnyEvent); } //TODO: Which timeout is acceptable and also needed to transmit image data? Is there a maximum data limit? static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 100; mitk::IGTLDevice::IGTLDevice(bool ReadFully) : // m_Data(mitk::DeviceDataUnspecified), m_State(mitk::IGTLDevice::Setup), m_Name("Unspecified Device"), m_StopCommunication(false), m_Hostname("127.0.0.1"), m_PortNumber(-1), m_LogMessages(false) { m_ReadFully = ReadFully; // execution rights are owned by the application thread at the beginning m_SendingFinishedMutex.lock(); m_ReceivingFinishedMutex.lock(); m_ConnectingFinishedMutex.lock(); // m_Data = mitk::DeviceDataUnspecified; // m_LatestMessage = igtl::MessageBase::New(); m_MessageFactory = mitk::IGTLMessageFactory::New(); m_MessageQueue = mitk::IGTLMessageQueue::New(); } mitk::IGTLDevice::~IGTLDevice() { /* stop communication and disconnect from igtl device */ if (GetState() == Running) { this->StopCommunication(); this->CloseConnection(); } else if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if (m_SendThread.joinable()) m_SendThread.detach(); if (m_ReceiveThread.joinable()) m_ReceiveThread.detach(); if (m_ConnectThread.joinable()) m_ConnectThread.detach(); } mitk::IGTLDevice::IGTLDeviceState mitk::IGTLDevice::GetState() const { std::lock_guard lock(m_StateMutex); return m_State; } void mitk::IGTLDevice::SetState(IGTLDeviceState state) { itkDebugMacro("setting m_State to " << state); m_StateMutex.lock(); // MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex if (m_State == state) { m_StateMutex.unlock(); return; } m_State = state; m_StateMutex.unlock(); this->Modified(); } bool mitk::IGTLDevice::TestConnection() { return true; } unsigned int mitk::IGTLDevice::ReceivePrivate(igtl::Socket* socket) { // Create a message buffer to receive header igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); // Initialize receive buffer headerMsg->InitPack(); // Receive generic header from the socket + bool timeout = false; int r = - socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 0); + socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), timeout, 0); //MITK_INFO << "Server received r = " << r; //MITK_INFO << "Received r = " << r; if (r == 0) //connection error { // an error was received, therefore the communication with this socket // must be stoppedy return IGTL_STATUS_NOT_PRESENT; } else if (r == -1) //timeout { // a timeout was received, this is no error state, thus, do nothing return IGTL_STATUS_TIME_OUT; } else if (r == headerMsg->GetPackSize()) { // Deserialize the header and check the CRC // ERROR HERE: This probably means the header data is corrupted... int crcCheck = headerMsg->Unpack(1); if (crcCheck & igtl::MessageHeader::UNPACK_HEADER) { // Allocate a time stamp igtl::TimeStamp::Pointer ts; ts = igtl::TimeStamp::New(); // Get time stamp igtlUint32 sec; igtlUint32 nanosec; headerMsg->GetTimeStamp(ts); ts->GetTimeStamp(&sec, &nanosec); // std::cerr << "Time stamp: " // << sec << "." // << nanosec << std::endl; // std::cerr << "Dev type and name: " << headerMsg->GetDeviceType() << " " // << headerMsg->GetDeviceName() << std::endl; // headerMsg->Print(std::cout); //check the type of the received message //if it is a GET_, STP_ or RTS_ command push it into the command queue //otherwise continue reading the whole message from the socket const char* curDevType = headerMsg->GetDeviceType(); if (std::strstr(curDevType, "GET_") != nullptr || std::strstr(curDevType, "STP_") != nullptr || std::strstr(curDevType, "RTS_") != nullptr) { this->m_MessageQueue->PushCommandMessage(headerMsg); this->InvokeEvent(CommandReceivedEvent()); return IGTL_STATUS_OK; } //Create a message according to the header message igtl::MessageBase::Pointer curMessage; curMessage = m_MessageFactory->CreateInstance(headerMsg); //check if the curMessage is created properly, if not the message type is //not supported and the message has to be skipped if (curMessage.IsNull()) { socket->Skip(headerMsg->GetBodySizeToRead(), 0); // MITK_ERROR("IGTLDevice") << "The received type is not supported. Please " // "add it to the message factory."; return IGTL_STATUS_NOT_FOUND; } //insert the header to the message and allocate the pack curMessage->SetMessageHeader(headerMsg); curMessage->AllocatePack(); // Receive transform data from the socket int receiveCheck = 0; receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(), curMessage->GetPackBodySize(), m_ReadFully); if (receiveCheck > 0) { int c = curMessage->Unpack(1); if (!(c & igtl::MessageHeader::UNPACK_BODY)) { return IGTL_STATUS_CHECKSUM_ERROR; } //check the type of the received message //if it is a command push it into the command queue //otherwise into the normal receive queue //STP_ commands are handled here because they implemented additional //member variables that are not stored in the header message if (std::strstr(curDevType, "STT_") != nullptr) { this->m_MessageQueue->PushCommandMessage(curMessage); this->InvokeEvent(CommandReceivedEvent()); } else { if(m_LogMessages) MITK_INFO << "Received Message: " << mitk::IGTLMessage::New(curMessage)->ToString(); this->m_MessageQueue->PushMessage(curMessage); this->InvokeEvent(MessageReceivedEvent()); } return IGTL_STATUS_OK; } else { MITK_WARN("IGTLDevice") << "Received a valid header but could not " << "read the whole message."; return IGTL_STATUS_UNKNOWN_ERROR; } } else { //CRC check failed MITK_WARN << "CRC Check failed"; return IGTL_STATUS_CHECKSUM_ERROR; } } else { //Message size information and actual data size don't match. //this state is not suppossed to be reached, return unknown error MITK_WARN << "IGTL status unknown"; return IGTL_STATUS_UNKNOWN_ERROR; } } void mitk::IGTLDevice::SendMessage(mitk::IGTLMessage::Pointer msg) { m_MessageQueue->PushSendMessage(msg); } unsigned int mitk::IGTLDevice::SendMessagePrivate(mitk::IGTLMessage::Pointer msg, igtl::Socket::Pointer socket) { //check the input message if (msg.IsNull()) { MITK_ERROR("IGTLDevice") << "Could not send message because message is not " "valid. Please check."; return false; } igtl::MessageBase* sendMessage = msg->GetMessage(); // Pack (serialize) and send sendMessage->Pack(); int sendSuccess = socket->Send(sendMessage->GetPackPointer(), sendMessage->GetPackSize()); if (sendSuccess) { if (m_LogMessages) { MITK_INFO << "Send IGTL message: " << msg->ToString(); } this->InvokeEvent(MessageSentEvent()); return IGTL_STATUS_OK; } else { return IGTL_STATUS_UNKNOWN_ERROR; } } void mitk::IGTLDevice::RunCommunication(void (IGTLDevice::*ComFunction)(void), std::mutex& mutex) { if (this->GetState() != Running) return; try { // keep lock until end of scope std::lock_guard communicationFinishedLockHolder(mutex); // Because m_StopCommunication is used by two threads, access has to be guarded // by a mutex. To minimize thread locking, a local copy is used here bool localStopCommunication; // update the local copy of m_StopCommunication this->m_StopCommunicationMutex.lock(); localStopCommunication = this->m_StopCommunication; this->m_StopCommunicationMutex.unlock(); while ((this->GetState() == Running) && (localStopCommunication == false)) { (this->*ComFunction)(); /* Update the local copy of m_StopCommunication */ this->m_StopCommunicationMutex.lock(); localStopCommunication = m_StopCommunication; this->m_StopCommunicationMutex.unlock(); // time to relax, this sets the maximum ever possible framerate to 1000 Hz itksys::SystemTools::Delay(1); } } catch (...) { mutex.unlock(); this->StopCommunication(); MITK_ERROR("IGTLDevice::RunCommunication") << "Error while communicating. Thread stopped."; //mitkThrowException(mitk::IGTException) << "Error while communicating. Thread stopped."; } // StopCommunication was called, thus the mode should be changed back to Ready now // that the tracking loop has ended. //this->SetState(Ready); //this is done elsewhere MITK_DEBUG("IGTLDevice::RunCommunication") << "Reached end of communication."; // returning from this function (and ThreadStartCommunication()) // this will end the thread return; } bool mitk::IGTLDevice::StartCommunication() { if (this->GetState() != Ready) return false; // go to mode Running this->SetState(Running); // set a timeout for the sending and receiving this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC); // update the local copy of m_StopCommunication this->m_StopCommunicationMutex.lock(); this->m_StopCommunication = false; this->m_StopCommunicationMutex.unlock(); // transfer the execution rights to tracking thread m_SendingFinishedMutex.unlock(); m_ReceivingFinishedMutex.unlock(); m_ConnectingFinishedMutex.unlock(); // start new threads that execute the communication m_SendThread = std::thread(&IGTLDevice::ThreadStartSending, this); m_ReceiveThread = std::thread(&IGTLDevice::ThreadStartReceiving, this); m_ConnectThread = std::thread(&IGTLDevice::ThreadStartConnecting, this); // mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } bool mitk::IGTLDevice::StopCommunication() { if (this->GetState() == Running) // Only if the object is in the correct state { // m_StopCommunication is used by two threads, so we have to ensure correct // thread handling m_StopCommunicationMutex.lock(); m_StopCommunication = true; m_StopCommunicationMutex.unlock(); // we have to wait here that the other thread recognizes the STOP-command // and executes it m_SendingFinishedMutex.lock(); m_ReceivingFinishedMutex.lock(); m_ConnectingFinishedMutex.lock(); // mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopCommunication was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); } return true; } bool mitk::IGTLDevice::CloseConnection() { if (this->GetState() == Setup) { return true; } else if (this->GetState() == Running) { this->StopCommunication(); } m_Socket->CloseSocket(); /* return to setup mode */ this->SetState(Setup); // this->InvokeEvent(mitk::LostConnectionEvent()); return true; } bool mitk::IGTLDevice::SendRTSMessage(const char* type) { //construct the device type for the return message, it starts with RTS_ and //continues with the requested type std::string returnType("RTS_"); returnType.append(type); //create a return message igtl::MessageBase::Pointer rtsMsg = this->m_MessageFactory->CreateInstance(returnType); //if retMsg is nullptr there is no return message defined and thus it is not //necessary to send one back if (rtsMsg.IsNotNull()) { this->SendMessage(mitk::IGTLMessage::New(rtsMsg)); return true; } else { return false; } } void mitk::IGTLDevice::Connect() { MITK_DEBUG << "mitk::IGTLDevice::Connect();"; } igtl::ImageMessage::Pointer mitk::IGTLDevice::GetNextImage2dMessage() { return this->m_MessageQueue->PullImage2dMessage(); } igtl::ImageMessage::Pointer mitk::IGTLDevice::GetNextImage3dMessage() { return this->m_MessageQueue->PullImage3dMessage(); } igtl::TransformMessage::Pointer mitk::IGTLDevice::GetNextTransformMessage() { return this->m_MessageQueue->PullTransformMessage(); } igtl::TrackingDataMessage::Pointer mitk::IGTLDevice::GetNextTrackingDataMessage() { igtl::TrackingDataMessage::Pointer msg = this->m_MessageQueue->PullTrackingMessage(); return msg; } igtl::StringMessage::Pointer mitk::IGTLDevice::GetNextStringMessage() { return this->m_MessageQueue->PullStringMessage(); } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextMiscMessage() { return this->m_MessageQueue->PullMiscMessage(); } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextCommand() { return m_MessageQueue->PullCommandMessage(); } void mitk::IGTLDevice::EnableNoBufferingMode(bool enable) { m_MessageQueue->EnableNoBufferingMode(enable); } void mitk::IGTLDevice::EnableNoBufferingMode( mitk::IGTLMessageQueue::Pointer queue, bool enable) { queue->EnableNoBufferingMode(enable); } void mitk::IGTLDevice::ThreadStartSending() { this->RunCommunication(&IGTLDevice::Send, m_SendingFinishedMutex); } void mitk::IGTLDevice::ThreadStartReceiving() { this->RunCommunication(&IGTLDevice::Receive, m_ReceivingFinishedMutex); } void mitk::IGTLDevice::ThreadStartConnecting() { this->RunCommunication(&IGTLDevice::Connect, m_ConnectingFinishedMutex); } diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp index e18c9ab5be..f68ad4fa30 100644 --- a/Modules/OpenIGTLink/mitkIGTLServer.cpp +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -1,207 +1,207 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkIGTLServer.h" #include #include #include #include #include -#include +#include mitk::IGTLServer::IGTLServer(bool ReadFully) : IGTLDevice(ReadFully) { } mitk::IGTLServer::~IGTLServer() { } bool mitk::IGTLServer::OpenConnection() { if (this->GetState() != Setup) { mitkThrowException(mitk::Exception) << "Can only try to create a server if in setup mode"; return false; } int portNumber = this->GetPortNumber(); if (portNumber == -1) { //port number was not correct return false; } //create a new server socket m_Socket = igtl::ServerSocket::New(); //try to create the igtl server int response = dynamic_cast(m_Socket.GetPointer())-> CreateServer(portNumber); //check the response if (response != 0) { mitkThrowException(mitk::Exception) << "The server could not be created. Port: " << portNumber; return false; } // everything is initialized and connected so the communication can be started this->SetState(Ready); return true; } bool mitk::IGTLServer::CloseConnection() { //remove all registered clients m_SentListMutex.lock(); m_ReceiveListMutex.lock(); SocketListType allRegisteredSockets(m_RegisteredClients); m_SentListMutex.unlock(); m_ReceiveListMutex.unlock(); this->StopCommunicationWithSocket(allRegisteredSockets); return mitk::IGTLDevice::CloseConnection(); } void mitk::IGTLServer::Connect() { igtl::Socket::Pointer socket; //check if another igtl device wants to connect to this socket socket = ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(1); //if there is a new connection the socket is not null if (socket.IsNotNull()) { //add the new client socket to the list of registered clients m_SentListMutex.lock(); m_ReceiveListMutex.lock(); this->m_RegisteredClients.push_back(socket); m_SentListMutex.unlock(); m_ReceiveListMutex.unlock(); //inform observers about this new client this->InvokeEvent(NewClientConnectionEvent()); MITK_INFO("IGTLServer") << "Connected to a new client: " << socket; } } void mitk::IGTLServer::Receive() { unsigned int status = IGTL_STATUS_OK; SocketListType socketsToBeRemoved; //the server can be connected with several clients, therefore it has to check //all registered clients SocketListIteratorType it; m_ReceiveListMutex.lock(); auto it_end = this->m_RegisteredClients.end(); for (it = this->m_RegisteredClients.begin(); it != it_end; ++it) { //it is possible that ReceivePrivate detects that the current socket is //already disconnected. Therefore, it is necessary to remove this socket //from the registered clients list status = this->ReceivePrivate(*it); if (status == IGTL_STATUS_NOT_PRESENT) { //remember this socket for later, it is not a good idea to remove it //from the list directly because we iterate over the list at this point socketsToBeRemoved.push_back(*it); MITK_WARN("IGTLServer") << "Lost connection to a client socket. "; } else if (status != 1) { MITK_DEBUG("IGTLServer") << "IGTL Message with status: " << status; } } m_ReceiveListMutex.unlock(); if (socketsToBeRemoved.size() > 0) { //remove the sockets that are not connected anymore this->StopCommunicationWithSocket(socketsToBeRemoved); //inform observers about loosing the connection to these sockets this->InvokeEvent(LostConnectionEvent()); } } void mitk::IGTLServer::Send() { //get the latest message from the queue mitk::IGTLMessage::Pointer curMessage = this->m_MessageQueue->PullSendMessage(); // there is no message => return if (curMessage.IsNull()) return; //the server can be connected with several clients, therefore it has to check //all registered clients //sending a message to all registered clients might not be the best solution, //it could be better to store the client together with the requested type. Then //the data would be send to the appropriate client and to noone else. //(I know it is no excuse but PLUS is doing exactly the same, they broadcast //everything) m_SentListMutex.lock(); SocketListIteratorType it; auto it_end = this->m_RegisteredClients.end(); for (it = this->m_RegisteredClients.begin(); it != it_end; ++it) { //maybe there should be a check here if the current socket is still active this->SendMessagePrivate(curMessage, *it); MITK_DEBUG("IGTLServer") << "Sent IGTL Message"; } m_SentListMutex.unlock(); } void mitk::IGTLServer::StopCommunicationWithSocket( SocketListType& toBeRemovedSockets) { for (auto i = toBeRemovedSockets.begin(); i != toBeRemovedSockets.end(); i++) this->StopCommunicationWithSocket(*i); } void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) { m_SentListMutex.lock(); m_ReceiveListMutex.lock(); auto i = m_RegisteredClients.begin(); auto end = m_RegisteredClients.end(); while (i != end) { if ((*i) == client) { // //close the socket (*i)->CloseSocket(); //and remove it from the list i = this->m_RegisteredClients.erase(i); MITK_INFO("IGTLServer") << "Removed client socket from server client list."; break; } else { ++i; } } m_SentListMutex.unlock(); m_ReceiveListMutex.unlock(); } unsigned int mitk::IGTLServer::GetNumberOfConnections() { return this->m_RegisteredClients.size(); } diff --git a/Modules/OpenIGTLink/mitkIGTLStatus.h b/Modules/OpenIGTLink/mitkIGTLStatus.h new file mode 100644 index 0000000000..1257cad374 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLStatus.h @@ -0,0 +1,39 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef __IGTL_STATUS_H // Same include guard as OpenIGTLink's igtl_status.h file +#define __IGTL_STATUS_H + +// Internal status codes from OpenIGTLink's igtl_status.h file + +#define IGTL_STATUS_INVALID 0 +#define IGTL_STATUS_OK 1 +#define IGTL_STATUS_UNKNOWN_ERROR 2 +#define IGTL_STATUS_PANICK_MODE 3 +#define IGTL_STATUS_NOT_FOUND 4 +#define IGTL_STATUS_ACCESS_DENIED 5 +#define IGTL_STATUS_BUSY 6 +#define IGTL_STATUS_TIME_OUT 7 +#define IGTL_STATUS_OVERFLOW 8 +#define IGTL_STATUS_CHECKSUM_ERROR 9 +#define IGTL_STATUS_CONFIG_ERROR 10 +#define IGTL_STATUS_RESOURCE_ERROR 11 +#define IGTL_STATUS_ILLEGAL_INSTRUCTION 12 +#define IGTL_STATUS_NOT_READY 13 +#define IGTL_STATUS_MANUAL_MODE 14 +#define IGTL_STATUS_DISABLED 15 +#define IGTL_STATUS_NOT_PRESENT 16 +#define IGTL_STATUS_UNKNOWN_VERSION 17 +#define IGTL_STATUS_HARDWARE_FAILURE 18 +#define IGTL_STATUS_SHUT_DOWN 19 + +#endif