Psock.pas.~1~
上传用户:szzdds
上传日期:2013-09-18
资源大小:293k
文件大小:72k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit Psock;
  2. {$IFDEF VER100}
  3. {$DEFINE NMF3}
  4. {$ENDIF}
  5. {$IFDEF VER110}
  6. {$DEFINE NMF3}
  7. {$ENDIF}
  8. {$IFDEF VER120}
  9. {$DEFINE NMF3}
  10. {$ENDIF}
  11. {$IFDEF VER125}
  12. {$DEFINE NMF3}
  13. {$ENDIF}
  14. {$IFDEF VER130}
  15. {$DEFINE NMF3}
  16. {$ENDIF}
  17. {$IFDEF VER150}
  18. {$DEFINE NMF3}
  19. {$ENDIF}
  20. {$X+}
  21. {$H+}
  22. {$R-}
  23. {$DEFINE _WINSOCKAPI_}
  24. interface
  25. uses
  26.   Winsock, Classes, SysUtils, Extctrls, Forms, Messages, StdCtrls,
  27.   WinProcs, NMConst, NMFIFOBuffer, SyncObjs;
  28. {$IFDEF VER110}
  29. {$OBJEXPORTALL On}
  30. {$ENDIF}
  31. {$IFDEF VER120}
  32. {$OBJEXPORTALL On}
  33. {$ENDIF}
  34. {$IFDEF VER125}
  35. {$OBJEXPORTALL On}
  36. {$ENDIF}
  37. type
  38.   TSocket = Word;
  39. const
  40.   FD_ALL = 63;
  41.   {Size of receive and send buffer}
  42.   MAX_RECV_BUF = 65536;
  43.   { Levels for reporting Status Messages}
  44.   Status_None = 0;
  45.   Status_Informational = 1;
  46.   Status_Basic = 2;
  47.   Status_Routines = 4;
  48.   Status_Debug = 8;
  49.   Status_Trace = 16;
  50.   {Carriage Return and Line Feed constants}
  51.   CR = #13;
  52.   LF = #10;
  53.   CRLF = #13#10;
  54.   WM_ASYNCHRONOUSPROCESS = WM_USER + 101; {Message number for asynchronous socket messages}
  55.   WM_WAITFORRESPONSE = WM_USER + 102; {Message number for synchronous responses}
  56. type
  57.   TErrorMessage = record
  58.     ErrorCode: Integer;
  59.     Text: string[50];
  60.   end;
  61. const
  62.   WinsockMessage: array[0..50] of TErrorMessage =
  63.   (
  64.     (ErrorCode: 10004; Text: 'Interrupted system call'),
  65.     (ErrorCode: 10009; Text: 'Bad file number'),
  66.     (ErrorCode: 10013; Text: 'Permission denied'),
  67.     (ErrorCode: 10014; Text: 'Bad address'),
  68.     (ErrorCode: 10022; Text: 'Invalid argument'),
  69.     (ErrorCode: 10024; Text: 'Too many open files'),
  70.     (ErrorCode: 10035; Text: 'Operation would block'),
  71.     (ErrorCode: 10036; Text: 'Operation now in progress'),
  72.     (ErrorCode: 10037; Text: 'Operation already in progress'),
  73.     (ErrorCode: 10038; Text: 'Socket operation on non-socket'),
  74.     (ErrorCode: 10039; Text: 'Destination address required'),
  75.     (ErrorCode: 10040; Text: 'Message too long'),
  76.     (ErrorCode: 10041; Text: 'Wrong protocol type for socket'),
  77.     (ErrorCode: 10042; Text: 'Bad protocol option'),
  78.     (ErrorCode: 10043; Text: 'Protocol not supported'),
  79.     (ErrorCode: 10044; Text: 'Socket type not supported'),
  80.     (ErrorCode: 10045; Text: 'Operation not supported on socket'),
  81.     (ErrorCode: 10046; Text: 'Protocol family not supported'),
  82.     (ErrorCode: 10047; Text: 'Address family not supported by protocol family'),
  83.     (ErrorCode: 10048; Text: 'Address already in use'),
  84.     (ErrorCode: 10049; Text: 'Can''t assign requested address'),
  85.     (ErrorCode: 10050; Text: 'Network is down'),
  86.     (ErrorCode: 10051; Text: 'Network is unreachable'),
  87.     (ErrorCode: 10052; Text: 'Network dropped connection or reset'),
  88.     (ErrorCode: 10053; Text: 'Software caused connection abort'),
  89.     (ErrorCode: 10054; Text: 'Connection reset by peer'),
  90.     (ErrorCode: 10055; Text: 'No buffer space available'),
  91.     (ErrorCode: 10056; Text: 'Socket is already connected'),
  92.     (ErrorCode: 10057; Text: 'Socket is not connected'),
  93.     (ErrorCode: 10058; Text: 'Can''t send after socket shutdown'),
  94.     (ErrorCode: 10059; Text: 'Too many references, can''t splice'),
  95.     (ErrorCode: 10060; Text: 'Connection timed out'),
  96.     (ErrorCode: 10061; Text: 'Connection refused'),
  97.     (ErrorCode: 10062; Text: 'Too many levels of symbolic links'),
  98.     (ErrorCode: 10063; Text: 'File name too long'),
  99.     (ErrorCode: 10064; Text: 'Host is down'),
  100.     (ErrorCode: 10065; Text: 'No route to Host'),
  101.     (ErrorCode: 10066; Text: 'Directory not empty'),
  102.     (ErrorCode: 10067; Text: 'Too many processes'),
  103.     (ErrorCode: 10068; Text: 'Too many users'),
  104.     (ErrorCode: 10069; Text: 'Disc quota exceeded'),
  105.     (ErrorCode: 10070; Text: 'Stale NFS file handle'),
  106.     (ErrorCode: 10071; Text: 'Too many levels of remote in path'),
  107.     (ErrorCode: 10091; Text: 'Network subsystem is unavailable'),
  108.     (ErrorCode: 10092; Text: 'Incompatible version of WINSOCK.DLL'),
  109.     (ErrorCode: 10093; Text: 'Successful WSAStartup not yet performed'),
  110.     (ErrorCode: 11001; Text: 'Host not found'),
  111.     (ErrorCode: 11002; Text: 'Non-Authoritative Host not found'),
  112.     (ErrorCode: 11003; Text: 'Non-Recoverable error: FORMERR, REFUSED, NOTIMP'),
  113.     (ErrorCode: 11004; Text: 'Valid name, no data record of requested type'),
  114.     (ErrorCode: 0; Text: 'Unrecognized error code')
  115.     );
  116. type
  117.     {Event Handlers}
  118.   TOnErrorEvent = procedure(Sender: TComponent; Errno: Word; Errmsg: string) of object;
  119.   TOnHostResolved = procedure(Sender: TComponent) of object;
  120.   TOnStatus = procedure(Sender: TComponent; Status: string) of object;
  121.   THandlerEvent = procedure(var Handled: Boolean) of object;
  122.   { new basic pointer types }
  123.   PLongint = ^Longint;
  124.   PPLongInt = ^PLongint;
  125.   PPChar = ^PChar;
  126.   PINT = ^PInteger;
  127.   THostInfo = record
  128.     Name: PChar;
  129.     AliasList: PPChar;
  130.     AddressType: Integer;
  131.     AddressSize: Integer;
  132.     AddressList: PPLongInt;
  133.     Reserved: array[1..MAXGETHOSTSTRUCT] of Char;
  134.   end;
  135.   TServerInfo = record
  136.     Name: PChar;
  137.     Aliases: PPChar;
  138.     PORT: Integer;
  139.     Protocol: PChar;
  140.     Reserved: array[1..MAXGETHOSTSTRUCT] of Char;
  141.   end;
  142.   TProtocolInfo = record
  143.     Name: PChar;
  144.     Aliases: PPChar;
  145.     ProtocolID: Integer;
  146.     Reserved: array[1..MAXGETHOSTSTRUCT] of Char;
  147.   end;
  148.   TSocketAddress = record
  149.     Family: Integer;
  150.     PORT: Word;
  151.     Address: Longint;
  152.     Unused: array[1..8] of Char;
  153.   end;
  154.   TSocketList = record
  155.     Count: Integer;
  156.     DescriptorList: array[1..64] of Integer;
  157.   end;
  158.   TTimeValue = record
  159.     Sec: Longint;
  160.     uSec: Longint;
  161.   end;
  162.   {new WINSOCK pointer types}
  163.   PWSAData = ^TWSAData;
  164.   PHostInfo = ^THostInfo;
  165.   PServerInfo = ^TServerInfo;
  166.   PProtocolInfo = ^TProtocolInfo;
  167.   PSocketAddress = ^TSocketAddress;
  168.   PSocketList = ^TSocketList;
  169.   PTimeValue = ^TTimeValue;
  170.   ESockError = class(Exception);
  171.   EAbortError = class(ESockError);
  172.   TThreadTimer = class(TComponent)
  173.   private
  174.     FInterval: Cardinal;
  175.     FWindowHandle: HWND;
  176.     FOnTimer: TNotifyEvent;
  177.     FEnabled: Boolean;
  178.     procedure UpdateTimer;
  179.     procedure SetEnabled(Value: Boolean);
  180.     procedure SetInterval(Value: Cardinal);
  181.     procedure SetOnTimer(Value: TNotifyEvent);
  182.     procedure Wndproc(var Msg: TMessage);
  183.   protected
  184.     procedure Timer; dynamic;
  185.   public
  186.     constructor Create(AOwner: TComponent); override;
  187.     destructor Destroy; override;
  188.   published
  189.     property Enabled: Boolean read FEnabled write SetEnabled default True;
  190.     property Interval: Cardinal read FInterval write SetInterval default 1000;
  191.     property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  192.   end;
  193. {$IFNDEF NMF3}
  194.   { TStringStream }
  195.   TStringStream = class(TStream)
  196.   private
  197.     FDataString: string;
  198.     FPosition: Integer;
  199.   protected
  200.   public
  201.     procedure SetSize(NewSize: Longint);
  202.     constructor Create(const AString: string);
  203.     function Read(var Buffer; Count: Longint): Longint; override;
  204.     function ReadString(Count: Longint): string;
  205.     function Seek(Offset: Longint; Origin: Word): Longint; override;
  206.     function Write(const Buffer; Count: Longint): Longint; override;
  207.     procedure WriteString(const AString: string);
  208.     property DataString: string read FDataString;
  209.   end;
  210.   TThreadList = class
  211.   private
  212.     FList: TList;
  213.   public
  214.     constructor Create;
  215.     destructor Destroy; override;
  216.     procedure Add(Item: Pointer);
  217.     procedure Clear;
  218.     function LockList: TList;
  219.     procedure Remove(Item: Pointer);
  220.     procedure UnlockList;
  221.   end;
  222. {$ENDIF}
  223.   {*******************************************************************************************
  224.   Power Socket class definition
  225.   ********************************************************************************************}
  226.   TPowersock = class(TComponent)
  227.   private
  228.     Buf: array[0..MAX_RECV_BUF] of Char;
  229.     WaitSignal: TEvent;
  230.     {Event Handlers for Asynchronous socket events}
  231.     FOnReadEvent: TNotifyEvent;
  232.     FOnAcceptEvent: TNotifyEvent;
  233.     FOnConnect: TNotifyEvent;
  234.     FOnDisconnect: TNotifyEvent;
  235.     FOnErrorEvent: TOnErrorEvent; {Event handler for error notification}
  236.     FInvalidHost: THandlerEvent;
  237.     FOnHostResolved: TOnHostResolved; {Event handler after a host name is found}
  238.     FOnConnectionRequired: THandlerEvent;
  239.     FOnStatus: TOnStatus; {Event handler on a status change}
  240.     FOnConnectionFailed: TNotifyEvent;
  241.     FWSAInfo: TStringList;
  242.     {Component Internals}
  243.     FBytesSent: Longint; {Number of bytes currently sent}
  244.     Canceled: Boolean; {Flag to indicate request cancelled}
  245.     DestroySocket: Boolean; {flag to indicate socket to be destroyed or not}
  246.     FLastErrorno: Integer; {The last error Encountered}
  247.     FTimeOut: Integer; {Time to wait before timout}
  248.     FReportLevel: Integer; {Reporting Level}
  249.     _Status: string; {Current status}
  250.     FProxy: string; {Name or IP of proxy server}
  251.     FProxyPort: Integer; {Port of proxy server}
  252.     {TimeOut Functions}
  253.     Timer: TThreadTimer; {Timer for synchronous requests}
  254.     {For Documentation of functions and procedures see implementation}
  255.     procedure TimerFired(Sender: TObject);
  256.     procedure Wndproc(var message: TMessage); {}
  257.   protected
  258.     FifoQ: TNMFifoBuffer;
  259.     Succeed: Boolean; {Flag for indicating if synchronous request succeded}
  260.     TimedOut: Boolean; {Flag to indicate process timed out}
  261.     FPort: Integer; {Port at server to connect to}
  262.     FBytesTotal: Longint; {Total number of bytes to send or receive}
  263.     FBytesRecvd: Longint; {Number of bytes currently received}
  264.     FPacketRecvd: TNotifyEvent; {Handler after each packet received for progress reports etc}
  265.     FPacketSent: TNotifyEvent; {Handler after each packet received for progress reports etc}
  266.     Wait_Flag: Boolean; {Flag to indicate if synchronous request completed or not}
  267.     RemoteAddress: TSockAddr; {Address of remote host}
  268.     ServerName: string; {Name of remote host}
  269.     RemoteHost: PHostEnt; {Entity to store remote host linfo from a Hostname request}
  270.     FTransactionReply: string; {Reply to a command request}
  271.     FReplyNumber: Smallint; {Reply number to a command request}
  272.     DataGate: Boolean;
  273.     AbortGate: Boolean;
  274.     StrmType: Boolean;
  275.     OnAbortrestart: TNotifyEvent;
  276.     procedure TimerOn;
  277.     procedure TimerOff;
  278.     procedure InitWinsock;
  279.     procedure ReadToBuffer;
  280.     procedure SetLastErrorNo(Value: Integer);
  281.     function SocketErrorStr(Errno: Word): string;
  282.     function GetLastErrorNo: Integer;
  283.     function ErrorManager(Ignore: Word): string;
  284.     procedure SetWSAError(ErrorNo: Word; ErrorMsg: string);
  285.     procedure StatusMessage(Level: Byte; Value: string);
  286.     function GetRemoteIP: string;
  287.     function GetLocalIP: string;
  288.     procedure SetFifoCapacity(NewCapacity: Longint);
  289.     function GetFifoCapacity: Longint;
  290.     {Properties - Make Public the ones that the User needs to respond to in derived class}
  291.     {Event Handlers for Asynchronous Events}
  292.     property OnAccept: TNotifyEvent read FOnAcceptEvent write FOnAcceptEvent;
  293.     {Event Handler for Errors}
  294.     property OnError: TOnErrorEvent read FOnErrorEvent write FOnErrorEvent;
  295.     {Event Handler for Status changes}
  296.     property OnConnectionRequired: THandlerEvent read FOnConnectionRequired write FOnConnectionRequired;
  297.     property Proxy: string read FProxy write FProxy; {name or IP of proxy server}
  298.     property ProxyPort: Integer read FProxyPort write FProxyPort; {Port of proxy server}
  299.   public
  300.     ThisSocket: TSocket; {The socket number of the Powersocket}
  301.     FSocketWindow: HWND; {Dummy window handle to receive Socket messages}
  302.     FConnected: Boolean; {Flag indicating socket connected or not}
  303.     {For Documentation of functions and procedures see implementation}
  304.     constructor Create(AOwner: TComponent); override;
  305.     destructor Destroy; override;
  306.     {Runtime Properties}
  307.     {Methods}
  308.     function Accept: TSocket; virtual;
  309.     procedure Cancel;
  310.     procedure Connect; virtual;
  311.     procedure Disconnect; virtual;
  312.     procedure Wait;
  313.     procedure Listen(sync: Boolean);
  314.     procedure SendBuffer(Value: PChar; BufLen: Word);
  315.     procedure Write(Value: string);
  316.     procedure Writeln(Value: string);
  317.     function Read(Value: Word): string;
  318.     function Readln: string;
  319.     function Transaction(const CommandString: string): string; virtual;
  320.     procedure SendFile(Filename: string);
  321.     procedure SendStream(MainStream: TStream);
  322.     procedure SendRestStream(MainStream: TStream);
  323.     procedure CaptureFile(Filename: string);
  324.     procedure AppendFile(Filename: string);
  325.     procedure CaptureStream(MainStream: TStream; Size: Longint);
  326.     procedure CaptureString(var AString: string; Size: Longint);
  327.     procedure FilterHeader(HeaderStream: TFileStream);
  328.     procedure ResolveRemoteHost;
  329.     procedure RequestCloseSocket;
  330.     procedure Close(Socket: THandle);
  331.     procedure Abort; virtual;
  332.     procedure CertifyConnect;
  333.     function DataAvailable: Boolean;
  334.     procedure ClearInput;
  335.     procedure CloseAfterData;
  336.     procedure CloseImmediate;
  337.     function GetLocalAddress: string;
  338.     function GetPortString: string;
  339.     property WSAInfo: TStringList read FWSAInfo; {Winsock info}
  340.     property Connected: Boolean read FConnected;
  341.     property LastErrorNo: Integer read GetLastErrorNo write SetLastErrorNo; {Last Socket error}
  342.     property BeenCanceled: Boolean read Canceled write Canceled; {Status of Cancel request}
  343.     property BeenTimedOut: Boolean read TimedOut;
  344.     property ReplyNumber: Smallint read FReplyNumber; {Numerical result from transaction}
  345.     property RemoteIP: string read GetRemoteIP;
  346.     property LocalIP: string read GetLocalIP;
  347.     property TransactionReply: string read FTransactionReply; {Result from commnd request}
  348.     property BytesTotal: Longint read FBytesTotal; {Total bytes to send or receive}
  349.     property BytesSent: Longint read FBytesSent; {Bytes currently sent}
  350.     property BytesRecvd: Longint read FBytesRecvd; {Bytes currently received}
  351.     property Handle: TSocket read ThisSocket; {Power Socket handle}
  352.     property Status: string read _Status; {Current status}
  353.     property OnRead: TNotifyEvent read FOnReadEvent write FOnReadEvent;
  354.     property OnPacketRecvd: TNotifyEvent read FPacketRecvd write FPacketRecvd; {Handler for status messages during send or receive}
  355.     property OnPacketSent: TNotifyEvent read FPacketSent write FPacketSent; {Handler for status messages during send or receive}
  356.     property FifoCapacity: Longint read GetFifoCapacity write SetFifoCapacity;
  357.   published
  358.     {Properties}
  359.     property Host: string read ServerName write ServerName; {Host Nmae or IP of remote host}
  360.     property PORT: Integer read FPort write FPort; {Port of remote host}
  361.     property TimeOut: Integer read FTimeOut write FTimeOut default 0; {Time before being timed out}
  362.     property ReportLevel: Integer read FReportLevel write FReportLevel default Status_Informational;
  363.     {Events}
  364.     property OnDisconnect: TNotifyEvent read FOnDisconnect write FOnDisconnect;
  365.     property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
  366.     property OnInvalidHost: THandlerEvent read FInvalidHost write FInvalidHost;
  367.     property OnHostResolved: TOnHostResolved read FOnHostResolved write FOnHostResolved;
  368.     property OnStatus: TOnStatus read FOnStatus write FOnStatus;
  369.     property OnConnectionFailed: TNotifyEvent read FOnConnectionFailed write FOnConnectionFailed;
  370.   end;
  371.   {*******************************************************************************************
  372.   PowerSocket Server Class definition
  373.   ********************************************************************************************}
  374.   PTNMGeneralServer = ^TNMGeneralServer;
  375.   TNMGeneralServer = class(TPowersock)
  376.   private
  377.     ATlist: TThreadList;
  378.     FOnClientContact: TNotifyEvent;
  379.     procedure DisPatchResponse(data: Pointer);
  380.   protected
  381.     Chief: TNMGeneralServer;
  382.   public
  383.     ItsThread: TThread;
  384.     constructor Create(AOwner: TComponent); override;
  385.     procedure Connect; override;
  386.     procedure Loaded; override;
  387.     procedure Serve; virtual;
  388.     procedure Abort; override;
  389.     destructor Destroy; override;
  390.     procedure ServerAccept(Sender: TObject);
  391.   published
  392.     property OnClientContact: TNotifyEvent read FOnClientContact write FOnClientContact;
  393.   end;
  394.   {*******************************************************************************************
  395.   Thread to Serve Client in Server Class definition
  396.   ********************************************************************************************}
  397.   TThreadMethod = procedure(data: Pointer) of object;
  398.   TSimpleThread = class(TThread)
  399.   public
  400.     constructor CreateSimple(CreateSuspended: Boolean;
  401.       _Action: TThreadMethod;
  402.       _Data: Pointer);
  403.     procedure AbortThread;
  404.   protected
  405.     ThreadMethod: TThreadMethod;
  406.     data: Pointer;
  407.   private
  408.     procedure Execute; override;
  409.   end;
  410. function ExecuteInThread(Handler: TThreadMethod; data: Pointer): TSimpleThread;
  411. {For Documentation of functions and procedures see implementation}
  412. function NthWord(InputString: string; Delimiter: Char; Number: Integer): string;
  413. function NthPos(InputString: string; Delimiter: Char; Number: Integer): Integer;
  414. procedure StreamLn(AStream: TStream; AString: string);
  415. function PsockAllocateHWnd(Obj: TObject): HWND;
  416. function TmrAllocateHWnd(Obj: TObject): HWND;
  417. implementation
  418. uses
  419.   Shellapi;
  420. var
  421.   SockAvailable: Boolean;
  422.   MyWSAData: TWSAData; {Socket Information}
  423. constructor TSimpleThread.CreateSimple(CreateSuspended: Boolean;
  424.   _Action: TThreadMethod;
  425.   _Data: Pointer);
  426. begin
  427.   ThreadMethod := _Action; // Set these BEFORE calling
  428.   data := _Data; // inherited Create()!
  429.   FreeOnTerminate := True;
  430.   inherited Create(CreateSuspended);
  431. end;
  432. procedure TSimpleThread.Execute;
  433. begin
  434.   ThreadMethod(data);
  435. end;
  436. procedure TSimpleThread.AbortThread;
  437. begin
  438.   Suspend;
  439.   Free; // Kills thread
  440. end;
  441. function ExecuteInThread(Handler: TThreadMethod;
  442.   data: Pointer): TSimpleThread;
  443. begin
  444.   Result := TSimpleThread.CreateSimple(False, Handler, data);
  445. end;
  446. procedure WaitforSync(Handle: THandle);
  447. begin
  448.   repeat
  449.     if MsgWaitForMultipleObjects(1, Handle, False, INFINITE, QS_ALLINPUT) = WAIT_OBJECT_0 + 1 then
  450.       Application.ProcessMessages
  451.     else
  452.       Break;
  453.   until True = False;
  454. end;
  455. {*******************************************************************************************
  456. Create Power Socket
  457. ********************************************************************************************}
  458. constructor TPowersock.Create(AOwner: TComponent);
  459. begin
  460.   StatusMessage(Status_Debug, sPSk_Cons_msg_create); {Inform Status}
  461.   inherited Create(AOwner);
  462. {$IFDEF DEMOVER}
  463.   if not (csDesigning in ComponentState) then
  464.     ShowMessage('This uses the Demo Version of the Netmasters Componnents. Please Register');
  465. {$ENDIF}
  466.   FSocketWindow := PsockAllocateHWnd(self); {Create Window handle to receive message notification}
  467.   WaitSignal := TEvent.Create(nil, True, False, '');
  468.   if not (csDesigning in ComponentState) then
  469.     FifoQ := TNMFifoBuffer.Create;
  470.   FProxy := ''; {Default - No Proxy}
  471.   {Initialize memory }
  472.   GetMem(RemoteHost, MAXGETHOSTSTRUCT); {Initialize memory for host address structure}
  473.   Timer := TThreadTimer.Create(self); {Create timer}
  474.   Timer.Enabled := False; {Timer Disabled}
  475.   Timer.OnTimer := TimerFired; {Set Function to execcute on TimeOut}
  476.   FTimeOut := 0;
  477.   FWSAInfo := TStringList.Create;
  478.   if SockAvailable then
  479.   begin
  480.     FWSAInfo.Add(sPSk_Cons_winfo_ver + IntToStr(HiByte(MyWSAData.wVersion)) + '.' + IntToStr(LoByte(MyWSAData.wVersion)));
  481.     FWSAInfo.Add(sPSk_Cons_winfo_Hiver + IntToStr(HiByte(MyWSAData.wHighVersion)) + '.' + IntToStr(LoByte(MyWSAData.wHighVersion)));
  482.     FWSAInfo.Add(sPSk_Cons_winfo_Descr + MyWSAData.szDescription);
  483.     FWSAInfo.Add(sPSk_Cons_winfo_Sys + MyWSAData.szSystemStatus);
  484.     FWSAInfo.Add(sPSk_Cons_winfo_MaxSoc + IntToStr(MyWSAData.iMaxSockets));
  485.     FWSAInfo.Add(sPSk_Cons_winfo_MaxUdp + IntToStr(MyWSAData.iMaxUdpDg));
  486.   end;
  487.   Canceled := False; {Cancelled flag off}
  488.   DestroySocket := False; {Socket is active}
  489.   FConnected := False; {Socket is not connected}
  490.   {Call Initialization functions }
  491.   InitWinsock;
  492.   {Turn on Messaging.... }
  493. end;
  494. {*******************************************************************************************
  495. Destroy Power Socket
  496. ********************************************************************************************}
  497. destructor TPowersock.Destroy;
  498. begin
  499.   StatusMessage(Status_Debug, sPSk_Cons_msg_Dest); {Inform Status}
  500.   try
  501.     Abort;
  502.     Cancel;
  503.     FWSAInfo.Free;
  504.     Timer.Free;
  505.     FreeMem(RemoteHost, MAXGETHOSTSTRUCT); {Free memory for fetching Host Entity}
  506.     DestroyWindow(FSocketWindow); {Release window handle for Winsock messages}
  507.     WaitSignal.Destroy;
  508.     FifoQ.Free;
  509.     DestroySocket := True; {set flag to destoy socket}
  510.     if not (csDesigning in ComponentState) then
  511.       RequestCloseSocket; {close socket}
  512.   finally
  513.     inherited Destroy;
  514.   end
  515. end;
  516. {*******************************************************************************************
  517. Connect Power Socket to Remote
  518. ********************************************************************************************}
  519. procedure TPowersock.Connect;
  520. var
  521.   CT, I: Integer;
  522.   Handled: Boolean;
  523. begin
  524.   StatusMessage(Status_Debug, sPSk_Cons_msg_Conning); {Inform Status}
  525.   Canceled := False; {Turn Canceled off}
  526.   FifoQ.Clear;
  527.   if FConnected then {If already connected raise exception}
  528.     raise ESockError.Create(sPSk_Cons_msg_Conn);
  529.   CT := 0;
  530.   repeat
  531.     try
  532.       ResolveRemoteHost; {Resolve the IP address of remote host}
  533.     except
  534.       on E: ESockError do
  535.         if (E.message = sPSk_Cons_msg_host_to) or (E.message = sPSk_Cons_msg_host_Can) then
  536.           raise;
  537.     end;
  538.     if RemoteAddress.sin_addr.S_addr = 0 then
  539.       if CT > 0 then
  540.         raise ESockError.Create(sPSk_Cons_msg_add_null) {If Resolving failed raise exception}
  541.       else if not Assigned(OnInvalidHost) then
  542.         raise ESockError.Create(sPSk_Cons_msg_add_null)
  543.       else
  544.       begin
  545.         Handled := False;
  546.         OnInvalidHost(Handled);
  547.         if not Handled then
  548.           raise ESockError.Create(sPSk_Cons_msg_add_null);
  549.         CT := CT + 1;
  550.       end;
  551.   until RemoteAddress.sin_addr.S_addr <> 0;
  552.   RemoteAddress.sin_family := AF_INET; {Make connected true}
  553. {$R-}
  554.   if Proxy = '' then
  555.     RemoteAddress.sin_port := htons(PORT) {If no proxy get port from Port property}
  556.   else
  557.     RemoteAddress.sin_port := htons(FProxyPort); {else get port from ProxyPort property}
  558. {$R+}
  559.   Wait_Flag := False; { Wait for synchronous response}
  560.   I := SizeOf(RemoteAddress); { get size of remoteaddress structure}
  561.   {Connect to remote host}
  562.   Succeed := True;
  563.   I := Winsock.Connect(ThisSocket, RemoteAddress, I);
  564.   if (I = INVALID_SOCKET) then
  565.     ErrorManager(WSAEWOULDBLOCK); {If error handle error}
  566.   TimerOn; {Enable Timer on for TimeOuts}
  567.   try
  568.     while not (FConnected or TimedOut or Canceled or (not Succeed)) do
  569.       Wait;
  570.   finally
  571.     TimerOff; {Disable Timer}
  572.   end;
  573.   CloseAfterData;
  574.   if (TimedOut or Canceled or not Succeed) then
  575.   begin
  576.     if Assigned(FOnConnectionFailed) then
  577.       FOnConnectionFailed(self);
  578.     if TimedOut then
  579.     begin
  580.       try
  581.         Disconnect;
  582.       except
  583.       end;
  584.       raise ESockError.Create(Cons_Msg_ConnectionTimedOut);
  585.     end;
  586.     if Canceled then
  587.       raise ESockError.Create(sPSk_Cons_msg_Conn_can);
  588.     if Succeed = False then
  589.       raise ESockError.Create(sPSk_Cons_msg_Conn_fai);
  590.   end;
  591. end;
  592. {*******************************************************************************************
  593. DisConnect Socket From Remote
  594. ********************************************************************************************}
  595. procedure TPowersock.Disconnect;
  596. begin
  597.   StatusMessage(Status_Debug, sPSk_Cons_msg_Disconn); {Status Message}
  598.   if FConnected then
  599.     RequestCloseSocket; {Close socket and open new one}
  600. end;
  601. procedure TPowersock.Wait;
  602. begin
  603.   WaitforSync(WaitSignal.Handle);
  604.   WaitSignal.ResetEvent;
  605. end;
  606. procedure TPowersock.CertifyConnect;
  607. var
  608.   TryCt: Integer;
  609.   Handled: Boolean;
  610. begin
  611.   StatusMessage(Status_Debug, sPSk_Cons_msg_CertConn); {Status Message}
  612.   TryCt := 0;
  613.   while not Connected do
  614.   begin
  615.     if TryCt > 0 then
  616.       raise Exception.Create(sPSk_Cons_err_NotConn)
  617.     else if not Assigned(FOnConnectionRequired) then
  618.       raise Exception.Create(sPSk_Cons_err_NotConn)
  619.     else
  620.     begin
  621.       Handled := False;
  622.       FOnConnectionRequired(Handled);
  623.       if not Handled then
  624.         raise Exception.Create(sPSk_Cons_err_NotConn);
  625.       TryCt := TryCt + 1;
  626.     end;
  627.   end;
  628. end;
  629. {*******************************************************************************************
  630. Canel current transaction
  631. ********************************************************************************************}
  632. procedure TPowersock.Cancel;
  633. begin
  634.   StatusMessage(Status_Debug, sPSk_Cons_msg_Cancel); {Status Message}
  635.   Canceled := True;
  636.   WaitSignal.SetEvent;
  637. end;
  638. {*******************************************************************************************
  639. Send at value of length buflen
  640. ********************************************************************************************}
  641. procedure TPowersock.SendBuffer(Value: PChar; BufLen: Word);
  642. var
  643.   rc2, LeftB: Integer;
  644. begin
  645.   StatusMessage(Status_Routines, sPSk_Cons_msg_SBuff); {Status Message}
  646.   TimerOn;
  647.   try
  648.     if not Canceled then
  649.     begin
  650.         {If explicit buffer length given use it else get it from string length}
  651.       if BufLen = 0 then
  652.         BufLen := StrLen(Value);
  653.       LeftB := BufLen;
  654.       repeat
  655.         rc2 := Winsock.send(ThisSocket, Value[BufLen - LeftB], LeftB, 0);
  656.         if rc2 = 0 then
  657.           Break;
  658.         if rc2 > -1 then
  659.         begin
  660.           LeftB := LeftB - rc2;
  661.         end
  662.         else
  663.           ErrorManager(WSAEWOULDBLOCK);
  664.       until (LeftB = 0) or Canceled or TimedOut;
  665.     end;
  666.     if Canceled then
  667.     begin
  668.       Canceled := False;
  669.       raise EAbortError.Create(sPSk_Cons_msg_send_a);
  670.       if Assigned(OnAbortrestart) then
  671.         OnAbortrestart(self);
  672.     end;
  673.   finally
  674.     TimerOff;
  675.   end;
  676. end;
  677. {*******************************************************************************************
  678. Write String To Socket
  679. ********************************************************************************************}
  680. procedure TPowersock.Write(Value: string);
  681. var
  682.   MyStringStream: TStringStream;
  683. begin
  684.   StatusMessage(Status_Debug, sPSk_Cons_msg_write); {Report Status}
  685.   if Length(Value) > MAX_RECV_BUF then
  686.   begin
  687.     MyStringStream := TStringStream.Create(Value);
  688.     try
  689.       SendStream(MyStringStream);
  690.     finally
  691.       MyStringStream.Free;
  692.     end;
  693.   end
  694.   else
  695.   begin
  696.     StrPLCopy(Buf, Value, MAX_RECV_BUF); {Copy string to buffer}
  697.     SendBuffer(Buf, 0); {Send the buffer}
  698.   end;
  699. end;
  700. {*******************************************************************************************
  701. Write Line ending with Carriage Return and Line Feed To Socket
  702. ********************************************************************************************}
  703. procedure TPowersock.Writeln(Value: string);
  704. begin
  705.   StatusMessage(Status_Debug, sPSk_Cons_msg_writeln); {Inform Status}
  706.   Value := Value + CRLF;
  707.   Write(Value);
  708. end;
  709. {*******************************************************************************************
  710. Read Given Number of bytes from Socket
  711. ********************************************************************************************}
  712. function TPowersock.Read(Value: Word): string;
  713. begin
  714.   StatusMessage(Status_Debug, sPSk_Cons_msg_read + IntToStr(Value) + ' )'); {Inform status}
  715.   if Value = 0 then
  716.     Value := FifoQ.BufferSize;
  717.   TimerOn;
  718.   while (FifoQ.BufferSize < Value) and (not Canceled) and (not TimedOut) do
  719.     Wait;
  720.   TimerOff;
  721.   if Value = 0 then
  722.     Result := ''
  723.   else
  724.   begin
  725.     SetLength(Result, Value);
  726.     FifoQ.Remove(Pointer(@Result[1]), Value);
  727.   end;
  728.   if Canceled then
  729.   begin
  730.     Canceled := False;
  731.     raise EAbortError.Create(sPSk_Cons_msg_send_a);
  732.     if Assigned(OnAbortrestart) then
  733.       OnAbortrestart(self);
  734.   end;
  735. end;
  736. {*******************************************************************************************
  737. Read Line from Socket
  738. ********************************************************************************************}
  739. function TPowersock.Readln: string;
  740. var
  741.   I: Integer;
  742.   LF: string;
  743. begin
  744.   LF := #10;
  745.   StatusMessage(Status_Debug, sPSk_Cons_msg_readln); {Inform status}
  746.   Result := '';
  747.   I := 0;
  748.   TimerOn;
  749.   try
  750.     while not (TimedOut or Canceled) do
  751.     begin
  752.       if DataAvailable then
  753.       begin
  754.         I := FifoQ.Search(Pointer(LF));
  755.         if I > 0 then
  756.           Break;
  757.       end;
  758.       Wait;
  759.     end;
  760.     if I > 0 then
  761.     begin
  762.       SetLength(Result, I);
  763.       FifoQ.Remove(PChar(@Result[1]), I);
  764.     end;
  765.     if Canceled then
  766.     begin
  767.       Canceled := False;
  768.       raise EAbortError.Create(sPSk_Cons_msg_readln_a);
  769.       if Assigned(OnAbortrestart) then
  770.         OnAbortrestart(self);
  771.     end;
  772.   finally
  773.     TimerOff
  774.   end;
  775. end;
  776. {*******************************************************************************************
  777. Send command To Socket and get Reply
  778. ********************************************************************************************}
  779. function TPowersock.Transaction;
  780. var
  781.   I: Integer;
  782.   temp: string;
  783. begin
  784.   StatusMessage(Status_Debug, sPSk_Cons_msg_transa); {Inform status}
  785.   FReplyNumber := 0; {Initialise Numerical reply}
  786.   Writeln(CommandString); {Write Command string to Socket}
  787.   FTransactionReply := Readln; {Get Reply}
  788.   if Length(FTransactionReply) > 0 then
  789.   begin
  790.     StatusMessage(Status_Informational, FTransactionReply); {Report status}
  791.     temp := '';
  792.     for I := 1 to 10 do
  793.       if (FTransactionReply[I] >= '0') and (FTransactionReply[I] <= '9') then
  794.         temp := temp + FTransactionReply[I]
  795.       else
  796.         Break;
  797.     if temp <> '' then
  798.       FReplyNumber := StrToIntDef(temp, 0); {Extract Numerical Result if any}
  799.   end;
  800.   Result := FTransactionReply; {Return Reply}
  801. end;
  802. {*******************************************************************************************
  803. Send File To Socket
  804. ********************************************************************************************}
  805. procedure TPowersock.SendFile(Filename: string);
  806. var
  807.   strm: TFileStream;
  808.   rc, LeftB, rc2: Integer;
  809. begin
  810.   StatusMessage(Status_Debug, sPSk_Cons_msg_sendf); {Status Message}
  811.   strm := TFileStream.Create(Filename, fmOpenRead);
  812.   try
  813.     repeat
  814.       if not Canceled then
  815.       begin
  816.         rc := strm.Read(Buf, MAX_RECV_BUF);
  817.           {If explicit buffer length given use it else get it from string length}
  818.         LeftB := rc;
  819.         repeat
  820.           rc2 := Winsock.send(ThisSocket, Buf[rc - LeftB], LeftB, 0);
  821.           if rc2 = 0 then
  822.             Break;
  823.           if rc2 > -1 then
  824.           begin
  825.             LeftB := LeftB - rc2;
  826.             FBytesSent := FBytesSent + rc2;
  827.             if Assigned(FPacketSent) then
  828.               FPacketSent(self);
  829.             TimerOn;
  830.           end
  831.           else
  832.             ErrorManager(WSAEWOULDBLOCK);
  833.           Application.ProcessMessages;
  834.         until (LeftB = 0) or Canceled;
  835.       end;
  836.     until (strm.position = strm.Size) or Canceled;
  837.   finally
  838.     strm.Free;
  839.   end;
  840.   if Canceled then
  841.   begin
  842.     Canceled := False;
  843.     raise EAbortError.Create(sPSk_Cons_msg_send_a);
  844.     if Assigned(OnAbortrestart) then
  845.       OnAbortrestart(self);
  846.   end;
  847. end;
  848. {*******************************************************************************************
  849. Send File To Socket
  850. ********************************************************************************************}
  851. procedure TPowersock.SendRestStream(MainStream: TStream);
  852. var
  853.   rc, LeftB, rc2, r3: Longint;
  854. begin
  855.   StatusMessage(Status_Debug, sPSk_Cons_msg_sendstrm); {Status Message}
  856.   if not Canceled then
  857.   begin
  858.       {If explicit buffer length given use it else get it from string length}
  859.     FBytesSent := 0;
  860.     FBytesTotal := MainStream.Size;
  861.     repeat
  862.       r3 := MainStream.Size - MainStream.position;
  863.       if r3 > MAX_RECV_BUF then
  864.         r3 := MAX_RECV_BUF;
  865.       rc := MainStream.Read(Buf, r3);
  866.       LeftB := rc;
  867.       repeat
  868.         rc2 := Winsock.send(ThisSocket, Buf[rc - LeftB], LeftB, 0);
  869.         if rc2 = 0 then
  870.           Exit;
  871.         if rc2 > 0 then
  872.         begin
  873.           LeftB := LeftB - rc2;
  874.           FBytesSent := FBytesSent + rc2;
  875.           TimerOn;
  876.           if Assigned(FPacketSent) then
  877.             FPacketSent(self);
  878.         end
  879.         else
  880.           ErrorManager(WSAEWOULDBLOCK);
  881.         Application.ProcessMessages;
  882.       until (LeftB = 0) or Canceled;
  883.     until (MainStream.Size = MainStream.position) or Canceled;
  884.   end;
  885.   if Canceled then
  886.   begin
  887.     Canceled := False;
  888.     raise EAbortError.Create(sPSk_Cons_msg_send_a);
  889.     if Assigned(OnAbortrestart) then
  890.       OnAbortrestart(self);
  891.   end;
  892. end;
  893. {*******************************************************************************************
  894. Send File To Socket
  895. ********************************************************************************************}
  896. procedure TPowersock.SendStream(MainStream: TStream);
  897. var
  898.   rc, LeftB, rc2, r3: Longint;
  899. begin
  900.   StatusMessage(Status_Debug, sPSk_Cons_msg_sendstrm); {Status Message}
  901.   MainStream.position := 0;
  902.   if not Canceled then
  903.   begin
  904.       {If explicit buffer length given use it else get it from string length}
  905.     FBytesSent := 0;
  906.     FBytesTotal := MainStream.Size;
  907.     repeat
  908.       r3 := MainStream.Size - MainStream.position;
  909.       if r3 > MAX_RECV_BUF then
  910.         r3 := MAX_RECV_BUF;
  911.       rc := MainStream.Read(Buf, r3);
  912.       LeftB := rc;
  913.       repeat
  914.         rc2 := Winsock.send(ThisSocket, Buf[rc - LeftB], LeftB, 0);
  915.         if rc2 = 0 then
  916.           Exit;
  917.         if rc2 > 0 then
  918.         begin
  919.           LeftB := LeftB - rc2;
  920.           FBytesSent := FBytesSent + rc2;
  921.           if Assigned(FPacketSent) then
  922.             FPacketSent(self);
  923.         end
  924.         else
  925.           ErrorManager(WSAEWOULDBLOCK);
  926.         Application.ProcessMessages;
  927.       until (LeftB = 0) or Canceled;
  928.     until (MainStream.Size = MainStream.position) or Canceled;
  929.   end;
  930.   if Canceled then
  931.   begin
  932.     Canceled := False;
  933.     raise EAbortError.Create(sPSk_Cons_msg_send_a);
  934.     if Assigned(OnAbortrestart) then
  935.       OnAbortrestart(self);
  936.   end;
  937. end;
  938. {*******************************************************************************************
  939. Append File from Socket
  940. ********************************************************************************************}
  941. procedure TPowersock.AppendFile(Filename: string);
  942. var
  943.   strm: TFileStream;
  944. begin
  945.   StatusMessage(Status_Debug, sPSk_Cons_msg_cap_fil_app); {Send status}
  946.   strm := TFileStream.Create(Filename, fmOpenWrite); {Create file stream to read from}
  947.   try
  948.     strm.position := strm.Size;
  949.     CaptureStream(strm, -2);
  950.   finally
  951.     strm.Free;
  952.   end;
  953. end;
  954. {*******************************************************************************************
  955. Capture File from Socket
  956. ********************************************************************************************}
  957. procedure TPowersock.CaptureFile(Filename: string);
  958. var
  959.   strm: TFileStream;
  960. begin
  961.   StatusMessage(Status_Debug, sPSk_Cons_msg_cap_fil); {Send status}
  962.   strm := TFileStream.Create(Filename, fmCreate); {Create file stream to read from}
  963.   try
  964.     CaptureStream(strm, -2);
  965.   finally
  966.     strm.Free;
  967.   end;
  968. end;
  969. {*******************************************************************************************
  970. Capture File from Socket
  971. ********************************************************************************************}
  972. procedure TPowersock.CaptureStream(MainStream: TStream; Size: Longint);
  973. var
  974.   j: Longint;
  975. begin
  976.   StatusMessage(Status_Debug, sPSk_Cons_msg_cap_strm); {Send status}
  977.   FBytesRecvd := 0;
  978.   TimerOn;
  979.   try
  980.     while (not Canceled) do
  981.     begin
  982.       while ((not (DataAvailable)) and (not Canceled) and (Connected) and (Size <> -1)) do
  983.         Wait;
  984.       j := FifoQ.BufferSize;
  985.       if j > MAX_RECV_BUF then
  986.         j := MAX_RECV_BUF;
  987.       FifoQ.Remove(@Buf, j);
  988.       MainStream.WriteBuffer(Buf, j); {Write it to stream}
  989.       FBytesRecvd := FBytesRecvd + j;
  990.       if Assigned(FPacketRecvd) then
  991.         FPacketRecvd(self);
  992.       TimerOn;
  993.       if ((not Connected) or (MainStream.Size = Size)) or (Size = -1) then
  994.         Break;
  995.     end;
  996.     if Canceled then
  997.     begin
  998.       Canceled := False;
  999.       raise EAbortError.Create(sPSk_Cons_msg_cap_a);
  1000.       if Assigned(OnAbortrestart) then
  1001.         OnAbortrestart(self);
  1002.     end;
  1003.   finally
  1004.     TimerOff;
  1005.   end;
  1006. end;
  1007. {*******************************************************************************************
  1008. Capture File from Socket
  1009. ********************************************************************************************}
  1010. procedure TPowersock.CaptureString(var AString: string; Size: Longint);
  1011. var
  1012.   I, j: Longint;
  1013. begin
  1014.   StatusMessage(Status_Debug, sPSk_Cons_msg_string); {Send status}
  1015.   StatusMessage(Status_Debug, sPSk_Cons_msg_cap_fil);
  1016.   FBytesRecvd := 0;
  1017.   SetLength(AString, 0);
  1018.   TimerOn;
  1019.   try
  1020.     while (not Canceled) do
  1021.     begin
  1022.       while ((FifoQ.BufferSize = 0) and (not Canceled) and (Connected) and (Size <> -1)) do
  1023.         Wait;
  1024.       I := Length(AString);
  1025.       j := FifoQ.BufferSize;
  1026.       if Size <> -1 then
  1027.         if I + j < Size then
  1028.           j := Size - I;
  1029.       if j <> 0 then
  1030.       begin
  1031.         SetLength(AString, I + j);
  1032.         FifoQ.Remove(@AString[I + 1], j);
  1033.         FBytesRecvd := FBytesRecvd + j;
  1034.         TimerOn;
  1035.       end;
  1036.       if Assigned(FPacketRecvd) then
  1037.         FPacketRecvd(self);
  1038.       if not Connected then
  1039.         Break;
  1040.     end;
  1041.     if Canceled then
  1042.     begin
  1043.       Canceled := False;
  1044.       raise EAbortError.Create(sPSk_Cons_msg_cap_a);
  1045.       if Assigned(OnAbortrestart) then
  1046.         OnAbortrestart(self);
  1047.     end;
  1048.   finally
  1049.     TimerOff;
  1050.   end;
  1051. end;
  1052. {*******************************************************************************************
  1053. Filter out a MIME header
  1054. ********************************************************************************************}
  1055. procedure TPowersock.FilterHeader(HeaderStream: TFileStream);
  1056. var
  1057.   StrIn: string;
  1058. begin
  1059.   StatusMessage(Status_Debug, sPSk_Cons_msg_filthead); {Inform status}
  1060.   repeat
  1061.     StrIn := Readln; {Read a line}
  1062.     HeaderStream.WriteBuffer(StrIn[1], Length(StrIn)) {Write it to buffer}
  1063.   until (StrIn = LF) or (StrIn = CRLF) or (StrIn = ''); {Until blank line}
  1064. end;
  1065. {*******************************************************************************************
  1066. Initialize Socket and Listen to It
  1067. ********************************************************************************************}
  1068. procedure TPowersock.Listen(sync: Boolean);
  1069. begin
  1070.   StatusMessage(Status_Debug, sPSk_Cons_msg_Listen); {Report status}
  1071.   {Set Address to blank}
  1072.   RemoteAddress.sin_addr.S_addr := Inet_Addr(StrPCopy(Buf, '0.0.0.0'));
  1073.   RemoteAddress.sin_family := AF_INET; {Family = Internet address}
  1074.   RemoteAddress.sin_port := htons(PORT); {Set port to given port}
  1075.   {Bind Socket to given address}
  1076.   Winsock.bind(ThisSocket, RemoteAddress, SizeOf(RemoteAddress));
  1077.   {Direct reply message to WM_WAITFORRESPONSE handler}
  1078.   if sync then
  1079.     WSAAsyncselect(ThisSocket, FSocketWindow, WM_WAITFORRESPONSE, FD_ALL)
  1080.   else
  1081.     WSAAsyncselect(ThisSocket, FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_ALL);
  1082.   {Listen to socket}
  1083.   Winsock.Listen(ThisSocket, 5);
  1084. end;
  1085. {*******************************************************************************************
  1086. Accept Input from Listening Socket
  1087. ********************************************************************************************}
  1088. function TPowersock.Accept;
  1089. var
  1090.   SockHandle: TSocket;
  1091.   ASocKAddr: TSockAddr;
  1092.   Asize: Integer;
  1093. begin
  1094.   StatusMessage(Status_Routines, sPSk_Cons_msg_accept); {Status message}
  1095.   TimerOn;
  1096.   while (not Wait_Flag) and (not Canceled) do
  1097.     Wait;
  1098.   TimerOff;
  1099.   {if error create exception}
  1100.   if Canceled then
  1101.     raise ESockError.Create(sPSk_Cons_msg_acc_can);
  1102.   if not Succeed then
  1103.     raise ESockError.Create(sPSk_Cons_err_data_conn);
  1104.   Asize := SizeOf(ASocKAddr); {Size of Socket address structure}
  1105.   {Accept socket}
  1106. {$IFDEF NMF3}
  1107.   SockHandle := Winsock.Accept(ThisSocket, @ASocKAddr, @Asize);
  1108. {$ELSE}
  1109.   SockHandle := Winsock.Accept(ThisSocket, ASocKAddr, Asize);
  1110. {$ENDIF}
  1111.   Result := SockHandle; {Make the Accepte socket This Socket}
  1112.   WSAAsyncselect(SockHandle, FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_ALL); {To direct messages to clientsocket}
  1113.   RemoteAddress := ASocKAddr; {save remote host address info}
  1114.   if Canceled then
  1115.   begin
  1116.     Canceled := False;
  1117.     raise EAbortError.Create(sPSk_Cons_msg_send_a);
  1118.     if Assigned(OnAbortrestart) then
  1119.       OnAbortrestart(self);
  1120.   end;
  1121. end;
  1122. {*******************************************************************************************
  1123. Return Error Message Corresponding To Error number
  1124. ********************************************************************************************}
  1125. function TPowersock.SocketErrorStr(Errno: Word): string;
  1126. var
  1127.   x: Integer;
  1128. begin
  1129.   StatusMessage(Status_Debug, sPSk_Cons_msg_elookup + Result); {Status message}
  1130.   Result := '';
  1131.   if Errno <> 0 then
  1132.   begin
  1133.     for x := 0 to 50 do {Get error string}
  1134.       if WinsockMessage[x].ErrorCode = Errno then
  1135.         Result := IntToStr(WinsockMessage[x].ErrorCode) + ':' + WinsockMessage[x].Text;
  1136.     if Result = '' then {If not found say unknown error}
  1137.       Result := sPSk_Cons_msg_unknown + IntToStr(Errno);
  1138.   end;
  1139. end;
  1140. procedure TPowersock.CloseAfterData;
  1141. var
  1142.   gudtLinger: Tlinger;
  1143. begin
  1144.   gudtLinger.l_onoff := 0;
  1145.   gudtLinger.l_linger := 0;
  1146.   setsockopt(ThisSocket, SOL_SOCKET, SO_LINGER, @gudtLinger, 4);
  1147. end;
  1148. procedure TPowersock.CloseImmediate;
  1149. var
  1150.   gudtLinger: Tlinger;
  1151. begin
  1152.   gudtLinger.l_onoff := 0;
  1153.   gudtLinger.l_linger := 0;
  1154.   setsockopt(ThisSocket, SOL_SOCKET, SO_DONTLINGER, @gudtLinger, 4);
  1155. end;
  1156. {*******************************************************************************************
  1157. TimeOut Handler
  1158. ********************************************************************************************}
  1159. procedure TPowersock.TimerFired(Sender: TObject);
  1160. begin
  1161.   StatusMessage(Status_Debug, sPSk_Cons_msg_ttrig); {Status Message}
  1162.   TimerOff; {Switch off timer}
  1163.   TimedOut := True; {Set timed out flag}
  1164.   WaitSignal.SetEvent;
  1165.   Abort;
  1166. end;
  1167. {*******************************************************************************************
  1168. Set Timer On
  1169. ********************************************************************************************}
  1170. procedure TPowersock.TimerOn;
  1171. begin
  1172.   StatusMessage(Status_Debug, sPSk_Cons_msg_TimerOn); {Status Message}
  1173.   TimedOut := False; {Timed out flag reset}
  1174.   Timer.Enabled := False; {Enable timer}
  1175.   Timer.Interval := FTimeOut; {Set TimeOut Interval}
  1176.   Timer.Enabled := True; {Enable timer}
  1177. end;
  1178. {*******************************************************************************************
  1179. Set Timer Off
  1180. ********************************************************************************************}
  1181. procedure TPowersock.TimerOff;
  1182. begin
  1183.   StatusMessage(Status_Debug, sPSk_Cons_msg_TimerOff); {Status Message}
  1184.   Timer.Enabled := False; {Disable timer}
  1185. end;
  1186. {*******************************************************************************************
  1187. Initialize WinSock
  1188. ********************************************************************************************}
  1189. procedure TPowersock.InitWinsock;
  1190. var
  1191.   gudtLinger: Tlinger;
  1192. begin
  1193.   StatusMessage(Status_Debug, sPSk_Cons_msg_InitSock); {Status Message}
  1194.   {Startup Winsock}
  1195.   if (not (csDesigning in ComponentState)) and SockAvailable then
  1196.   try
  1197.     ThisSocket := Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  1198.     gudtLinger.l_onoff := 0;
  1199.     gudtLinger.l_linger := 0;
  1200. {$T-}
  1201.     setsockopt(ThisSocket, SO_DONTLINGER, SO_LINGER, @gudtLinger, 4);
  1202. {$T+}
  1203.     if ThisSocket = TSocket(INVALID_SOCKET) then
  1204.       ErrorManager(WSAEWOULDBLOCK); {If error handle error}
  1205.     WSAAsyncselect(ThisSocket, FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_ALL);
  1206.   except
  1207.     raise ESockError.Create(sPSk_Cons_err_werr);
  1208.   end;
  1209. end;
  1210. {*******************************************************************************************
  1211. Socket Windows Message handler
  1212. ********************************************************************************************}
  1213. procedure TPowersock.Wndproc(var message: TMessage);
  1214. begin
  1215.   try
  1216.     with message do
  1217.     begin
  1218.       if LParamHi > 0 then
  1219.         Succeed := False {Succeed flag not set}
  1220.       else
  1221.         Succeed := True;
  1222.       case Msg of
  1223.         WM_ASYNCHRONOUSPROCESS:
  1224.           case LParamLo of
  1225.             FD_CONNECT:
  1226.               if Succeed then
  1227.               begin
  1228.                     // If any data has come in, it should be added to the incoming data queue now.
  1229.                 FConnected := True;
  1230.                 WaitSignal.SetEvent;
  1231.                 if Assigned(FOnConnect) then
  1232.                   FOnConnect(self);
  1233.               end;
  1234.             FD_CLOSE:
  1235.               begin
  1236.                 try
  1237.                   if FConnected then
  1238.                   begin
  1239.                     ClearInput;
  1240.                     RequestCloseSocket;
  1241.                   end;
  1242.                 except
  1243.                 end;
  1244.                 WaitSignal.SetEvent;
  1245.                 if Assigned(FOnDisconnect) then
  1246.                   FOnDisconnect(self);
  1247.               end;
  1248.             FD_READ:
  1249.               try
  1250.                 ReadToBuffer;
  1251.                 if Assigned(FOnReadEvent) then
  1252.                   FOnReadEvent(self)
  1253.               except
  1254.               end;
  1255.             FD_ACCEPT:
  1256.               begin
  1257.                 FConnected := True;
  1258.                 WaitSignal.SetEvent;
  1259.                 if Assigned(FOnAcceptEvent) then
  1260.                   FOnAcceptEvent(self);
  1261.               end;
  1262.           end;
  1263.         WM_WAITFORRESPONSE:
  1264.           begin
  1265.             Wait_Flag := True;
  1266.             WaitSignal.SetEvent;
  1267.             if LParamLo = FD_ACCEPT then
  1268.             begin
  1269.               FConnected := True;
  1270.               if not (csDestroying in ComponentState) then
  1271.                 if Assigned(FOnConnect) then
  1272.                   FOnConnect(self);
  1273.             end;
  1274.           end;
  1275.       end;
  1276.     end;
  1277.   except
  1278.   end;
  1279. end;
  1280. procedure TPowersock.ReadToBuffer;
  1281. var
  1282.   rc: Integer;
  1283. begin
  1284.   repeat
  1285.     rc := recv(ThisSocket, Buf, MAX_RECV_BUF, 0);
  1286.     if rc = 0 then
  1287.       RequestCloseSocket;
  1288.     if rc > 0 then
  1289.       FifoQ.Append(Pointer(@Buf), rc);
  1290.     WaitSignal.SetEvent;
  1291.   until rc < MAX_RECV_BUF;
  1292. end;
  1293. {*******************************************************************************************
  1294. Request Socket to be closed
  1295. ********************************************************************************************}
  1296. procedure TPowersock.RequestCloseSocket;
  1297. begin
  1298.   StatusMessage(Status_Routines, sPSk_Cons_msg_RCloseSock); {Report status}
  1299.   FConnected := False;
  1300.   if ThisSocket <> TSocket(INVALID_SOCKET) then
  1301.   begin
  1302.       {Close it}
  1303.     Winsock.CloseSocket(ThisSocket);
  1304.     if not (csDestroying in ComponentState) then
  1305.       if Assigned(FOnDisconnect) then
  1306.         FOnDisconnect(self);
  1307.     if not DestroySocket then
  1308.     begin
  1309.       ThisSocket := Socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
  1310.       WSAAsyncselect(ThisSocket, FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_OOB or FD_ACCEPT or FD_CONNECT or FD_CLOSE or FD_READ);
  1311.     end
  1312.   end;
  1313. end;
  1314. {*******************************************************************************************
  1315. Get The last error
  1316. ********************************************************************************************}
  1317. function TPowersock.GetLastErrorNo: Integer;
  1318. begin
  1319.   StatusMessage(Status_Debug, sPSk_Cons_msg_getLastE); {Report Status}
  1320.   Result := FLastErrorno; {Get Last error to result}
  1321. end;
  1322. {*******************************************************************************************
  1323. Set The Last Error
  1324. ********************************************************************************************}
  1325. procedure TPowersock.SetLastErrorNo(Value: Integer);
  1326. begin
  1327.   StatusMessage(Status_Debug, sPSk_Cons_msg_setLastE); {Report status}
  1328.   FLastErrorno := Value; {Set Last error to value}
  1329. end;
  1330. {*******************************************************************************************
  1331. Handle Power socket error
  1332. ********************************************************************************************}
  1333. function TPowersock.ErrorManager(Ignore: Word): string;
  1334. var
  1335.   slasterror: string;
  1336. begin
  1337.   FLastErrorno := wsagetlasterror; {Set last error}
  1338.   if FLastErrorno <> Ignore then
  1339.     if (FLastErrorno > 10000) then
  1340.     begin
  1341.       slasterror := SocketErrorStr(FLastErrorno); {Get the description string for error}
  1342.       if Assigned(FOnErrorEvent) then {If error handler present excecute it}
  1343.         FOnErrorEvent(self, FLastErrorno, slasterror);
  1344.       raise ESockError.Create(slasterror); {raise exception}
  1345.     end;
  1346.   Result := slasterror; {return error string}
  1347. end;
  1348. {*******************************************************************************************
  1349. Set Powersock error
  1350. ********************************************************************************************}
  1351. procedure TPowersock.SetWSAError(ErrorNo: Word; ErrorMsg: string);
  1352. begin
  1353.   StatusMessage(Status_Debug, sPSk_Cons_msg_SetSockE); {Report status}
  1354.   FLastErrorno := ErrorNo; {Set Last error to error}
  1355.   if Length(ErrorMsg) = 0 then
  1356.     SocketErrorStr(ErrorNo); {If error message not there set it to error no}
  1357.   WSASetLastError(ErrorNo); {Set Socket error to error no}
  1358.   if Assigned(FOnErrorEvent) then {If error handler present excecute it}
  1359.     FOnErrorEvent(self, FLastErrorno, ErrorMsg);
  1360. end;
  1361. {*******************************************************************************************
  1362. Output a Status message: depends on current Reporting Level
  1363. ********************************************************************************************}
  1364. procedure TPowersock.StatusMessage(Level: Byte; Value: string);
  1365. begin
  1366.   try
  1367.     if Level <= ReportLevel then
  1368.     begin
  1369.       _Status := Value; {Set status to vale of error}
  1370.       if not (csDestroying in ComponentState) then
  1371.         if Assigned(FOnStatus) then
  1372.           FOnStatus(self, _Status); {If Status handler present excecute it}
  1373.     end;
  1374.   except
  1375.   end;
  1376. end;
  1377. function TPowersock.DataAvailable: Boolean;
  1378. var
  1379.   rc: Integer;
  1380.   mc: Char;
  1381. begin
  1382.   Result := FifoQ.BufferSize > 0;
  1383.   if not Result then
  1384.   begin
  1385.     rc := recv(ThisSocket, mc, 1, MSG_PEEK);
  1386.     if rc > 0 then
  1387.     begin
  1388.       Result := True;
  1389.       ReadToBuffer;
  1390.     end
  1391.     else if rc = 0 then
  1392.     begin
  1393.       Result := True;
  1394.       try
  1395.         if FConnected then
  1396.         begin
  1397.           ClearInput;
  1398.           RequestCloseSocket;
  1399.         end;
  1400.       except
  1401.       end;
  1402.       WaitSignal.SetEvent;
  1403.       if Assigned(FOnDisconnect) then
  1404.         FOnDisconnect(self);
  1405.     end;
  1406.   end;
  1407. end;
  1408. procedure TPowersock.ClearInput;
  1409. var
  1410.   Buf: array[0..MAX_RECV_BUF] of Char;
  1411. begin
  1412.   StatusMessage(Status_Debug, sPSk_Cons_msg_ClearInput); {Inform status}
  1413.   recv(ThisSocket, Buf, MAX_RECV_BUF, 0);
  1414. end;
  1415. {*******************************************************************************************
  1416. Resolve IP Address of Remote Host
  1417. ********************************************************************************************}
  1418. procedure TPowersock.ResolveRemoteHost;
  1419. begin
  1420.   StatusMessage(Status_Debug, sPSk_Cons_msg_ResolvHos); {Inform status}
  1421.   if FProxy = '' then
  1422.     RemoteAddress.sin_addr.S_addr := Inet_Addr(StrPCopy(Buf, ServerName))
  1423.   else
  1424.     {else use Host address}
  1425.     RemoteAddress.sin_addr.S_addr := Inet_Addr(StrPCopy(Buf, FProxy));
  1426.   if RemoteAddress.sin_addr.S_addr = SOCKET_ERROR then
  1427.     {If given name not an IP address already}
  1428.   begin
  1429.     RemoteAddress.sin_addr.S_addr := 0;
  1430.     TimerOn; {Enable Timer}
  1431.     Wait_Flag := False; {Reset flag indicating wait over}
  1432.       {Resolve IP address}
  1433.     wsaasyncgethostbyname(FSocketWindow, WM_WAITFORRESPONSE, Buf, PChar(RemoteHost), MAXGETHOSTSTRUCT);
  1434.     repeat
  1435.       Wait;
  1436.     until Wait_Flag or TimedOut or Canceled; {Till host name resolved, Timed out or Cancelled}
  1437.     TimerOff; {Disable timer}
  1438.       {Handle errors}
  1439.     if TimedOut then
  1440.       raise ESockError.Create(sPSk_Cons_msg_host_to);
  1441.     if Canceled then
  1442.       raise ESockError.Create(sPSk_Cons_msg_host_Can);
  1443.     if Succeed = False then
  1444.       raise ESockError.Create(sPSk_Cons_msg_host_Fail);
  1445.       {Fill up remote host information with retreived results}
  1446.     with RemoteAddress.sin_addr.S_un_b do
  1447.     begin
  1448.       s_b1 := RemoteHost.h_addr_list^[0];
  1449.       s_b2 := RemoteHost.h_addr_list^[1];
  1450.       s_b3 := RemoteHost.h_addr_list^[2];
  1451.       s_b4 := RemoteHost.h_addr_list^[3];
  1452.     end;
  1453.       {If Remote host handler exists execute it}
  1454.     if Assigned(FOnHostResolved) then
  1455.       FOnHostResolved(self);
  1456.   end;
  1457. end;
  1458. {*******************************************************************************************
  1459. Abort a Socket
  1460. ********************************************************************************************}
  1461. procedure TPowersock.Abort;
  1462. begin
  1463.   StatusMessage(Status_Debug, sPSk_Cons_msg_Abort); {Inform status}
  1464.   Cancel;
  1465. end;
  1466. {*******************************************************************************************
  1467. Close a Socket
  1468. ********************************************************************************************}
  1469. procedure TPowersock.Close(Socket: THandle);
  1470. begin
  1471.   StatusMessage(Status_Debug, sPSk_Cons_msg_CloseSock); {Inform status}
  1472.   CloseSocket(Socket); {Close socket}
  1473. end;
  1474. {*******************************************************************************************
  1475. Get IP Address of remote machine in dotted decimal notation
  1476. ********************************************************************************************}
  1477. function TPowersock.GetRemoteIP: string;
  1478. begin
  1479.   StatusMessage(Status_Debug, sPSk_Cons_msg_GetRemoteIP); {Inform status}
  1480.   Result := inet_ntoa(RemoteAddress.sin_addr);
  1481. end;
  1482. {*******************************************************************************************
  1483. Get IP Address of local machine in dotted decimal notation
  1484. ********************************************************************************************}
  1485. function TPowersock.GetLocalIP: string;
  1486. var
  1487.   pH: PHostEnt;
  1488.   T: PChar;
  1489. begin
  1490.   StatusMessage(Status_Debug, sPSk_Cons_msg_GetLocalIP); {Inform status}
  1491.   T := AllocMem(200);
  1492.   try
  1493.     gethostname(T, 200);
  1494.     pH := gethostbyname(T);
  1495.     Result := Format('%d.%d.%d.%d', [Ord(pH.h_addr_list^[0]), Ord(pH.h_addr_list^[1]), Ord(pH.h_addr_list^[2]), Ord(pH.h_addr_list^[3])]);
  1496.   finally
  1497.     FreeMem(T, 200);
  1498.   end;
  1499. end;
  1500. {*******************************************************************************************
  1501. Get Address String of Local Machine
  1502. ********************************************************************************************}
  1503. function TPowersock.GetLocalAddress;
  1504. var
  1505.   sockaddr: TSockAddrIn;
  1506.   iSize, Commas: Integer;
  1507.   P: PChar;
  1508. begin
  1509.   iSize := SizeOf(TSockAddr); {Size of Address structure}
  1510.   {Get Local Socket info}
  1511.   getsockname(ThisSocket, sockaddr, iSize);
  1512.   P := inet_ntoa(sockaddr.sin_addr);
  1513.   iSize := 0;
  1514.   Commas := 0;
  1515.   while Commas < 3 do
  1516.   begin
  1517.     if P[iSize] = '.' then
  1518.     begin
  1519.       P[iSize] := ',';
  1520.       inc(Commas);
  1521.     end;
  1522.     inc(iSize);
  1523.   end;
  1524.   Result := StrPas(P);
  1525. end;
  1526. {*******************************************************************************************
  1527. Get Port String of a listening Port
  1528. ********************************************************************************************}
  1529. function TPowersock.GetPortString;
  1530. var
  1531.   sockaddr: TSockAddrIn;
  1532.   iSize: Integer;
  1533. begin
  1534.   iSize := SizeOf(TSockAddr); {Size of Address structure}
  1535.   getsockname(ThisSocket, sockaddr, iSize);
  1536.   with sockaddr do {Format IP address to required string type}
  1537.     Result := Format(',%d,%d', [Lo(sin_port), Hi(sin_port)]);
  1538. end;
  1539. procedure TPowersock.SetFifoCapacity(NewCapacity: Longint);
  1540. begin
  1541.   FifoQ.MemoryBufferCapacity := NewCapacity;
  1542. end;
  1543. function TPowersock.GetFifoCapacity: Longint;
  1544. begin
  1545.   Result := FifoQ.MemoryBufferCapacity;
  1546. end;
  1547. {*******************************************************************************************
  1548. ********************************************************************************************
  1549. ********************************************************************************************}
  1550. { TTimer }
  1551. constructor TThreadTimer.Create(AOwner: TComponent);
  1552. begin
  1553.   inherited Create(AOwner);
  1554.   FEnabled := True;
  1555.   FInterval := 1000;
  1556.   FWindowHandle := TmrAllocateHWnd(self);
  1557. end;
  1558. destructor TThreadTimer.Destroy;
  1559. begin
  1560.   FEnabled := False;
  1561.   UpdateTimer;
  1562.   DestroyWindow(FWindowHandle);
  1563.   inherited Destroy;
  1564. end;
  1565. procedure TThreadTimer.Wndproc(var Msg: TMessage);
  1566. begin
  1567.   with Msg do
  1568.     if Msg = WM_TIMER then
  1569.     try
  1570.       Timer;
  1571.     except
  1572.       Application.HandleException(self);
  1573.     end
  1574.     else
  1575.       Result := DefWindowProc(0, Msg, WPARAM, LPARAM);
  1576. end;
  1577. procedure TThreadTimer.UpdateTimer;
  1578. begin
  1579.   KillTimer(FWindowHandle, 1);
  1580.   if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  1581.     if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
  1582.       raise Exception.Create(sPSk_Cons_msg_NoTimer);
  1583. end;
  1584. procedure TThreadTimer.SetEnabled(Value: Boolean);
  1585. begin
  1586.   if Value <> FEnabled then
  1587.   begin
  1588.     FEnabled := Value;
  1589.     UpdateTimer;
  1590.   end;
  1591. end;
  1592. procedure TThreadTimer.SetInterval(Value: Cardinal);
  1593. begin
  1594.   if Value <> FInterval then
  1595.   begin
  1596.     FInterval := Value;
  1597.     UpdateTimer;
  1598.   end;
  1599. end;
  1600. procedure TThreadTimer.SetOnTimer(Value: TNotifyEvent);
  1601. begin
  1602.   FOnTimer := Value;
  1603.   UpdateTimer;
  1604. end;
  1605. procedure TThreadTimer.Timer;
  1606. begin
  1607.   if Assigned(FOnTimer) then
  1608.     FOnTimer(self);
  1609. end;
  1610. {*******************************************************************************************
  1611. ********************************************************************************************
  1612. ********************************************************************************************}
  1613. {*******************************************************************************************
  1614. Create Server - If Demo version handles demo Registering
  1615. ********************************************************************************************}
  1616. constructor TNMGeneralServer.Create;
  1617. var
  1618.   Tp: TClass;
  1619. begin
  1620.   inherited Create(AOwner);
  1621.   Tp := AOwner.ClassType;
  1622.   ATlist := nil;
  1623.   repeat
  1624.     if Tp = TNMGeneralServer then
  1625.       Break
  1626.     else
  1627.       Tp := Tp.ClassParent;
  1628.   until Tp = nil;
  1629.   if Tp = nil then
  1630.     ATlist := TThreadList.Create;
  1631. end;
  1632. destructor TNMGeneralServer.Destroy;
  1633. begin
  1634.   try
  1635.     try
  1636.       Abort;
  1637.     finally
  1638.       if ATlist <> nil then
  1639.         ATlist.Free;
  1640.       ATlist := nil;
  1641.     end;
  1642.   finally
  1643.     inherited Destroy;
  1644.   end;
  1645. end;
  1646. {*******************************************************************************************
  1647. Override connect so no inherited connection
  1648. ********************************************************************************************}
  1649. procedure TNMGeneralServer.Connect;
  1650. begin
  1651.   {Does not call inherited connect}
  1652. end;
  1653. {*******************************************************************************************
  1654. On Loading the General Sever. Set the ServerAccept method to handle accepts from
  1655. a client and start listening for connections.
  1656. ********************************************************************************************}
  1657. procedure TNMGeneralServer.Loaded;
  1658. begin
  1659.   inherited Loaded;
  1660.   if not (csDesigning in ComponentState) then
  1661.   begin
  1662.     OnAccept := ServerAccept;
  1663.     Listen(False);
  1664.   end;
  1665. end;
  1666. procedure TNMGeneralServer.Abort;
  1667. var
  1668.   x: Integer;
  1669. begin
  1670.   if ATlist <> nil then
  1671.   begin
  1672.     with ATlist.LockList do
  1673.     try
  1674.       for x := 0 to Count - 1 do
  1675.         TNMGeneralServer(Items[x]).Cancel;
  1676.     finally
  1677.       ATlist.UnlockList;
  1678.     end;
  1679.   end;
  1680. end;
  1681. {*******************************************************************************************
  1682. The method to accept a connection from a client.  It kicks off a thread to handle a client
  1683. and resumes listning on the original socket.
  1684. ********************************************************************************************}
  1685. procedure TNMGeneralServer.ServerAccept;
  1686. begin
  1687.   ExecuteInThread(DisPatchResponse, nil);
  1688. end;
  1689. procedure TNMGeneralServer.DisPatchResponse(data: Pointer);
  1690. var
  1691.   ServSock: TNMGeneralServer;
  1692. begin
  1693.   ServSock := TNMGeneralServer(TComponentClass((self.ClassType())).Create(Owner));
  1694.   ServSock.FConnected := True;
  1695.   ServSock.RemoteAddress := RemoteAddress;
  1696.   ServSock.OnConnect := OnConnect;
  1697.   ServSock.OnDisconnect := OnDisconnect;
  1698.   Winsock.CloseSocket(ServSock.ThisSocket);
  1699.   Wait_Flag := True;
  1700.   ServSock.ThisSocket := Accept;
  1701.   WSAAsyncselect(ServSock.ThisSocket, ServSock.FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_ALL); {To direct messages to clientsocket}
  1702.   ATlist.Add(ServSock);
  1703.   ServSock.Chief := self;
  1704.   ServSock.Serve;
  1705.   ATlist.Remove(ServSock);
  1706.   ServSock.Destroy;
  1707. end;
  1708. {*******************************************************************************************
  1709. The base server metod for GeneralServer. This has to be overridden by a derived
  1710. server to provide the servers functionality.
  1711. ********************************************************************************************}
  1712. procedure TNMGeneralServer.Serve;
  1713. begin
  1714. end;
  1715. {*******************************************************************************************
  1716. ********************************************************************************************
  1717. ********************************************************************************************}
  1718. {$IFNDEF NMF3}
  1719. { TStringStream }
  1720. constructor TStringStream.Create(const AString: string);
  1721. begin
  1722.   inherited Create;
  1723.   FDataString := AString;
  1724. end;
  1725. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  1726. begin
  1727.   Result := Length(FDataString) - FPosition;
  1728.   if Result > Count then
  1729.     Result := Count;
  1730.   Move(PChar(@FDataString[FPosition + 1])^, Buffer, Result);
  1731.   inc(FPosition, Result);
  1732. end;
  1733. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  1734. begin
  1735.   Result := Count;
  1736.   SetLength(FDataString, (FPosition + Result));
  1737.   Move(Buffer, PChar(@FDataString[FPosition + 1])^, Result);
  1738.   inc(FPosition, Result);
  1739. end;
  1740. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  1741. begin
  1742.   case Origin of
  1743.     soFromBeginning: FPosition := Offset;
  1744.     soFromCurrent: FPosition := FPosition + Offset;
  1745.     soFromEnd: FPosition := Length(FDataString) - Offset;
  1746.   end;
  1747.   if FPosition > Length(FDataString) then
  1748.     FPosition := Length(FDataString)
  1749.   else if FPosition < 0 then
  1750.     FPosition := 0;
  1751.   Result := FPosition;
  1752. end;
  1753. function TStringStream.ReadString(Count: Longint): string;
  1754. var
  1755.   Len: Integer;
  1756. begin
  1757.   Len := Length(FDataString) - FPosition;
  1758.   if Len > Count then
  1759.     Len := Count;
  1760.   SetString(Result, PChar(@FDataString[FPosition + 1]), Len);
  1761.   inc(FPosition, Len);
  1762. end;
  1763. procedure TStringStream.WriteString(const AString: string);
  1764. begin
  1765.   Write(PChar(AString)^, Length(AString));
  1766. end;
  1767. procedure TStringStream.SetSize(NewSize: Longint);
  1768. begin
  1769.   SetLength(FDataString, NewSize);
  1770.   if FPosition > NewSize then
  1771.     FPosition := NewSize;
  1772. end;
  1773. {*******************************************************************************************
  1774. ********************************************************************************************
  1775. ********************************************************************************************}
  1776. { TThreadList }
  1777. constructor TThreadList.Create;
  1778. begin
  1779.   inherited Create;
  1780.   FList := TList.Create;
  1781. end;
  1782. destructor TThreadList.Destroy;
  1783. begin
  1784.   LockList; // Make sure nobody else is inside the list.
  1785.   try
  1786.     FList.Free;
  1787.     inherited Destroy;
  1788.   finally
  1789.     UnlockList;
  1790.   end;
  1791. end;
  1792. procedure TThreadList.Add(Item: Pointer);
  1793. begin
  1794.   LockList;
  1795.   try
  1796.     if FList.IndexOf(Item) = -1 then
  1797.       FList.Add(Item);
  1798.   finally
  1799.     UnlockList;
  1800.   end;
  1801. end;
  1802. procedure TThreadList.Clear;
  1803. begin
  1804.   LockList;
  1805.   try
  1806.     FList.Clear;
  1807.   finally
  1808.     UnlockList;
  1809.   end;
  1810. end;
  1811. function TThreadList.LockList: TList;
  1812. begin
  1813.   Result := FList;
  1814. end;
  1815. procedure TThreadList.Remove(Item: Pointer);
  1816. begin
  1817.   LockList;
  1818.   try
  1819.     FList.Remove(Item);
  1820.   finally
  1821.     UnlockList;
  1822.   end;
  1823. end;
  1824. procedure TThreadList.UnlockList;
  1825. begin
  1826. end;
  1827. {$ENDIF}
  1828. {*******************************************************************************************
  1829. ********************************************************************************************
  1830. ********************************************************************************************}
  1831. {*******************************************************************************************
  1832. Get Nth Word in a string
  1833.   InputString: The string on which the Nth Word is to be found
  1834.   Delimiter: The seperator for words - normally the space charachter but can be anything else
  1835.              for example if you are parsing an URL it can be the '/' charachter
  1836.   Number: The Nth word to be found . ie if you want the third Number:=3
  1837.   Result: The Nth Word as a string
  1838. ********************************************************************************************}
  1839. function NthWord(InputString: string; Delimiter: Char; Number: Integer): string;
  1840. var
  1841.   I, j, K: Integer;
  1842.   temp: string;
  1843. begin
  1844.   if InputString = '' then
  1845.     Result := ''
  1846.   else
  1847.   begin
  1848.     I := 0; {Initialize variables}
  1849.     j := 1;
  1850.     K := Length(InputString) + 1;
  1851.     temp := '';
  1852.     repeat
  1853.       if InputString[j] = Delimiter then
  1854.         inc(I)
  1855.       else
  1856.           {if delimter count is correct, copy to output string}
  1857.         if I = Number - 1 then
  1858.           temp := temp + InputString[j];
  1859.       inc(j); {Go to next character}
  1860.     until ((I = Number) or (j = K)); {Until delimter past count or end of string}
  1861.     Result := temp; {Return result}
  1862.   end;
  1863. end;
  1864. {*******************************************************************************************
  1865. Get Position of Nth Occurrence of a Delimiter
  1866.   InputString: The string on which the Nth Occurence is to be found
  1867.   Delimiter: The charachter for whose Nth Occurence you are surching for
  1868.   Number: The Nth Occurence to be found . ie if you want the third Occurence Number:=3
  1869.   Result: The Positio of the Nth Occurence
  1870. ********************************************************************************************}
  1871. function NthPos(InputString: string; Delimiter: Char; Number: Integer): Integer;
  1872. var
  1873.   I, j, K: Integer;
  1874. begin
  1875.   I := 0;
  1876.   j := 1;
  1877.   K := Length(InputString) + 1; {Initialize variables}
  1878.   repeat
  1879.     if InputString[j] = Delimiter then
  1880.       I := I + 1;
  1881.     j := j + 1; {Go to next word}
  1882.   until ((I = Number) or (j = K)); {Until pos found or end of string}
  1883.   if j <> K then
  1884.     Result := j - 1
  1885.   else
  1886.     Result := K;
  1887. end;
  1888. {*******************************************************************************************
  1889. Append string to stream
  1890.   Astream: The stream to append to
  1891.   AString: The string to be  appended
  1892. ********************************************************************************************}
  1893. procedure StreamLn(AStream: TStream; AString: string);
  1894. var
  1895.   Tempstr: string;
  1896. begin
  1897.   Tempstr := AString + CRLF; {Add Carriage Return  and Line Feed}
  1898.   AStream.WriteBuffer(Tempstr[1], Length(Tempstr)); {Write string to stream}
  1899. end;
  1900. {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  1901. { The windows message handler                                               }
  1902. function PsockWindowProc(
  1903.   ahWnd: HWND;
  1904.   auMsg: Integer;
  1905.   awParam: WPARAM;
  1906.   alParam: LPARAM): Integer; stdcall;
  1907. var
  1908.   Obj: TPowersock;
  1909.   MsgRec: TMessage;
  1910. begin
  1911.   Obj := TPowersock(GetWindowLong(ahWnd, 0));
  1912.   if ((not Assigned(Obj)) or (auMsg < WM_ASYNCHRONOUSPROCESS)) then
  1913.     Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
  1914.   else
  1915.   begin
  1916.     MsgRec.Msg := auMsg;
  1917.     MsgRec.WPARAM := awParam;
  1918.     MsgRec.LPARAM := alParam;
  1919.     MsgRec.Result := 0;
  1920.     Obj.Wndproc(MsgRec);
  1921.     Result := MsgRec.Result;
  1922.   end;
  1923. end;
  1924. {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  1925. { This global variable is used to store the windows class characteristic    }
  1926. { and is needed to register the window class used by TWSocket               }
  1927. var
  1928.   PsockWindowClass: TWndClass = (
  1929.     Style: 0;
  1930.     lpfnWndproc: @PsockWindowProc;
  1931.     cbClsExtra: 0;
  1932.     cbWndExtra: SizeOf(Pointer);
  1933.     HInstance: 0;
  1934.     HICON: 0;
  1935.     HCURSOR: 0;
  1936.     hbrBackground: 0;
  1937.     lpszMenuName: nil;
  1938.     lpszClassName: 'PsockWindowClass');
  1939. function PsockAllocateHWnd(Obj: TObject): HWND;
  1940. var
  1941.   TempClass: TWndClass;
  1942.   ClassRegistered: Boolean;
  1943. begin
  1944.   { Check if the window class is  registered}
  1945.   if PsockWindowClass.HInstance = 0 then
  1946.     PsockWindowClass.HInstance := HInstance;
  1947.   ClassRegistered := GetClassInfo(HInstance, PsockWindowClass.lpszClassName, TempClass);
  1948.   if not ClassRegistered then
  1949.   begin
  1950.     Result := WinProcs.RegisterClass(PsockWindowClass);
  1951.     if Result = 0 then
  1952.       Exit;
  1953.   end;
  1954.   { Create a new window                                               }
  1955.   Result := CreateWindowEx(WS_EX_TOOLWINDOW,
  1956.     PsockWindowClass.lpszClassName,
  1957.     '', { Window name   }
  1958.     WS_POPUP, { Window Style  }
  1959.     0, 0, { X, Y          }
  1960.     0, 0, { Width, Height }
  1961.     0, { hWndParent    }
  1962.     0, { hMenu         }
  1963.     HInstance, { hInstance     }
  1964.     nil); { CreateParam   }
  1965.   if (Result <> 0) and Assigned(Obj) then
  1966.     SetWindowLong(Result, 0, Integer(Obj));
  1967. end;
  1968. {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  1969. { The windows message handler                                               }
  1970. function TmrWindowProc(
  1971.   ahWnd: HWND;
  1972.   auMsg: Integer;
  1973.   awParam: WPARAM;
  1974.   alParam: LPARAM): Integer; stdcall;
  1975. var
  1976.   Obj: TThreadTimer;
  1977.   MsgRec: TMessage;
  1978. begin
  1979.   // OBJ is created by you here every time I get a window message.
  1980.   Obj := TThreadTimer(GetWindowLong(ahWnd, 0));
  1981.   if not Assigned(Obj) then
  1982.     Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
  1983.   else
  1984.   begin
  1985.     MsgRec.Msg := auMsg;
  1986.     MsgRec.WPARAM := awParam;
  1987.     MsgRec.LPARAM := alParam;
  1988.     if (auMsg <> WM_TIMER) then
  1989.       Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
  1990.     else
  1991.     begin
  1992.       Obj.Wndproc(MsgRec);
  1993.       Result := MsgRec.Result;
  1994.     end;
  1995.   end;
  1996. end;
  1997. {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  1998. { This global variable is used to store the windows class characteristic    }
  1999. { and is needed to register the window class used by TWSocket               }
  2000. var
  2001.   TmrWindowClass: TWndClass = (
  2002.     Style: 0;
  2003.     lpfnWndproc: @TmrWindowProc;
  2004.     cbClsExtra: 0;
  2005.     cbWndExtra: SizeOf(Pointer);
  2006.     HInstance: 0;
  2007.     HICON: 0;
  2008.     HCURSOR: 0;
  2009.     hbrBackground: 0;
  2010.     lpszMenuName: nil;
  2011.     lpszClassName: 'TmrWindowClass');
  2012. function TmrAllocateHWnd(Obj: TObject): HWND;
  2013. var
  2014.   TempClass: TWndClass;
  2015.   ClassRegistered: Boolean;
  2016. begin
  2017.   { Check if the window class is  registered}
  2018.   if TmrWindowClass.HInstance = 0 then
  2019.     TmrWindowClass.HInstance := HInstance;
  2020.   ClassRegistered := GetClassInfo(HInstance, TmrWindowClass.lpszClassName, TempClass);
  2021.   if not ClassRegistered then
  2022.   begin
  2023.     Result := WinProcs.RegisterClass(TmrWindowClass);
  2024.     if Result = 0 then
  2025.       Exit;
  2026.   end;
  2027.   { Create a new window                                               }
  2028.   Result := CreateWindowEx(WS_EX_TOOLWINDOW,
  2029.     TmrWindowClass.lpszClassName,
  2030.     '', { Window name   }
  2031.     WS_POPUP, { Window Style  }
  2032.     0, 0, { X, Y          }
  2033.     0, 0, { Width, Height }
  2034.     0, { hWndParent    }
  2035.     0, { hMenu         }
  2036.     HInstance, { hInstance     }
  2037.     nil); { CreateParam   }
  2038.   if (Result <> 0) and Assigned(Obj) then
  2039.     SetWindowLong(Result, 0, Integer(Obj));
  2040. end;
  2041. initialization;
  2042.   try
  2043.     SockAvailable := WSAStartUp($0101, MyWSAData) <> -1;
  2044.   except
  2045.   end;
  2046. finalization;
  2047.   try
  2048.     if SockAvailable then WSACleanUp; {Clean up Winsock}
  2049.   except
  2050.   end;
  2051. end.