bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / plugin / unx / mediator.cxx
blob76045f3724a3291bdbc8185bcb8bcb85715562dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <errno.h>
30 #include <unistd.h>
32 #include <plugin/unx/mediator.hxx>
33 #include <sal/log.hxx>
34 #include <vcl/svapp.hxx>
35 #include <boost/scoped_array.hpp>
37 #define MEDIATOR_MAGIC 0xf7a8d2f4
39 Mediator::Mediator( int nSocket ) :
40 m_nSocket( nSocket ),
41 m_pListener( NULL ),
42 m_nCurrentID( 1 ),
43 m_bValid( true )
45 m_pListener = new MediatorListener( this );
46 m_pListener->create();
49 Mediator::~Mediator()
51 if( m_pListener )
54 ::osl::MutexGuard aGuard( m_pListener->m_aMutex );
55 m_pListener->m_pMediator = NULL;
57 m_pListener = NULL;
58 if( m_bValid )
60 sal_uLong aHeader[3];
61 aHeader[0] = 0;
62 aHeader[1] = 0;
63 aHeader[2] = MEDIATOR_MAGIC;
64 ssize_t nToWrite = sizeof(aHeader);
65 bool bSuccess = (nToWrite == write(m_nSocket, aHeader, nToWrite));
66 SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
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 sal_uLong Mediator::SendMessage( sal_uLong nBytes, const char* pBytes, sal_uLong nMessageID )
83 if( ! m_pListener )
84 return 0;
86 osl::MutexGuard 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 boost::scoped_array<sal_uLong> pBuffer(new sal_uLong[ (nBytes/sizeof(sal_uLong)) + 4 ]);
98 pBuffer[ 0 ] = nMessageID;
99 pBuffer[ 1 ] = nBytes;
100 pBuffer[ 2 ] = MEDIATOR_MAGIC;
101 memcpy( &pBuffer[3], pBytes, (size_t)nBytes );
102 ssize_t nToWrite = nBytes + 3*sizeof( sal_uLong );
103 bool bSuccess = (nToWrite == write( m_nSocket, pBuffer.get(), nToWrite ));
104 SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
106 return nMessageID;
109 bool Mediator::WaitForMessage( sal_uLong nTimeOut )
111 if( ! m_pListener )
112 return false;
114 size_t nItems = m_aMessageQueue.size();
116 if( ! nTimeOut && nItems > 0 )
117 return true;
119 TimeValue aValue;
120 aValue.Seconds = nTimeOut/1000;
121 aValue.Nanosec = ( nTimeOut % 1000 ) * 1000;
123 while( m_aMessageQueue.size() == nItems )
125 m_aNewMessageCdtn.wait( & aValue );
126 m_aNewMessageCdtn.reset();
127 if( nTimeOut && m_aMessageQueue.size() == nItems )
128 return false;
130 return true;
133 MediatorMessage* Mediator::WaitForAnswer( sal_uLong nMessageID )
135 nMessageID &= 0x00ffffff;
136 while( m_pListener )
139 osl::MutexGuard aGuard( m_aQueueMutex );
140 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
142 MediatorMessage* pMessage = m_aMessageQueue[ i ];
143 sal_uLong nID = pMessage->m_nID;
144 if( ( nID & 0xff000000 ) &&
145 ( ( nID & 0x00ffffff ) == nMessageID ) )
147 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
148 return pMessage;
152 WaitForMessage( 10 );
154 return NULL;
157 MediatorMessage* Mediator::GetNextMessage( bool bWait )
159 while( m_pListener )
162 // guard must be after WaitForMessage, else the listener
163 // cannot insert a new one -> deadlock
164 osl::MutexGuard aGuard( m_aQueueMutex );
165 for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
167 MediatorMessage* pMessage = m_aMessageQueue[ i ];
168 if( ! ( pMessage->m_nID & 0xff000000 ) )
170 m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
171 return pMessage;
174 if( ! bWait )
175 return NULL;
177 WaitForMessage();
179 return NULL;
182 MediatorMessage* Mediator::TransactMessage( sal_uLong nBytes, char* pBytes )
184 sal_uLong nID = SendMessage( nBytes, pBytes );
185 return WaitForAnswer( nID );
188 MediatorListener::MediatorListener( Mediator* pMediator ) :
189 m_pMediator( pMediator )
193 MediatorListener::~MediatorListener()
197 void MediatorListener::run()
199 osl_setThreadName("MediatorListener");
201 bool bRun = true;
202 while( schedule() && m_pMediator && bRun )
204 sal_uLong nHeader[ 3 ];
205 int nBytes;
207 if( ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC)
209 if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 )
210 return;
211 boost::scoped_array<char> pBuffer(new char[ nHeader[ 1 ] ]);
212 if( m_pMediator && (sal_uLong)read( m_pMediator->m_nSocket, pBuffer.get(), nHeader[ 1 ] ) == nHeader[ 1 ] )
214 ::osl::MutexGuard aMyGuard( m_aMutex );
216 osl::MutexGuard
217 aGuard( m_pMediator->m_aQueueMutex );
218 MediatorMessage* pMessage =
219 new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer.get() );
220 m_pMediator->m_aMessageQueue.push_back( pMessage );
222 m_pMediator->m_aNewMessageCdtn.set();
223 m_pMediator->m_aNewMessageHdl.Call( m_pMediator );
225 else
227 SAL_WARN(
228 "extensions.plugin",
229 "got incomplete MediatorMessage: { " << nHeader[0] << ", "
230 << nHeader[1] << ", ... }");
231 bRun = false;
234 else
236 SAL_WARN(
237 "extensions.plugin",
238 "got incomplete message header of " << nBytes
239 << " bytes (nHeader = [" << nHeader[0] << ", " << nHeader[1]
240 << "]), errno is " << errno);
241 bRun = false;
246 void MediatorListener::onTerminated()
248 if( m_pMediator )
250 m_pMediator->m_aConnectionLostHdl.Call( m_pMediator );
251 m_pMediator->m_pListener = NULL;
253 delete this;
256 sal_uLong MediatorMessage::ExtractULONG()
258 if( ! m_pRun )
259 m_pRun = m_pBytes;
261 SAL_WARN_IF(
262 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
263 "overflow in MediatorMessage::ExtractULONG");
264 sal_uLong nCount;
265 memcpy( &nCount, m_pRun, sizeof( sal_uLong ) );
266 m_pRun += sizeof( sal_uLong );
267 return nCount;
270 void* MediatorMessage::GetBytes( sal_uLong& rBytes )
272 if( ! m_pRun )
273 m_pRun = m_pBytes;
275 SAL_WARN_IF(
276 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
277 "overflow in MediatorMessage::GetBytes");
278 sal_uLong nBytes = ExtractULONG();
280 if( nBytes == 0 )
281 return NULL;
283 SAL_WARN_IF(
284 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
285 "overflow in MediatorMessage::GetBytes");
286 char* pBuffer = new char[ nBytes ];
287 memcpy( pBuffer, m_pRun, nBytes );
288 m_pRun += nBytes;
289 rBytes = nBytes;
290 return pBuffer;
293 char* MediatorMessage::GetString()
295 if( ! m_pRun )
296 m_pRun = m_pBytes;
298 SAL_WARN_IF(
299 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
300 "overflow in MediatorMessage::GetString");
301 sal_uLong nBytes = ExtractULONG();
303 if( nBytes == 0 )
304 return NULL;
306 SAL_WARN_IF(
307 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
308 "overflow in MediatorMessage::GetString");
309 char* pBuffer = new char[ nBytes+1 ];
310 memcpy( pBuffer, m_pRun, nBytes );
311 pBuffer[ nBytes ] = 0;
312 m_pRun += nBytes;
313 return pBuffer;
316 sal_uInt32 MediatorMessage::GetUINT32()
318 if( ! m_pRun )
319 m_pRun = m_pBytes;
321 SAL_WARN_IF(
322 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
323 "overflow in MediatorMessage::GetUINT32");
324 sal_uLong nBytes = ExtractULONG();
325 SAL_WARN_IF(
326 nBytes != sizeof( sal_uInt32 ), "extensions.plugin",
327 "no sal_uInt32 in MediatorMessage::GetUINT32");
328 SAL_WARN_IF(
329 (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
330 "overflow in MediatorMessage::GetUINT32");
331 sal_uInt32 nRet;
332 memcpy( &nRet, m_pRun, sizeof( nRet ) );
333 m_pRun += sizeof( sal_uInt32 );
334 return nRet;
337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */