Update ooo320-m1
[ooovba.git] / extensions / source / plugin / unx / mediator.cxx
blob09497bf504cf923d013c89e7fc02cf376d2e87ce
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: mediator.cxx,v $
10 * $Revision: 1.11.90.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
33 #include <errno.h>
34 #include <unistd.h>
36 #include <plugin/unx/mediator.hxx>
37 #include <vcl/svapp.hxx>
39 #define MEDIATOR_MAGIC 0xf7a8d2f4
41 Mediator::Mediator( int nSocket ) :
42 m_nSocket( nSocket ),
43 m_pListener( NULL ),
44 m_nCurrentID( 1 ),
45 m_bValid( true )
47 m_pListener = new MediatorListener( this );
48 m_pListener->create();
51 Mediator::~Mediator()
53 if( m_pListener )
56 ::vos::OGuard aGuard( m_pListener->m_aMutex );
57 m_pListener->m_pMediator = NULL;
59 m_pListener = NULL;
60 if( m_bValid )
62 ULONG aHeader[3];
63 aHeader[0] = 0;
64 aHeader[1] = 0;
65 aHeader[2] = MEDIATOR_MAGIC;
66 write( m_nSocket, aHeader, sizeof( aHeader ) );
68 // kick the thread out of its run method; it deletes itself
69 close( m_nSocket );
71 else
72 close( m_nSocket );
73 for( std::vector< MediatorMessage* >::iterator it = m_aMessageQueue.begin();
74 it != m_aMessageQueue.end(); ++it )
76 delete *it;
81 ULONG Mediator::SendMessage( ULONG nBytes, const char* pBytes, ULONG nMessageID )
83 if( ! m_pListener )
84 return 0;
86 NAMESPACE_VOS(OGuard) aGuard( m_aSendMutex );
87 if( ! nMessageID )
88 nMessageID = m_nCurrentID;
90 m_nCurrentID++;
91 if( m_nCurrentID >= 1 << 24 ) // protection against overflow
92 m_nCurrentID = 1;
94 if( ! m_bValid )
95 return nMessageID;
97 ULONG* pBuffer = new ULONG[ (nBytes/sizeof(ULONG)) + 4 ];
98 pBuffer[ 0 ] = nMessageID;
99 pBuffer[ 1 ] = nBytes;
100 pBuffer[ 2 ] = MEDIATOR_MAGIC;
101 memcpy( &pBuffer[3], pBytes, (size_t)nBytes );
102 write( m_nSocket, pBuffer, nBytes + 3*sizeof( ULONG ) );
103 delete [] pBuffer;
105 return nMessageID;
108 BOOL Mediator::WaitForMessage( ULONG nTimeOut )
110 if( ! m_pListener )
111 return FALSE;
113 size_t nItems = m_aMessageQueue.size();
115 if( ! nTimeOut && nItems > 0 )
116 return TRUE;
118 TimeValue aValue;
119 aValue.Seconds = nTimeOut/1000;
120 aValue.Nanosec = ( nTimeOut % 1000 ) * 1000;
122 while( m_aMessageQueue.size() == nItems )
124 m_aNewMessageCdtn.wait( & aValue );
125 m_aNewMessageCdtn.reset();
126 if( nTimeOut && m_aMessageQueue.size() == nItems )
127 return FALSE;
129 return TRUE;
132 MediatorMessage* Mediator::WaitForAnswer( ULONG nMessageID )
134 nMessageID &= 0x00ffffff;
135 while( m_pListener )
138 NAMESPACE_VOS(OGuard) aGuard( m_aQueueMutex );
139 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
141 MediatorMessage* pMessage = m_aMessageQueue[ i ];
142 ULONG nID = pMessage->m_nID;
143 if( ( nID & 0xff000000 ) &&
144 ( ( nID & 0x00ffffff ) == nMessageID ) )
146 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
147 return pMessage;
151 WaitForMessage( 10 );
153 return NULL;
156 MediatorMessage* Mediator::GetNextMessage( BOOL bWait )
158 while( m_pListener )
161 // guard must be after WaitForMessage, else the listener
162 // cannot insert a new one -> deadlock
163 NAMESPACE_VOS(OGuard) aGuard( m_aQueueMutex );
164 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
166 MediatorMessage* pMessage = m_aMessageQueue[ i ];
167 if( ! ( pMessage->m_nID & 0xff000000 ) )
169 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
170 return pMessage;
173 if( ! bWait )
174 return NULL;
176 WaitForMessage();
178 return NULL;
181 MediatorMessage* Mediator::TransactMessage( ULONG nBytes, char* pBytes )
183 ULONG nID = SendMessage( nBytes, pBytes );
184 return WaitForAnswer( nID );
187 MediatorListener::MediatorListener( Mediator* pMediator ) :
188 m_pMediator( pMediator )
192 MediatorListener::~MediatorListener()
196 void MediatorListener::run()
198 bool bRun = true;
199 while( schedule() && m_pMediator && bRun )
201 ULONG nHeader[ 3 ];
202 int nBytes;
204 if( m_pMediator && ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC)
206 if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 )
207 return;
208 char* pBuffer = new char[ nHeader[ 1 ] ];
209 if( m_pMediator && (ULONG)read( m_pMediator->m_nSocket, pBuffer, nHeader[ 1 ] ) == nHeader[ 1 ] )
211 ::vos::OGuard aMyGuard( m_aMutex );
213 NAMESPACE_VOS(OGuard)
214 aGuard( m_pMediator->m_aQueueMutex );
215 MediatorMessage* pMessage =
216 new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer );
217 m_pMediator->m_aMessageQueue.push_back( pMessage );
219 m_pMediator->m_aNewMessageCdtn.set();
220 m_pMediator->m_aNewMessageHdl.Call( m_pMediator );
222 else
224 medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n",
225 nHeader[0], nHeader[1], nHeader[1], pBuffer );
226 bRun = false;
228 delete [] pBuffer;
230 else
232 medDebug( 1, "got incomplete message header of %d bytes ( nHeader = [ %u, %u ] ), errno is %d\n",
233 nBytes, nHeader[ 0 ], nHeader[ 1 ], (int)errno );
234 bRun = false;
239 void MediatorListener::onTerminated()
241 if( m_pMediator )
243 m_pMediator->m_aConnectionLostHdl.Call( m_pMediator );
244 m_pMediator->m_pListener = NULL;
246 delete this;
249 ULONG MediatorMessage::ExtractULONG()
251 if( ! m_pRun )
252 m_pRun = m_pBytes;
254 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::ExtractULONG\n" );
255 ULONG nCount;
256 memcpy( &nCount, m_pRun, sizeof( ULONG ) );
257 m_pRun += sizeof( ULONG );
258 return nCount;
261 void* MediatorMessage::GetBytes( ULONG& rBytes )
263 if( ! m_pRun )
264 m_pRun = m_pBytes;
266 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
267 ULONG nBytes = ExtractULONG();
269 if( nBytes == 0 )
270 return NULL;
272 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
273 char* pBuffer = new char[ nBytes ];
274 memcpy( pBuffer, m_pRun, nBytes );
275 m_pRun += nBytes;
276 rBytes = nBytes;
277 return pBuffer;
280 char* MediatorMessage::GetString()
282 if( ! m_pRun )
283 m_pRun = m_pBytes;
285 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
286 ULONG nBytes = ExtractULONG();
288 if( nBytes == 0 )
289 return NULL;
291 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
292 char* pBuffer = new char[ nBytes+1 ];
293 memcpy( pBuffer, m_pRun, nBytes );
294 pBuffer[ nBytes ] = 0;
295 m_pRun += nBytes;
296 return pBuffer;
299 UINT32 MediatorMessage::GetUINT32()
301 if( ! m_pRun )
302 m_pRun = m_pBytes;
304 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
305 ULONG nBytes = ExtractULONG();
306 medDebug( nBytes != sizeof( UINT32 ), "No UINT32 in MediatorMessage::GetUINT32\n" );
307 medDebug( (ULONG)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
308 UINT32 nRet;
309 memcpy( &nRet, m_pRun, sizeof( nRet ) );
310 m_pRun += sizeof( UINT32 );
311 return nRet;