summaryrefslogtreecommitdiff
path: root/extensions/source/plugin/unx/mediator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/plugin/unx/mediator.cxx')
-rw-r--r--extensions/source/plugin/unx/mediator.cxx309
1 files changed, 309 insertions, 0 deletions
diff --git a/extensions/source/plugin/unx/mediator.cxx b/extensions/source/plugin/unx/mediator.cxx
new file mode 100644
index 000000000000..6191fa5e897a
--- /dev/null
+++ b/extensions/source/plugin/unx/mediator.cxx
@@ -0,0 +1,309 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+#include <errno.h>
+#include <unistd.h>
+
+#include <plugin/unx/mediator.hxx>
+#include <vcl/svapp.hxx>
+
+#define MEDIATOR_MAGIC 0xf7a8d2f4
+
+Mediator::Mediator( int nSocket ) :
+ m_nSocket( nSocket ),
+ m_pListener( NULL ),
+ m_nCurrentID( 1 ),
+ m_bValid( true )
+{
+ m_pListener = new MediatorListener( this );
+ m_pListener->create();
+}
+
+Mediator::~Mediator()
+{
+ if( m_pListener )
+ {
+ {
+ ::vos::OGuard aGuard( m_pListener->m_aMutex );
+ m_pListener->m_pMediator = NULL;
+ }
+ m_pListener = NULL;
+ if( m_bValid )
+ {
+ ULONG aHeader[3];
+ aHeader[0] = 0;
+ aHeader[1] = 0;
+ aHeader[2] = MEDIATOR_MAGIC;
+ write( m_nSocket, aHeader, sizeof( aHeader ) );
+ }
+ // kick the thread out of its run method; it deletes itself
+ close( m_nSocket );
+ }
+ else
+ close( m_nSocket );
+ for( std::vector< MediatorMessage* >::iterator it = m_aMessageQueue.begin();
+ it != m_aMessageQueue.end(); ++it )
+ {
+ delete *it;
+ }
+}
+
+
+ULONG Mediator::SendMessage( ULONG nBytes, const char* pBytes, ULONG nMessageID )
+{
+ if( ! m_pListener )
+ return 0;
+
+ NAMESPACE_VOS(OGuard) aGuard( m_aSendMutex );
+ if( ! nMessageID )
+ nMessageID = m_nCurrentID;
+
+ m_nCurrentID++;
+ if( m_nCurrentID >= 1 << 24 ) // protection against overflow
+ m_nCurrentID = 1;
+
+ if( ! m_bValid )
+ return nMessageID;
+
+ ULONG* pBuffer = new ULONG[ (nBytes/sizeof(ULONG)) + 4 ];
+ pBuffer[ 0 ] = nMessageID;
+ pBuffer[ 1 ] = nBytes;
+ pBuffer[ 2 ] = MEDIATOR_MAGIC;
+ memcpy( &pBuffer[3], pBytes, (size_t)nBytes );
+ write( m_nSocket, pBuffer, nBytes + 3*sizeof( ULONG ) );
+ delete [] pBuffer;
+
+ return nMessageID;
+}
+
+BOOL Mediator::WaitForMessage( ULONG nTimeOut )
+{
+ if( ! m_pListener )
+ return FALSE;
+
+ size_t nItems = m_aMessageQueue.size();
+
+ if( ! nTimeOut && nItems > 0 )
+ return TRUE;
+
+ TimeValue aValue;
+ aValue.Seconds = nTimeOut/1000;
+ aValue.Nanosec = ( nTimeOut % 1000 ) * 1000;
+
+ while( m_aMessageQueue.size() == nItems )
+ {
+ m_aNewMessageCdtn.wait( & aValue );
+ m_aNewMessageCdtn.reset();
+ if( nTimeOut && m_aMessageQueue.size() == nItems )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+MediatorMessage* Mediator::WaitForAnswer( ULONG nMessageID )
+{
+ nMessageID &= 0x00ffffff;
+ while( m_pListener )
+ {
+ {
+ NAMESPACE_VOS(OGuard) aGuard( m_aQueueMutex );
+ for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
+ {
+ MediatorMessage* pMessage = m_aMessageQueue[ i ];
+ ULONG nID = pMessage->m_nID;
+ if( ( nID & 0xff000000 ) &&
+ ( ( nID & 0x00ffffff ) == nMessageID ) )
+ {
+ m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
+ return pMessage;
+ }
+ }
+ }
+ WaitForMessage( 10 );
+ }
+ return NULL;
+}
+
+MediatorMessage* Mediator::GetNextMessage( BOOL bWait )
+{
+ while( m_pListener )
+ {
+ {
+ // guard must be after WaitForMessage, else the listener
+ // cannot insert a new one -> deadlock
+ NAMESPACE_VOS(OGuard) aGuard( m_aQueueMutex );
+ for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
+ {
+ MediatorMessage* pMessage = m_aMessageQueue[ i ];
+ if( ! ( pMessage->m_nID & 0xff000000 ) )
+ {
+ m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
+ return pMessage;
+ }
+ }
+ if( ! bWait )
+ return NULL;
+ }
+ WaitForMessage();
+ }
+ return NULL;
+}
+
+MediatorMessage* Mediator::TransactMessage( ULONG nBytes, char* pBytes )
+{
+ ULONG nID = SendMessage( nBytes, pBytes );
+ return WaitForAnswer( nID );
+}
+
+MediatorListener::MediatorListener( Mediator* pMediator ) :
+ m_pMediator( pMediator )
+{
+}
+
+MediatorListener::~MediatorListener()
+{
+}
+
+void MediatorListener::run()
+{
+ bool bRun = true;
+ while( schedule() && m_pMediator && bRun )
+ {
+ ULONG nHeader[ 3 ];
+ int nBytes;
+
+ if( m_pMediator && ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC)
+ {
+ if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 )
+ return;
+ char* pBuffer = new char[ nHeader[ 1 ] ];
+ if( m_pMediator && (ULONG)read( m_pMediator->m_nSocket, pBuffer, nHeader[ 1 ] ) == nHeader[ 1 ] )
+ {
+ ::vos::OGuard aMyGuard( m_aMutex );
+ {
+ NAMESPACE_VOS(OGuard)
+ aGuard( m_pMediator->m_aQueueMutex );
+ MediatorMessage* pMessage =
+ new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer );
+ m_pMediator->m_aMessageQueue.push_back( pMessage );
+ }
+ m_pMediator->m_aNewMessageCdtn.set();
+ m_pMediator->m_aNewMessageHdl.Call( m_pMediator );
+ }
+ else
+ {
+ medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n",
+ nHeader[0], nHeader[1], nHeader[1], pBuffer );
+ bRun = false;
+ }
+ delete [] pBuffer;
+ }
+ else
+ {
+ medDebug( 1, "got incomplete message header of %d bytes ( nHeader = [ %u, %u ] ), errno is %d\n",
+ nBytes, nHeader[ 0 ], nHeader[ 1 ], (int)errno );
+ bRun = false;
+ }
+ }
+}
+
+void MediatorListener::onTerminated()
+{
+ if( m_pMediator )
+ {
+ m_pMediator->m_aConnectionLostHdl.Call( m_pMediator );
+ m_pMediator->m_pListener = NULL;
+ }
+ delete this;
+}
+
+ULONG MediatorMessage::ExtractULONG()
+{
+ if( ! m_pRun )
+ m_pRun = m_pBytes;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::ExtractULONG\n" );
+ ULONG nCount;
+ memcpy( &nCount, m_pRun, sizeof( ULONG ) );
+ m_pRun += sizeof( ULONG );
+ return nCount;
+}
+
+void* MediatorMessage::GetBytes( ULONG& rBytes )
+{
+ if( ! m_pRun )
+ m_pRun = m_pBytes;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
+ ULONG nBytes = ExtractULONG();
+
+ if( nBytes == 0 )
+ return NULL;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
+ char* pBuffer = new char[ nBytes ];
+ memcpy( pBuffer, m_pRun, nBytes );
+ m_pRun += nBytes;
+ rBytes = nBytes;
+ return pBuffer;
+}
+
+char* MediatorMessage::GetString()
+{
+ if( ! m_pRun )
+ m_pRun = m_pBytes;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
+ ULONG nBytes = ExtractULONG();
+
+ if( nBytes == 0 )
+ return NULL;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
+ char* pBuffer = new char[ nBytes+1 ];
+ memcpy( pBuffer, m_pRun, nBytes );
+ pBuffer[ nBytes ] = 0;
+ m_pRun += nBytes;
+ return pBuffer;
+}
+
+UINT32 MediatorMessage::GetUINT32()
+{
+ if( ! m_pRun )
+ m_pRun = m_pBytes;
+
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
+ ULONG nBytes = ExtractULONG();
+ medDebug( nBytes != sizeof( UINT32 ), "No UINT32 in MediatorMessage::GetUINT32\n" );
+ medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
+ UINT32 nRet;
+ memcpy( &nRet, m_pRun, sizeof( nRet ) );
+ m_pRun += sizeof( UINT32 );
+ return nRet;
+}