7 IdTCPServer
, IdTCPClient
, IdTunnelCommon
,
11 // TIdTunnelMaster = object(TObj);
12 //PIdTunnelMaster=^TIdTunnelMaster; type MyStupid0=DWord;
14 MClientThread
= object(TThread
)
16 MasterParent
: PObj
;//TIdTunnelMaster;
18 MasterThread
: TIdPeerThread
;
19 OutboundClient
: TIdTCPClient
;
20 DisconnectedOnRequest
: Boolean;
21 Locker
: TCriticalSection
;
22 SelfDisconnected
: Boolean;
23 // procedure Execute; virtual;
26 { constructor Create(master: TIdTunnelMaster);
29 PMClientThread
=^MClientThread
;
30 function NewMClientThread(master
: PObj
{TIdTunnelMaster}):PMClientThread
;
33 TSlaveData
= object(TObj
)
37 Locker
: TCriticalSection
;
38 SelfDisconnected
: Boolean;
41 PSlaveData
=^TSlaveData
;
42 function NewSlaveData
:PSlaveData
;
45 TSendMsgEvent
= procedure(Thread
: TIdPeerThread
; var CustomMsg
: string) of
47 TSendTrnEvent
= procedure(Thread
: TIdPeerThread
; var Header
: TIdHeader
; var
48 CustomMsg
: string) of object;
49 TSendTrnEventC
= procedure(var Header
: TIdHeader
; var CustomMsg
: string) of
51 TTunnelEventC
= procedure(Receiver
: TReceiver
) of object;
52 TSendMsgEventC
= procedure(var CustomMsg
: string) of object;
54 TIdTunnelMaster
= object(TIdTCPServer
)
56 fiMappedPort
: Integer;
58 // Clients: TThreadList;
61 fOnTransformRead: TIdServerThreadEvent;}
62 fOnTransformSend
: TSendTrnEvent
;
63 fOnInterpretMsg
: TSendMsgEvent
;
64 OnlyOneThread
: TCriticalSection
;
66 StatisticsLocker
: TCriticalSection
;
68 fbLockDestinationHost
: Boolean;
69 fbLockDestinationPort
: Boolean;
74 fNumberOfConnectionsValue
,
75 fNumberOfPacketsValue
,
76 fCompressionRatioValue
,
80 procedure ClientOperation(Operation
: Integer; UserId
: Integer; s
: string);
81 procedure SendMsg(MasterThread
: TIdPeerThread
; var Header
: TIdHeader
; s
:
83 procedure DisconectAllUsers
;
84 procedure DisconnectAllSubThreads(TunnelThread
: TIdPeerThread
);
85 function GetNumSlaves
: Integer;
86 function GetNumServices
: Integer;
87 function GetClientThread(UserID
: Integer): MClientThread
;
89 procedure SetActive(pbValue
: Boolean); virtual;//override;
90 procedure DoConnect(Thread
: TIdPeerThread
); virtual;//override;
91 procedure DoDisconnect(Thread
: TIdPeerThread
);virtual;// override;
92 function DoExecute(Thread
: TIdPeerThread
): boolean; virtual;//override;
93 procedure DoTransformRead(Thread
: TIdPeerThread
); virtual;
94 procedure DoTransformSend(Thread
: TIdPeerThread
; var Header
: TIdHeader
; var
97 procedure DoInterpretMsg(Thread
: TIdPeerThread
; var CustomMsg
: string);
99 procedure LogEvent(Msg
: string);
101 property MappedHost
: string read fsMappedHost write fsMappedHost
;
102 property MappedPort
: Integer read fiMappedPort write fiMappedPort
;
103 property LockDestinationHost
: Boolean read fbLockDestinationHost write
104 fbLockDestinationHost
106 property LockDestinationPort
: Boolean read fbLockDestinationPort write
107 fbLockDestinationPort
109 property OnConnect
: TIdServerThreadEvent read FOnConnect write FOnConnect
;
110 property OnDisconnect
: TIdServerThreadEvent read FOnDisconnect write
112 // property OnTransformRead: TIdServerThreadEvent read fOnTransformRead write
114 property OnTransformSend
: TSendTrnEvent read fOnTransformSend write
116 property OnInterpretMsg
: TSendMsgEvent read fOnInterpretMsg write
119 property Active
: Boolean read FbActive write SetActive default
True;
120 property Logger
: TLogger read fLogger write fLogger
;
121 property NumSlaves
: Integer read GetNumSlaves
;
122 property NumServices
: Integer read GetNumServices
;
123 procedure SetStatistics(Module
: Integer; Value
: Integer);
124 procedure GetStatistics(Module
: Integer; var Value
: Integer);
125 // constructor Create(AOwner: TComponent); override;
126 destructor Destroy
; virtual;//override;
129 PIdTunnelMaster
=^TIdTunnelMaster
;
131 function NewIdTunnelMaster(AOwner
: PControl
):PIdTunnelMaster
;
134 uses {KOL, IdException,}
135 IdGlobal
, IdStack
, IdResourceStrings
, SysUtils
;
137 { constructor TIdTunnelMaster.Create(AOwner: TComponent);
139 function NewIdTunnelMaster (AOwner
: PControl
):PIdTunnelMaster
;
141 New( Result
, Create
);
144 { Clients := TThreadList.Create;
145 inherited Create(AOwner);
147 flConnectedSlaves := 0;
148 flConnectedServices := 0;
150 fNumberOfConnectionsValue := 0;
151 fNumberOfPacketsValue := 0;
152 fCompressionRatioValue := 0;
153 fCompressedBytes := 0;
157 OnlyOneThread := TCriticalSection.Create;
158 StatisticsLocker := TCriticalSection.Create;}
162 destructor TIdTunnelMaster
.Destroy
;
172 StatisticsLocker
.Free
;
175 procedure TIdTunnelMaster
.SetActive(pbValue
: Boolean);
178 if fbActive
= pbValue
then
183 inherited SetActive(True);
187 inherited SetActive(False);
195 procedure TIdTunnelMaster
.LogEvent(Msg
: string);
197 // if Assigned(fLogger) then
198 // fLogger.LogEvent(Msg);
201 function TIdTunnelMaster
.GetNumSlaves
: Integer;
205 GetStatistics(NumberOfSlavesType
, ClientsNo
);
209 function TIdTunnelMaster
.GetNumServices
: Integer;
213 GetStatistics(NumberOfServicesType
, ClientsNo
);
217 procedure TIdTunnelMaster
.GetStatistics(Module
: Integer; var Value
: Integer);
219 StatisticsLocker
.Enter
;
224 Value
:= flConnectedSlaves
;
227 NumberOfServicesType
:
229 Value
:= flConnectedServices
;
232 NumberOfConnectionsType
:
234 Value
:= fNumberOfConnectionsValue
;
239 Value
:= fNumberOfPacketsValue
;
242 CompressionRatioType
:
244 if fCompressedBytes
> 0 then
246 Value
:= Trunc((fBytesRead
* 1.0) / (fCompressedBytes
* 1.0) * 100.0)
256 Value
:= fCompressedBytes
;
266 Value
:= fBytesWrite
;
270 StatisticsLocker
.Leave
;
274 procedure TIdTunnelMaster
.SetStatistics(Module
: Integer; Value
: Integer);
279 StatisticsLocker
.Enter
;
284 if TIdStatisticsOperation(Value
) = soIncrease
then
286 Inc(flConnectedSlaves
);
290 Dec(flConnectedSlaves
);
294 NumberOfServicesType
:
296 if TIdStatisticsOperation(Value
) = soIncrease
then
298 Inc(flConnectedServices
);
299 Inc(fNumberOfConnectionsValue
);
303 Dec(flConnectedServices
);
307 NumberOfConnectionsType
:
309 Inc(fNumberOfConnectionsValue
);
314 Inc(fNumberOfPacketsValue
);
317 CompressionRatioType
:
319 ratio
:= fCompressionRatioValue
;
320 packets
:= fNumberOfPacketsValue
;
321 ratio
:= (ratio
/ 100.0 * (packets
- 1.0) + Value
/ 100.0) / packets
;
322 fCompressionRatioValue
:= Trunc(ratio
* 100);
327 fCompressedBytes
:= fCompressedBytes
+ Value
;
332 fBytesRead
:= fBytesRead
+ Value
;
337 fBytesWrite
:= fBytesWrite
+ Value
;
341 StatisticsLocker
.Leave
;
345 procedure TIdTunnelMaster
.DoConnect(Thread
: TIdPeerThread
);
348 // Thread.Data := TSlaveData.Create;
349 { with TSlaveData(Thread.Data) do
351 Receiver := TReceiver.Create;
352 Sender := TSender.Create;
353 SelfDisconnected := False;
354 Locker := TCriticalSection.Create;
356 if Assigned(OnConnect) then
360 SetStatistics(NumberOfSlavesType, Integer(soIncrease));
364 procedure TIdTunnelMaster
.DoDisconnect(Thread
: TIdPeerThread
);
367 SetStatistics(NumberOfSlavesType
, Integer(soDecrease
));
368 DisconnectAllSubThreads(Thread
);
369 if Thread
.Connection
.Connected
then
370 Thread
.Connection
.Disconnect
;
372 if Assigned(OnDisconnect
) then
374 OnDisconnect(Thread
);
377 { with TSlaveData(Thread.Data) do
382 TSlaveData(Thread.Data).Free;
388 function TIdTunnelMaster
.DoExecute(Thread
: TIdPeerThread
): boolean;
391 clientThread
: MClientThread
;
393 ErrorConnecting
: Boolean;
400 // user := TSlaveData(Thread.Data);
401 { if Thread.Connection.Binding.Readable(IdTimeoutInfinite) then
403 user.receiver.Data := Thread.Connection.CurrentReadBuffer;
405 SetStatistics(NumberOfPacketsType, 0);
407 while user.receiver.TypeDetected do
409 if not (user.receiver.Header.MsgType in [tmData, tmDisconnect, tmConnect,
412 Thread.Connection.Disconnect;
416 if user.receiver.NewMessage then
418 if user.Receiver.CRCFailed then
420 Thread.Connection.Disconnect;
425 DoTransformRead(Thread);
427 Thread.Connection.Disconnect;
431 case user.Receiver.Header.MsgType of
435 Thread.Connection.Disconnect;
445 SetString(s, user.Receiver.Msg, user.Receiver.MsgLen);
446 ClientOperation(tmData, user.Receiver.Header.UserId, s);
455 ClientOperation(tmDisconnect, user.Receiver.Header.UserId, '');
464 clientThread := MClientThread.Create(self);
466 ErrorConnecting := False;
469 UserId := user.Receiver.Header.UserId;
470 MasterThread := Thread;
471 OutboundClient := TIdTCPClient.Create(nil);
472 sIP := GStack.TInAddrToString(user.Receiver.Header.IpAddr);
473 if fbLockDestinationHost then
475 OutboundClient.Host := fsMappedHost;
476 if fbLockDestinationPort then
477 OutboundClient.Port := fiMappedPort
479 OutboundClient.Port := user.Receiver.Header.Port;
483 if sIP = '0.0.0.0' then
485 OutboundClient.Host := fsMappedHost;
486 OutboundClient.Port := user.Receiver.Header.Port;
490 OutboundClient.Host := sIP;
491 OutboundClient.Port := user.Receiver.Header.Port;
494 OutboundClient.Connect;
497 ErrorConnecting := True;
499 if ErrorConnecting then
501 clientThread.Destroy;
516 DoInterpretMsg(Thread, CustomMsg);
517 if Length(CustomMsg) > 0 then
519 Header.MsgType := tmCustom;
521 SendMsg(Thread, Header, CustomMsg);
527 user.Receiver.ShiftData;
537 procedure TIdTunnelMaster
.DoTransformRead(Thread
: TIdPeerThread
);
540 // if Assigned(fOnTransformRead) then
541 // fOnTransformRead(Thread);
545 procedure TIdTunnelMaster
.DoTransformSend(Thread
: TIdPeerThread
; var Header
:
546 TIdHeader
; var CustomMsg
: string);
549 if Assigned(fOnTransformSend
) then
550 fOnTransformSend(Thread
, Header
, CustomMsg
);
554 procedure TIdTunnelMaster
.DoInterpretMsg(Thread
: TIdPeerThread
; var CustomMsg
:
558 if Assigned(fOnInterpretMsg
) then
559 fOnInterpretMsg(Thread
, CustomMsg
);
563 procedure TIdTunnelMaster
.DisconnectAllSubThreads(TunnelThread
: TIdPeerThread
);
565 Thread
: MClientThread
;
570 { OnlyOneThread.Enter;
571 listTemp := Clients.LockList;
573 for i := 0 to listTemp.count - 1 do
575 if Assigned(listTemp[i]) then
577 Thread := MClientThread(listTemp[i]);
578 if Thread.MasterThread = TunnelThread then
580 Thread.DisconnectedOnRequest := True;
581 Thread.OutboundClient.Disconnect;
592 procedure TIdTunnelMaster
.SendMsg(MasterThread
: TIdPeerThread
; var Header
:
593 TIdHeader
; s
: string);
599 { if Assigned(MasterThread.Data) then
602 TSlaveData(MasterThread.Data).Locker.Enter;
604 user := TSlaveData(MasterThread.Data);
608 DoTransformSend(MasterThread, Header, tmpString);
613 EIdTunnelTransformErrorBeforeSend.Create(RSTunnelTransformErrorBS);
616 if Header.MsgType = tmError then
617 begin // error ocured in transformation
619 EIdTunnelTransformErrorBeforeSend.Create(RSTunnelTransformErrorBS);
622 user.Sender.PrepareMsg(Header, PChar(@tmpString[1]), Length(tmpString));
623 MasterThread.Connection.Write(user.Sender.Msg);
628 TSlaveData(MasterThread.Data).Locker.Leave;
634 function TIdTunnelMaster
.GetClientThread(UserID
: Integer): MClientThread
;
636 Thread
: MClientThread
;
641 { with Clients.LockList do
643 for i := 0 to Count - 1 do
646 if Assigned(Items[i]) then
648 Thread := MClientThread(Items[i]);
649 if Thread.UserId = UserID then
665 procedure TIdTunnelMaster
.DisconectAllUsers
;
670 procedure TIdTunnelMaster
.ClientOperation(Operation
: Integer; UserId
: Integer;
673 Thread
: MClientThread
;
676 Thread
:= GetClientThread(UserID
);
677 { if Assigned(Thread) then
681 if not Thread.SelfDisconnected then
687 Thread.OutboundClient.CheckForDisconnect;
688 if Thread.OutboundClient.Connected then
689 Thread.OutboundClient.Write(s);
692 Thread.OutboundClient.Disconnect;
701 Thread.DisconnectedOnRequest := True;
703 Thread.OutboundClient.Disconnect;
719 { constructor MClientThread.Create(master: TIdTunnelMaster);
721 function NewClientThread (master
: TIdTunnelMaster
):PMClientThread
;
723 New( Result
, Create
);
726 // MasterParent := master;
727 // FreeOnTerminate := True;
728 DisconnectedOnRequest
:= False;
729 SelfDisconnected
:= False;
730 Locker
:= TCriticalSection
.Create
;
731 // MasterParent.Clients.Add(self);
732 master
.SetStatistics(NumberOfServicesType
, Integer(soIncrease
));
734 // inherited Create(True);
738 destructor MClientThread
.Destroy
;
743 // MasterParent.SetStatistics(NumberOfServicesType, Integer(soDecrease));
745 // MasterParent.Clients.Remove(self);
747 if not DisconnectedOnRequest
then
750 Header
.MsgType
:= tmDisconnect
;
751 Header
.UserId
:= UserId
;
752 // MasterParent.SendMsg(MasterThread, Header, RSTunnelDisconnectMsg);
758 if OutboundClient
.Connected
then
759 OutboundClient
.Disconnect
;
765 // MasterThread := nil;
780 {procedure MClientThread.Execute;
786 while not Terminated do
789 if OutboundClient.Connected then
791 if OutboundClient.Binding.Readable(IdTimeoutInfinite) then
793 s := OutboundClient.CurrentReadBuffer;
795 Header.MsgType := tmData;
796 Header.UserId := UserId;
797 MasterParent.SendMsg(MasterThread, Header, s);
817 SelfDisconnected := True;
824 function NewMClientThread(master
: PObj
{TIdTunnelMaster}):PMClientThread
;
826 New( Result
, Create
);
829 function NewSlaveData
:PSlaveData
;
831 New( Result
, Create
);