Link to home
Start Free TrialLog in
Avatar of Peter Kiers
Peter KiersFlag for Netherlands

asked on

Combine 2 units.

Hello Experts,

I have found source code of a Telnet emulator-programm that makes
a connection to a mainframe.

On the form is a TImage-component that is the 3270-screen
and it uses 2 units, one for creating the connection (winsock) and the
other is used when the connection has been established a thread is created
to receive data from the remote host. So, when the first unit has made
the connection it calls the Thread that is specified in the second unit.

type
  RecvThrd = class(TThread)
  private
    IOSocket: TSocket ;
    { Private declarations }
  protected  
    etc.. etc…

Is it possible to combine these 2 units to 1? Because in the unit where
the connection is created I miss the structure of the unit, and in the second
unit there is class specified.

This is the first unit:

unit telnetu;

interface

uses
  Windows, Winsock, Messages, SysUtils,
  Classes, Dialogs;

procedure TcpStartup ;
procedure TcpCleanup ;
procedure Log(str: string) ;
procedure Disconnect ;
procedure SendData(sdata: string) ; //calls the RecvThrd = class(TThread)
procedure MakeConnect ;    


implementation

uses
  Screenu,  utilu ;

          etc.. etc..

Second unit:

unit RecThrd;

interface

uses
  Windows, Winsock, Messages, SysUtils,
  Classes ;

const
  IO_BUF_SIZE = 4096 ;
type
  RecvThrd = class(TThread)
  private
    IOSocket: TSocket ;
    { Private declarations }
  protected  
    procedure Log(str: string) ;
    procedure DumpChar(ch: char) ;
    procedure DumpFlush ;
    procedure DispChar(ch: byte) ;
    procedure ProcessDataStream ;
    procedure LogDisp ;
    procedure Display ;
    procedure Execute; override;
  public
    constructor Create(ios: TSocket) ;
  end;

  TBuf = array[0..IO_BUF_SIZE] of char ;

threadvar
  s: string[16] ;
  numchars: integer ;
  bytecnt: integer ;
         
             etc.. etc...


Greetings,

Peter Kiers

ASKER CERTIFIED SOLUTION
Avatar of Pierre Cornelius
Pierre Cornelius
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Peter Kiers

ASKER

I get this error:

[Error] telnetu.pas(432): Incompatible types: 'RecThrd.RecvThrd' and 'telnetu.RecvThrd'

at line:

            RecThread := RecvThrd.Create(soc) ;

This is the whole unit:

unit telnetu;

interface

uses
  Windows, Winsock, Messages, SysUtils,
  Classes, Dialogs;

const
  IO_BUF_SIZE = 4096 ;

type
  RecvThrd = class(TThread)
  private
    IOSocket: TSocket ;
    { Private declarations }
  protected
    procedure ProcessDataStream ;
    procedure Execute; override;
  public
    constructor Create(ios: TSocket) ;
  end;

  TBuf = array[0..IO_BUF_SIZE] of char ;

procedure TcpStartup ;
procedure TcpCleanup ;
procedure Log(str: string) ;
procedure Disconnect ;
procedure SendData(sdata: string) ;
procedure MakeConnect ;

threadvar
  s: string[16] ;
  numchars: integer ;
  bytecnt: integer ;

implementation

uses
  Screenu,  utilu ;


procedure  TcpStartup ;
var
  err: integer ;
  VersionReq: word ;
  wsaData: TWSAData ;
begin
  VersionReq := $0101 ;
  err := WSAStartup(VersionReq,wsaData) ;
end ;

procedure TcpCleanup ;
var
  err: integer ;
begin
  err := WSACancelBlockingCall() ;
  err := WSACleanup() ;
end ;

procedure Log(str: string) ;
begin
    ShowMessage(str) ;
end ;

procedure DumpChar(ch: char) ;
var
  sf: string ;
  ic: integer ;
  i: integer ;
  e: char ;
begin
               etc…


procedure DumpFlush ;
var
  sf: string ;
  ic: integer ;
  i: integer ;
  e: char ;
begin
               etc…
                         
procedure Disconnect ;
begin
  if RecThreadRunning then
    RecThread.Terminate() ;
  if socOpen then
    begin
      closesocket(soc) ;
      socOpen := false ;
    end ;
  TcpCleanup() ;
  if deb then
    Log('TCP Ended.') ;
end;

procedure SendData(sdata: string) ;
const
  C_CR    = $0A ; { carrage return }
  C_LF    = $0D ; { line feed }
type
  TOutBuf = array[0..4096] of char ;
var
  err: integer ;
  size: integer ;
  pc: PChar ;
  OutBuffer: TOutBuf ;
  i: integer ;
begin                
  if EorFlag then
    sdata := sdata + Char(IAC) + Char(C_EOR) ;
  pc := @OutBuffer ;
  StrPCopy(pc,sdata) ;
  size := Length(sdata) ;
  err := send(soc,OutBuffer,size,0) ;
  if err = SOCKET_ERROR then
    Log('Send error: '
      +Format('%d',[WSAGetLastError()]))
  else
    begin
      if deb then
        begin
          Log('Send: '+Format(' (%d)',[size])) ;
          for i:=0 to (size-1) do
            DumpChar(OutBuffer[i]) ;
          DumpFlush ;
        end ;
    end ;
end;

procedure MakeConnect ;
type
  TPint = ^Longint ;
var
  err: integer ;
  phost: PHostEnt ;
  ina: TInAddr ;
  lina: TInAddr ;
  pint: TPint ;
  RemoteHostName: TPath ;
  PRemoteHostName: PChar ;
  LocalHostName: TPath ;
  PLocalHostName: PChar ;
  LocalAddr: TSockAddrIn ;
  psaddr: PSockAddr ;
  RemoteAddr: TSockAddrIn ;
  pServAddr: PServEnt ;
  usPort: u_short ;
  InitCmd: string ;
  NonBlocked: u_long ;
begin
  TcpStartup() ;
  if deb then
    Log('TCP Started.') ;
  soc := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
  if soc = INVALID_SOCKET then
    begin
      Log('Error socket invalid.') ;
      socOpen := False ;
    end
  else
    begin
      if deb then
        Log('Socket opened OK.') ;
      socOpen := True ;
    end ;

  { get foreign host name and addr }
  PRemoteHostName := @RemoteHostName ;
  StrPCopy(PRemoteHostName,ConnectHostName) ;
  phost := gethostbyname(PRemoteHostName) ;
  if phost = nil then
    begin
      Log('Error, failed to find host.') ;
      Disconnect ;
    end
  else
    begin
      if deb then
        begin
          Log('Foreign host name: '
            +PChar(phost^.h_name)) ;
          Log('    Address type: '
            +format('%x',[phost^.h_addrtype])) ;
          Log('    Address length: '
            +format('%d',[phost^.h_length])) ;
        end ;
      pint := Pointer(phost^.h_addr_list^) ;
      ina.s_addr := pint^ ;
      if deb then
        Log('    Foreign host address: '
          +PChar(inet_ntoa(ina))) ;

      { get local host name and addr }
      PLocalHostName := @LocalHostName ;
      if gethostname(PLocalHostName,MAX_PATH) <> SOCKET_ERROR then
        begin
          phost := gethostbyname(PLocalHostName) ;
          if phost = nil then
            begin
              Log('Error, failed to find local host.') ;
              Disconnect ;
            end
          else
            begin
              if deb then
                begin
                  Log('Local host name: '
                    +PChar(phost^.h_name)) ;
                  Log('    Address type: '
                    +format('%x',[phost^.h_addrtype])) ;
                  Log('    Address length: '
                    +format('%d',[phost^.h_length])) ;
                end ;
              pint := Pointer(phost^.h_addr_list^) ;
              lina.s_addr := pint^ ;
              if deb then
                Log('    Local host address: '
                  +PChar(inet_ntoa(lina))) ;

              { bind socket to addr }
              LocalAddr.sin_family := AF_INET ;
              LocalAddr.sin_addr.s_addr := lina.s_addr ;
              LocalAddr.sin_port := htonl(INADDR_ANY) ;
              psaddr := Pointer(@LocalAddr) ;
              err := bind(soc,psaddr^,SizeOf(LocalAddr)) ;
              if err = SOCKET_ERROR then
                begin
                  Log('Bind error: '
                    +Format('%d',[WSAGetLastError()])) ;
                  Disconnect ;
                end
              else
                begin
                  if deb then
                    Log('Bind successful') ;

                  { get service port }
                  pServAddr := getservbyname('telnet','tcp') ;
                  if pServAddr <> nil then
                    begin
                      if deb then
                        begin
                          Log('Remote Service Info.:') ;
                          Log('    Name: '+PChar(pServAddr^.s_name)) ;
                          Log('    Port: '+Format('%d',[ntohs(pServAddr^.s_port)])) ;
                        end ;
                      usPort := pServAddr^.s_port ;

                      { connect to server }
                      RemoteAddr.sin_family := AF_INET ;
                      RemoteAddr.sin_addr.s_addr := ina.s_addr ;
                      RemoteAddr.sin_port := usPort ;
                      psaddr := Pointer(@RemoteAddr) ;
                      err := connect(soc,psaddr^,SizeOf(RemoteAddr)) ;
                      if err = SOCKET_ERROR then
                        begin
                          Log('Connect error: '
                            +Format('%d',[WSAGetLastError()])) ;
                          Disconnect ;
                        end
                      else
                        begin
                          if deb then
                            Log('Connected.') ;

                          { start thread to receive all data - will
                            also do all telnet negotiation }
                          RecThread := RecvThrd.Create(soc) ;

                          { send CR LF to get server started }
                          SendData(InitCmd) ;
                        end ;
                    end
                  else
                    begin
                      Log('Getservbyname error: '
                        +Format('%d',[WSAGetLastError()])) ;
                      Disconnect ;
                    end ;

                end ;
            end ;
        end
      else
        begin
          Log('Get local host error:'
            +Format('%d',[WSAGetLastError()])) ;
          Disconnect ;
        end ;
    end ;
end;

{ RecvThrd }

constructor RecvThrd.Create(ios: TSocket);
var
  i: integer ;
begin
  FreeOnTerminate := True ;
  IOSocket := ios ;
  numchars := 0 ;
  for i := 1 to 16 do
    s[i] := chr(0) ;
  inherited Create(False) ;  { dont run thread yet }
end ;

procedure RecvThrd.Execute;
type
  PTelCmd = ^TTelCmd ;
  TTelCmd = packed record
    c_iac: Byte ;
    c_cmd: Byte ;
    c_func: Byte ;
  end ;
  PTelTermCmd = ^TTelTermCmd ;
  TTelTermCmd = packed record
    c_iac:  Byte ;
    c_sb:   Byte ;
    c_term: Byte ;
    c_is:   Byte ;
    c_type: array[1..10] of char ;
    c_iace: Byte ;
    c_se:   Byte ;
  end ;
                     etc…

procedure RecvThrd.ProcessDataStream;
begin
 //   Ds3270.DataIn(DataStreamBuf) ;
end;

end.

Greetings,

Peter

YES,YES,YES

I have got it.

change it to: RecvThrd.Create(soc);

And it works thanks to you.

Greetings,

Peter Kiers
Glad to help.