Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
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.
15 : *
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).
21 : *
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.
26 : *
27 : ************************************************************************/
28 :
29 : #include <errno.h>
30 : #include <unistd.h>
31 :
32 : #include <plugin/unx/mediator.hxx>
33 : #include <sal/log.hxx>
34 : #include <vcl/svapp.hxx>
35 :
36 : #define MEDIATOR_MAGIC 0xf7a8d2f4
37 :
38 0 : Mediator::Mediator( int nSocket ) :
39 : m_nSocket( nSocket ),
40 : m_pListener( NULL ),
41 : m_nCurrentID( 1 ),
42 0 : m_bValid( true )
43 : {
44 0 : m_pListener = new MediatorListener( this );
45 0 : m_pListener->create();
46 0 : }
47 :
48 0 : Mediator::~Mediator()
49 : {
50 0 : if( m_pListener )
51 : {
52 : {
53 0 : ::osl::MutexGuard aGuard( m_pListener->m_aMutex );
54 0 : m_pListener->m_pMediator = NULL;
55 : }
56 0 : m_pListener = NULL;
57 0 : if( m_bValid )
58 : {
59 : sal_uLong aHeader[3];
60 0 : aHeader[0] = 0;
61 0 : aHeader[1] = 0;
62 0 : aHeader[2] = MEDIATOR_MAGIC;
63 0 : ssize_t nToWrite = sizeof(aHeader);
64 0 : bool bSuccess = (nToWrite == write(m_nSocket, aHeader, nToWrite));
65 : SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
66 : }
67 : // kick the thread out of its run method; it deletes itself
68 0 : close( m_nSocket );
69 : }
70 : else
71 0 : close( m_nSocket );
72 0 : for( std::vector< MediatorMessage* >::iterator it = m_aMessageQueue.begin();
73 0 : it != m_aMessageQueue.end(); ++it )
74 : {
75 0 : delete *it;
76 : }
77 0 : }
78 :
79 :
80 0 : sal_uLong Mediator::SendMessage( sal_uLong nBytes, const char* pBytes, sal_uLong nMessageID )
81 : {
82 0 : if( ! m_pListener )
83 0 : return 0;
84 :
85 0 : osl::MutexGuard aGuard( m_aSendMutex );
86 0 : if( ! nMessageID )
87 0 : nMessageID = m_nCurrentID;
88 :
89 0 : m_nCurrentID++;
90 0 : if( m_nCurrentID >= 1 << 24 ) // protection against overflow
91 0 : m_nCurrentID = 1;
92 :
93 0 : if( ! m_bValid )
94 0 : return nMessageID;
95 :
96 0 : sal_uLong* pBuffer = new sal_uLong[ (nBytes/sizeof(sal_uLong)) + 4 ];
97 0 : pBuffer[ 0 ] = nMessageID;
98 0 : pBuffer[ 1 ] = nBytes;
99 0 : pBuffer[ 2 ] = MEDIATOR_MAGIC;
100 0 : memcpy( &pBuffer[3], pBytes, (size_t)nBytes );
101 0 : ssize_t nToWrite = nBytes + 3*sizeof( sal_uLong );
102 0 : bool bSuccess = (nToWrite == write( m_nSocket, pBuffer, nToWrite ));
103 : SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
104 0 : delete [] pBuffer;
105 :
106 0 : return nMessageID;
107 : }
108 :
109 0 : sal_Bool Mediator::WaitForMessage( sal_uLong nTimeOut )
110 : {
111 0 : if( ! m_pListener )
112 0 : return sal_False;
113 :
114 0 : size_t nItems = m_aMessageQueue.size();
115 :
116 0 : if( ! nTimeOut && nItems > 0 )
117 0 : return sal_True;
118 :
119 : TimeValue aValue;
120 0 : aValue.Seconds = nTimeOut/1000;
121 0 : aValue.Nanosec = ( nTimeOut % 1000 ) * 1000;
122 :
123 0 : while( m_aMessageQueue.size() == nItems )
124 : {
125 0 : m_aNewMessageCdtn.wait( & aValue );
126 0 : m_aNewMessageCdtn.reset();
127 0 : if( nTimeOut && m_aMessageQueue.size() == nItems )
128 0 : return sal_False;
129 : }
130 0 : return sal_True;
131 : }
132 :
133 0 : MediatorMessage* Mediator::WaitForAnswer( sal_uLong nMessageID )
134 : {
135 0 : nMessageID &= 0x00ffffff;
136 0 : while( m_pListener )
137 : {
138 : {
139 0 : osl::MutexGuard aGuard( m_aQueueMutex );
140 0 : for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
141 : {
142 0 : MediatorMessage* pMessage = m_aMessageQueue[ i ];
143 0 : sal_uLong nID = pMessage->m_nID;
144 0 : if( ( nID & 0xff000000 ) &&
145 : ( ( nID & 0x00ffffff ) == nMessageID ) )
146 : {
147 0 : m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
148 0 : return pMessage;
149 : }
150 0 : }
151 : }
152 0 : WaitForMessage( 10 );
153 : }
154 0 : return NULL;
155 : }
156 :
157 0 : MediatorMessage* Mediator::GetNextMessage( sal_Bool bWait )
158 : {
159 0 : while( m_pListener )
160 : {
161 : {
162 : // guard must be after WaitForMessage, else the listener
163 : // cannot insert a new one -> deadlock
164 0 : osl::MutexGuard aGuard( m_aQueueMutex );
165 0 : for( size_t i = 0; i < m_aMessageQueue.size(); i++ )
166 : {
167 0 : MediatorMessage* pMessage = m_aMessageQueue[ i ];
168 0 : if( ! ( pMessage->m_nID & 0xff000000 ) )
169 : {
170 0 : m_aMessageQueue.erase( m_aMessageQueue.begin() + i );
171 0 : return pMessage;
172 : }
173 : }
174 0 : if( ! bWait )
175 0 : return NULL;
176 : }
177 0 : WaitForMessage();
178 : }
179 0 : return NULL;
180 : }
181 :
182 0 : MediatorMessage* Mediator::TransactMessage( sal_uLong nBytes, char* pBytes )
183 : {
184 0 : sal_uLong nID = SendMessage( nBytes, pBytes );
185 0 : return WaitForAnswer( nID );
186 : }
187 :
188 0 : MediatorListener::MediatorListener( Mediator* pMediator ) :
189 0 : m_pMediator( pMediator )
190 : {
191 0 : }
192 :
193 0 : MediatorListener::~MediatorListener()
194 : {
195 0 : }
196 :
197 0 : void MediatorListener::run()
198 : {
199 0 : bool bRun = true;
200 0 : while( schedule() && m_pMediator && bRun )
201 : {
202 : sal_uLong nHeader[ 3 ];
203 : int nBytes;
204 :
205 0 : if( ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC)
206 : {
207 0 : if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 )
208 0 : return;
209 0 : char* pBuffer = new char[ nHeader[ 1 ] ];
210 0 : if( m_pMediator && (sal_uLong)read( m_pMediator->m_nSocket, pBuffer, nHeader[ 1 ] ) == nHeader[ 1 ] )
211 : {
212 0 : ::osl::MutexGuard aMyGuard( m_aMutex );
213 : {
214 : osl::MutexGuard
215 0 : aGuard( m_pMediator->m_aQueueMutex );
216 : MediatorMessage* pMessage =
217 0 : new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer );
218 0 : m_pMediator->m_aMessageQueue.push_back( pMessage );
219 : }
220 0 : m_pMediator->m_aNewMessageCdtn.set();
221 0 : m_pMediator->m_aNewMessageHdl.Call( m_pMediator );
222 : }
223 : else
224 : {
225 : SAL_WARN(
226 : "extensions.plugin",
227 : "got incomplete MediatorMessage: { " << nHeader[0] << ", "
228 : << nHeader[1] << ", ... }");
229 0 : bRun = false;
230 : }
231 0 : delete [] pBuffer;
232 : }
233 : else
234 : {
235 : SAL_WARN(
236 : "extensions.plugin",
237 : "got incomplete message header of " << nBytes
238 : << " bytes (nHeader = [" << nHeader[0] << ", " << nHeader[1]
239 : << "]), errno is " << errno);
240 0 : bRun = false;
241 : }
242 : }
243 : }
244 :
245 0 : void MediatorListener::onTerminated()
246 : {
247 0 : if( m_pMediator )
248 : {
249 0 : m_pMediator->m_aConnectionLostHdl.Call( m_pMediator );
250 0 : m_pMediator->m_pListener = NULL;
251 : }
252 0 : delete this;
253 0 : }
254 :
255 0 : sal_uLong MediatorMessage::ExtractULONG()
256 : {
257 0 : if( ! m_pRun )
258 0 : m_pRun = m_pBytes;
259 :
260 : SAL_WARN_IF(
261 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
262 : "overflow in MediatorMessage::ExtractULONG");
263 : sal_uLong nCount;
264 0 : memcpy( &nCount, m_pRun, sizeof( sal_uLong ) );
265 0 : m_pRun += sizeof( sal_uLong );
266 0 : return nCount;
267 : }
268 :
269 0 : void* MediatorMessage::GetBytes( sal_uLong& rBytes )
270 : {
271 0 : if( ! m_pRun )
272 0 : m_pRun = m_pBytes;
273 :
274 : SAL_WARN_IF(
275 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
276 : "overflow in MediatorMessage::GetBytes");
277 0 : sal_uLong nBytes = ExtractULONG();
278 :
279 0 : if( nBytes == 0 )
280 0 : return NULL;
281 :
282 : SAL_WARN_IF(
283 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
284 : "overflow in MediatorMessage::GetBytes");
285 0 : char* pBuffer = new char[ nBytes ];
286 0 : memcpy( pBuffer, m_pRun, nBytes );
287 0 : m_pRun += nBytes;
288 0 : rBytes = nBytes;
289 0 : return pBuffer;
290 : }
291 :
292 0 : char* MediatorMessage::GetString()
293 : {
294 0 : if( ! m_pRun )
295 0 : m_pRun = m_pBytes;
296 :
297 : SAL_WARN_IF(
298 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
299 : "overflow in MediatorMessage::GetString");
300 0 : sal_uLong nBytes = ExtractULONG();
301 :
302 0 : if( nBytes == 0 )
303 0 : return NULL;
304 :
305 : SAL_WARN_IF(
306 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
307 : "overflow in MediatorMessage::GetString");
308 0 : char* pBuffer = new char[ nBytes+1 ];
309 0 : memcpy( pBuffer, m_pRun, nBytes );
310 0 : pBuffer[ nBytes ] = 0;
311 0 : m_pRun += nBytes;
312 0 : return pBuffer;
313 : }
314 :
315 0 : sal_uInt32 MediatorMessage::GetUINT32()
316 : {
317 0 : if( ! m_pRun )
318 0 : m_pRun = m_pBytes;
319 :
320 : SAL_WARN_IF(
321 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
322 : "overflow in MediatorMessage::GetUINT32");
323 0 : sal_uLong nBytes = ExtractULONG();
324 : SAL_WARN_IF(
325 : nBytes != sizeof( sal_uInt32 ), "extensions.plugin",
326 : "no sal_uInt32 in MediatorMessage::GetUINT32");
327 : SAL_WARN_IF(
328 : (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "extensions.plugin",
329 : "overflow in MediatorMessage::GetUINT32");
330 : sal_uInt32 nRet;
331 0 : memcpy( &nRet, m_pRun, sizeof( nRet ) );
332 0 : m_pRun += sizeof( sal_uInt32 );
333 0 : return nRet;
334 : }
335 :
336 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|