2014-09-23 08:04:57 -05:00
/////////////////////////////////////////////////////////////////////////////////
2012-05-18 02:45:23 -05:00
//
2014-09-23 08:04:57 -05:00
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
2012-05-18 02:45:23 -05:00
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
2013-05-06 03:55:00 -05:00
# include "RiaSocketServer.h"
2013-05-22 02:18:57 -05:00
# include "RiaSocketCommand.h"
2012-05-18 02:45:23 -05:00
2013-03-22 10:24:42 -05:00
# include "RiaApplication.h"
2013-05-06 03:55:00 -05:00
2016-01-06 16:01:27 -06:00
# include "RimEclipseCase.h"
# include "RimEclipseView.h"
# include "RimProject.h"
2017-01-09 13:27:46 -06:00
# include "RimCase.h"
2013-05-26 14:55:05 -05:00
2016-01-06 16:01:27 -06:00
# include "RiuMainWindow.h"
# include "RiuViewer.h"
2013-05-06 03:55:00 -05:00
2013-05-16 04:15:34 -05:00
# include "cafFactory.h"
2016-01-06 16:01:27 -06:00
2018-11-26 02:53:43 -06:00
# if QT_VERSION >= 0x050000
# include <QtWidgets/qerrormessage.h>
# include <QtWidgets/qmdisubwindow.h>
# else
2016-01-06 16:01:27 -06:00
# include <QtGui>
2018-11-26 02:53:43 -06:00
# endif
2016-01-06 16:01:27 -06:00
# include <QtNetwork>
2019-01-10 09:16:49 -06:00
# include <cstdlib>
2013-05-16 04:15:34 -05:00
2012-05-18 02:45:23 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer : : RiaSocketServer ( QObject * parent )
: QObject ( parent ) ,
2018-02-18 11:56:43 -06:00
m_tcpServer ( nullptr ) ,
m_currentClient ( nullptr ) ,
2012-05-18 02:45:23 -05:00
m_currentCommandSize ( 0 ) ,
2018-02-18 11:56:43 -06:00
m_currentCommand ( nullptr ) ,
2013-05-26 14:55:05 -05:00
m_currentCaseId ( - 1 )
2012-05-18 02:45:23 -05:00
{
2013-03-22 11:17:56 -05:00
m_errorMessageDialog = new QErrorMessage ( RiuMainWindow : : instance ( ) ) ;
2012-05-18 02:45:23 -05:00
// TCP server setup
m_tcpServer = new QTcpServer ( this ) ;
2013-10-08 07:21:18 -05:00
m_nextPendingConnectionTimer = new QTimer ( this ) ;
m_nextPendingConnectionTimer - > setInterval ( 100 ) ;
m_nextPendingConnectionTimer - > setSingleShot ( true ) ;
2012-05-18 02:45:23 -05:00
if ( ! m_tcpServer - > listen ( QHostAddress : : LocalHost , 40001 ) )
{
m_errorMessageDialog - > showMessage ( " Octave communication disabled : \n "
" \n "
2013-04-16 05:08:45 -05:00
" This instance of ResInsight could not start the Socket Server enabling octave to get and set data. \n "
2012-05-18 02:45:23 -05:00
" This is probably because you already have a running ResInsight process. \n "
" Octave can only communicate with one ResInsight process at a time, so the Octave \n "
" communication in this ResInsight instance will be disabled. \n "
" \n "
+ tr ( " The error from the socket system is: %1. " ) . arg ( m_tcpServer - > errorString ( ) ) ) ;
return ;
}
2014-09-08 08:39:23 -05:00
connect ( m_nextPendingConnectionTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotNewClientConnection ( ) ) ) ;
2012-10-15 08:13:41 -05:00
connect ( m_tcpServer , SIGNAL ( newConnection ( ) ) , this , SLOT ( slotNewClientConnection ( ) ) ) ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer : : ~ RiaSocketServer ( )
{
2018-10-10 03:17:07 -05:00
assert ( m_currentCommand = = nullptr ) ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned short RiaSocketServer : : serverPort ( )
{
if ( m_tcpServer ) return m_tcpServer - > serverPort ( ) ;
else return 0 ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2012-10-15 08:13:41 -05:00
void RiaSocketServer : : slotNewClientConnection ( )
2012-05-18 02:45:23 -05:00
{
2013-10-04 07:29:11 -05:00
// If we are currently handling a connection, just ignore the new one until the current one is disconnected.
2012-05-18 02:45:23 -05:00
2014-09-08 08:39:23 -05:00
if ( m_currentClient & & ( m_currentClient - > state ( ) ! = QAbstractSocket : : UnconnectedState ) )
2012-10-15 08:13:41 -05:00
{
2013-10-08 07:21:18 -05:00
//PMonLog("Starting Timer");
m_nextPendingConnectionTimer - > start ( ) ; // Reset and start again
2013-10-04 07:29:11 -05:00
return ;
2012-10-15 08:13:41 -05:00
}
2013-10-04 07:29:11 -05:00
// Read pending data from socket
2012-05-18 02:45:23 -05:00
2013-10-04 07:29:11 -05:00
if ( m_currentClient & & m_currentCommand )
2012-05-18 02:45:23 -05:00
{
2013-10-04 07:29:11 -05:00
bool isFinshed = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
if ( ! isFinshed )
{
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Warning : The command did not finish up correctly at the presence of a new one. " ) ) ;
}
2012-05-18 02:45:23 -05:00
}
2013-10-04 07:29:11 -05:00
handleNextPendingConnection ( ) ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
2013-05-15 07:37:03 -05:00
/// Find the requested reservoir by caseId
2012-05-18 02:45:23 -05:00
//--------------------------------------------------------------------------------------------------
2015-05-15 01:40:27 -05:00
RimEclipseCase * RiaSocketServer : : findReservoir ( int caseId )
2012-05-18 02:45:23 -05:00
{
2013-09-27 09:25:40 -05:00
int currCaseId = caseId ;
2013-05-15 07:37:03 -05:00
if ( caseId < 0 )
2013-09-27 09:25:40 -05:00
{
currCaseId = this - > currentCaseId ( ) ;
}
if ( currCaseId < 0 )
2012-05-18 02:45:23 -05:00
{
2018-09-25 00:37:40 -05:00
RimEclipseView * eclipseView = dynamic_cast < RimEclipseView * > ( RiaApplication : : instance ( ) - > activeReservoirView ( ) ) ;
if ( eclipseView )
2012-05-18 02:45:23 -05:00
{
2018-09-25 00:37:40 -05:00
return eclipseView - > eclipseCase ( ) ;
2012-05-18 02:45:23 -05:00
}
2016-01-06 16:01:27 -06:00
// If the active mdi window is different from an Eclipse view, search through available mdi windows to find the last activated
// Eclipse view. The sub windows are returned with the most recent activated window at the back.
QList < QMdiSubWindow * > subWindows = RiuMainWindow : : instance ( ) - > subWindowList ( QMdiArea : : ActivationHistoryOrder ) ;
2018-03-12 05:12:39 -05:00
for ( int i = subWindows . size ( ) - 1 ; i > - 1 ; i - - )
{
RiuViewer * viewer = subWindows [ i ] - > widget ( ) - > findChild < RiuViewer * > ( ) ;
if ( viewer )
{
2016-01-06 16:01:27 -06:00
RimEclipseView * riv = dynamic_cast < RimEclipseView * > ( viewer - > ownerReservoirView ( ) ) ;
if ( riv )
{
return riv - > eclipseCase ( ) ;
}
2018-03-12 05:12:39 -05:00
}
}
2012-05-18 02:45:23 -05:00
}
else
{
2013-03-22 09:50:44 -05:00
RimProject * project = RiaApplication : : instance ( ) - > project ( ) ;
2018-02-18 11:56:43 -06:00
if ( ! project ) return nullptr ;
2012-05-18 02:45:23 -05:00
2015-05-15 11:51:49 -05:00
std : : vector < RimCase * > cases ;
2013-05-15 07:37:03 -05:00
project - > allCases ( cases ) ;
for ( size_t i = 0 ; i < cases . size ( ) ; i + + )
{
2013-09-27 10:06:20 -05:00
if ( cases [ i ] - > caseId = = currCaseId )
2013-05-15 07:37:03 -05:00
{
2015-05-15 11:51:49 -05:00
return dynamic_cast < RimEclipseCase * > ( cases [ i ] ) ;
2013-05-15 07:37:03 -05:00
}
}
2012-05-18 02:45:23 -05:00
}
2018-02-18 11:56:43 -06:00
return nullptr ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
2013-10-04 07:29:11 -05:00
/// Reads the command name size, the command string and creates a new command object based on the string read.
/// Tries to interpret the command as well.
/// Returns whether the command actually was completely finished in one go.
2012-05-18 02:45:23 -05:00
//--------------------------------------------------------------------------------------------------
2013-10-04 07:29:11 -05:00
bool RiaSocketServer : : readCommandFromOctave ( )
2012-05-18 02:45:23 -05:00
{
QDataStream socketStream ( m_currentClient ) ;
2013-05-22 02:18:57 -05:00
socketStream . setVersion ( riOctavePlugin : : qtDataStreamVersion ) ;
2012-05-18 02:45:23 -05:00
// If we have not read the currentCommandSize
// read the size of the command if all the data is available
2013-10-04 07:29:11 -05:00
2012-05-18 02:45:23 -05:00
if ( m_currentCommandSize = = 0 )
{
2013-10-04 07:29:11 -05:00
if ( m_currentClient - > bytesAvailable ( ) < ( int ) sizeof ( qint64 ) ) return false ;
2012-05-18 02:45:23 -05:00
socketStream > > m_currentCommandSize ;
}
// Check if the complete command is available, return and whait for readyRead() if not
2013-10-04 07:29:11 -05:00
if ( m_currentClient - > bytesAvailable ( ) < m_currentCommandSize ) return false ;
2012-05-18 02:45:23 -05:00
2013-10-04 07:29:11 -05:00
// Now we can read the command name
2012-05-18 02:45:23 -05:00
QByteArray command = m_currentClient - > read ( m_currentCommandSize ) ;
QTextStream commandStream ( command ) ;
QList < QByteArray > args ;
while ( ! commandStream . atEnd ( ) )
{
QByteArray arg ;
commandStream > > arg ;
args . push_back ( arg ) ;
}
CVF_ASSERT ( args . size ( ) > 0 ) ;
2013-10-04 07:29:11 -05:00
// Create the actual RiaSocketCommand object that will interpret the socket data
2013-05-16 04:15:34 -05:00
m_currentCommand = RiaSocketCommandFactory : : instance ( ) - > create ( args [ 0 ] ) ;
2013-05-24 04:36:59 -05:00
2013-05-16 04:15:34 -05:00
if ( m_currentCommand )
{
bool finished = m_currentCommand - > interpretCommand ( this , args , socketStream ) ;
2013-10-04 07:29:11 -05:00
return finished ;
2013-05-16 04:15:34 -05:00
}
else
{
2012-05-18 02:45:23 -05:00
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Unknown command: %1 " ) . arg ( args [ 0 ] . data ( ) ) ) ;
2013-10-04 07:29:11 -05:00
return true ;
2012-05-18 02:45:23 -05:00
}
}
2012-06-26 09:10:41 -05:00
2012-05-18 02:45:23 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : slotCurrentClientDisconnected ( )
{
2013-05-24 04:36:59 -05:00
if ( m_currentCommand )
{
2013-10-04 07:29:11 -05:00
// Make sure we read what can be read.
bool isFinished = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
if ( ! isFinished )
2013-05-24 04:36:59 -05:00
{
2013-10-04 07:29:11 -05:00
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Warning : The command was interrupted and did not finish because the connection to octave disconnected. " ) ) ;
2013-05-24 04:36:59 -05:00
}
}
2013-10-04 07:29:11 -05:00
handleNextPendingConnection ( ) ;
2012-10-15 08:13:41 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : slotReadyRead ( )
{
2013-05-24 04:36:59 -05:00
if ( m_currentCommand )
{
2013-10-04 07:29:11 -05:00
bool isFinished = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
2013-05-29 03:07:35 -05:00
2013-10-04 07:29:11 -05:00
if ( isFinished )
{
handleNextPendingConnection ( ) ;
2013-05-24 04:36:59 -05:00
}
}
else
{
2013-10-04 07:29:11 -05:00
bool isFinished = readCommandFromOctave ( ) ;
if ( isFinished )
{
handleNextPendingConnection ( ) ;
}
2013-05-24 04:36:59 -05:00
}
2012-05-18 02:45:23 -05:00
}
2012-10-19 03:05:55 -05:00
2013-05-26 14:55:05 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : setCurrentCaseId ( int caseId )
{
m_currentCaseId = caseId ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiaSocketServer : : currentCaseId ( ) const
{
return m_currentCaseId ;
}
2013-10-04 07:29:11 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : terminateCurrentConnection ( )
{
if ( m_currentClient )
{
m_currentClient - > disconnect ( SIGNAL ( disconnected ( ) ) ) ;
m_currentClient - > disconnect ( SIGNAL ( readyRead ( ) ) ) ;
m_currentClient - > deleteLater ( ) ;
2018-02-18 11:56:43 -06:00
m_currentClient = nullptr ;
2013-10-04 07:29:11 -05:00
}
// Clean up more state:
if ( m_currentCommand )
{
delete m_currentCommand ;
2018-02-18 11:56:43 -06:00
m_currentCommand = nullptr ;
2013-10-04 07:29:11 -05:00
}
m_currentCommandSize = 0 ;
}
2013-05-29 03:07:35 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-10-04 07:29:11 -05:00
void RiaSocketServer : : handleNextPendingConnection ( )
2013-05-29 03:07:35 -05:00
{
2014-09-08 08:39:23 -05:00
if ( m_currentClient & & ( m_currentClient - > state ( ) ! = QAbstractSocket : : UnconnectedState ) )
2013-05-29 03:07:35 -05:00
{
2013-10-08 07:21:18 -05:00
//PMonLog("Starting Timer");
m_nextPendingConnectionTimer - > start ( ) ; // Reset and start again
2013-10-04 07:29:11 -05:00
return ;
}
2013-10-08 07:21:18 -05:00
// Stop timer
if ( m_nextPendingConnectionTimer - > isActive ( ) )
{
//PMonLog("Stopping Timer");
m_nextPendingConnectionTimer - > stop ( ) ;
}
2013-10-04 07:29:11 -05:00
terminateCurrentConnection ( ) ;
QTcpSocket * clientToHandle = m_tcpServer - > nextPendingConnection ( ) ;
if ( clientToHandle )
{
2018-02-18 11:56:43 -06:00
CVF_ASSERT ( m_currentClient = = nullptr ) ;
CVF_ASSERT ( m_currentCommand = = nullptr ) ;
2013-05-29 03:07:35 -05:00
2013-10-04 07:29:11 -05:00
m_currentClient = clientToHandle ;
m_currentCommandSize = 0 ;
connect ( m_currentClient , SIGNAL ( disconnected ( ) ) , this , SLOT ( slotCurrentClientDisconnected ( ) ) ) ;
connect ( m_currentClient , SIGNAL ( readyRead ( ) ) , this , SLOT ( slotReadyRead ( ) ) ) ;
if ( m_currentClient - > bytesAvailable ( ) )
{
bool isFinished = this - > readCommandFromOctave ( ) ;
if ( isFinished )
{
// Call ourselves recursively until there are none left, or until it can not be processed in one go.
this - > handleNextPendingConnection ( ) ;
}
}
2013-05-29 03:07:35 -05:00
}
}