1 {*******************************************************}
2 { IdSLPP20 - Indy Client for SLPP Connection }
4 { Copyright (c) 2002-2003 naruto/CANO-Lab }
5 {*******************************************************}
12 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
13 IdTCPClient, IdGlobal, IdException;
17 SLPP_HOST = 'bottle.mikage.to';
20 TIdSLPPEventType = (etConnectOk, etScript, etMemberCount, etChannelCount,
21 etChannelList, etUnicast, etForceBroadcast, etCloseChannel,
22 etForceBroadcastInformation, etBroadcastInformation);
23 TIdSLPPEvent = procedure (Sender: TObject;
24 EventType: TIdSlppEventType; const Param: String) of Object;
28 TIdSLPP20ReadThread = class(TThread)
32 FRecvData: TStringList;
33 FEvent: TIdSLPPEventType; // SLPP Command
34 FParam: String; // SLPP Command Parameter
35 FReceivedLog: TStringList;
36 function Parse: boolean;
37 procedure Execute; override;
39 constructor Create(AClient: TIdSLPP20); reintroduce;
40 property Client: TIdSLPP20 read FClient;
43 TIdSLPP20 = class(TIdTCPClient)
45 FSLPPThread: TIdSLPP20ReadThread;
49 FOnSlppEvent: TIdSlppEvent;
50 FOnConnect: TNotifyEvent;
51 FOnDisconnect: TNotifyEvent;
54 FOnConnectFailed: TNotifyEvent;
55 procedure SetDebugMode(const Value: boolean);
56 procedure SetLUID(const Value: String);
57 procedure SetOnSlppEvent(const Value: TIdSlppEvent);
58 procedure SetProxyMode(const Value: boolean);
59 procedure SetOnConnect(const Value: TNotifyEvent);
60 procedure SetOnDisconnect(const Value: TNotifyEvent);
61 function GetLastReadTimeInterval: integer;
62 procedure SetLastReadTime(const Value: Int64);
63 procedure SetOnConnectFailed(const Value: TNotifyEvent);
65 constructor Create(AOwner: TComponent); override;
66 destructor Destroy; override;
67 procedure Connect(const ATimeout: Integer = IdTimeoutDefault); override;
68 procedure ConnectServer(const ATimeout: Integer = IdTimeoutDefault);
69 procedure Disconnect; override;
70 procedure DoOnSlppEvent;
71 procedure DoOnConnect;
72 procedure DoOnConnectFailed;
73 property SLPP20ReadThread: TIdSLPP20ReadThread read FSLPPThread;
74 property LastReadTime: Int64 read FLastReadTime write SetLastReadTime;
75 property LastReadTimeInterval: integer read GetLastReadTimeInterval;
77 property LUID: String read FLUID write SetLUID;
78 property Port default SLPP_PORT;
79 property DebugMode: boolean read FDebugMode write SetDebugMode;
80 property ProxyMode: boolean read FProxyMode write SetProxyMode;
81 property OnConnect: TNotifyEvent read FOnConnect write SetOnConnect;
82 property OnConnectFailed: TNotifyEvent read FOnConnectFailed write SetOnConnectFailed;
83 property OnDisconnect: TNotifyEvent read FOnDisconnect write SetOnDisconnect;
84 property OnSLPPEvent: TIdSlppEvent read FOnSlppEvent write SetOnSlppEvent;
85 {ProxyMode = true
\82Ì
\82Æ
\82«
\82Í
\81AHost, Port
\82É
\83v
\83\8d\83L
\83V
\96¼
\82ð}
88 EIdSlppError = class(EIdException);
89 EIdSlppClientConnectError = class(EIdSlppError);
97 RegisterComponents('Indy Clients', [TIdSLPP20]);
102 procedure TIdSLPP20.Connect(const ATimeout: Integer);
104 inherited Connect(ATimeout);
107 procedure TIdSLPP20.ConnectServer;
110 FTimeout := ATimeout;
111 FSLPPThread := TIdSLPP20ReadThread.Create(self);
112 except on E: EIdSocketError do
113 raise EIdSlppClientConnectError.Create('Connection Failed');
117 constructor TIdSLPP20.Create(AOwner: TComponent);
119 inherited Create(AOwner);
124 destructor TIdSLPP20.Destroy;
129 procedure TIdSLPP20.Disconnect;
131 inherited Disconnect;
132 if Assigned(FSLPPThread) then begin
133 FSLPPThread.Terminate;
134 // FSLPPThread.WaitFor;
137 if Assigned(FOnDisconnect) then begin
142 procedure TIdSLPP20.DoOnConnect;
144 if Assigned(FOnConnect) then
148 procedure TIdSLPP20.DoOnConnectFailed;
150 if Assigned(FOnConnectFailed) then
151 FOnConnectFailed(self);
154 procedure TIdSLPP20.DoOnSlppEvent;
157 FOnSlppEvent(self, FSLPPThread.FEvent, FSLPPThread.FParam);
160 ShowMessage('Exception occured in OnSlppEvent: '#13#10 + E.Message);
164 function TIdSLPP20.GetLastReadTimeInterval: integer;
167 if Connected then Result := GetTickCount - FLastReadTime;
170 procedure TIdSLPP20.SetDebugMode(const Value: boolean);
175 procedure TIdSLPP20.SetLastReadTime(const Value: Int64);
177 FLastReadTime := Value;
180 procedure TIdSLPP20.SetLUID(const Value: String);
185 procedure TIdSLPP20.SetOnConnect(const Value: TNotifyEvent);
190 procedure TIdSLPP20.SetOnConnectFailed(const Value: TNotifyEvent);
192 FOnConnectFailed := Value;
195 procedure TIdSLPP20.SetOnDisconnect(const Value: TNotifyEvent);
197 FOnDisconnect := Value;
200 procedure TIdSLPP20.SetOnSlppEvent(const Value: TIdSlppEvent);
202 FOnSlppEvent := Value;
205 procedure TIdSLPP20.SetProxyMode(const Value: boolean);
210 { TIdSLPP20ReadThread }
212 constructor TIdSLPP20ReadThread.Create(AClient: TIdSLPP20);
214 inherited Create(true);
216 FreeOnTerminate := true;
220 procedure TIdSLPP20ReadThread.Execute;
224 FClient.Connect(FClient.FTimeout);
225 if Assigned(FClient.OnConnect) then begin
226 Synchronize(FClient.DoOnConnect);
229 Synchronize(FClient.DoOnConnectFailed);
233 FRecvData := TStringList.Create;
234 FReceivedLog := TStringList.Create;
235 if FClient.ProxyMode then begin
236 FClient.Writeln('POST http://bottle.mikage.to:9871/ HTTP/1.0');
237 FClient.Writeln('Content-Length: ' + IntToStr(Length(FClient.LUID)));
238 FClient.Writeln('Connection: close');
240 FClient.Writeln(FClient.LUID);
242 FClient.WriteLn('POST / HTTP/1.0');
244 FClient.WriteLn(FClient.LUID);
246 while not Terminated do begin
248 FClient.CheckForDisconnect;
249 Line := FClient.ReadLn(EOL);
250 if FClient.DebugMode then begin
251 FReceivedLog.Add(Line);
252 FReceivedLog.SaveToFile(ExtractFilePath(Application.ExeName)+'slpp20_debug.log');
254 if not FClient.ReadLnTimedOut then FClient.LastReadTime := getTickCount;
255 if Length(Line) = 0 then begin
256 if FRecvData.Count > 0 then begin
258 Synchronize(FClient.DoOnSlppEvent);
266 on EIdException do begin
267 Synchronize(self.Terminate);
271 FreeAndNil(FReceivedLog);
272 FreeAndNil(FRecvData);
275 function TIdSLPP20ReadThread.Parse: boolean;
279 command := FRecvData[0];
281 FParam := FRecvData.Text;
284 if command = 'broadcastMessage' then begin
286 end else if command = 'allUsers' then begin
287 FEvent := etMemberCount;
288 end else if command = 'channelUsers' then begin
289 FEvent := etChannelCount;
290 end else if command = 'channelList' then begin
291 FEvent := etChannelList;
292 end else if (command = 'HTTP/1.0 200 OK') or (command = 'HTTP/1.1 200 OK') then begin
293 FEvent := etConnectOk;
294 end else if command = 'forceBroadcastMessage' then begin
295 FEvent := etForceBroadcast;
296 end else if command = 'forceBroadcastInformation' then begin
297 FEvent := etForceBroadcastInformation;
298 end else if command = 'BroadcastInformation' then begin
299 FEvent := etBroadcastInformation;
300 end else if command = 'closeChannel' then begin
301 FEvent := etCloseChannel;
302 end else if command = 'unicastMessage' then begin
304 end else Result := false;