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"
33 #include <plugin/unx/mediator.hxx>
34 #include <vcl/svapp.hxx>
36 #define MEDIATOR_MAGIC 0xf7a8d2f4
38 Mediator::Mediator( int nSocket
) :
44 m_pListener
= new MediatorListener( this );
45 m_pListener
->create();
53 ::vos::OGuard
aGuard( m_pListener
->m_aMutex
);
54 m_pListener
->m_pMediator
= NULL
;
62 aHeader
[2] = MEDIATOR_MAGIC
;
63 write( m_nSocket
, aHeader
, sizeof( aHeader
) );
65 // kick the thread out of its run method; it deletes itself
70 for( std::vector
< MediatorMessage
* >::iterator it
= m_aMessageQueue
.begin();
71 it
!= m_aMessageQueue
.end(); ++it
)
78 sal_uLong
Mediator::SendMessage( sal_uLong nBytes
, const char* pBytes
, sal_uLong nMessageID
)
83 vos::OGuard
aGuard( m_aSendMutex
);
85 nMessageID
= m_nCurrentID
;
88 if( m_nCurrentID
>= 1 << 24 ) // protection against overflow
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
) );
105 sal_Bool
Mediator::WaitForMessage( sal_uLong nTimeOut
)
110 size_t nItems
= m_aMessageQueue
.size();
112 if( ! nTimeOut
&& nItems
> 0 )
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
)
129 MediatorMessage
* Mediator::WaitForAnswer( sal_uLong nMessageID
)
131 nMessageID
&= 0x00ffffff;
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
);
148 WaitForMessage( 10 );
153 MediatorMessage
* Mediator::GetNextMessage( sal_Bool bWait
)
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
);
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()
196 while( schedule() && m_pMediator
&& bRun
)
198 sal_uLong nHeader
[ 3 ];
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 )
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
);
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
);
221 medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n",
222 nHeader
[0], nHeader
[1], nHeader
[1], pBuffer
);
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
);
236 void MediatorListener::onTerminated()
240 m_pMediator
->m_aConnectionLostHdl
.Call( m_pMediator
);
241 m_pMediator
->m_pListener
= NULL
;
246 sal_uLong
MediatorMessage::ExtractULONG()
251 medDebug( (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::ExtractULONG\n" );
253 memcpy( &nCount
, m_pRun
, sizeof( sal_uLong
) );
254 m_pRun
+= sizeof( sal_uLong
);
258 void* MediatorMessage::GetBytes( sal_uLong
& rBytes
)
263 medDebug( (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::GetBytes\n" );
264 sal_uLong nBytes
= ExtractULONG();
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
);
277 char* MediatorMessage::GetString()
282 medDebug( (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "Overflow in MediatorMessage::GetString\n" );
283 sal_uLong nBytes
= ExtractULONG();
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;
296 sal_uInt32
MediatorMessage::GetUINT32()
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" );
306 memcpy( &nRet
, m_pRun
, sizeof( nRet
) );
307 m_pRun
+= sizeof( sal_uInt32
);