1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_automation.hxx"
26*b1cdbd2cSJim Jagielski #include <stdio.h>
27*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
28*b1cdbd2cSJim Jagielski #define DEBUGPRINTF(x) { printf(x); fflush( stdout ); }
29*b1cdbd2cSJim Jagielski #else
30*b1cdbd2cSJim Jagielski #define DEBUGPRINTF(x)
31*b1cdbd2cSJim Jagielski #endif
32*b1cdbd2cSJim Jagielski #include <tools/debug.hxx>
33*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
34*b1cdbd2cSJim Jagielski #include <vos/socket.hxx>
35*b1cdbd2cSJim Jagielski #include <tools/stream.hxx>
36*b1cdbd2cSJim Jagielski #include <vcl/timer.hxx>
37*b1cdbd2cSJim Jagielski #include <tools/fsys.hxx>
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski #include <automation/communi.hxx>
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski /*	Um den Destruktor protected zu machen wurde unten das delete entfernt.
43*b1cdbd2cSJim Jagielski 	Die Methode wird ohnehin hucht benutzt.
44*b1cdbd2cSJim Jagielski //				delete *((AE*)pData+n);
45*b1cdbd2cSJim Jagielski */
46*b1cdbd2cSJim Jagielski 
47*b1cdbd2cSJim Jagielski #undef  SV_IMPL_PTRARR_SORT
48*b1cdbd2cSJim Jagielski #define SV_IMPL_PTRARR_SORT( nm,AE )\
49*b1cdbd2cSJim Jagielski _SV_IMPL_SORTAR_ALG( nm,AE )\
50*b1cdbd2cSJim Jagielski 	void nm::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL ) { \
51*b1cdbd2cSJim Jagielski 		if( nL ) {\
52*b1cdbd2cSJim Jagielski 			DBG_ASSERT( nP < nA && nP + nL <= nA, "ERR_VAR_DEL" );\
53*b1cdbd2cSJim Jagielski 			for( sal_uInt16 n=nP; n < nP + nL; n++ ) \
54*b1cdbd2cSJim Jagielski 				DBG_ERROR("Das Element der Liste wurde nicht gel�scht"); \
55*b1cdbd2cSJim Jagielski 			SvPtrarr::Remove( nP, nL ); \
56*b1cdbd2cSJim Jagielski 		} \
57*b1cdbd2cSJim Jagielski 	} \
58*b1cdbd2cSJim Jagielski _SV_SEEK_PTR( nm, AE )
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski 
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski SV_IMPL_PTRARR_SORT( CommunicationLinkList, CommunicationLink* );
64*b1cdbd2cSJim Jagielski 
65*b1cdbd2cSJim Jagielski vos::OMutex *pMPostUserEvent=NULL;		// Notwendig, da nicht threadfest
66*b1cdbd2cSJim Jagielski 
CommunicationLinkViaSocket(CommunicationManager * pMan,vos::OStreamSocket * pSocket)67*b1cdbd2cSJim Jagielski CommunicationLinkViaSocket::CommunicationLinkViaSocket( CommunicationManager *pMan, vos::OStreamSocket *pSocket )
68*b1cdbd2cSJim Jagielski : SimpleCommunicationLinkViaSocket( pMan, pSocket )
69*b1cdbd2cSJim Jagielski , nConnectionClosedEventId( 0 )
70*b1cdbd2cSJim Jagielski , nDataReceivedEventId( 0 )
71*b1cdbd2cSJim Jagielski , bShutdownStarted( sal_False )
72*b1cdbd2cSJim Jagielski , bDestroying( sal_False )
73*b1cdbd2cSJim Jagielski {
74*b1cdbd2cSJim Jagielski     SetPutDataReceivedHdl(LINK( this, CommunicationLinkViaSocket, PutDataReceivedHdl ));
75*b1cdbd2cSJim Jagielski     if ( !pMPostUserEvent )
76*b1cdbd2cSJim Jagielski         pMPostUserEvent = new vos::OMutex;
77*b1cdbd2cSJim Jagielski     // this is necassary to prevent the running thread from sending the close event
78*b1cdbd2cSJim Jagielski     // before the open event has been sent.
79*b1cdbd2cSJim Jagielski    	StartCallback();
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski 	create();
82*b1cdbd2cSJim Jagielski }
83*b1cdbd2cSJim Jagielski 
~CommunicationLinkViaSocket()84*b1cdbd2cSJim Jagielski CommunicationLinkViaSocket::~CommunicationLinkViaSocket()
85*b1cdbd2cSJim Jagielski {
86*b1cdbd2cSJim Jagielski     bDestroying = sal_True;
87*b1cdbd2cSJim Jagielski 	StopCommunication();
88*b1cdbd2cSJim Jagielski 	while ( nConnectionClosedEventId || nDataReceivedEventId )
89*b1cdbd2cSJim Jagielski 		GetpApp()->Yield();
90*b1cdbd2cSJim Jagielski 	{
91*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMConnectionClosed );
92*b1cdbd2cSJim Jagielski 		if ( nConnectionClosedEventId )
93*b1cdbd2cSJim Jagielski 		{
94*b1cdbd2cSJim Jagielski 			GetpApp()->RemoveUserEvent( nConnectionClosedEventId );
95*b1cdbd2cSJim Jagielski 			nConnectionClosedEventId = 0;
96*b1cdbd2cSJim Jagielski 			INFO_MSG( CByteString("Event gel�scht"),
97*b1cdbd2cSJim Jagielski 				CByteString( "ConnectionClosedEvent aus Queue gel�scht"),
98*b1cdbd2cSJim Jagielski 				CM_MISC, NULL );
99*b1cdbd2cSJim Jagielski 		}
100*b1cdbd2cSJim Jagielski 	}
101*b1cdbd2cSJim Jagielski 	{
102*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMDataReceived );
103*b1cdbd2cSJim Jagielski 		if ( nDataReceivedEventId )
104*b1cdbd2cSJim Jagielski 		{
105*b1cdbd2cSJim Jagielski 			GetpApp()->RemoveUserEvent( nDataReceivedEventId );
106*b1cdbd2cSJim Jagielski 			nDataReceivedEventId = 0;
107*b1cdbd2cSJim Jagielski 			delete GetServiceData();
108*b1cdbd2cSJim Jagielski 			INFO_MSG( CByteString("Event gel�scht"),
109*b1cdbd2cSJim Jagielski 				CByteString( "DataReceivedEvent aus Queue gel�scht"),
110*b1cdbd2cSJim Jagielski 				CM_MISC, NULL );
111*b1cdbd2cSJim Jagielski 		}
112*b1cdbd2cSJim Jagielski 	}
113*b1cdbd2cSJim Jagielski }
114*b1cdbd2cSJim Jagielski 
ShutdownCommunication()115*b1cdbd2cSJim Jagielski sal_Bool CommunicationLinkViaSocket::ShutdownCommunication()
116*b1cdbd2cSJim Jagielski {
117*b1cdbd2cSJim Jagielski 	if ( isRunning() )
118*b1cdbd2cSJim Jagielski 	{
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski 		terminate();
121*b1cdbd2cSJim Jagielski 		if ( GetStreamSocket() )
122*b1cdbd2cSJim Jagielski 			GetStreamSocket()->shutdown();
123*b1cdbd2cSJim Jagielski 
124*b1cdbd2cSJim Jagielski 		if ( GetStreamSocket() )	// Mal wieder nach oben verschoben, da sonst nicht vom Read runtergesprungen wird.
125*b1cdbd2cSJim Jagielski 			GetStreamSocket()->close();
126*b1cdbd2cSJim Jagielski 
127*b1cdbd2cSJim Jagielski 		resume();	// So da� das run auch die Schleife verlassen kann
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski 		join();
130*b1cdbd2cSJim Jagielski 
131*b1cdbd2cSJim Jagielski         vos::OStreamSocket *pTempSocket = GetStreamSocket();
132*b1cdbd2cSJim Jagielski         SetStreamSocket( NULL );
133*b1cdbd2cSJim Jagielski         delete pTempSocket;
134*b1cdbd2cSJim Jagielski 
135*b1cdbd2cSJim Jagielski //		ConnectionClosed();		Wird am Ende des Thread gerufen
136*b1cdbd2cSJim Jagielski 
137*b1cdbd2cSJim Jagielski 	}
138*b1cdbd2cSJim Jagielski 	else
139*b1cdbd2cSJim Jagielski 	{
140*b1cdbd2cSJim Jagielski 		join();
141*b1cdbd2cSJim Jagielski 	}
142*b1cdbd2cSJim Jagielski 
143*b1cdbd2cSJim Jagielski 	return sal_True;
144*b1cdbd2cSJim Jagielski }
145*b1cdbd2cSJim Jagielski 
StopCommunication()146*b1cdbd2cSJim Jagielski sal_Bool CommunicationLinkViaSocket::StopCommunication()
147*b1cdbd2cSJim Jagielski {
148*b1cdbd2cSJim Jagielski     if ( !bShutdownStarted )
149*b1cdbd2cSJim Jagielski     {
150*b1cdbd2cSJim Jagielski         return SimpleCommunicationLinkViaSocket::StopCommunication();
151*b1cdbd2cSJim Jagielski     }
152*b1cdbd2cSJim Jagielski     else
153*b1cdbd2cSJim Jagielski     {
154*b1cdbd2cSJim Jagielski         WaitForShutdown();
155*b1cdbd2cSJim Jagielski         return sal_True;
156*b1cdbd2cSJim Jagielski     }
157*b1cdbd2cSJim Jagielski }
158*b1cdbd2cSJim Jagielski 
159*b1cdbd2cSJim Jagielski 
IMPL_LINK(CommunicationLinkViaSocket,ShutdownLink,void *,EMPTYARG)160*b1cdbd2cSJim Jagielski IMPL_LINK( CommunicationLinkViaSocket, ShutdownLink, void*, EMPTYARG )
161*b1cdbd2cSJim Jagielski {
162*b1cdbd2cSJim Jagielski 	if ( !IsCommunicationError() )
163*b1cdbd2cSJim Jagielski     	ShutdownCommunication();
164*b1cdbd2cSJim Jagielski     return 0;
165*b1cdbd2cSJim Jagielski }
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski 
WaitForShutdown()168*b1cdbd2cSJim Jagielski void CommunicationLinkViaSocket::WaitForShutdown()
169*b1cdbd2cSJim Jagielski {
170*b1cdbd2cSJim Jagielski     if ( !bShutdownStarted )
171*b1cdbd2cSJim Jagielski     {
172*b1cdbd2cSJim Jagielski 	    aShutdownTimer.SetTimeout( 30000 );		// Should be 30 Seconds
173*b1cdbd2cSJim Jagielski 	    aShutdownTimer.SetTimeoutHdl( LINK( this, CommunicationLinkViaSocket, ShutdownLink ) );
174*b1cdbd2cSJim Jagielski 	    aShutdownTimer.Start();
175*b1cdbd2cSJim Jagielski         bShutdownStarted = sal_True;
176*b1cdbd2cSJim Jagielski     }
177*b1cdbd2cSJim Jagielski     if ( bDestroying )
178*b1cdbd2cSJim Jagielski     {
179*b1cdbd2cSJim Jagielski 	    while ( pMyManager && aShutdownTimer.IsActive() )
180*b1cdbd2cSJim Jagielski 	    {
181*b1cdbd2cSJim Jagielski 		    if ( IsCommunicationError() )
182*b1cdbd2cSJim Jagielski 			    return;
183*b1cdbd2cSJim Jagielski 		    GetpApp()->Yield();
184*b1cdbd2cSJim Jagielski 	    }
185*b1cdbd2cSJim Jagielski 	    ShutdownCommunication();
186*b1cdbd2cSJim Jagielski     }
187*b1cdbd2cSJim Jagielski }
188*b1cdbd2cSJim Jagielski 
IsCommunicationError()189*b1cdbd2cSJim Jagielski sal_Bool CommunicationLinkViaSocket::IsCommunicationError()
190*b1cdbd2cSJim Jagielski {
191*b1cdbd2cSJim Jagielski 	return !isRunning() || SimpleCommunicationLinkViaSocket::IsCommunicationError();
192*b1cdbd2cSJim Jagielski }
193*b1cdbd2cSJim Jagielski 
run()194*b1cdbd2cSJim Jagielski void CommunicationLinkViaSocket::run()
195*b1cdbd2cSJim Jagielski {
196*b1cdbd2cSJim Jagielski 	sal_Bool bWasError = sal_False;
197*b1cdbd2cSJim Jagielski     while ( schedule() && !bWasError && GetStreamSocket() )
198*b1cdbd2cSJim Jagielski 	{
199*b1cdbd2cSJim Jagielski 		bWasError |= !DoReceiveDataStream();
200*b1cdbd2cSJim Jagielski 		if( bWasError)
201*b1cdbd2cSJim Jagielski 			continue;
202*b1cdbd2cSJim Jagielski 
203*b1cdbd2cSJim Jagielski 		TimeValue sNochEins = {0, 1000000};
204*b1cdbd2cSJim Jagielski 		while ( schedule() && bIsInsideCallback )	// solange der letzte Callback nicht beendet ist
205*b1cdbd2cSJim Jagielski 			sleep( sNochEins );
206*b1cdbd2cSJim Jagielski 		SetNewPacketAsCurrent();
207*b1cdbd2cSJim Jagielski 		StartCallback();
208*b1cdbd2cSJim Jagielski 		{
209*b1cdbd2cSJim Jagielski 			vos::OGuard aGuard( aMDataReceived );
210*b1cdbd2cSJim Jagielski             vos::OGuard aGuard2( *pMPostUserEvent );
211*b1cdbd2cSJim Jagielski             mlPutDataReceived.Call(this);
212*b1cdbd2cSJim Jagielski 		}
213*b1cdbd2cSJim Jagielski 	}
214*b1cdbd2cSJim Jagielski 	TimeValue sNochEins = {0, 1000000};
215*b1cdbd2cSJim Jagielski 	while ( schedule() && bIsInsideCallback )	// solange der letzte Callback nicht beendet ist
216*b1cdbd2cSJim Jagielski 		sleep( sNochEins );
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski     StartCallback();
219*b1cdbd2cSJim Jagielski 	{
220*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMConnectionClosed );
221*b1cdbd2cSJim Jagielski         vos::OGuard aGuard2( *pMPostUserEvent );
222*b1cdbd2cSJim Jagielski 		nConnectionClosedEventId = GetpApp()->PostUserEvent( LINK( this, CommunicationLinkViaSocket, ConnectionClosed ) );
223*b1cdbd2cSJim Jagielski 	}
224*b1cdbd2cSJim Jagielski }
225*b1cdbd2cSJim Jagielski 
DoTransferDataStream(SvStream * pDataStream,CMProtocol nProtocol)226*b1cdbd2cSJim Jagielski sal_Bool CommunicationLinkViaSocket::DoTransferDataStream( SvStream *pDataStream, CMProtocol nProtocol )
227*b1cdbd2cSJim Jagielski {
228*b1cdbd2cSJim Jagielski 	if ( !isRunning() )
229*b1cdbd2cSJim Jagielski 		return sal_False;
230*b1cdbd2cSJim Jagielski 
231*b1cdbd2cSJim Jagielski 	return SimpleCommunicationLinkViaSocket::DoTransferDataStream( pDataStream, nProtocol );
232*b1cdbd2cSJim Jagielski }
233*b1cdbd2cSJim Jagielski 
234*b1cdbd2cSJim Jagielski /// Dies ist ein virtueller Link!!!
ConnectionClosed(void * EMPTYARG)235*b1cdbd2cSJim Jagielski long CommunicationLinkViaSocket::ConnectionClosed( void* EMPTYARG )
236*b1cdbd2cSJim Jagielski {
237*b1cdbd2cSJim Jagielski 	{
238*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMConnectionClosed );
239*b1cdbd2cSJim Jagielski 		nConnectionClosedEventId = 0;	// Achtung!! alles andere mu� oben gemacht werden.
240*b1cdbd2cSJim Jagielski 	}
241*b1cdbd2cSJim Jagielski 	ShutdownCommunication();
242*b1cdbd2cSJim Jagielski 	return CommunicationLink::ConnectionClosed( );
243*b1cdbd2cSJim Jagielski }
244*b1cdbd2cSJim Jagielski 
245*b1cdbd2cSJim Jagielski /// Dies ist ein virtueller Link!!!
DataReceived(void * EMPTYARG)246*b1cdbd2cSJim Jagielski long CommunicationLinkViaSocket::DataReceived( void* EMPTYARG )
247*b1cdbd2cSJim Jagielski {
248*b1cdbd2cSJim Jagielski 	{
249*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMDataReceived );
250*b1cdbd2cSJim Jagielski 		nDataReceivedEventId = 0;	// Achtung!! alles andere mu� oben gemacht werden.
251*b1cdbd2cSJim Jagielski 	}
252*b1cdbd2cSJim Jagielski 	return CommunicationLink::DataReceived( );
253*b1cdbd2cSJim Jagielski }
254*b1cdbd2cSJim Jagielski 
IMPL_LINK(CommunicationLinkViaSocket,PutDataReceivedHdl,CommunicationLinkViaSocket *,EMPTYARG)255*b1cdbd2cSJim Jagielski IMPL_LINK( CommunicationLinkViaSocket, PutDataReceivedHdl, CommunicationLinkViaSocket*, EMPTYARG )
256*b1cdbd2cSJim Jagielski {
257*b1cdbd2cSJim Jagielski     nDataReceivedEventId = GetpApp()->PostUserEvent( LINK( this, CommunicationLink, DataReceived ) );
258*b1cdbd2cSJim Jagielski     return 0;
259*b1cdbd2cSJim Jagielski }
260*b1cdbd2cSJim Jagielski 
261*b1cdbd2cSJim Jagielski 
262*b1cdbd2cSJim Jagielski 
MultiCommunicationManager(sal_Bool bUseMultiChannel)263*b1cdbd2cSJim Jagielski MultiCommunicationManager::MultiCommunicationManager( sal_Bool bUseMultiChannel )
264*b1cdbd2cSJim Jagielski : CommunicationManager( bUseMultiChannel )
265*b1cdbd2cSJim Jagielski , bGracefullShutdown( sal_True )
266*b1cdbd2cSJim Jagielski {
267*b1cdbd2cSJim Jagielski 	ActiveLinks = new CommunicationLinkList;
268*b1cdbd2cSJim Jagielski 	InactiveLinks = new CommunicationLinkList;
269*b1cdbd2cSJim Jagielski }
270*b1cdbd2cSJim Jagielski 
~MultiCommunicationManager()271*b1cdbd2cSJim Jagielski MultiCommunicationManager::~MultiCommunicationManager()
272*b1cdbd2cSJim Jagielski {
273*b1cdbd2cSJim Jagielski 	StopCommunication();
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski     if ( bGracefullShutdown )   // first try to collect all callbacks for closing channels
276*b1cdbd2cSJim Jagielski     {
277*b1cdbd2cSJim Jagielski         Timer aTimeout;
278*b1cdbd2cSJim Jagielski         aTimeout.SetTimeout( 40000 );
279*b1cdbd2cSJim Jagielski         aTimeout.Start();
280*b1cdbd2cSJim Jagielski         sal_uInt16 nLinkCount = 0;
281*b1cdbd2cSJim Jagielski         sal_uInt16 nNewLinkCount = 0;
282*b1cdbd2cSJim Jagielski         while ( aTimeout.IsActive() )
283*b1cdbd2cSJim Jagielski         {
284*b1cdbd2cSJim Jagielski             GetpApp()->Yield();
285*b1cdbd2cSJim Jagielski             nNewLinkCount = GetCommunicationLinkCount();
286*b1cdbd2cSJim Jagielski             if ( nNewLinkCount == 0 )
287*b1cdbd2cSJim Jagielski                 aTimeout.Stop();
288*b1cdbd2cSJim Jagielski             if ( nNewLinkCount != nLinkCount )
289*b1cdbd2cSJim Jagielski             {
290*b1cdbd2cSJim Jagielski                 aTimeout.Start();
291*b1cdbd2cSJim Jagielski                 nLinkCount = nNewLinkCount;
292*b1cdbd2cSJim Jagielski             }
293*b1cdbd2cSJim Jagielski         }
294*b1cdbd2cSJim Jagielski     }
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski 	// Alles weghauen, was nicht rechtzeitig auf die B�ume gekommen ist
297*b1cdbd2cSJim Jagielski 	// Was bei StopCommunication �brig geblieben ist, da es sich asynchron austragen wollte
298*b1cdbd2cSJim Jagielski 	sal_uInt16 i = ActiveLinks->Count();
299*b1cdbd2cSJim Jagielski 	while ( i-- )
300*b1cdbd2cSJim Jagielski 	{
301*b1cdbd2cSJim Jagielski 		CommunicationLinkRef rTempLink = ActiveLinks->GetObject( i );
302*b1cdbd2cSJim Jagielski 		ActiveLinks->Remove( i );
303*b1cdbd2cSJim Jagielski 		rTempLink->InvalidateManager();
304*b1cdbd2cSJim Jagielski 		rTempLink->ReleaseReference();
305*b1cdbd2cSJim Jagielski 	}
306*b1cdbd2cSJim Jagielski 	delete ActiveLinks;
307*b1cdbd2cSJim Jagielski 
308*b1cdbd2cSJim Jagielski 	/// Die Links zwischen ConnectionClosed und Destruktor.
309*b1cdbd2cSJim Jagielski 	/// Hier NICHT gerefcounted, da sie sich sonst im Kreis festhaten w�rden,
310*b1cdbd2cSJim Jagielski 	/// da die Links sich erst in ihrem Destruktor austragen
311*b1cdbd2cSJim Jagielski 	i = InactiveLinks->Count();
312*b1cdbd2cSJim Jagielski 	while ( i-- )
313*b1cdbd2cSJim Jagielski 	{
314*b1cdbd2cSJim Jagielski 		CommunicationLinkRef rTempLink = InactiveLinks->GetObject( i );
315*b1cdbd2cSJim Jagielski 		InactiveLinks->Remove( i );
316*b1cdbd2cSJim Jagielski 		rTempLink->InvalidateManager();
317*b1cdbd2cSJim Jagielski 	}
318*b1cdbd2cSJim Jagielski 	delete InactiveLinks;
319*b1cdbd2cSJim Jagielski }
320*b1cdbd2cSJim Jagielski 
StopCommunication()321*b1cdbd2cSJim Jagielski sal_Bool MultiCommunicationManager::StopCommunication()
322*b1cdbd2cSJim Jagielski {
323*b1cdbd2cSJim Jagielski 	// Alle Verbindungen abbrechen
324*b1cdbd2cSJim Jagielski 	// ConnectionClosed entfernt die Links aus der Liste. Je nach Implementation syncron
325*b1cdbd2cSJim Jagielski 	// oder asyncron. Daher Von oben nach unten Abr�umen, so da� sich nichts verschiebt.
326*b1cdbd2cSJim Jagielski 	sal_uInt16 i = ActiveLinks->Count();
327*b1cdbd2cSJim Jagielski 	int nFail = 0;
328*b1cdbd2cSJim Jagielski 	while ( i )
329*b1cdbd2cSJim Jagielski 	{
330*b1cdbd2cSJim Jagielski 		if ( !ActiveLinks->GetObject(i-1)->StopCommunication() )
331*b1cdbd2cSJim Jagielski             nFail++;    // Hochz�hlen, da Verbindung sich nicht (sofort) beenden l�sst.
332*b1cdbd2cSJim Jagielski 		i--;
333*b1cdbd2cSJim Jagielski 	}
334*b1cdbd2cSJim Jagielski 
335*b1cdbd2cSJim Jagielski 	return nFail == 0;
336*b1cdbd2cSJim Jagielski }
337*b1cdbd2cSJim Jagielski 
IsLinkValid(CommunicationLink * pCL)338*b1cdbd2cSJim Jagielski sal_Bool MultiCommunicationManager::IsLinkValid( CommunicationLink* pCL )
339*b1cdbd2cSJim Jagielski {
340*b1cdbd2cSJim Jagielski 	if ( ActiveLinks->Seek_Entry( pCL ) )
341*b1cdbd2cSJim Jagielski 		return sal_True;
342*b1cdbd2cSJim Jagielski 	else
343*b1cdbd2cSJim Jagielski 		return sal_False;
344*b1cdbd2cSJim Jagielski }
345*b1cdbd2cSJim Jagielski 
GetCommunicationLinkCount()346*b1cdbd2cSJim Jagielski sal_uInt16 MultiCommunicationManager::GetCommunicationLinkCount()
347*b1cdbd2cSJim Jagielski {
348*b1cdbd2cSJim Jagielski 	return ActiveLinks->Count();
349*b1cdbd2cSJim Jagielski }
350*b1cdbd2cSJim Jagielski 
GetCommunicationLink(sal_uInt16 nNr)351*b1cdbd2cSJim Jagielski CommunicationLinkRef MultiCommunicationManager::GetCommunicationLink( sal_uInt16 nNr )
352*b1cdbd2cSJim Jagielski {
353*b1cdbd2cSJim Jagielski 	return ActiveLinks->GetObject( nNr );
354*b1cdbd2cSJim Jagielski }
355*b1cdbd2cSJim Jagielski 
CallConnectionOpened(CommunicationLink * pCL)356*b1cdbd2cSJim Jagielski void MultiCommunicationManager::CallConnectionOpened( CommunicationLink* pCL )
357*b1cdbd2cSJim Jagielski {
358*b1cdbd2cSJim Jagielski 	CommunicationLinkRef rHold(pCL);	// H�lt den Zeiger bis zum Ende des calls
359*b1cdbd2cSJim Jagielski 	ActiveLinks->C40_PTR_INSERT(CommunicationLink, pCL);
360*b1cdbd2cSJim Jagielski 	rHold->AddRef();
361*b1cdbd2cSJim Jagielski 
362*b1cdbd2cSJim Jagielski 	CommunicationManager::CallConnectionOpened( pCL );
363*b1cdbd2cSJim Jagielski }
364*b1cdbd2cSJim Jagielski 
CallConnectionClosed(CommunicationLink * pCL)365*b1cdbd2cSJim Jagielski void MultiCommunicationManager::CallConnectionClosed( CommunicationLink* pCL )
366*b1cdbd2cSJim Jagielski {
367*b1cdbd2cSJim Jagielski 	CommunicationLinkRef rHold(pCL);	// H�lt denm Zeiger bis zum Ende des calls
368*b1cdbd2cSJim Jagielski 
369*b1cdbd2cSJim Jagielski 	CommunicationManager::CallConnectionClosed( pCL );
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski 	sal_uInt16 nPos;
372*b1cdbd2cSJim Jagielski 	if ( ActiveLinks->Seek_Entry( pCL, &nPos ) )
373*b1cdbd2cSJim Jagielski 	{
374*b1cdbd2cSJim Jagielski 		InactiveLinks->C40_PTR_INSERT(CommunicationLink, pCL);	// Ohne Reference
375*b1cdbd2cSJim Jagielski 		ActiveLinks->Remove( nPos );
376*b1cdbd2cSJim Jagielski 	}
377*b1cdbd2cSJim Jagielski 	pCL->ReleaseReference();
378*b1cdbd2cSJim Jagielski 
379*b1cdbd2cSJim Jagielski 	bIsCommunicationRunning = ActiveLinks->Count() > 0;
380*b1cdbd2cSJim Jagielski //	delete pCL;
381*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
382*b1cdbd2cSJim Jagielski         rHold->bFlag = sal_True;
383*b1cdbd2cSJim Jagielski #endif
384*b1cdbd2cSJim Jagielski }
385*b1cdbd2cSJim Jagielski 
DestroyingLink(CommunicationLink * pCL)386*b1cdbd2cSJim Jagielski void MultiCommunicationManager::DestroyingLink( CommunicationLink *pCL )
387*b1cdbd2cSJim Jagielski {
388*b1cdbd2cSJim Jagielski 	sal_uInt16 nPos;
389*b1cdbd2cSJim Jagielski 	if ( InactiveLinks->Seek_Entry( pCL, &nPos ) )
390*b1cdbd2cSJim Jagielski 		InactiveLinks->Remove( nPos );
391*b1cdbd2cSJim Jagielski 	pCL->InvalidateManager();
392*b1cdbd2cSJim Jagielski }
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski 
395*b1cdbd2cSJim Jagielski 
CommunicationManagerClient(sal_Bool bUseMultiChannel)396*b1cdbd2cSJim Jagielski CommunicationManagerClient::CommunicationManagerClient( sal_Bool bUseMultiChannel )
397*b1cdbd2cSJim Jagielski : MultiCommunicationManager( bUseMultiChannel )
398*b1cdbd2cSJim Jagielski {
399*b1cdbd2cSJim Jagielski 	ByteString aApplication("Something inside ");
400*b1cdbd2cSJim Jagielski 	aApplication.Append( ByteString( DirEntry( Application::GetAppFileName() ).GetName(), gsl_getSystemTextEncoding() ) );
401*b1cdbd2cSJim Jagielski     SetApplication( aApplication );
402*b1cdbd2cSJim Jagielski }
403*b1cdbd2cSJim Jagielski 
404*b1cdbd2cSJim Jagielski 
405*b1cdbd2cSJim Jagielski 
CommunicationManagerServerViaSocket(sal_uLong nPort,sal_uInt16 nMaxCon,sal_Bool bUseMultiChannel)406*b1cdbd2cSJim Jagielski CommunicationManagerServerViaSocket::CommunicationManagerServerViaSocket( sal_uLong nPort, sal_uInt16 nMaxCon, sal_Bool bUseMultiChannel )
407*b1cdbd2cSJim Jagielski : CommunicationManagerServer( bUseMultiChannel )
408*b1cdbd2cSJim Jagielski , nPortToListen( nPort )
409*b1cdbd2cSJim Jagielski , nMaxConnections( nMaxCon )
410*b1cdbd2cSJim Jagielski , pAcceptThread( NULL )
411*b1cdbd2cSJim Jagielski {
412*b1cdbd2cSJim Jagielski }
413*b1cdbd2cSJim Jagielski 
~CommunicationManagerServerViaSocket()414*b1cdbd2cSJim Jagielski CommunicationManagerServerViaSocket::~CommunicationManagerServerViaSocket()
415*b1cdbd2cSJim Jagielski {
416*b1cdbd2cSJim Jagielski 	StopCommunication();
417*b1cdbd2cSJim Jagielski }
418*b1cdbd2cSJim Jagielski 
StartCommunication()419*b1cdbd2cSJim Jagielski sal_Bool CommunicationManagerServerViaSocket::StartCommunication()
420*b1cdbd2cSJim Jagielski {
421*b1cdbd2cSJim Jagielski 	if ( !pAcceptThread )
422*b1cdbd2cSJim Jagielski 		pAcceptThread = new CommunicationManagerServerAcceptThread( this, nPortToListen, nMaxConnections );
423*b1cdbd2cSJim Jagielski 	return sal_True;
424*b1cdbd2cSJim Jagielski }
425*b1cdbd2cSJim Jagielski 
426*b1cdbd2cSJim Jagielski 
StopCommunication()427*b1cdbd2cSJim Jagielski sal_Bool CommunicationManagerServerViaSocket::StopCommunication()
428*b1cdbd2cSJim Jagielski {
429*b1cdbd2cSJim Jagielski 	// Erst den Acceptor anhalten
430*b1cdbd2cSJim Jagielski 	delete pAcceptThread;
431*b1cdbd2cSJim Jagielski 	pAcceptThread = NULL;
432*b1cdbd2cSJim Jagielski 
433*b1cdbd2cSJim Jagielski 	// Dann alle Verbindungen kappen
434*b1cdbd2cSJim Jagielski 	return CommunicationManagerServer::StopCommunication();
435*b1cdbd2cSJim Jagielski }
436*b1cdbd2cSJim Jagielski 
437*b1cdbd2cSJim Jagielski 
AddConnection(CommunicationLink * pNewConnection)438*b1cdbd2cSJim Jagielski void CommunicationManagerServerViaSocket::AddConnection( CommunicationLink *pNewConnection )
439*b1cdbd2cSJim Jagielski {
440*b1cdbd2cSJim Jagielski 	CallConnectionOpened( pNewConnection );
441*b1cdbd2cSJim Jagielski }
442*b1cdbd2cSJim Jagielski 
443*b1cdbd2cSJim Jagielski 
CommunicationManagerServerAcceptThread(CommunicationManagerServerViaSocket * pServer,sal_uLong nPort,sal_uInt16 nMaxCon)444*b1cdbd2cSJim Jagielski CommunicationManagerServerAcceptThread::CommunicationManagerServerAcceptThread( CommunicationManagerServerViaSocket* pServer, sal_uLong nPort, sal_uInt16 nMaxCon )
445*b1cdbd2cSJim Jagielski : pMyServer( pServer )
446*b1cdbd2cSJim Jagielski , pAcceptorSocket( NULL )
447*b1cdbd2cSJim Jagielski , nPortToListen( nPort )
448*b1cdbd2cSJim Jagielski , nMaxConnections( nMaxCon )
449*b1cdbd2cSJim Jagielski , nAddConnectionEventId( 0 )
450*b1cdbd2cSJim Jagielski , xmNewConnection( NULL )
451*b1cdbd2cSJim Jagielski {
452*b1cdbd2cSJim Jagielski     if ( !pMPostUserEvent )
453*b1cdbd2cSJim Jagielski         pMPostUserEvent = new vos::OMutex;
454*b1cdbd2cSJim Jagielski 	create();
455*b1cdbd2cSJim Jagielski }
456*b1cdbd2cSJim Jagielski 
457*b1cdbd2cSJim Jagielski 
~CommunicationManagerServerAcceptThread()458*b1cdbd2cSJim Jagielski CommunicationManagerServerAcceptThread::~CommunicationManagerServerAcceptThread()
459*b1cdbd2cSJim Jagielski {
460*b1cdbd2cSJim Jagielski #ifndef aUNX		// Weil das Accept nicht abgebrochen werden kann, so terminiert wenigstens das Prog
461*b1cdbd2cSJim Jagielski 	// #62855# pl: gilt auch bei anderen Unixen
462*b1cdbd2cSJim Jagielski 	// die richtige Loesung waere natuerlich, etwas auf die pipe zu schreiben,
463*b1cdbd2cSJim Jagielski 	// was der thread als Abbruchbedingung erkennt
464*b1cdbd2cSJim Jagielski 	// oder wenigstens ein kill anstatt join
465*b1cdbd2cSJim Jagielski 	terminate();
466*b1cdbd2cSJim Jagielski 	if ( pAcceptorSocket )
467*b1cdbd2cSJim Jagielski 		pAcceptorSocket->close();	// Dann das Accept unterbrechen
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski 	join();		// Warten bis fertig
470*b1cdbd2cSJim Jagielski 
471*b1cdbd2cSJim Jagielski 	if ( pAcceptorSocket )
472*b1cdbd2cSJim Jagielski 	{
473*b1cdbd2cSJim Jagielski 		delete pAcceptorSocket;
474*b1cdbd2cSJim Jagielski 		pAcceptorSocket = NULL;
475*b1cdbd2cSJim Jagielski 	}
476*b1cdbd2cSJim Jagielski #else
477*b1cdbd2cSJim Jagielski 	DEBUGPRINTF ("Destructor CommunicationManagerServerAcceptThread �bersprungen!!!! (wegen Solaris BUG)\n");
478*b1cdbd2cSJim Jagielski #endif
479*b1cdbd2cSJim Jagielski 	{
480*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMAddConnection );
481*b1cdbd2cSJim Jagielski 		if ( nAddConnectionEventId )
482*b1cdbd2cSJim Jagielski 		{
483*b1cdbd2cSJim Jagielski 			GetpApp()->RemoveUserEvent( nAddConnectionEventId );
484*b1cdbd2cSJim Jagielski 			nAddConnectionEventId = 0;
485*b1cdbd2cSJim Jagielski 			CommunicationLinkRef xNewConnection = GetNewConnection();
486*b1cdbd2cSJim Jagielski 			INFO_MSG( CByteString("Event gel�scht"),
487*b1cdbd2cSJim Jagielski 				CByteString( "AddConnectionEvent aus Queue gel�scht"),
488*b1cdbd2cSJim Jagielski 				CM_MISC, xNewConnection );
489*b1cdbd2cSJim Jagielski 			xNewConnection->InvalidateManager();
490*b1cdbd2cSJim Jagielski 			xNewConnection.Clear();	// sollte das Objekt hier l�schen
491*b1cdbd2cSJim Jagielski 		}
492*b1cdbd2cSJim Jagielski 	}
493*b1cdbd2cSJim Jagielski }
494*b1cdbd2cSJim Jagielski 
run()495*b1cdbd2cSJim Jagielski void CommunicationManagerServerAcceptThread::run()
496*b1cdbd2cSJim Jagielski {
497*b1cdbd2cSJim Jagielski 	if ( !nPortToListen )
498*b1cdbd2cSJim Jagielski 		return;
499*b1cdbd2cSJim Jagielski 
500*b1cdbd2cSJim Jagielski 	pAcceptorSocket = new vos::OAcceptorSocket();
501*b1cdbd2cSJim Jagielski 	vos::OInetSocketAddr Addr;
502*b1cdbd2cSJim Jagielski 	Addr.setPort( nPortToListen );
503*b1cdbd2cSJim Jagielski 	pAcceptorSocket->setReuseAddr( 1 );
504*b1cdbd2cSJim Jagielski 	if ( !pAcceptorSocket->bind( Addr ) )
505*b1cdbd2cSJim Jagielski 	{
506*b1cdbd2cSJim Jagielski 		return;
507*b1cdbd2cSJim Jagielski 	}
508*b1cdbd2cSJim Jagielski 	if ( !pAcceptorSocket->listen( nMaxConnections ) )
509*b1cdbd2cSJim Jagielski 	{
510*b1cdbd2cSJim Jagielski 		return;
511*b1cdbd2cSJim Jagielski 	}
512*b1cdbd2cSJim Jagielski 
513*b1cdbd2cSJim Jagielski 
514*b1cdbd2cSJim Jagielski 	vos::OStreamSocket *pStreamSocket = NULL;
515*b1cdbd2cSJim Jagielski 
516*b1cdbd2cSJim Jagielski 	while ( schedule() )
517*b1cdbd2cSJim Jagielski 	{
518*b1cdbd2cSJim Jagielski 		pStreamSocket = new vos::OStreamSocket;
519*b1cdbd2cSJim Jagielski 		switch ( pAcceptorSocket->acceptConnection( *pStreamSocket ) )
520*b1cdbd2cSJim Jagielski 		{
521*b1cdbd2cSJim Jagielski 		case vos::ISocketTypes::TResult_Ok:
522*b1cdbd2cSJim Jagielski 			{
523*b1cdbd2cSJim Jagielski 				pStreamSocket->setTcpNoDelay( 1 );
524*b1cdbd2cSJim Jagielski 
525*b1cdbd2cSJim Jagielski 				TimeValue sNochEins = {0, 100};
526*b1cdbd2cSJim Jagielski 				while ( schedule() && xmNewConnection.Is() )	// Solange die letzte Connection nicht abgeholt wurde warten wir
527*b1cdbd2cSJim Jagielski 					sleep( sNochEins );
528*b1cdbd2cSJim Jagielski 				xmNewConnection = new CommunicationLinkViaSocket( pMyServer, pStreamSocket );
529*b1cdbd2cSJim Jagielski 				xmNewConnection->StartCallback();
530*b1cdbd2cSJim Jagielski 				{
531*b1cdbd2cSJim Jagielski 					vos::OGuard aGuard( aMAddConnection );
532*b1cdbd2cSJim Jagielski                     vos::OGuard aGuard2( *pMPostUserEvent );
533*b1cdbd2cSJim Jagielski 					nAddConnectionEventId = GetpApp()->PostUserEvent( LINK( this, CommunicationManagerServerAcceptThread, AddConnection ) );
534*b1cdbd2cSJim Jagielski 				}
535*b1cdbd2cSJim Jagielski 			}
536*b1cdbd2cSJim Jagielski 			break;
537*b1cdbd2cSJim Jagielski 		case vos::ISocketTypes::TResult_TimedOut:
538*b1cdbd2cSJim Jagielski 			delete pStreamSocket;
539*b1cdbd2cSJim Jagielski 			pStreamSocket = NULL;
540*b1cdbd2cSJim Jagielski 			break;
541*b1cdbd2cSJim Jagielski 		case vos::ISocketTypes::TResult_Error:
542*b1cdbd2cSJim Jagielski 			delete pStreamSocket;
543*b1cdbd2cSJim Jagielski 			pStreamSocket = NULL;
544*b1cdbd2cSJim Jagielski 			break;
545*b1cdbd2cSJim Jagielski 
546*b1cdbd2cSJim Jagielski 		case vos::ISocketTypes::TResult_Interrupted:
547*b1cdbd2cSJim Jagielski 		case vos::ISocketTypes::TResult_InProgress:
548*b1cdbd2cSJim Jagielski 			break;  // -Wall not handled...
549*b1cdbd2cSJim Jagielski 		}
550*b1cdbd2cSJim Jagielski 	}
551*b1cdbd2cSJim Jagielski }
552*b1cdbd2cSJim Jagielski 
553*b1cdbd2cSJim Jagielski 
IMPL_LINK(CommunicationManagerServerAcceptThread,AddConnection,void *,EMPTYARG)554*b1cdbd2cSJim Jagielski IMPL_LINK( CommunicationManagerServerAcceptThread, AddConnection, void*, EMPTYARG )
555*b1cdbd2cSJim Jagielski {
556*b1cdbd2cSJim Jagielski 	{
557*b1cdbd2cSJim Jagielski 		vos::OGuard aGuard( aMAddConnection );
558*b1cdbd2cSJim Jagielski 		nAddConnectionEventId = 0;
559*b1cdbd2cSJim Jagielski 	}
560*b1cdbd2cSJim Jagielski 	pMyServer->AddConnection( xmNewConnection );
561*b1cdbd2cSJim Jagielski 	xmNewConnection.Clear();
562*b1cdbd2cSJim Jagielski 	return 1;
563*b1cdbd2cSJim Jagielski }
564*b1cdbd2cSJim Jagielski 
565*b1cdbd2cSJim Jagielski 
566*b1cdbd2cSJim Jagielski #define GETSET(aVar, KeyName, Dafault)                 \
567*b1cdbd2cSJim Jagielski 	aVar = aConf.ReadKey(KeyName,"No Entry");          \
568*b1cdbd2cSJim Jagielski 	if ( aVar == "No Entry" )                          \
569*b1cdbd2cSJim Jagielski 	{                                                  \
570*b1cdbd2cSJim Jagielski 		aVar = Dafault;                                \
571*b1cdbd2cSJim Jagielski 		aConf.WriteKey(KeyName, aVar);                 \
572*b1cdbd2cSJim Jagielski 	}
573*b1cdbd2cSJim Jagielski 
574*b1cdbd2cSJim Jagielski 
CommunicationManagerClientViaSocket(ByteString aHost,sal_uLong nPort,sal_Bool bUseMultiChannel)575*b1cdbd2cSJim Jagielski CommunicationManagerClientViaSocket::CommunicationManagerClientViaSocket( ByteString aHost, sal_uLong nPort, sal_Bool bUseMultiChannel )
576*b1cdbd2cSJim Jagielski : CommunicationManagerClient( bUseMultiChannel )
577*b1cdbd2cSJim Jagielski , aHostToTalk( aHost )
578*b1cdbd2cSJim Jagielski , nPortToTalk( nPort )
579*b1cdbd2cSJim Jagielski {
580*b1cdbd2cSJim Jagielski }
581*b1cdbd2cSJim Jagielski 
CommunicationManagerClientViaSocket(sal_Bool bUseMultiChannel)582*b1cdbd2cSJim Jagielski CommunicationManagerClientViaSocket::CommunicationManagerClientViaSocket( sal_Bool bUseMultiChannel )
583*b1cdbd2cSJim Jagielski : CommunicationManagerClient( bUseMultiChannel )
584*b1cdbd2cSJim Jagielski , aHostToTalk( "" )
585*b1cdbd2cSJim Jagielski , nPortToTalk( 0 )
586*b1cdbd2cSJim Jagielski {
587*b1cdbd2cSJim Jagielski }
588*b1cdbd2cSJim Jagielski 
~CommunicationManagerClientViaSocket()589*b1cdbd2cSJim Jagielski CommunicationManagerClientViaSocket::~CommunicationManagerClientViaSocket()
590*b1cdbd2cSJim Jagielski {
591*b1cdbd2cSJim Jagielski }
592*b1cdbd2cSJim Jagielski 
593*b1cdbd2cSJim Jagielski 
594