This is the network message class used in my program Troxy. You'll have to use this if you want to use the Packet Parser Loop (my other post).
Code:
unit netmsg;
interface
uses
WinSock, Math, SysUtils, Dialogs;
const
MAXNETMSG_SIZE = 16384;
type TXteaKey = array [1..16] of byte;
type
TNetMsg = class(TObject)
public
amsgsize, adatasize, areadpos : integer;
amsgbuf : array[1..MAXNETMSG_SIZE] of byte;
bEncrypt: boolean;
bProxy : boolean;
m_XteaKey : TXteaKey;
procedure BlockPacket;
procedure Reset;
procedure Dump(fn : string);
procedure Skip(numbytes : word);
procedure SkipString;
function isEOP : boolean;
function ReadSock(Sock : u_int) : boolean;
function WriteSock(Sock : u_int) : boolean;
function GetByte : byte;
function GetU16 : word;
function GetU32 : cardinal;
function GetString : string;
function GetByteOnPos(iPos: integer) : byte;
procedure PutByte(B : byte);
procedure PutU16(I : word);
procedure PutU32(I : cardinal);
procedure PutString(S : string);
procedure OverwriteByte(b : byte);
procedure OverwriteU16(i : word);
procedure OverwriteU32(i : cardinal);
procedure OverwriteString(S : string);
function GetReadPos(): integer;
procedure SetReadPos(i: integer);
function GetPacketLength(): integer;
function toString(): string;
procedure SetEncryption(enc: boolean; key: TXteaKey);
procedure SetProxy(proxy: boolean);
procedure XTeaEncrypt();
procedure XTeaDecrypt();
constructor Create; reintroduce; virtual;
Destructor Destroy; override;
end;
implementation
constructor TNetMsg.Create;
begin
inherited Create;
Reset;
end;
destructor TNetMsg.Destroy;
begin
inherited;
end;
procedure TNetMsg.BlockPacket;
begin
amsgsize := 0;
fillchar(amsgbuf,MAXNETMSG_SIZE,0);
end;
procedure TNetMsg.Reset;
begin
fillchar(amsgbuf,MAXNETMSG_SIZE,0);
amsgsize := 0;
adatasize := 0;
areadpos := 5;
bEncrypt := false;
bProxy := false;
end;
procedure TNetMsg.Dump(fn : string);
var wbuf : array[1..1024] of byte; i, s : integer; f : file of byte;
begin
assignfile(f, fn);
rewrite(f);
s := 0;
repeat
i := min(1024, amsgsize - s);
move( (@amsgbuf[s+1])^, (@wbuf[1])^, i);
blockwrite(f, wbuf, i);
inc(s, i);
until s = amsgsize + 2;
closefile(f);
end;
procedure TNetMsg.Skip(numbytes : word);
begin
inc(areadpos,numbytes);
end;
procedure TNetMsg.SkipString;
var i : word;
begin
i := getu16;
skip(i);
end;
function TNetMsg.isEOP : boolean;
begin
result := NOT (areadpos < (adatasize+5));
end;
function TNetMsg.ReadSock(Sock : u_int) : boolean;
var t, p : integer; keep : boolean; buf : array[1..1000] of byte;
begin
keep := true;
p := 1;
while keep do
begin
if p = 1 then // copia somente 2 bytes para ler apenas uma mensagem
t := recv(sock, buf, 2, 0)
else
t := recv(sock, buf, min(1000, amsgsize - p + 3), 0);
if (t = SOCKET_ERROR) or (t = 0) then
begin
result := false;
exit;
end;
if p = 1 then
amsgsize := buf[1] or (buf[2] shl 8);
if t > 0 then
begin
move((@buf[1])^, (@amsgbuf[p])^, t);
inc(p, t);
end;
keep := amsgsize <> p - 3;
end;
areadpos := 3;
// Stel de encryption in
if (bEncrypt = true) then
begin
XTeaDecrypt();
end;
result := true;
end;
function TNetMsg.WriteSock(Sock : u_int) : boolean;
var sent, x, t, i : integer; buf : array[1..1000] of byte;
begin
result := false;
if amsgsize = 0 then begin
result := true;
exit;
end;
// modo I/O
t := 1;
//ioctlsocket(Sock,FIONBIO,t);
// Stel de encryption in
if (bEncrypt = true) then
begin
XTeaEncrypt();
end;
sent := 0;
repeat
t := min(1000, 2+amsgsize-sent);
for i := 1 to t do buf[i] := amsgbuf[i+sent];
x := send(Sock, buf, t, 0);
if x <= 0 then exit;
inc(sent, x);
until (sent = amsgsize+2);
// modo block
t := 0;
//ioctlsocket(Sock,FIONBIO,t);
result := true;
end;
function TNetMsg.GetByte : byte;
begin
result := amsgbuf[areadpos];
inc(areadpos,1);
end;
function TNetMsg.GetU16 : word;
begin
result := word(amsgbuf[areadpos] or
(amsgbuf[areadpos+1] shl 8));
inc(areadpos,2);
end;
function TNetMsg.GetU32 : cardinal;
begin
result := cardinal(amsgbuf[areadpos] or
(amsgbuf[areadpos+1] shl 8) or
(amsgbuf[areadpos+2] shl 16) or
(amsgbuf[areadpos+3] shl 24));
inc(areadpos,4);
end;
function TNetMsg.GetString : string;
var tam,a : integer;
begin
tam := getu16;
{ temporario, ate eu achar um metodo pra ler }
setlength(result,tam);
for a := 1 to tam do
result[a] := chr(GetByteOnPos(areadpos+a-1));
{ end temp }
//result := copy(amsgbuf, areadpos, tam);
inc(areadpos,tam);
end;
function TNetMsg.GetByteOnPos(iPos: integer) : byte;
begin
result := amsgbuf[iPos];
end;
procedure TNetMsg.PutByte(b : byte);
begin
amsgbuf[areadpos] := b;
inc(areadpos,1);
inc(amsgsize,1);
inc(adatasize, 1);
end;
procedure TNetMsg.PutU16(i : word);
begin
amsgbuf[areadpos] := byte(i);
amsgbuf[areadpos+1] := byte(i shr 8);
inc(areadpos,2);
inc(amsgsize,2);
inc(adatasize, 2);
end;
procedure TNetMsg.PutU32(i : cardinal);
begin
amsgbuf[areadpos] := byte(i);
amsgbuf[areadpos+1] := byte(i shr 8);
amsgbuf[areadpos+2] := byte(i shr 16);
amsgbuf[areadpos+3] := byte(i shr 24);
inc(areadpos,4);
inc(amsgsize,4);
inc(adatasize, 4);
end;
procedure TNetMsg.PutString(s : string);
var tam,a : integer;
begin
tam := length(s);
putu16(tam);
{ temporario, ate achar um metodo possivel }
for a := 1 to tam do
amsgbuf[areadpos+a-1] := ord(s[a]);
{ end if }
//insert(s,amsgbuf,areadpos);
inc(areadpos,tam);
inc(amsgsize,tam);
inc(adatasize, tam);
end;
procedure TNetMsg.OverwriteByte(b : byte);
begin
amsgbuf[areadpos] := b;
inc(areadpos,1);
end;
procedure TNetMsg.OverwriteU16(i : word);
begin
amsgbuf[areadpos] := byte(i);
amsgbuf[areadpos+1] := byte(i shr 8);
inc(areadpos,2);
end;
procedure TNetMsg.OverwriteU32(i : cardinal);
begin
amsgbuf[areadpos] := byte(i);
amsgbuf[areadpos+1] := byte(i shr 8);
amsgbuf[areadpos+2] := byte(i shr 16);
amsgbuf[areadpos+3] := byte(i shr 24);
inc(areadpos,4);
end;
procedure TNetMsg.OverwriteString(s : string);
var tam,a : integer;
begin
tam := length(s);
putu16(tam);
for a := 1 to tam do
amsgbuf[areadpos+a-1] := ord(s[a]);
end;
function TNetMsg.GetReadPos(): integer;
begin
result := areadpos;
end;
procedure TNetMsg.SetReadPos(i: integer);
begin
areadpos := i;
end;
function TNetMsg.GetPacketLength(): integer;
begin
result := amsgsize+4;
end;
function TNetMsg.toString(): string;
var
i: integer;
begin
result := '';
for i := 1 to GetPacketLength() do
begin
result := result + inttohex(amsgbuf[i], 2) + ' ';
end;
end;