BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Socket Error # 0 in RETR handler

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock
View previous topic :: View next topic  
Author Message
Vern Six
Guest





PostPosted: Thu Oct 30, 2003 2:08 am    Post subject: Socket Error # 0 in RETR handler Reply with quote



The following code is killing me. I keep getting Socket Error # 0 during
the WriteStream call. And even if I try to handle/ignore it, I still lose
the connection. I would be willing to pay anyone who could help me solve
this one. Argh.

Thanks

--------------------------------

procedure TMainForm.PopServerRETR(ASender: TIdCommand;
AMessageNum: Integer);
var
s, sMsgFile: string;
AStream: TMemoryStream;
AMsg : TIdMessage;
begin

with TVsUserData(ASender.Thread.Data) do begin

AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );
s := '+OK ' + IntToStr(TVsMsgInfo(MsgList.Items[AMessageNum-1]).Size) +
' octets';
ASender.thread.Connection.WriteLn(s);

sMsgFile := MsgPath + TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );

try

try
AMsg := TIdMessage.create(nil);
except
on e: exception do begin
AddToLog('TIdMessage.create exception: ' + e.Message );
exit;
end;
end;

AMsg.NoEncode := true;
AMsg.NoDecode := true;


try
AMsg.LoadFromFile(sMsgFile,false);
except
on e: exception do begin
AddToLog('TIdMessage.LoadFromFile exception: ' + e.Message );
exit;
end;
end;

try
AStream := TmemoryStream.Create;
except
on e: exception do begin
AddToLog('TMemoryStream.create exception: ' + e.Message );
exit;
end;
end;

try
AMsg.SaveToStream(AStream,false);
except
on e: exception do begin
AddToLog('TIdMessage.SaveToStream exception: ' + e.Message );
exit;
end;
end;


try
ASender.Thread.Connection.WriteStream(AStream); // always
blows an error here!
except
on e: exception do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
if ( lowercase(trim(e.Message)) <> 'socket error # 0' ) then begin
exit;
end;
end;
end;

AddToLog( 'S: <contents of ' + sMsgFile + ' sent successfully>' );

finally
if assigned(AStream) then freeandnil(AStream);
if assigned(AMsg) then freeandnil(AMsg);
end;

end;

end; // RETR


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Thu Oct 30, 2003 2:45 am    Post subject: Re: Socket Error # 0 in RETR handler Reply with quote




"Vern Six" <Vern (AT) VernSix (DOT) com> wrote


Quote:
s := '+OK ' + IntToStr(TVsMsgInfo(MsgList.Items[AMessageNum-1]).Size)
+
' octets';
ASender.thread.Connection.WriteLn(s);

I would not recommend you call WriteLn() until after you have already loaded
and prepared the TIdMessage for sending. Otherwise you are going to be
sending an incomplete response to the client. Also, whenever you are
catching exceptions, you are simply calling 'Exit' without letting the
exception make its way back to TIdPOP3Server. You should let exceptions
make their way back so that it can know that something wrong happened and
return an error response to the client. In back, to make sure that you do
not send an incomplete respnse, you should buffer the response using
OpenWriteBuffer() and CloseWriteBuffer(), with CancelWriteBuffer() in case
an error occurs.

Quote:
AMsg.NoEncode := true;
AMsg.NoDecode := true;

Since you are essentially loading and message file without any extra
processing whatever, then why not just load the file into a stream, such as
TFileStream, and send it directly without using TIdMessage at all?

Quote:
if ( lowercase(trim(e.Message)) <> 'socket error # 0' ) then
begin


An easier way to test the error would be to cast the exception to
EIdSocketError (or just catch EIdSocketError to begin with) and then use its
ErrorCode property:

except
on e: EIdSocketError do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
if ( e.ErrorCode <> 0 ) then exit;
end;
on e: exception do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
exit;
end;
end;


With all that said, try this instead (untested):

procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TMemoryStream;
AMsg : TIdMessage;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );

sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );

try
try
AMsg := TIdMessage.create(nil);
AMsg.NoEncode := true;
AMsg.NoDecode := true;
except
on e: Exception do AddToLog('TIdMessage.create
exception: ' + e.Message);
Raise; // so TIdPop3Server knows something went wrong
end;

try
AMsg.LoadFromFile(sMsgFile, false);
except
on e: exception do AddToLog('TIdMessage.LoadFromFile
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;

try
AStream := TMemoryStream.Create;
except
on e: Exception do AddToLog('TMemoryStream.create
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;

try
AMsg.SaveToStream(AStream, false);
AStream.Seek(0, soFromBeginning);
except
on e: Exception do AddToLog('TIdMessage.SaveToStream
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;

ASender.Thread.Connection.OpenWriteBuffer;
try
ASender.Thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.Thread.Connection.CloseWriteBuffer;
except
on e: Exception do begin
ASender.Thread.Connection.ClearWriteBuffer;
AddToLog('ASender.Thread.Connection exception: ' +
e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;

AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
finally
if Assigned(AStream) then FreeAndNil(AStream);
if Assigned(AMsg) then FreeAndNil(AMsg);
end;
end;
end; // RETR

Or simply:

procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TFileStream;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );

sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );

try
AStream := TFileStream.Create(sMsgFile, fmOpenRead or
fmShareDenyWrite);
try
ASender.thread.Connection.OpenWriteBuffer;
try
ASender.thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.thread.Connection.CloseWriteBuffer;
AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
except
ASender.thread.Connection.ClearWriteBuffer;
Raise;
end;
finally
FreeAndNil(AStream);
end;
except
on e: Exception do begin
AddToLog('Exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;
end;
end;
end; // RETR


Gambit



Back to top
Vern Six
Guest





PostPosted: Thu Oct 30, 2003 5:35 am    Post subject: Re: Socket Error # 0 in RETR handler Reply with quote



You, Sir... are my hero!!! It appears to have worked. I guess I need a
little help with the try...except blocks huh? <grin>

The problem seems to have been fixed by the placement of the +OK statement.
Go figure.


"Remy Lebeau (TeamB)" <gambit47.no.spam (AT) no (DOT) spam.yahoo.com> wrote

Quote:

"Vern Six" <Vern (AT) VernSix (DOT) com> wrote in message
news:3fa0728f$1 (AT) newsgroups (DOT) borland.com...

s := '+OK ' +
IntToStr(TVsMsgInfo(MsgList.Items[AMessageNum-1]).Size)
+
' octets';
ASender.thread.Connection.WriteLn(s);

I would not recommend you call WriteLn() until after you have already
loaded
and prepared the TIdMessage for sending. Otherwise you are going to be
sending an incomplete response to the client. Also, whenever you are
catching exceptions, you are simply calling 'Exit' without letting the
exception make its way back to TIdPOP3Server. You should let exceptions
make their way back so that it can know that something wrong happened and
return an error response to the client. In back, to make sure that you do
not send an incomplete respnse, you should buffer the response using
OpenWriteBuffer() and CloseWriteBuffer(), with CancelWriteBuffer() in case
an error occurs.

AMsg.NoEncode := true;
AMsg.NoDecode := true;

Since you are essentially loading and message file without any extra
processing whatever, then why not just load the file into a stream, such
as
TFileStream, and send it directly without using TIdMessage at all?

if ( lowercase(trim(e.Message)) <> 'socket error # 0' ) then
begin

An easier way to test the error would be to cast the exception to
EIdSocketError (or just catch EIdSocketError to begin with) and then use
its
ErrorCode property:

except
on e: EIdSocketError do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
if ( e.ErrorCode <> 0 ) then exit;
end;
on e: exception do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
exit;
end;
end;


With all that said, try this instead (untested):

procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TMemoryStream;
AMsg : TIdMessage;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );

sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );

try
try
AMsg := TIdMessage.create(nil);
AMsg.NoEncode := true;
AMsg.NoDecode := true;
except
on e: Exception do AddToLog('TIdMessage.create
exception: ' + e.Message);
Raise; // so TIdPop3Server knows something went
wrong
end;

try
AMsg.LoadFromFile(sMsgFile, false);
except
on e: exception do AddToLog('TIdMessage.LoadFromFile
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;

try
AStream := TMemoryStream.Create;
except
on e: Exception do AddToLog('TMemoryStream.create
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;

try
AMsg.SaveToStream(AStream, false);
AStream.Seek(0, soFromBeginning);
except
on e: Exception do AddToLog('TIdMessage.SaveToStream
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;

ASender.Thread.Connection.OpenWriteBuffer;
try
ASender.Thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.Thread.Connection.CloseWriteBuffer;
except
on e: Exception do begin
ASender.Thread.Connection.ClearWriteBuffer;
AddToLog('ASender.Thread.Connection exception: ' +
e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;

AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
finally
if Assigned(AStream) then FreeAndNil(AStream);
if Assigned(AMsg) then FreeAndNil(AMsg);
end;
end;
end; // RETR

Or simply:

procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TFileStream;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );

sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );

try
AStream := TFileStream.Create(sMsgFile, fmOpenRead or
fmShareDenyWrite);
try
ASender.thread.Connection.OpenWriteBuffer;
try
ASender.thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.thread.Connection.CloseWriteBuffer;
AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
except
ASender.thread.Connection.ClearWriteBuffer;
Raise;
end;
finally
FreeAndNil(AStream);
end;
except
on e: Exception do begin
AddToLog('Exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;
end;
end;
end; // RETR


Gambit





Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.