Guest User

L2Stream

a guest
Oct 15th, 2011
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 9.61 KB | None | 0 0
  1. unit L2Stream;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, Classes, SysUtils, Math;
  7.  
  8. type
  9.   TL2Stream = class;
  10.  
  11.   TL2Packet = class(TObject)
  12.   private
  13.     FCursor: Cardinal;
  14.     FData: RawByteString;
  15.  
  16.     procedure SetData(Data: RawByteString);
  17.     function GetId: Byte;
  18.     procedure SetId(Id: Byte);
  19.   public
  20.     property Id: Byte read GetId write SetId;
  21.     property Data: RawByteString read FData write SetData;
  22.     property Cursor: Cardinal read FCursor write FCursor;
  23.  
  24.     procedure WriteB(Buf: Pointer; Size: Integer; Index: Integer = 0);
  25.     procedure WriteC(Value: Byte; Index: Integer = 0);
  26.     procedure WriteH(Value: Word; Index: Integer = 0);
  27.     procedure WriteD(Value: Integer; Index: Integer = 0);
  28.     procedure WriteQ(Value: Int64; Index: Integer = 0);
  29.     procedure WriteF(Value: Double; Index: Integer = 0);
  30.     procedure WriteS(Value: string; Index: Integer = 0);
  31.     function ReadC: Byte;
  32.     function ReadH: Word;
  33.     function ReadD: Integer;
  34.     function ReadQ: Int64;
  35.     function ReadF: Double;
  36.     function ReadS: string;
  37.     function ReadB(Size: Integer): RawByteString;
  38.     function EndOfPacket(RaiseException: Boolean = True): Boolean;
  39.     procedure Skip(Fields: AnsiString); overload;
  40.     procedure Skip(Bytes: Integer); overload;
  41.     procedure Clear;
  42.  
  43.     constructor Create;
  44.     destructor Destroy; override;
  45.   end;
  46.  
  47.   TL2PacketEvent = procedure(Packet: TL2Packet; Sender: TL2Stream) of object;
  48.   TL2SendEvent = procedure(Data: RawByteString) of object;
  49.  
  50.   TL2Key = array [0..15] of Byte;
  51.  
  52.   TL2Stream = class(TObject)
  53.   private
  54.     FEmptyKey: Boolean;
  55.     FRecvBuf: RawByteString;
  56.     RKey, SKey: TL2Key;
  57.     Packet: TL2Packet;
  58.  
  59.     procedure DecryptPacket(var Packet: RawByteString; var Key: TL2Key);
  60.     procedure EncryptPacket(var Packet: RawByteString; var Key: TL2Key);
  61.  
  62.   public
  63.     PacketEvent: TL2PacketEvent;
  64.     SendEvent: TL2SendEvent;
  65.  
  66.     property EmptyKey: Boolean read FEmptyKey;
  67.  
  68.     procedure Reset;
  69.     function SetKey(Key: RawByteString): Boolean;
  70.     procedure Send(Data: RawByteString);
  71.     function ProcessData(const Data: RawByteString): Boolean;
  72.  
  73.     constructor Create;
  74.     destructor Destroy; override;
  75.   end;
  76.  
  77. implementation
  78.  
  79. constructor TL2Packet.Create;
  80. begin
  81.   inherited Create;
  82.  
  83.   Clear;
  84. end;
  85.  
  86. destructor TL2Packet.Destroy;
  87. begin
  88.   // Nothing
  89.  
  90.   inherited Destroy;
  91. end;
  92.  
  93. procedure TL2Packet.Clear;
  94. begin
  95.   SetData(#$00);
  96. end;
  97.  
  98. procedure TL2Packet.WriteB(Buf: Pointer; Size: Integer; Index: Integer = 0);
  99. var
  100.   L, MinLen: Integer;
  101. begin
  102.   L := Length(FData);
  103.   if Index < 2 then Index := L + 1;
  104.   MinLen := Index + Size - 1;
  105.   if L < MinLen then SetLength(FData, MinLen);
  106.   Move(Buf^, FData[Index], Size);
  107. end;
  108.  
  109. procedure TL2Packet.WriteC(Value: Byte; Index: Integer = 0);
  110. begin
  111.   WriteB(@Value, 1, Index);
  112. end;
  113.  
  114. procedure TL2Packet.WriteH(Value: Word; Index: Integer = 0);
  115. begin
  116.   WriteB(@Value, 2, Index);
  117. end;
  118.  
  119. procedure TL2Packet.WriteD(Value: Integer; Index: Integer = 0);
  120. begin
  121.   WriteB(@Value, 4, Index);
  122. end;
  123.  
  124. procedure TL2Packet.WriteQ(Value: Int64; Index: Integer = 0);
  125. begin
  126.   WriteB(@Value, 8, Index);
  127. end;
  128.  
  129. procedure TL2Packet.WriteF(Value: Double; Index: Integer = 0);
  130. begin
  131.   WriteB(@Value, 8, Index);
  132. end;
  133.  
  134. procedure TL2Packet.WriteS(Value: string; Index: Integer = 0);
  135. var
  136.   WS: WideString;
  137.   S: RawByteString;
  138.   L: Integer;
  139. begin
  140.   WS := Value;
  141.   L := Length(WS) * 2;
  142.   SetLength(S, L);
  143.   if L > 0 then Move(WS[1], S[1], L);
  144.   S := S + #0#0;
  145.   WriteB(@S[1], L + 2, Index);
  146. end;
  147.  
  148. function TL2Packet.ReadC: Byte;
  149. begin
  150.   if FCursor < 2 then FCursor := 2;
  151.   if Length(FData) < FCursor then raise Exception.Create('Error in ReadC!');
  152.   Result := Ord(FData[FCursor]);
  153.   Inc(FCursor);
  154. end;
  155.  
  156. function TL2Packet.ReadH: Word;
  157. begin
  158.   if FCursor < 2 then FCursor := 2;
  159.   if Length(FData) < FCursor + 1 then raise Exception.Create('Error in ReadH!');
  160.   Move(FData[FCursor], Result, 2);
  161.   Inc(FCursor, 2);
  162. end;
  163.  
  164. function TL2Packet.ReadD: Integer;
  165. begin
  166.   if FCursor < 2 then FCursor := 2;
  167.   if Length(FData) < FCursor + 3 then raise Exception.Create('Error in ReadD!');
  168.   Move(FData[FCursor], Result, 4);
  169.   Inc(FCursor, 4);
  170. end;
  171.  
  172. function TL2Packet.ReadQ: Int64;
  173. begin
  174.   if FCursor < 2 then FCursor := 2;
  175.   if Length(FData) < FCursor + 7 then raise Exception.Create('Error in ReadQ!');
  176.   Move(FData[FCursor], Result, 8);
  177.   Inc(FCursor, 8);
  178. end;
  179.  
  180. function TL2Packet.ReadF: Double;
  181. begin
  182.   if FCursor < 2 then FCursor := 2;
  183.   if Length(FData) < FCursor + 7 then raise Exception.Create('Error in ReadF!');
  184.   Move(FData[FCursor], Result, 8);
  185.   Inc(FCursor, 8);
  186. end;
  187.  
  188. function TL2Packet.ReadB(Size: Integer): RawByteString;
  189. begin
  190.   if FCursor < 2 then FCursor := 2;
  191.   if Size < 1 then raise Exception.Create('Error in ReadB!');
  192.   if Length(FData) < FCursor + Size - 1 then raise Exception.Create('Error in ReadB!');
  193.   SetLength(Result, Size);
  194.   Move(FData[FCursor], Result[1], Size);
  195.   Inc(FCursor, Size);
  196. end;
  197.  
  198. function TL2Packet.ReadS: string;
  199. var
  200.   I, Len, N: Integer;
  201.   WS: WideString;
  202. begin
  203.   if FCursor < 2 then FCursor := 2;
  204.   Result := '';
  205.   I := FCursor;
  206.   Len := Length(FData);
  207.   while True do
  208.     begin
  209.       if I + 1 > Len then
  210.         begin
  211.           FCursor := Len + 1;
  212.           raise Exception.Create('Error in ReadS!');
  213.           Exit;
  214.         end;
  215.       if (FData[I] = #0) and (FData[I + 1] = #0) then
  216.         begin
  217.           N := I - FCursor;
  218.           SetLength(WS, N div 2);
  219.           Move(FData[FCursor], WS[1], N);
  220.           Result := WS;
  221.           FCursor := I + 2;
  222.           Exit;
  223.         end;
  224.       Inc(I, 2);
  225.     end;
  226. end;
  227.  
  228. function TL2Packet.EndOfPacket(RaiseException: Boolean = True): Boolean;
  229. var
  230.   N: Integer;
  231. begin
  232.   N := Length(FData) + 1 - FCursor;
  233.   Result := N = 0;
  234.   if (not Result) and RaiseException then raise Exception.Create(Format('EndOfPacket expected (%d)!', [N]));
  235. end;
  236.  
  237. procedure TL2Packet.Skip(Bytes: Integer);
  238. begin
  239.   if Bytes < 1 then raise Exception.Create('Error in Skip!');
  240.   Inc(FCursor, Bytes);
  241. end;
  242.  
  243. procedure TL2Packet.Skip(Fields: AnsiString);
  244. var
  245.   I, FI, N: Integer;
  246.   C: AnsiChar;
  247.   T: AnsiString;
  248. begin
  249.   Fields := AnsiString(LowerCase(String(Fields)));
  250.   T := '';
  251.   for FI := 1 to Length(Fields) do
  252.     begin
  253.       C := Fields[FI];
  254.       if C in ['0'..'9'] then
  255.         begin
  256.           T := T + C;
  257.           Continue;
  258.         end;
  259.  
  260.       if T <> '' then
  261.         begin
  262.           N := StrToInt(String(T));
  263.           T := '';
  264.           if N < 1 then raise Exception.Create('Invalid amount!');
  265.         end
  266.       else
  267.         begin
  268.           N := 1;
  269.         end;
  270.  
  271.       case C of
  272.         'c': Inc(FCursor, 1 * N);
  273.         'h': Inc(FCursor, 2 * N);
  274.         'd': Inc(FCursor, 4 * N);
  275.         'q': Inc(FCursor, 8 * N);
  276.         'f': Inc(FCursor, 8 * N);
  277.         's': for I := 1 to N do ReadS;
  278.       end;
  279.     end;
  280. end;
  281.  
  282. procedure TL2Packet.SetData(Data: RawByteString);
  283. begin
  284.   if Data = '' then Data := #$00;  
  285.   FData := Data;
  286.   FCursor := 2;
  287. end;
  288.  
  289. function TL2Packet.GetId: Byte;
  290. begin
  291.   Result := Ord(FData[1]);
  292. end;
  293.  
  294. procedure TL2Packet.SetId(Id: Byte);
  295. begin
  296.   FData[1] := AnsiChar(Id);
  297. end;
  298.  
  299. constructor TL2Stream.Create;
  300. begin
  301.   inherited Create;
  302.  
  303.   Packet := TL2Packet.Create;
  304.   Reset;
  305. end;
  306.  
  307. destructor TL2Stream.Destroy;
  308. begin
  309.   Packet.Free;
  310.  
  311.   inherited Destroy;
  312. end;
  313.  
  314. procedure TL2Stream.Reset;
  315. begin
  316.   FRecvBuf := '';
  317.   SetKey('');
  318. end;
  319.  
  320. function TL2Stream.SetKey(Key: RawByteString): Boolean;
  321. var
  322.   L2Key: TL2Key;
  323.   I: Integer;
  324. begin
  325.   if Length(Key) <> Length(L2Key) then
  326.     begin
  327.       FEmptyKey := True;
  328.       Exit(False);
  329.     end;
  330.  
  331.   for I := 1 to Length(Key) do L2Key[I - 1] := Byte(Key[I]);
  332.   RKey := L2Key;
  333.   SKey := L2Key;
  334.   FEmptyKey := False;
  335.   Result := True;
  336. end;
  337.  
  338. procedure TL2Stream.EncryptPacket(var Packet: RawByteString; var Key: TL2Key);
  339. var
  340.   I, L: Integer;
  341.   K: Byte;
  342.   PB: PByte;
  343. begin
  344.   if EmptyKey then Exit;
  345.  
  346.   L := Length(Packet);
  347.   if L = 0 then Exit;
  348.  
  349.   K := 0;
  350.   PB := @Packet[1];
  351.   for i := 0 to L - 1 do
  352.     begin
  353.       PB^ := PB^ xor Key[I and 15] xor K;
  354.       K := PB^;
  355.       Inc(PB);
  356.     end;
  357.  
  358.   Inc(PInteger(@Key[8])^, L);
  359. end;
  360.  
  361. procedure TL2Stream.DecryptPacket(var Packet: RawByteString; var Key: TL2Key);
  362. var
  363.   I, L: Integer;
  364.   T, K: Byte;
  365.   PB: PByte;
  366. begin
  367.   if EmptyKey then Exit;
  368.  
  369.   L := Length(Packet);
  370.   if L = 0 then Exit;
  371.  
  372.   K := 0;
  373.   PB := @Packet[1];
  374.   for i := 0 to L - 1 do
  375.     begin
  376.       T := PB^;
  377.       PB^ := PB^ xor Key[I and 15] xor K;
  378.       K := T;
  379.  
  380.       Inc(PB);
  381.     end;
  382.  
  383.   Inc(PInteger(@Key[8])^, L);
  384. end;
  385.  
  386. procedure TL2Stream.Send(Data: RawByteString);
  387. var
  388.   L, W: Word;
  389.   S: RawByteString;
  390. begin
  391.   if Length(Data) = 0 then Exit;
  392.  
  393.   EncryptPacket(Data, SKey);
  394.   if not Assigned(SendEvent) then Exit;
  395.  
  396.   L := Length(Data);
  397.   W := L + 2;
  398.   SetLength(S, W);
  399.   Move(W, S[1], 2);
  400.   Move(Data[1], S[3], L);
  401.  
  402.   SendEvent(S);
  403. end;
  404.  
  405. function TL2Stream.ProcessData(const Data: RawByteString): Boolean;
  406. var
  407.   S: RawByteString;
  408.   Size: Word;
  409.   L, I: Integer;
  410. begin
  411.   FRecvBuf := FRecvBuf + Data;
  412.   L := Length(FRecvBuf);
  413.   I := 1;
  414.   while L > 2 do
  415.     begin
  416.       Move(FRecvBuf[I], Size, 2);
  417.       if Size < 3 then Exit(False);      
  418.       if L < Size then Break;
  419.  
  420.       S := Copy(FRecvBuf, I + 2, Size - 2);
  421.       DecryptPacket(S, RKey);
  422.  
  423.       if Assigned(PacketEvent) then
  424.         begin
  425.           Packet.Data := S;
  426.           PacketEvent(Packet, Self);
  427.         end;
  428.  
  429.       Inc(I, Size);
  430.       Dec(L, Size);
  431.     end;
  432.  
  433.   if I > 1 then
  434.     begin
  435.       Delete(FRecvBuf, 1, I - 1);
  436.     end;
  437.  
  438.   Result := True;
  439. end;
  440.  
  441. end.
  442.  
  443.  
Add Comment
Please, Sign In to add comment