1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef _SIMPLECM_HXX
24 #define _SIMPLECM_HXX
25 
26 #include <tools/link.hxx>
27 #include <tools/string.hxx>
28 #include <tools/stream.hxx>
29 #include <vos/socket.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/datetime.hxx>
32 
33 #include <automation/commdefines.hxx>
34 
35 // CM steht f�r CommunicationManager
36 #define CM_UNLIMITED_CONNECTIONS	0xffff
37 
38 typedef sal_uInt16 CM_NameType;
39 #define CM_DOTTED	( (CM_NameType) 01 )
40 #define CM_FQDN		( (CM_NameType) 02 )
41 
42 typedef sal_uInt16 CM_InfoType;
43 // nur eines dieser 3 defines darf verwendet werden
44 #define CM_NO_TEXT		( (CM_InfoType) 01 )
45 #define CM_SHORT_TEXT	( (CM_InfoType) 02 )
46 #define CM_VERBOSE_TEXT	( (CM_InfoType) 03 )
47 
48 #define CM_OPEN			( (CM_InfoType) 0x0004 )
49 #define CM_CLOSE		( (CM_InfoType) 0x0008 )
50 #define CM_RECEIVE		( (CM_InfoType) 0x0010 )
51 #define CM_SEND			( (CM_InfoType) 0x0020 )
52 #define CM_ERROR		( (CM_InfoType) 0x0040 )
53 #define CM_MISC			( (CM_InfoType) 0x0080 )
54 
55 #define CM_USER_1		( (CM_InfoType) 0x0100 )
56 #define CM_USER_2		( (CM_InfoType) 0x0200 )
57 #define CM_USER_3		( (CM_InfoType) 0x0400 )
58 #define CM_USER_4		( (CM_InfoType) 0x0800 )
59 
60 #define CM_ALL			( CM_OPEN | CM_CLOSE | CM_RECEIVE | CM_SEND | CM_ERROR | CM_MISC )
61 #define CM_NONE			( 0 )
62 
63 #define CByteString( constAsciiStr ) ByteString( RTL_CONSTASCII_STRINGPARAM ( constAsciiStr ) )
64 
65 #define INFO_MSG( Short, Long, Type, CLink ) \
66 { \
67 	if ( (Type & GetInfoType()) > 0 ) \
68 	{ \
69 		switch ( GetInfoType() & 03 ) \
70 		{ \
71 		    case CM_NO_TEXT: \
72                 { \
73        		        ByteString aByteString; \
74         	        CallInfoMsg( InfoString( aByteString, Type, CLink ) ); \
75                 } \
76 	            break; \
77 		    case CM_SHORT_TEXT: \
78                 { \
79        		        ByteString aByteString( Short ); \
80 	                CallInfoMsg( InfoString( aByteString, Type, CLink ) ); \
81                 } \
82 	            break; \
83 		    case CM_VERBOSE_TEXT: \
84                 { \
85        		        ByteString aByteString( Long ); \
86 	                CallInfoMsg( InfoString( aByteString, Type, CLink ) ); \
87                 } \
88 	            break; \
89     		default: \
90     	        break; \
91 		} \
92 	} \
93 }\
94 
95 class CommunicationLink;
96 
97 /*#undef  PRV_SV_DECL_REF_LOCK
98 #define PRV_SV_DECL_REF_LOCK(ClassName, Ref)	\
99 protected:										\
100     ClassName * pObj;							\
101 public:											\
102 PRV_SV_DECL_REF_SIGNATURE(ClassName, Ref)		\
103     inline               ClassName##Ref( void * pObjP ){ClassName##Ref ((ClassName *) pObjP);}			\
104 */
105 
106 SV_DECL_REF( CommunicationLink )
107 
108 class InfoString : public ByteString
109 {
110 public:
InfoString(ByteString & nMsg,CM_InfoType nIT,CommunicationLink * pCL=NULL)111 	InfoString( ByteString &nMsg, CM_InfoType nIT, CommunicationLink *pCL = NULL ): ByteString( nMsg ), nInfoType( nIT ), pCommLink( pCL ) {;}
GetInfoType()112 	CM_InfoType GetInfoType(){ return nInfoType; }
GetCommunicationLink()113 	CommunicationLinkRef GetCommunicationLink(){ return pCommLink; }
114 private:
115 	CM_InfoType nInfoType;
116 	CommunicationLinkRef pCommLink;
117 };
118 
119 class PacketHandler;
120 class CommunicationManager;
121 class SingleCommunicationManager;
122 class MultiCommunicationManager;
123 class CommunicationManagerServerAcceptThread;
124 class CommunicationLink : public SvRefBase
125 {
126 protected:
127 	friend class CommunicationManager;
128 	friend class SingleCommunicationManager;
129 	friend class MultiCommunicationManager;
130 	friend class CommunicationManagerServerAcceptThread;
131 	// Darf nicht abger�umt werden zwischen Empfang des Streams und ende des Callbacks
132 
133 protected:	// so da� nur �ber Ref gel�scht werden kann
134 	virtual ~CommunicationLink();
InvalidateManager()135 	void InvalidateManager() { pMyManager = NULL; }
136 
137 	PacketHandler* pPacketHandler;
138 
139 public:
140 	CommunicationLink( CommunicationManager *pMan );
141 
142 	virtual sal_Bool StopCommunication()=0;
143 	virtual sal_Bool IsCommunicationError()=0;
GetCommunicationManager()144 	CommunicationManager* GetCommunicationManager(){ return pMyManager; }
145 
146 //	Der Name oder die IP-Adresse oder sonstwas um den Communikationspartner zu identifizieren
147 	virtual ByteString GetCommunicationPartner( CM_NameType eType )=0;
148 
149 //	Der Name oder die IP-Adresse oder sonstwas um den Communikationspartner zu identifizieren
150 	virtual ByteString GetMyName( CM_NameType eType )=0;
151 
152 //	Liefert einen neuen Stream zum Versenden von Daten.
153 	virtual SvStream* GetBestCommunicationStream()=0;
154 
155 	/** will call virtual function DoTransferDataStream to do actual work
156 		Purpos is to allow housekeeping
157 	**/
158 	sal_Bool TransferDataStream( SvStream *pDataStream, CMProtocol nProtocol = CM_PROTOCOL_OLDSTYLE );
159 
160 	// Liefert die ID, die vom Sender angegeben wurde.
161 	// Dadurch lassen sich virtuelle Kommunikationen �ber einen physikalischen Link realisiren.
162 	// Da die Kommunikation zu �lteren Versionen kompatibel bleiben mu�, mu� der Empf�nger raten,
163 	// die neue oder die alte verwendet wird, da sich der Kopf eines Auftrages dann �ndert.
GetProtocol()164 	sal_uInt16 GetProtocol(){ return nServiceProtocol; }
165 
166 	// Der Stream wird hier �bergeben. Der Aufrufer ist f�r dessen L�schung zust�ndig
167 	// Die Methode MUSS gerufen werden, da sonst keine weiteren Daten empfangen werden.
GetServiceData()168 	SvStream* GetServiceData(){ SvStream *pTemp = pServiceData; pServiceData = NULL; return pTemp; }
169 
170 	/// Erm�glicht das Ausl�sen des n�chsten Callbacks. Wird auch Implizit gerufen.
FinishCallback()171 	void FinishCallback(){ bIsInsideCallback = sal_False; }
172 
173 	/// Syncrones Empfangen der Daten. Nur f�r Kommandozeile, sonst leer implementiert
ReceiveDataStream()174 	virtual sal_Bool ReceiveDataStream(){ return sal_False; }
175 
176 	/// Statistics
GetStart()177 	DateTime GetStart() { return aStart; }
GetTotalBytes()178 	sal_uLong GetTotalBytes() { return nTotalBytes; }
GetLastAccess()179 	DateTime GetLastAccess() { return aLastAccess; }
GetApplication()180 	const ByteString& GetApplication() { return maApplication; }
181 	virtual void SetApplication( const ByteString& aApp );
182 
183 protected:
184 	void CallInfoMsg( InfoString aMsg );
185 	CM_InfoType GetInfoType();
186 	CommunicationManager *pMyManager;
187 // Diese Methoden werden im Main Kontext gerufen und an den Manager weitergereicht.
188 	virtual DECL_LINK( ConnectionClosed, void* = NULL );
189     virtual DECL_LINK( DataReceived, void* = NULL );
190 
191 	virtual sal_Bool DoTransferDataStream( SvStream *pDataStream, CMProtocol nProtocol = CM_PROTOCOL_OLDSTYLE );
192 
193 	SvStream *pServiceData;
194 	sal_uInt16 nServiceProtocol;
195 	sal_uInt16 nServiceHeaderType;
196 
197 	/// Verhindert das vorzeitige Ausl�sen des n�chsten Callbacks.
StartCallback()198 	void StartCallback(){ bIsInsideCallback = sal_True; }
199 	sal_Bool bIsInsideCallback;
200 
201 	virtual sal_Bool SendHandshake( HandshakeType aHandshakeType, SvStream* pData = NULL)=0;
202 
203 	virtual sal_Bool ShutdownCommunication() = 0;	/// Really stop the Communication
204 
205 	/// Statistics
206 	DateTime aStart;
207 	sal_uLong nTotalBytes;
208 	DateTime aLastAccess;
209 
210 private:
211     ByteString maApplication;
212 
213 #if OSL_DEBUG_LEVEL > 1
214 public:
215     // misc (debuging) purposes
216     sal_Bool bFlag;
217     sal_uLong nSomething;
218 #endif
219 
220 };
221 
222 SV_IMPL_REF( CommunicationLink );
223 
224 class CommonSocketFunctions;
225 class CommunicationManager
226 {
227     friend class CommunicationLink;
228 	friend class CommonSocketFunctions;
229 public:
230 	CommunicationManager( sal_Bool bUseMultiChannel = sal_False );
231 	virtual ~CommunicationManager();
232 
233 	virtual sal_Bool StartCommunication()=0;
234 	virtual sal_Bool StartCommunication( String aApp, String aParams );
235 	virtual sal_Bool StartCommunication( ByteString aHost, sal_uLong nPort );
236 	virtual sal_Bool StopCommunication()=0;		// H�lt alle CommunicationLinks an
IsCommunicationRunning()237 	virtual sal_Bool IsCommunicationRunning() { return bIsCommunicationRunning; }
238 //	virtual sal_Bool IsCommunicationError();
239 
240 //	Der Name oder die IP-Adresse oder sonstwas um den Communikationspartner zu identifizieren
241 	virtual ByteString GetMyName( CM_NameType eType );
242 
243 	virtual sal_Bool IsLinkValid( CommunicationLink* pCL )=0;	// Notwendig f�r call im Destruktor
244 
245 	virtual sal_uInt16 GetCommunicationLinkCount()=0;
246 	virtual CommunicationLinkRef GetCommunicationLink( sal_uInt16 nNr )=0;
247 
248 	// Liefert den letzten neuen Link oder NULL wenn dieser schon wieder geschlossen ist.
GetLastNewLink()249 	CommunicationLinkRef GetLastNewLink() { return xLastNewLink; }
250 
SetConnectionOpenedHdl(Link lConnectionOpened)251 	void SetConnectionOpenedHdl( Link lConnectionOpened ){ mlConnectionOpened = lConnectionOpened; }
SetConnectionClosedHdl(Link lConnectionClosed)252 	void SetConnectionClosedHdl( Link lConnectionClosed ){ mlConnectionClosed = lConnectionClosed; }
SetDataReceivedHdl(Link lDataReceived)253 	void SetDataReceivedHdl( Link lDataReceived ){ mlDataReceived = lDataReceived; }
SetInfoMsgHdl(Link lInfoMsg)254 	void SetInfoMsgHdl( Link lInfoMsg ){ mlInfoMsg = lInfoMsg; }
255 
SetInfoType(CM_InfoType nIT)256 	void SetInfoType( CM_InfoType nIT ){ nInfoType = nIT; }
GetInfoType()257 	CM_InfoType GetInfoType(){ return nInfoType; }
258 
IsMultiChannel()259 	sal_Bool IsMultiChannel(){ return bIsMultiChannel; }
260 	void SetApplication( const ByteString& aApp, sal_Bool bRunningLinks = sal_False );
GetApplication()261 	const ByteString& GetApplication() { return maApplication; }
262 
263 protected:
264 	// Diese Methoden werden innerhalb gerufen. Sie erledigen eventuelles Housekeeping
265 	// und rufen dann die entsprechende Methode
266 	virtual void CallConnectionOpened( CommunicationLink* pCL );
267 	virtual void CallConnectionClosed( CommunicationLink* pCL );
268 	void CallDataReceived( CommunicationLink* pCL );
269 	void CallInfoMsg( InfoString aMsg );
270 
271 	CM_InfoType nInfoType;
272 
273 	// 	Diese Routinen rufen den Link oder sind �berladen
ConnectionOpened(CommunicationLink * pCL)274 	virtual void ConnectionOpened( CommunicationLink* pCL ){ mlConnectionOpened.Call( pCL ); }
ConnectionClosed(CommunicationLink * pCL)275 	virtual void ConnectionClosed( CommunicationLink* pCL ){ mlConnectionClosed.Call( pCL ); }
DataReceived(CommunicationLink * pCL)276 	virtual void DataReceived( CommunicationLink* pCL ){ mlDataReceived.Call( pCL ); }
InfoMsg(InfoString aMsg)277 	virtual void InfoMsg( InfoString aMsg ){ mlInfoMsg.Call( &aMsg ); }
278 
279 	sal_Bool bIsCommunicationRunning;
280 
281 	virtual void DestroyingLink( CommunicationLink *pCL )=0;	// Link tr�gt sich im Destruktor aus
282 
283 private:
284 	ByteString maApplication;
285 	Link mlConnectionOpened;
286 	Link mlConnectionClosed;
287 	Link mlDataReceived;
288 	Link mlInfoMsg;
289 	CommunicationLinkRef xLastNewLink;
290 
291 	sal_Bool bIsMultiChannel;
292 };
293 
294 class SingleCommunicationManager : public CommunicationManager
295 {
296 public:
297 	SingleCommunicationManager( sal_Bool bUseMultiChannel = sal_False );
298 	virtual ~SingleCommunicationManager();
299 	virtual sal_Bool StopCommunication();		// H�lt alle CommunicationLinks an
300 	virtual sal_Bool IsLinkValid( CommunicationLink* pCL );
301 	virtual sal_uInt16 GetCommunicationLinkCount();
302 	virtual CommunicationLinkRef GetCommunicationLink( sal_uInt16 nNr );
303 
304 protected:
305 	virtual void CallConnectionOpened( CommunicationLink* pCL );
306 	virtual void CallConnectionClosed( CommunicationLink* pCL );
307 	CommunicationLinkRef xActiveLink;
308 	CommunicationLink *pInactiveLink;
309 	virtual void DestroyingLink( CommunicationLink *pCL );	// Link tr�gt sich im Destruktor aus
310 };
311 
312 class ICommunicationManagerClient
313 {
314 	friend class CommonSocketFunctions;
315 protected:
RetryConnect()316 	virtual sal_Bool RetryConnect() { return sal_False; }	// Kann dann eventuell die Applikation starten
317 };
318 
319 class TCPIO;
320 class SimpleCommunicationLinkViaSocket : public CommunicationLink
321 {
322 public:
323 	virtual sal_Bool IsCommunicationError();
324 	virtual sal_Bool StopCommunication();
325 
326 	virtual ByteString GetCommunicationPartner( CM_NameType eType );
327 	virtual ByteString GetMyName( CM_NameType eType );
328 	virtual SvStream* GetBestCommunicationStream();
329 	virtual void SetApplication( const ByteString& aApp );
330 
331 private:
332 	ByteString aCommunicationPartner;
333 	ByteString aMyName;
334 
335 	TCPIO* pTCPIO;
336 	vos::OStreamSocket *pStreamSocket;
337 
338 protected:
339 	SimpleCommunicationLinkViaSocket( CommunicationManager *pMan, vos::OStreamSocket *pSocket );
340 	virtual ~SimpleCommunicationLinkViaSocket();
341 
GetStreamSocket()342     vos::OStreamSocket* GetStreamSocket() { return pStreamSocket; }
343     void SetStreamSocket( vos::OStreamSocket* pSocket );
344 
345 	SvStream *pReceiveStream;
346 	sal_Bool DoReceiveDataStream();				/// Recieve DataPacket from Socket
347 	virtual sal_Bool SendHandshake( HandshakeType aHandshakeType, SvStream* pData = NULL);
348 	void SetFinalRecieveTimeout();
349 	sal_Bool bIsRequestShutdownPending;
350 	virtual void WaitForShutdown()=0;
351 	void SetNewPacketAsCurrent();
352 };
353 
354 class SimpleCommunicationLinkViaSocketWithReceiveCallbacks : public SimpleCommunicationLinkViaSocket
355 {
356 public:
357 	SimpleCommunicationLinkViaSocketWithReceiveCallbacks( CommunicationManager *pMan, vos::OStreamSocket *pSocket );
358 	~SimpleCommunicationLinkViaSocketWithReceiveCallbacks();
359 	virtual sal_Bool ReceiveDataStream();
360 protected:
361 	virtual sal_Bool ShutdownCommunication();	/// Really stop the Communication
362 	virtual void WaitForShutdown();
363 };
364 
365 class CommonSocketFunctions
366 {
367 public:
368 	sal_Bool DoStartCommunication( CommunicationManager *pCM, ICommunicationManagerClient *pCMC, ByteString aHost, sal_uLong nPort );
369 protected:
370 	virtual CommunicationLink *CreateCommunicationLink( CommunicationManager *pCM, vos::OConnectorSocket *pCS )=0;
371 };
372 
373 class SingleCommunicationManagerClientViaSocket : public SingleCommunicationManager, public ICommunicationManagerClient, CommonSocketFunctions
374 {
375 public:
376     using CommunicationManager::StartCommunication;
377 
378 	SingleCommunicationManagerClientViaSocket( ByteString aHost, sal_uLong nPort, sal_Bool bUseMultiChannel = sal_False );
379 	SingleCommunicationManagerClientViaSocket( sal_Bool bUseMultiChannel = sal_False );
StartCommunication()380 	virtual sal_Bool StartCommunication(){ return DoStartCommunication( this, (ICommunicationManagerClient*) this, aHostToTalk, nPortToTalk );}
StartCommunication(ByteString aHost,sal_uLong nPort)381 	virtual sal_Bool StartCommunication( ByteString aHost, sal_uLong nPort ){ return DoStartCommunication( this, (ICommunicationManagerClient*) this, aHost, nPort );}
382 private:
383 	ByteString aHostToTalk;
384 	sal_uLong nPortToTalk;
385 protected:
CreateCommunicationLink(CommunicationManager * pCM,vos::OConnectorSocket * pCS)386 	virtual CommunicationLink *CreateCommunicationLink( CommunicationManager *pCM, vos::OConnectorSocket *pCS ){ return new SimpleCommunicationLinkViaSocketWithReceiveCallbacks( pCM, pCS ); }
387 };
388 
389 #endif
390