Board index » delphi » Newsserver disconnects - how to notice this

Newsserver disconnects - how to notice this


2006-05-03 02:11:05 AM
delphi80
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 is 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!
 
 

Re:Newsserver disconnects - how to notice this

"Shiva" <XXXX@XXXXX.COM>writes
Quote
I've used a TIdTCPServer component to achieve this and everything works
fine
Any reason why you are not using TIdNNTPServer instead? Or even
TIdMappedPortTCP?
Quote
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.
So, you simply send the 400 reply to OE and disconnect from OE when your
program receives it from the server. What exactly are you having a problem
with?
Quote
Unfortunately, I am not able to trigger an event once the server
disconnects (anyway, I don't know how to do that!).
Since you are using TIdTCPServer, you are in full control of the connection
with the server. Even though the connection with the server is
disconnected, you still have the data that the server sent before
disconnecting, and you still have the connection to OE. So why can not you
forward the data to OE?
Quote
OE does not notice the disconnection
You are not sending anything to OE when your thread's Disconnect() method is
called, and your are not checking the server for pending data to send to OE
in between commands.
Quote
So the question is: how can I pass the disconnection to OE?
Where EXACTLY are you having the problem? Please provide SPECIFIC details
about what you are trying to do, the steps the reproduce the problem, etc.
Quote
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
That is not the correct way to handle multi-line responses, not even close.
You need to look for a '-' character following the 3-digit response number
instead, ie:
repeat
ResponseNewsserverISP := NewsserverISP.ReadLn;
LogMessage('Response ISP=' + ResponseNewsserverISP);
ClientConn.WriteLn(ResponseNewsserverISP);
until Copy(ResponseNewsserverISP, 4, 1) <>'-';
Gambit