Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 227
  • Last Modified:

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

0
peterkiers
Asked:
peterkiers
  • 2
  • 2
1 Solution
 
Pierre CorneliusCommented:
You can easily combine the 2 units. e.g.

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 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 ;

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


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

uses
  Screenu,  utilu ;

          etc.. etc..


You would have to move the code from the 2nd unit implementation section to the 1st unit implementation section too.


Regards
Pierre

0
 
peterkiersAuthor Commented:
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

0
 
peterkiersAuthor Commented:
YES,YES,YES

I have got it.

change it to: RecvThrd.Create(soc);

And it works thanks to you.

Greetings,

Peter Kiers
0
 
Pierre CorneliusCommented:
Glad to help.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now