Hi Arno
Once again many thanks for the quick reply.
I have now implemented a working multithreaded test (server) application
which uses both the TWSocket and the TSslWSocket in a non-blocking
manner.
The "regular" WSocket is used to accept incoming sessions, which are
then carried on in a new client thread in which the sockethandle is
"dupped" onto a TSslWSocket for further processing.
I just have to be sure that I understood your reference to
f_ERR_remove_state(unsigned ThreadID).
Should I call this function just before the Thread's execute method
returns, sending the threads ThreadID as param ?
I have provided my sample code, for the benefit of others who had the
same initial problem as me.
If you can spare the time, I would be grateful if you could please
verify that my use of the TSslWSocket is correct ?
Excerpt of my sample code is listed below:
Best regards
Kurt
***Main Thread***
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
...
// Enable safe OpenSSL Multithreading before creating any
ICS SSL sockets
m_pSslDynamicLock = new TSslDynamicLock(NULL);
m_pSslDynamicLock->Enabled = true;
// Shared (thread-safe) SSL context
m_pSslContext = new TSslContext(NULL);
m_pSslContext->SslCertFile = "c:\\MyCertificate.pem";
m_pSslContext->SslPassPhrase = "password";
m_pSslContext->SslPrivKeyFile = "c:\\MyKey.pem";
m_pSslContext->SslCAFile = "c:\\root.cer";
m_pSslContext->SslCAPath = "";
m_pSslContext->SslVerifyPeer = false;// No client
certificate verification
// Listen for incoming connections
m_pServerSocket = new TWSocket(NULL);
m_pServerSocket->OnSessionAvailable =
ServerSocketSessionAvailable;
m_pServerSocket->Addr = "0.0.0.0";
m_pServerSocket->Port = "443";
m_pServerSocket->MultiThreaded = false;// We're in mainthread
and should be fine.
m_pServerSocket->Listen();
}
//----------------------------------------------------------------------
-----
void __fastcall TForm2::ServerSocketSessionAvailable(TObject *Sender,
WORD ErrCode)
{
try
{
// Accept incoming connection request
unsigned int nSocketHandle = m_pServerSocket-> Accept();
// Do we have a valid Socket handle ?
if( nSocketHandle > 0 &&
nSocketHandle < INVALID_SOCKET - 1 )
{
// Thread initially created as suspended
TSslClientThread* pClientThread = new
TSslClientThread( m_hVclComponentCreationMutex,
m_pSslContext,
nSocketHandle );
pClientThread->OnTerminate =
OnSslClientThreadTerminate;
pClientThread->OnDebug = OnSslClientThreadDebug;
// Add reference to thread, to keep track of
session count
m_SessionList.Add( pClientThread );
// Resume Thread
pClientThread->Resume();
}
}
catch(Exception& ex)
{
DebugLog("TForm2::ServerSocketSessionAvailable,
exception: " + ex.Message);
}
UpdateSessionCount();
}
//----------------------------------------------------------------------
-----
void __fastcall TForm2::OnSslClientThreadTerminate(TObject* Sender)
{
if( Sender != NULL &&
Sender->ClassNameIs("TSslClientThread") )
{
TSslClientThread* pThread = (TSslClientThread*)Sender;
// Remove thread from list of active sessions
int nIndex = m_SessionList.IndexOf( pThread );
// Valid index ?
if( nIndex >= 0 &&
nIndex < m_SessionList.Count )
{
m_SessionList.Remove( nIndex );// Only remove
reference, not deleting obj.
}
UpdateSessionCount();
}
}
//----------------------------------------------------------------------
-----
***Session Thread***
__fastcall TSslClientThread::TSslClientThread(HANDLE hMutex,
TSslContext* pSslContext, unsigned int nSocketHandle )
: TThread(true)// create suspended
{
OnDebug = NULL;
m_hVclComponentCreationMutex = hMutex;
m_pSslContext = pSslContext;
m_nSocketHandle = nSocketHandle;
FreeOnTerminate = true;
}
//----------------------------------------------------------------------
-----
void __fastcall TSslClientThread::Execute()
{
// Init members
// using a shared Mutex to avoid errors with components
calling AllocateHwnd/DeallocateHwnd, which are not thread safe
WaitForSingleObject( m_hVclComponentCreationMutex, INFINITE );
Init();
ReleaseMutex( m_hVclComponentCreationMutex );
// Loop until terminated ...
while(!Terminated)
{
m_pClientSocket->ProcessMessages();
Sleep(1);
}
// Cleam up
WaitForSingleObject( m_hVclComponentCreationMutex, INFINITE );
UnInit();
ReleaseMutex( m_hVclComponentCreationMutex );
}
//----------------------------------------------------------------------
-----
bool TSslClientThread::Init(void)
{
bool bRetVal(false);
try
{
m_pClientSocket = new TSslWSocket(NULL);
m_pClientSocket->MultiThreaded = true;// Tell
SslWSocket that it is run inside a seperate thread
m_pClientSocket->SslContext = m_pSslContext;//
According to Arno Garrels TSslContext should be threadsafe
m_pClientSocket->SslMode =
sslModeServer;
m_pClientSocket->OnDataAvailable = ClientDataAvailable;
m_pClientSocket->OnSessionClosed = ClientSessionClosed;
m_pClientSocket->SslEnable = true;
// Assign socket handle
m_pClientSocket->Dup( m_nSocketHandle );
bRetVal = true;
}
catch(Exception& ex)
{
Fire_OnDebug("TSslClientThread::Init, exception: " +
ex.Message);
}
return bRetVal;
}
//----------------------------------------------------------------------
-----
bool TSslClientThread::UnInit(void)
{
bool bRetVal(false);
try
{
m_pClientSocket->Close();
while( m_pClientSocket->State != wsClosed )
{
m_pClientSocket->ProcessMessages();
Sleep(1);
}
delete m_pClientSocket;
m_pClientSocket = NULL;
// DESCRIPTION
// ERR_remove_state() frees the error queue associated
with thread pid.
// If pid == 0, the current thread will have its error
queue removed.
// Since error queue data structures are allocated
automatically for
// new threads, they must be freed when threads are
terminated in order
// to avoid memory leaks.
f_ERR_remove_state(this->ThreadID);
bRetVal = true;
}
catch(Exception& ex)
{
Fire_OnDebug("TSslClientThread::UnInit, exception: " +
ex.Message);
}
return bRetVal;
}
//----------------------------------------------------------------------
-----
void __fastcall TSslClientThread::ClientDataAvailable(TObject* Sender,
Word Error)
{
try
{
TSslWSocket* pSocket = (TSslWSocket*)Sender;
AnsiString msg = pSocket->ReceiveStr();
}
catch(Exception& ex)
{
Fire_OnDebug("TSslClientThread::ClientDataAvailable,
exception: " + ex.Message);
}
}
//----------------------------------------------------------------------
-----
void __fastcall TSslClientThread::ClientSessionClosed(TObject* Sender,
Word Error)
{
try
{
// Terminate this thread ...
Terminate();
}
catch(Exception& ex)
{
Fire_OnDebug("TSslClientThread::ClientSessionClosed,
exception: " + ex.Message);
}
}
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be