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, IdCoderMIME, 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;
51 FOnSlppEvent: TIdSlppEvent;
52 FOnConnect: TNotifyEvent;
53 FOnDisconnect: TNotifyEvent;
56 FOnConnectFailed: TNotifyEvent;
57 procedure SetDebugMode(const Value: boolean);
58 procedure SetLUID(const Value: String);
59 procedure SetOnSlppEvent(const Value: TIdSlppEvent);
60 procedure SetProxyMode(const Value: boolean);
61 procedure SetProxyUser(const Value: String);
62 procedure SetProxyPass(const Value: String);
63 procedure SetOnConnect(const Value: TNotifyEvent);
64 procedure SetOnDisconnect(const Value: TNotifyEvent);
65 function GetLastReadTimeInterval: integer;
66 procedure SetLastReadTime(const Value: Int64);
67 procedure SetOnConnectFailed(const Value: TNotifyEvent);
69 constructor Create(AOwner: TComponent); override;
70 destructor Destroy; override;
71 procedure Connect(const ATimeout: Integer = IdTimeoutDefault); override;
72 procedure ConnectServer(const ATimeout: Integer = IdTimeoutDefault);
73 procedure Disconnect; override;
74 procedure DoOnSlppEvent;
75 procedure DoOnConnect;
76 procedure DoOnConnectFailed;
77 property SLPP20ReadThread: TIdSLPP20ReadThread read FSLPPThread;
78 property LastReadTime: Int64 read FLastReadTime write SetLastReadTime;
79 property LastReadTimeInterval: integer read GetLastReadTimeInterval;
81 property LUID: String read FLUID write SetLUID;
82 property Port default SLPP_PORT;
83 property DebugMode: boolean read FDebugMode write SetDebugMode;
84 property ProxyMode: boolean read FProxyMode write SetProxyMode;
85 property ProxyUser: String read FProxyUser write SetProxyUser;
86 property ProxyPass: String read FProxyPass write SetProxyPass;
87 property OnConnect: TNotifyEvent read FOnConnect write SetOnConnect;
88 property OnConnectFailed: TNotifyEvent read FOnConnectFailed write SetOnConnectFailed;
89 property OnDisconnect: TNotifyEvent read FOnDisconnect write SetOnDisconnect;
90 property OnSLPPEvent: TIdSlppEvent read FOnSlppEvent write SetOnSlppEvent;
91 {ProxyMode = true
\82Ì
\82Æ
\82«
\82Í
\81AHost, Port
\82É
\83v
\83\8d\83L
\83V
\96¼
\82ð}
94 EIdSlppError = class(EIdException);
95 EIdSlppClientConnectError = class(EIdSlppError);
103 RegisterComponents('Indy Clients', [TIdSLPP20]);
108 procedure TIdSLPP20.Connect(const ATimeout: Integer);
110 inherited Connect(ATimeout);
113 procedure TIdSLPP20.ConnectServer;
116 FTimeout := ATimeout;
117 FSLPPThread := TIdSLPP20ReadThread.Create(self);
118 except on E: EIdSocketError do
119 raise EIdSlppClientConnectError.Create('Connection Failed');
123 constructor TIdSLPP20.Create(AOwner: TComponent);
125 inherited Create(AOwner);
132 destructor TIdSLPP20.Destroy;
137 procedure TIdSLPP20.Disconnect;
139 inherited Disconnect;
140 if Assigned(FSLPPThread) then begin
141 FSLPPThread.Terminate;
142 // FSLPPThread.WaitFor;
145 if Assigned(FOnDisconnect) then begin
150 procedure TIdSLPP20.DoOnConnect;
152 if Assigned(FOnConnect) then
156 procedure TIdSLPP20.DoOnConnectFailed;
158 if Assigned(FOnConnectFailed) then
159 FOnConnectFailed(self);
162 procedure TIdSLPP20.DoOnSlppEvent;
165 FOnSlppEvent(self, FSLPPThread.FEvent, FSLPPThread.FParam);
168 ShowMessage('Exception occured in OnSlppEvent: '#13#10 + E.Message);
172 function TIdSLPP20.GetLastReadTimeInterval: integer;
175 if Connected then Result := GetTickCount - FLastReadTime;
178 procedure TIdSLPP20.SetDebugMode(const Value: boolean);
183 procedure TIdSLPP20.SetLastReadTime(const Value: Int64);
185 FLastReadTime := Value;
188 procedure TIdSLPP20.SetLUID(const Value: String);
193 procedure TIdSLPP20.SetOnConnect(const Value: TNotifyEvent);
198 procedure TIdSLPP20.SetOnConnectFailed(const Value: TNotifyEvent);
200 FOnConnectFailed := Value;
203 procedure TIdSLPP20.SetOnDisconnect(const Value: TNotifyEvent);
205 FOnDisconnect := Value;
208 procedure TIdSLPP20.SetOnSlppEvent(const Value: TIdSlppEvent);
210 FOnSlppEvent := Value;
213 procedure TIdSLPP20.SetProxyMode(const Value: boolean);
218 procedure TIdSLPP20.SetProxyUser(const Value: String);
223 procedure TIdSLPP20.SetProxyPass(const Value: String);
228 { TIdSLPP20ReadThread }
230 constructor TIdSLPP20ReadThread.Create(AClient: TIdSLPP20);
232 inherited Create(true);
234 FreeOnTerminate := true;
238 procedure TIdSLPP20ReadThread.Execute;
240 EncodedPassword,PlainPassword: String;
241 Base64Encoder: TIdEncoderMIME;
244 FClient.Connect(FClient.FTimeout);
245 if Assigned(FClient.OnConnect) then begin
246 Synchronize(FClient.DoOnConnect);
249 Synchronize(FClient.DoOnConnectFailed);
253 EncodedPassword := '';
254 if FClient.ProxyUser <> '' then begin
255 if FClient.ProxyPass <> '' then begin
256 PlainPassword := FClient.ProxyUser + ':' + FClient.ProxyPass;
257 Base64Encoder.Create(nil);
258 EncodedPassword := Base64Encoder.Encode(PlainPassword);
259 FreeAndNil(Base64Encoder);
263 FRecvData := TStringList.Create;
264 FReceivedLog := TStringList.Create;
265 if FClient.ProxyMode then begin
266 FClient.Writeln('POST http://bottle.mikage.to:9871/ HTTP/1.0');
267 FClient.Writeln('Content-Length: ' + IntToStr(Length(FClient.LUID)));
268 FClient.Writeln('Connection: close');
270 if EncodedPassword <> '' then begin
271 FClient.Writeln('Proxy-Authorization: Basic ' + EncodedPassword);
275 FClient.Writeln(FClient.LUID);
277 FClient.WriteLn('POST / HTTP/1.0');
279 FClient.WriteLn(FClient.LUID);
281 while not Terminated do begin
283 FClient.CheckForDisconnect;
284 Line := FClient.ReadLn(EOL);
285 if FClient.DebugMode then begin
286 FReceivedLog.Add(Line);
287 FReceivedLog.SaveToFile(ExtractFilePath(Application.ExeName)+'slpp20_debug.log');
289 if not FClient.ReadLnTimedOut then FClient.LastReadTime := getTickCount;
290 if Length(Line) = 0 then begin
291 if FRecvData.Count > 0 then begin
292 FClient.CheckForDisconnect; //
\90Ø
\92f
\8cã
\82Ì
\92\86\93r
\94¼
\92[
\82È
\83f
\81[
\83^
\91\97\90M
\82ð
\96h
\82®
294 Synchronize(FClient.DoOnSlppEvent);
302 on EIdException do begin
303 Synchronize(self.Terminate);
308 if ( FClient.Connected ) then FClient.Disconnect;
309 FreeAndNil(FReceivedLog);
310 FreeAndNil(FRecvData);
313 function TIdSLPP20ReadThread.Parse: boolean;
317 //
\8dÅ
\92á
\8cÀ
\83R
\83}
\83\93\83h
\8ds+1
\82Í
\82È
\82¢
\82Æ
\83_
\83\81 - 2
\88È
\8fã
318 if FRecvData.Count <= 1 then begin
323 command := FRecvData[0];
325 FParam := FRecvData.Text;
328 if command = 'broadcastMessage' then begin
330 end else if command = 'allUsers' then begin
331 FEvent := etMemberCount;
332 end else if command = 'channelUsers' then begin
333 FEvent := etChannelCount;
334 end else if command = 'channelList' then begin
335 FEvent := etChannelList;
336 end else if (command = 'HTTP/1.0 200 OK') or (command = 'HTTP/1.1 200 OK') then begin
337 FEvent := etConnectOk;
338 end else if command = 'forceBroadcastMessage' then begin
339 FEvent := etForceBroadcast;
340 end else if command = 'forceBroadcastInformation' then begin
341 FEvent := etForceBroadcastInformation;
342 end else if command = 'BroadcastInformation' then begin
343 FEvent := etBroadcastInformation;
344 end else if command = 'closeChannel' then begin
345 FEvent := etCloseChannel;
346 end else if command = 'unicastMessage' then begin
348 end else Result := false;