masterfix DEV300: #i10000# build fix
[LibreOffice.git] / extensions / source / plugin / unx / mediator.cxx
blob4d8fd64a8407a50c759d5b826d387ca19a86753e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include <errno.h>
31 #include <unistd.h>
33 #include <plugin/unx/mediator.hxx>
34 #include <vcl/svapp.hxx>
36 #define MEDIATOR_MAGIC 0xf7a8d2f4
38 Mediator::Mediator( int nSocket ) :
39 m_nSocket( nSocket ),
40 m_pListener( NULL ),
41 m_nCurrentID( 1 ),
42 m_bValid( true )
44 m_pListener = new MediatorListener( this );
45 m_pListener->create();
48 Mediator::~Mediator()
50 if( m_pListener )
53 ::vos::OGuard aGuard( m_pListener->m_aMutex );
54 m_pListener->m_pMediator = NULL;
56 m_pListener = NULL;
57 if( m_bValid )
59 sal_uLong aHeader[3];
60 aHeader[0] = 0;
61 aHeader[1] = 0;
62 aHeader[2] = MEDIATOR_MAGIC;
63 write( m_nSocket, aHeader, sizeof( aHeader ) );
65 // kick the thread out of its run method; it deletes itself
66 close( m_nSocket );
68 else
69 close( m_nSocket );
70 for( std::vector< MediatorMessage* >::iterator it = m_aMessageQueue.begin();
71 it != m_aMessageQueue.end(); ++it )
73 delete *it;
78 sal_uLong Mediator::SendMessage( sal_uLong nBytes, const char* pBytes, sal_uLong nMessageID )
80 if( ! m_pListener )
81 return 0;
83 vos::OGuard aGuard( m_aSendMutex );
84 if( ! nMessageID )
85 nMessageID = m_nCurrentID;
87 m_nCurrentID++;
88 if( m_nCurrentID >= 1 << 24 ) // protection against overflow
89 m_nCurrentID = 1;
91 if( ! m_bValid )
92 return nMessageID;
94 sal_uLong* pBuffer = new sal_uLong[ (nBytes/sizeof(sal_uLong)) + 4 ];
95 pBuffer[ 0 ] = nMessageID;
96 pBuffer[ 1 ] = nBytes;
97 pBuffer[ 2 ] = MEDIATOR_MAGIC;
98 memcpy( &pBuffer[3], pBytes, (size_t)nBytes );
99 write( m_nSocket, pBuffer, nBytes + 3*sizeof( sal_uLong ) );
100 delete [] pBuffer;
102 return nMessageID;
105 sal_Bool Mediator::WaitForMessage( sal_uLong nTimeOut )
107 if( ! m_pListener )
108 return sal_False;
110 size_t nItems = m_aMessageQueue.size();
112 if( ! nTimeOut && nItems > 0 )
113 return sal_True;
115 TimeValue aValue;
116 aValue.Seconds = nTimeOut/1000;
117 aValue.Nanosec = ( nTimeOut % 1000 ) * 1000;
119 while( m_aMessageQueue.size() == nItems )
121 m_aNewMessageCdtn.wait( & aValue );
122 m_aNewMessageCdtn.reset();
123 if( nTimeOut && m_aMessageQueue.size() == nItems )
124 return sal_False;
126 return sal_True;
129 MediatorMessage* Mediator::WaitForAnswer( sal_uLong nMessageID )
131 nMessageID &= 0x00ffffff;
132 while( m_pListener )
135 vos::OGuard aGuard( m_aQueueMutex );
136 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
138 MediatorMessage* pMessage = m_aMessageQueue[ i ];
139 sal_uLong nID = pMessage->m_nID;
140 if( ( nID & 0xff000000 ) &&
141 ( ( nID & 0x00ffffff ) == nMessageID ) )
143 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
144 return pMessage;
148 WaitForMessage( 10 );
150 return NULL;
153 MediatorMessage* Mediator::GetNextMessage( sal_Bool bWait )
155 while( m_pListener )
158 // guard must be after WaitForMessage, else the listener
159 // cannot insert a new one -> deadlock
160 vos::OGuard aGuard( m_aQueueMutex );
161 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
163 MediatorMessage* pMessage = m_aMessageQueue[ i ];
164 if( ! ( pMessage->m_nID & 0xff000000 ) )
166 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
167 return pMessage;
170 if( ! bWait )
171 return NULL;
173 WaitForMessage();
175 return NULL;
178 MediatorMessage* Mediator::TransactMessage( sal_uLong nBytes, char* pBytes )
180 sal_uLong nID = SendMessage( nBytes, pBytes );
181 return WaitForAnswer( nID );
184 MediatorListener::MediatorListener( Mediator* pMediator ) :
185 m_pMediator( pMediator )
189 MediatorListener::~MediatorListener()
193 void MediatorListener::run()
195 bool bRun = true;
196 while( schedule() && m_pMediator && bRun )
198 sal_uLong nHeader[ 3 ];
199 int nBytes;
201 if( m_pMediator && ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC)
203 if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 )
204 return;
205 char* pBuffer = new char[ nHeader[ 1 ] ];
206 if( m_pMediator && (sal_uLong)read( m_pMediator->m_nSocket, pBuffer, nHeader[ 1 ] ) == nHeader[ 1 ] )
208 ::vos::OGuard aMyGuard( m_aMutex );
210 vos::OGuard
211 aGuard( m_pMediator->m_aQueueMutex );
212 MediatorMessage* pMessage =
213 new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer );
214 m_pMediator->m_aMessageQueue.push_back( pMessage );
216 m_pMediator->m_aNewMessageCdtn.set();
217 m_pMediator->m_aNewMessageHdl.Call( m_pMediator );
219 else
221 medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n",
222 nHeader[0], nHeader[1], nHeader[1], pBuffer );
223 bRun = false;
225 delete [] pBuffer;
227 else
229 medDebug( 1, "got incomplete message header of %d bytes ( nHeader = [ %u, %u ] ), errno is %d\n",
230 nBytes, nHeader[ 0 ], nHeader[ 1 ], (int)errno );
231 bRun = false;
236 void MediatorListener::onTerminated()
238 if( m_pMediator )
240 m_pMediator->m_aConnectionLostHdl.Call( m_pMediator );
241 m_pMediator->m_pListener = NULL;
243 delete this;
246 sal_uLong MediatorMessage::ExtractULONG()
248 if( ! m_pRun )
249 m_pRun = m_pBytes;
251 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::ExtractULONG\n" );
252 sal_uLong nCount;
253 memcpy( &nCount, m_pRun, sizeof( sal_uLong ) );
254 m_pRun += sizeof( sal_uLong );
255 return nCount;
258 void* MediatorMessage::GetBytes( sal_uLong& rBytes )
260 if( ! m_pRun )
261 m_pRun = m_pBytes;
263 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
264 sal_uLong nBytes = ExtractULONG();
266 if( nBytes == 0 )
267 return NULL;
269 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" );
270 char* pBuffer = new char[ nBytes ];
271 memcpy( pBuffer, m_pRun, nBytes );
272 m_pRun += nBytes;
273 rBytes = nBytes;
274 return pBuffer;
277 char* MediatorMessage::GetString()
279 if( ! m_pRun )
280 m_pRun = m_pBytes;
282 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
283 sal_uLong nBytes = ExtractULONG();
285 if( nBytes == 0 )
286 return NULL;
288 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" );
289 char* pBuffer = new char[ nBytes+1 ];
290 memcpy( pBuffer, m_pRun, nBytes );
291 pBuffer[ nBytes ] = 0;
292 m_pRun += nBytes;
293 return pBuffer;
296 sal_uInt32 MediatorMessage::GetUINT32()
298 if( ! m_pRun )
299 m_pRun = m_pBytes;
301 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
302 sal_uLong nBytes = ExtractULONG();
303 medDebug( nBytes != sizeof( sal_uInt32 ), "No sal_uInt32 in MediatorMessage::GetUINT32\n" );
304 medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" );
305 sal_uInt32 nRet;
306 memcpy( &nRet, m_pRun, sizeof( nRet ) );
307 m_pRun += sizeof( sal_uInt32 );
308 return nRet;