Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 May : Newsserver disconnects - how to notice this

www.cryer.info
Managed Newsgroup Archive

Newsserver disconnects - how to notice this

Subject:Newsserver disconnects - how to notice this
Posted by:"Shiva" (shi..@gonzo.com)
Date:Tue, 2 May 2006 20:11:05

Hi,

My program acts as a proxy / gateway between a client like Outlook Express
(OE) and my ISP's newsserver. Any NNTP-command send by OE is sent to my
program; the program sends the command to the newsserver and the response
messages of the newsserver are sent back to OE (the only exception is the
NNTP-command POST, this command is intercepted and its data is sent to a
mail2news gateway).
I've used a TIdTCPServer component to achieve this and everything works fine
except for the situation when the newsserver decides to disconnect after
being idle for a couple of minutes (the response is: "400
text.nova.planet.nl: Idle timeout." and then it disconnects). The
disconnection cannot be noticed by OE, because it is connected to my
program, not to the newsserver. Unfortunately, I am not able to trigger an
event once the server disconnects (anyway, I don't know how to do that!).

The connection to the newsserver is stored in a TIdPeerThread descendant
called TMyNNTPThread. It's the field fNewsserverISP.

The source of this class look like this:

  TMyNNTPThread = class(TIdPeerThread)
  private
     fNewsserverISP: TIdTCPClient;
     fMail2News: TIdSMTP;
  public
    constructor Create(ACreateSuspended: boolean); override;
    destructor Destroy; override;
    procedure Connect(const AHost: String; APort: Integer; aReconnect:
boolean);
    procedure Disconnect;
    property NewsserverISP: TIdTCPClient read fNewsserverISP;
    property Mail2News: TIdSmtp read fMail2News;
  end;

implementation

constructor TMyNNTPThread.Create(ACreateSuspended: boolean);
begin
  fNewsserverISP := TIdTCPClient.Create(nil);

  fMail2News := TIdSmtp.Create(nil);
  fMail2News.Host := 'mail.planet.nl';
  fMail2News.Port := 25;

  inherited Create(ACreateSuspended);
end;

destructor TMyNNTPThread.Destroy;
begin
  LogMessage('Before freeing fMail2News');
  FreeAndNil(fMail2News);
  LogMessage('After freeing fMail2News');
  FreeAndNil(fNewsserverISP);
  inherited Destroy;
end;


procedure TMyNNTPThread.Connect(const AHost: String; APort: Integer;
aReconnect: boolean);
var
  s: string;

begin
  fNewsserverISP.Host := AHost;
  fNewsserverISP.Port := APort;
  fNewsserverISP.Connect;
  s := fNewsserverISP.ReadLn;
  if not aReconnect then
    Connection.WriteLn(s);
  LogMessage('Connect='+ s);
end;

procedure TMyNNTPThread.Disconnect;
begin
  if fNewsserverISP.Connected then begin
    LogMessage('Disconnect, fNewsserverISP.Connected = true');
    fNewsserverISP.Disconnect;
  end
  else
    LogMessage('Disconnect, fNewsserverISP.Connected = false');
end;

OE does not notice the disconnection so I guess it assumes the connection is
still active, iow it does not try to reestablish the connection. OE then
receives the 400 response and display the message "Outlook Express was
unable to switch to the newsgroup alt.test" (that's what I wanted to do).

So the question is: how can I pass the disconnection to OE? Or should I keep
the connection alive by sending commands like "MODE READER" to the
newsserver? If so, what's the best way to do this?

By the way, this is what the execute handler of TIdTCPServer looks like:

procedure TFormMain.Exec(AThread: TIdPeerThread);
Var ClientNNTPLine, ResponseNewsserverISP: string;
    ClientConn: TIdTCPServerConnection;
    ii: integer;
    NewsserverISP: TIdTCPClient;

begin
  NewsserverISP := TMyNNTPThread(AThread).NewsserverISP;
  ClientConn := TMyNNTPThread(AThread).Connection;

  ClientNNTPLine := ClientConn.ReadLn;
  LogMessage('ClientNNTPLine ='+ ClientNNTPLine);

  if Pos('POST', ClientNNTPLine) = 1 then
    GetPostAndSend2Mail2News(AThread)
  else begin
    NewsserverISP.WriteLn(ClientNNTPLine);

    ResponseNewsserverISP := NewsserverISP.ReadLn;
    LogMessage('Response ISP=' + ResponseNewsserverISP);
    ClientConn.WriteLn(ResponseNewsserverISP);

    if      (Pos('215', ResponseNewsserverISP) = 1)
         or (Pos('220', ResponseNewsserverISP) = 1)
         or (Pos('221', ResponseNewsserverISP) = 1)
         or (Pos('222', ResponseNewsserverISP) = 1)
         or (Pos('223', ResponseNewsserverISP) = 1)
         or (Pos('224', ResponseNewsserverISP) = 1)
         or (Pos('231', ResponseNewsserverISP) = 1)
         or (Pos('282', ResponseNewsserverISP) = 1) then begin
      repeat
        ResponseNewsserverISP := NewsserverISP.ReadLn;
        LogMessage('Response ISP (>1) =' + ResponseNewsserverISP);
        if     ClientConn.Connected
          and (not athread.Stopped) then
           ClientConn.WriteLn(ResponseNewsserverISP);

      until ResponseNewsserverISP = '.';
    end
    else
    if Pos('400', ResponseNewsserverISP) = 1 then begin
      TMyNNTPThread(AThread).NewsserverISP.Disconnect;
      TMyNNTPThread(AThread).Disconnect;
    end;
  end;
end;

Thanks in advance!

Replies:

www.cryer.info
Managed Newsgroup Archive