Infinite loop when sending a welcome message to th (General questions)
We've got a project using wodSSHD (version 1.3.0.194) in Telnet mode which sends information to the client after they've logged in. This occurs in the LoginPassword event once we've verified the user.
Unfortunately it seems possible to lock up the server (wodSSHD) if the client (in this case PuTTY) sends data to the server while the server is sending this data to the client (or it's occuring during handshaking). The processor usage then spikes up to 100 and the application's OnDataReceived event never gets triggered.
I've reproduced this in a simple test application which only features a wodSSHD server running in telnet mode. I connect to the server using PuTTY and immediately press return several times to send data to the server.
Here's the code for the test application:
[code]
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Server = new TwodSSHDCom((TComponent*)NULL);
Server->set_LicenseKey(WideString( XXXX-XXXX-XXXX-XXXX ));
Server->set_Protocol(Wodsshdcomlib_tlb::Telnet);
Server->OnReceived = DataReceived;
Server->OnLoginPassword = ServerLoginPassword;
Server->set_Port(6000);
StartServer();
}
//------------------------------------------------------------------
void TForm1::StartServer()
{
int RetryCount = 0;
VARIANT var;
var.vt = VT_ERROR;
HRESULT hr;
hr = Server->GetDefaultInterface()->Start(var);
if(hr != 0)
{
int ErrorCode = HRESULT_CODE(hr);
// If the port is in use, try the next... and so on.
while(ErrorCode == WSAEADDRINUSE)
{
int Port = Server->get_Port();
hr = Server->GetDefaultInterface()->Start(var);
ErrorCode = HRESULT_CODE(hr);
RetryCount++;
if(RetryCount >= 100)
break;
}
// If there's some other error, then log it out.
if(ErrorCode)
Application->MessageBox(AnsiString( Error + IntToStr(ErrorCode)).c_str(), Error , MB_OK|MB_ICONERROR);
}
}
//------------------------------------------------------------------
void __fastcall TForm1::ServerLoginPassword(TObject *Sender,
ISSHUser *User, BSTR Login, BSTR Password, SSHActions *Action)
{
*Action = Allow;
if(Server->Protocol != Wodsshdcomlib_tlb::SSH2)
{
for(int i = 0; i < 100000; i++)
{
User->Send(WideString( Enjoy your stay! ));
}
}
// Release extra User Reference
User->Release();
// Memory leak fix
::SysFreeString(Login);
::SysFreeString(Password);
}
//------------------------------------------------------------------
void __fastcall TForm1::DataReceived(TObject *Sender,
ISSHUser *User, int ServiceIndex, int BytesCount)
{
User->Send(WideString( DataReceived ));
try
{
}
catch(Exception &e)
{
}
}
[/code]
Obviously the message in the above example is not what we'd normally display to the user and we wouldn't be spewing it out 100000 times (that's just to make it easier to duplicate the problem).
If I connect to this server with PuTTY in raw mode then it doesn't seem to matter how quickly or often I hit return, it'll continue to work as expected. If I connect to this server with PuTTY in telnet mode then quickly pressing return as the PuTTY window opens causes the application to lock up, and processor usage spikes at 100 . The wodSSHD component is run in Telnet mode in both cases.
This is built in C++ Builder 6.