3 (*
\95Ê
\83X
\83\8c\83b
\83h
\82ÅSSTP
\83T
\81[
\83o
\82ÆDirectSSTP
\82ð
\92Ê
\82¶
\82Ä
\92Ê
\90M
\82·
\82é *)
7 uses Classes, Contnrs, SyncObjs, Windows, Logs, SysUtils, Controls, Forms,
8 Messages, BottleDef, SakuraSeekerInstance, Dialogs;
27 TBottleSstpResendEvent = procedure(Sender: TObject; MID: String) of object;
29 TBottleSstp = class(TThread)
32 FTargetSetName: String;
33 FProcessBottle: TLogItem;
34 FDirectSstpResult: String;
35 FSentLog: TStringList;
36 FRecvLog: TStringList;
37 FCueLock: TCriticalSection;
38 FCue: TObjectList; //
\83X
\83\8c\83b
\83h
\83Z
\81[
\83t
\82É
\82È
\82é
\82æ
\82¤
\82É
\92\8d\88Ó
40 FOnResendCountChange: TNotifyEvent;
41 FOnResendTrying: TBottleSstpResendEvent;
42 FOnResendEnd: TBottleSstpResendEvent;
43 FLastTickCount: Int64;
44 FResendSleep: boolean;
45 function GetCueCount: integer;
46 procedure SetOnResendCountChange(const Value: TNotifyEvent);
47 procedure SetOnResendEnd(const Value: TBottleSstpResendEvent);
48 procedure SetOnResendTrying(const Value: TBottleSstpResendEvent);
49 procedure SetResendSleep(const Value: boolean);
51 function ConnectSstp(Source: TStrings): TBottleSstpResult;
52 procedure WndProc(var Msg: TMessage);
53 function ExtractCode(const CodeStr: String): integer;
54 function CodeToStatus(const Code: integer): TBottleSstpResult;
55 procedure DetectTargetHWND;
56 procedure DoOnResendCountChange;
57 procedure DoOnResendTrying;
58 procedure DoOnResendEnd;
60 constructor Create(CreateSuspended: boolean);
61 destructor Destroy; override;
62 procedure Execute; override;
63 procedure Push(Bottle: TLogItem); //
\8dÄ
\91\97\83o
\83b
\83t
\83@
\82Ì
\8dÅ
\8cã
\82É
\92Ç
\89Á(
\95\81\92Ê)
64 procedure Unshift(Bottle: TLogItem); //
\8dÄ
\91\97\83o
\83b
\83t
\83@
\82Ì
\90æ
\93ª
\82É
\92Ç
\89Á
65 procedure Clear; //
\8dÄ
\91\97\83o
\83b
\83t
\83@
\82ð
\83N
\83\8a\83A
66 property ResendSleep: boolean read FResendSleep write SetResendSleep;
67 property CueCount: integer read GetCueCount;
68 property OnResendCountChange: TNotifyEvent read FOnResendCountChange write SetOnResendCountChange;
69 property OnResendEnd: TBottleSstpResendEvent read FOnResendEnd write SetOnResendEnd;
70 property OnResendTrying: TBottleSstpResendEvent read FOnResendTrying write SetOnResendTrying;
76 //
\82±
\82Ì
\83G
\83\89\81[
\82Í
\81ASSTP
\83T
\81[
\83o
\82ª
\83X
\83e
\81[
\83^
\83X
\82ð
\95Ô
\82³
\82¸
\82É
\90Ø
\92f
\82µ
\82½
\82Æ
\82«
\82È
\82Ç
\82É
\95Ô
\82é
81 procedure TBottleSstp.Clear;
89 Synchronize(DoOnResendCountChange);
92 function TBottleSstp.CodeToStatus(const Code: integer): TBottleSstpResult;
96 204: Result := srNoContent;
97 210: Result := srBreak;
98 400: Result := srBadRequest;
99 408: Result := srRequestTimeout;
100 409: Result := srConflict;
101 420: Result := srRefuse;
102 501: Result := srNotImplemented;
103 503: Result := srServiceUnavailable;
104 504: Result := srNotLocalIP;
105 541: Result := srInBlackList;
106 512: Result := srInvisible;
108 Result := srUnknownError;
112 function TBottleSstp.ConnectSstp(Source: TStrings): TBottleSstpResult;
113 var Mes: TCopyDataStruct;
115 Dummy: DWORD; //SendMessageTimeout
\97p
118 Result := srUnknownError;
120 if FTargetHWnd <> 0 then begin
121 MesStr := Source.Text;
123 Mes.cbData := Length(MesStr);
124 Mes.lpData := PChar(MesStr);
125 FDirectSstpResult := '';
126 //FSentLog.Text := MesStr;
127 SendMessageTimeout(FTargetHWnd, WM_COPYDATA, FWindowHandle, LPARAM(@Mes),
128 SMTO_ABORTIFHUNG or SMTO_NORMAL, 50000, Dummy);
129 FRecvLog.Text := FDirectSstpResult;
130 if FRecvLog.Count > 0 then
131 StatusCode := ExtractCode(FRecvLog[0])
133 StatusCode := UnknownError;
134 Result := CodeToStatus(StatusCode);
138 constructor TBottleSstp.Create(CreateSuspended: boolean);
141 FCueLock := TCriticalSection.Create;
142 FCue := TObjectList.Create(true);
143 FWindowHandle := AllocateHWnd(WndProc);
144 FSentLog := TStringList.Create;
145 FRecvLog := TStringList.Create;
148 destructor TBottleSstp.Destroy;
154 DeallocateHWnd(FWindowHandle);
158 procedure TBottleSstp.DetectTargetHWND;
161 //
\96Ú
\95W
\83S
\81[
\83X
\83g
\8ew
\92è
162 if ChannelList.Channel[FProcessBottle.Channel] <> nil then
163 Ghost := ChannelList.Channel[FProcessBottle.Channel].Ghost;
164 if FProcessBottle.Ghost <> '' then Ghost := FProcessBottle.Ghost;
166 SakuraSeeker.BeginDetect; //
\8dÅ
\90V
\82ÌFMO
\8eæ
\93¾
167 if SakuraSeeker.ProcessByName[Ghost] <> nil then begin
168 FTargetHWnd := SakuraSeeker.ProcessByName[Ghost].HWnd;
169 FTargetSetName := SakuraSeeker.ProcessByName[Ghost].SetName;
170 end else if SakuraSeeker.Count > 0 then begin
171 FTargetHWnd := SakuraSeeker[0].HWnd;
172 FTargetSetName := SakuraSeeker[0].SetName;
175 FTargetSetName := '';
179 procedure TBottleSstp.DoOnResendCountChange;
181 if Assigned(FOnResendCountChange) then
182 FOnResendCountChange(self);
185 procedure TBottleSstp.DoOnResendEnd;
187 if Assigned(FOnResendEnd) then
188 FOnResendEnd(self, FProcessBottle.MID);
191 procedure TBottleSstp.DoOnResendTrying;
193 if Assigned(FOnResendTrying) then
194 FOnResendTrying(self, FProcessBottle.MID);
197 procedure TBottleSstp.Execute;
198 var Source: TStringList;
200 Res: TBottleSstpResult;
203 while not Terminated do begin
205 if ResendSleep then Continue;
206 if (GetTickCount - FLastTickCount < 2000) and (GetTickCount > FLastTickCount) then
208 FLastTickCount := GetTickCount;
213 if FCue.Count = 0 then Continue;
214 FProcessBottle := FCue.Items[0] as TLogItem;
215 if FProcessBottle.LogType <> ltBottle then
223 // SakuraSeeker
\82Í
\83X
\83\8c\83b
\83h
\83A
\83\93\83Z
\81[
\83t
\82È
\82Ì
\82Å
224 // Synchronize
\82Å
\8cÄ
\82Ñ
\8fo
\82·
225 Synchronize(DetectTargetHWND);
226 if FTargetHWnd = 0 then
227 Continue; //
\89½
\82Å
\82à
\82¢
\82¢
\82©
\82ç
\83v
\83\8d\83Z
\83X
\8c©
\82Â
\82©
\82é
\82Ü
\82Å
\82Í
\91Ò
\82Â
229 Synchronize(DoOnResendTrying);
231 //
\82Å
\82Í
\91\97\90M
\92v
\82µ
\82Ü
\82µ
\82å
\82¤
232 Source := TStringList.Create;
234 if Pref.NoTranslate then begin
235 Opt := 'notranslate';
237 if Pref.NoDescript then begin
238 if Opt <> '' then Opt := Opt + ',';
239 Opt := Opt + 'nodescript';
241 Source.Add('SEND SSTP/1.4');
242 if FProcessBottle.Ghost <> '' then
243 Source.Add('Sender: SSTP Bottle / ' + FProcessBottle.Channel + '/' + FProcessBottle.Ghost)
245 Source.Add('Sender: SSTP Bottle / ' + FProcessBottle.Channel);
246 Source.Add('Charset: Shift_JIS');
247 if FProcessBottle.Ghost <> '' then begin
248 Source.Add('IfGhost: ' + FTargetSetName);
250 Source.Add('Script: ' + FProcessBottle.Script);
251 Source.Add('Option: ' + Opt);
252 Source.Add('HWnd: ' + IntToStr(FWindowHandle));
253 Source.Add(''); //
\8bó
\8ds
\82ª
\8fI
\97¹
\82ð
\8e¦
\82·
254 //
\8eÀ
\8dÛ
\82Ì
\91\97\90M
\81B
\95Ê
\82É
\82±
\82Ì
\95\94\95ª
\82³
\82¦
\95Ê
\83X
\83\8c\83b
\83h
\82È
\82ç
\82¢
\82¢
\82ñ
\82Å
\82·
\82¯
\82Ç
\81B
255 // Source.SaveToFile(ChangeFileExt(Application.ExeName, '.debug'));
256 Res := ConnectSstp(Source);
261 //
\91\97\90M
\8cã
\82Ì
\8f\88\97\9d\81B
\91\97\90M
\90¬
\8c÷
\82È
\82ç
\8fÁ
\82¦
\82Ä
\82à
\82ç
\82¢
\82Ü
\82µ
\82å
\82¤
262 if Res in [srOk] then begin
263 Synchronize(DoOnResendEnd);
266 // Delete(0)
\82¾
\82ÆSSTP
\90Ú
\91±
\92\86\82É
\89½
\82©
\91\9d\82¦
\82Ä
\82é
\89Â
\94\
\90«
\82ª
\82 \82é
267 FCue.Extract(FProcessBottle);
272 Synchronize(DoOnResendCountChange);
275 on E: Exception do begin
276 ShowMessage('Exception occured in SSTP dispatcher class:'#13#10#13#10 + E.Message);
279 //
\81«
\83\8b\81[
\83v
\8fI
\97¹
283 function TBottleSstp.ExtractCode(const CodeStr: String): integer;
287 if CodeStr = '' then begin
288 Result := UnknownError;
292 l := length(CodeStr);
293 while (CodeStr[i] <> ' ') and (i<=l) do begin
298 while (CodeStr[i] in ['0'..'9']) and (i<=l) do begin
303 Result := StrToInt(s);
305 on EConvertError do Result := UnknownError;
310 function TBottleSstp.GetCueCount: integer;
312 Result := FCue.Count;
315 procedure TBottleSstp.Push(Bottle: TLogItem);
323 Synchronize(DoOnResendCountChange);
326 procedure TBottleSstp.SetOnResendCountChange(const Value: TNotifyEvent);
328 FOnResendCountChange := Value;
331 procedure TBottleSstp.SetOnResendEnd(const Value: TBottleSstpResendEvent);
333 FOnResendEnd := Value;
336 procedure TBottleSstp.SetOnResendTrying(
337 const Value: TBottleSstpResendEvent);
339 FOnResendTrying := Value;
342 procedure TBottleSstp.SetResendSleep(const Value: boolean);
344 FResendSleep := Value;
347 procedure TBottleSstp.Unshift(Bottle: TLogItem);
350 Item := TLogItem.Create(Bottle);
353 FCue.Insert(0, Item);
357 Synchronize(DoOnResendCountChange);
360 procedure TBottleSstp.WndProc(var Msg: TMessage);
361 var Dat: TWMCopyData;
363 //
\83X
\83\8c\83b
\83h
\93à
\8aÖ
\90\94
364 if Msg.Msg = WM_COPYDATA then begin
365 Dat := TWMCopyData(Msg);
366 FDirectSstpResult := PChar(Dat.CopyDataStruct^.lpData);
368 Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam);