Search code examples
delphipascalindy10

Indy 9 to Indy 10 conversion


I have found an old .dpr file on the internet, the file is basically a Delphi 7 project from 2008 about server-emulation of an old game.

I tried to compile the file using RAD Studio, but it seemed that the file was using Indy 9 units/libs, where the availabe Indy that comes with RAD Studio is Indy 10.

The codes I want to convert are the ones with errors.

procedure aServer.Map_ServerExecute(AThread: TIdContext);
var
  i, n: integer;
  sz: integer;
  incom_buf: array[0..8192] of byte;
  str: string;
begin
  for i := 0 to max_connects do
    if Assigned(map_connections[i]) then
      if map_connections[i] = AThread then break;
  n := i;
  if i >= max_connects then exit;
  for i := 0 to 8191 do
    incom_buf[i] := 0;
  sz := AThread.Connection.ReadFromStack(); // E2003 Undeclared identifier: 'ReadFromStack'
  AThread.Connection.ReadBuffer(incom_buf,sz); // E2003 Undeclared identifier: 'ReadBuffer'
  decrypt_pkt(incom_buf, sz);
  if do_debug_output <> 0 then
  begin
    str := ByteArrayToHexString(incom_buf, sz-1);
    Writeln('in>'+str);
  end;
  sv_callback(n, 1, sz, @incom_buf[0]);
end;
procedure write_to_n(n: integer; is_map: integer; sz: integer; p:pointer); stdcall;
var
  TheThread: TIdContext; 
  i: integer;
  out_buf: array [0..2048] of byte;
  p_out_buf: PByteArray;
  str: string;
begin
  if n < 0 then exit;
  if n > max_connects then exit; 
  if sz <= 0 then exit;
  TheThread := nil;
  if is_map = 0 then
    TheThread := chr_connections[n]
  else 
    TheThread := map_connections[n];
  if not Assigned(TheThread) then exit;
  for i := 0 to 2048 do
    out_buf[i] := 0;
  p_out_buf := p;
  for i := 0 to sz do
    out_buf[i] := p_out_buf[i];
  if do_debug_output <> 0 then
  begin
    str := ByteArrayToHexString(out_buf, sz-1);
    Writeln('out>'+str);
  end;
  decrypt_pkt(out_buf, sz);
  TheThread.Connection.WriteBuffer(out_buf,sz-1); // E2003 Undeclared identifier: 'WriteBuffer' 
end;

I tried a few conversions from the internet, but other errors kept arising.


Solution

  • In Indy 10, most of the reading/writing methods were moved from TIdTCPConnection to TIdIOHandler, and also redesigned. For instance, Indy 10 supports .NET, so raw pointers to memory buffers are no longer accepted (that may change in a future version), so you have to use either the TIdBytes (dynamic array of bytes) type, or a TId(ReadOnly)MemoryBufferStream instead.

    So, in the code you have shown, try the following changes...

    Using TIdBytes:

    procedure aServer.Map_ServerExecute(AThread: TIdContext);
    var
      i, n: integer;
      sz: integer;
      incom_buf: TIdBytes;
      str: string;
    begin
      for i := 0 to max_connects do
        if Assigned(map_connections[i]) then
          if map_connections[i] = AThread then break;
      n := i;
      if i >= max_connects then exit;
      AThread.Connection.IOHandler.CheckForDataOnSource;
      sz := AThread.Connection.IOHandler.InputBuffer.Size;
      if sz = 0 then exit;
      AThread.Connection.IOHandler.ReadBytes(incom_buf, sz);
      decrypt_pkt(PByte(incom_buf), sz);
      if do_debug_output <> 0 then
      begin
        str := ByteArrayToHexString(PByte(incom_buf), sz-1); // why -1?
        Writeln('in>'+str);
      end;
      sv_callback(n, 1, sz, PByte(incom_buf));
    end;
    
    procedure write_to_n(n: integer; is_map: integer; sz: integer; p: Pointer); stdcall;
    var
      TheThread: TIdContext; 
      i: integer;
      out_buf: TIdBytes;
      str: string;
    begin
      if n < 0 then exit;
      if n > max_connects then exit; 
      if sz <= 0 then exit;
      TheThread := nil;
      if is_map = 0 then
        TheThread := chr_connections[n]
      else 
        TheThread := map_connections[n];
      if not Assigned(TheThread) then exit;
      out_buf := RawToBytes(p^, sz);
      if do_debug_output <> 0 then
      begin
        str := ByteArrayToHexString(PByte(out_buf), sz-1); // why -1?
        Writeln('out>'+str);
      end;
      decrypt_pkt(PByte(out_buf), sz);
      TheThread.Connection.IOHandler.Write(out_buf, sz-1); // why -1?
    end;
    

    Alternatively, using TId(ReadOnly)MemoryBufferStream:

    procedure aServer.Map_ServerExecute(AThread: TIdContext);
    var
      i, n: integer;
      sz: integer;
      incom_buf: array[0..8192] of byte;
      incom_strm: TIdMemoryBufferStream;
      str: string;
    begin
      for i := 0 to max_connects do
        if Assigned(map_connections[i]) then
          if map_connections[i] = AThread then break;
      n := i;
      if i >= max_connects then exit;
      ZeroMemory(incom_buf, SizeOf(incom_buf));
      AThread.Connection.IOHandler.CheckForDataOnSource;
      sz := AThread.Connection.IOHandler.InputBuffer.Size;
      if sz = 0 then exit;
      incom_strm := TIdMemoryBufferStream.Create(incom_buf, SizeOf(incom_buf));
      try
        AThread.Connection.IOHandler.ReadStream(incom_strm, sz);
      finally
        incom_strm.Free;
      end;
      decrypt_pkt(incom_buf, sz);
      if do_debug_output <> 0 then
      begin
        str := ByteArrayToHexString(incom_buf, sz-1); // why -1?
        Writeln('in>'+str);
      end;
      sv_callback(n, 1, sz, @incom_buf[0]);
    end;
    
    procedure write_to_n(n: integer; is_map: integer; sz: integer; p: Pointer); stdcall;
    var
      TheThread: TIdContext; 
      i: integer;
      out_buf: array [0..2048] of byte;
      p_out_buf: PByteArray;
      out_strm: TIdReadOnlyMemoryBufferStream;
      str: string;
    begin
      if n < 0 then exit;
      if n > max_connects then exit; 
      if sz <= 0 then exit;
      TheThread := nil;
      if is_map = 0 then
        TheThread := chr_connections[n]
      else 
        TheThread := map_connections[n];
      if not Assigned(TheThread) then exit;
      ZeroMemory(out_buf, SizeOf(out_buf));
      CopyMemory(out_buf, p, sz);
      if do_debug_output <> 0 then
      begin
        str := ByteArrayToHexString(out_buf, sz-1); // why -1?
        Writeln('out>'+str);
      end;
      decrypt_pkt(out_buf, sz);
      // NOTE: passing ASize=0 to IOHandler.Write(TStream) will send the entire stream instead of sending nothing...
      if sz = 1 then exit;
      out_strm := TIdReadOnlyMemoryBufferStream.Create(out_buf, SizeOf(out_buf));
      try
        TheThread.Connection.IOHandler.Write(out_strm, sz-1); // why -1?
      finally
        out_strm.Free;
      end;
    end;