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 ************************************************************************/
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
) :
45 m_pListener
= new MediatorListener( this );
46 m_pListener
->create();
54 ::osl::MutexGuard
aGuard( m_pListener
->m_aMutex
);
55 m_pListener
->m_pMediator
= NULL
;
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
73 for( std::vector
< MediatorMessage
* >::iterator it
= m_aMessageQueue
.begin();
74 it
!= m_aMessageQueue
.end(); ++it
)
81 sal_uLong
Mediator::SendMessage( sal_uLong nBytes
, const char* pBytes
, sal_uLong nMessageID
)
86 osl::MutexGuard
aGuard( m_aSendMutex
);
88 nMessageID
= m_nCurrentID
;
91 if( m_nCurrentID
>= 1 << 24 ) // protection against overflow
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");
109 bool Mediator::WaitForMessage( sal_uLong nTimeOut
)
114 size_t nItems
= m_aMessageQueue
.size();
116 if( ! nTimeOut
&& nItems
> 0 )
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
)
133 MediatorMessage
* Mediator::WaitForAnswer( sal_uLong nMessageID
)
135 nMessageID
&= 0x00ffffff;
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
);
152 WaitForMessage( 10 );
157 MediatorMessage
* Mediator::GetNextMessage( bool bWait
)
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
);
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");
202 while( schedule() && m_pMediator
&& bRun
)
204 sal_uLong nHeader
[ 3 ];
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 )
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
);
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
);
229 "got incomplete MediatorMessage: { " << nHeader
[0] << ", "
230 << nHeader
[1] << ", ... }");
238 "got incomplete message header of " << nBytes
239 << " bytes (nHeader = [" << nHeader
[0] << ", " << nHeader
[1]
240 << "]), errno is " << errno
);
246 void MediatorListener::onTerminated()
250 m_pMediator
->m_aConnectionLostHdl
.Call( m_pMediator
);
251 m_pMediator
->m_pListener
= NULL
;
256 sal_uLong
MediatorMessage::ExtractULONG()
262 (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "extensions.plugin",
263 "overflow in MediatorMessage::ExtractULONG");
265 memcpy( &nCount
, m_pRun
, sizeof( sal_uLong
) );
266 m_pRun
+= sizeof( sal_uLong
);
270 void* MediatorMessage::GetBytes( sal_uLong
& rBytes
)
276 (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "extensions.plugin",
277 "overflow in MediatorMessage::GetBytes");
278 sal_uLong nBytes
= ExtractULONG();
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
);
293 char* MediatorMessage::GetString()
299 (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "extensions.plugin",
300 "overflow in MediatorMessage::GetString");
301 sal_uLong nBytes
= ExtractULONG();
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;
316 sal_uInt32
MediatorMessage::GetUINT32()
322 (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "extensions.plugin",
323 "overflow in MediatorMessage::GetUINT32");
324 sal_uLong nBytes
= ExtractULONG();
326 nBytes
!= sizeof( sal_uInt32
), "extensions.plugin",
327 "no sal_uInt32 in MediatorMessage::GetUINT32");
329 (sal_uLong
)(m_pRun
- m_pBytes
) >= m_nBytes
, "extensions.plugin",
330 "overflow in MediatorMessage::GetUINT32");
332 memcpy( &nRet
, m_pRun
, sizeof( nRet
) );
333 m_pRun
+= sizeof( sal_uInt32
);
337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */