1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
36 #include <plugin/unx/mediator.hxx>
37 #include <vcl/svapp.hxx>
39 #define MEDIATOR_MAGIC 0xf7a8d2f4
41 Mediator::Mediator( int nSocket
) :
47 m_pListener
= new MediatorListener( this );
48 m_pListener
->create();
56 ::vos::OGuard
aGuard( m_pListener
->m_aMutex
);
57 m_pListener
->m_pMediator
= NULL
;
65 aHeader
[2] = MEDIATOR_MAGIC
;
66 write( m_nSocket
, aHeader
, sizeof( aHeader
) );
68 // kick the thread out of its run method; it deletes itself
73 for( std::vector
< MediatorMessage
* >::iterator it
= m_aMessageQueue
.begin();
74 it
!= m_aMessageQueue
.end(); ++it
)
81 ULONG
Mediator::SendMessage( ULONG nBytes
, const char* pBytes
, ULONG nMessageID
)
86 NAMESPACE_VOS(OGuard
) aGuard( m_aSendMutex
);
88 nMessageID
= m_nCurrentID
;
91 if( m_nCurrentID
>= 1 << 24 ) // protection against overflow
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
) );
108 BOOL
Mediator::WaitForMessage( ULONG nTimeOut
)
113 size_t nItems
= m_aMessageQueue
.size();
115 if( ! nTimeOut
&& nItems
> 0 )
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
)
132 MediatorMessage
* Mediator::WaitForAnswer( ULONG nMessageID
)
134 nMessageID
&= 0x00ffffff;
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
);
151 WaitForMessage( 10 );
156 MediatorMessage
* Mediator::GetNextMessage( BOOL bWait
)
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
);
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()
199 while( schedule() && m_pMediator
&& bRun
)
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 )
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
);
224 medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n",
225 nHeader
[0], nHeader
[1], nHeader
[1], pBuffer
);
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
);
239 void MediatorListener::onTerminated()
243 m_pMediator
->m_aConnectionLostHdl
.Call( m_pMediator
);
244 m_pMediator
->m_pListener
= NULL
;
249 ULONG
MediatorMessage::ExtractULONG()
254 medDebug( (ULONG
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::ExtractULONG\n" );
256 memcpy( &nCount
, m_pRun
, sizeof( ULONG
) );
257 m_pRun
+= sizeof( ULONG
);
261 void* MediatorMessage::GetBytes( ULONG
& rBytes
)
266 medDebug( (ULONG
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::GetBytes\n" );
267 ULONG nBytes
= ExtractULONG();
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
);
280 char* MediatorMessage::GetString()
285 medDebug( (ULONG
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::GetString\n" );
286 ULONG nBytes
= ExtractULONG();
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;
299 UINT32
MediatorMessage::GetUINT32()
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" );
309 memcpy( &nRet
, m_pRun
, sizeof( nRet
) );
310 m_pRun
+= sizeof( UINT32
);