Important Update:
- SelectableCore: - Bug fix: StateCallBack array to small - Implemented and tested UNIX sockets - Started implementation of UDP sockets - Add "TCP" to TCP socket related methods and types
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
@@ -147,6 +148,43 @@ bool CSelectableCore::LoadConfigData()
|
||||
}
|
||||
SetLinePrinterHandle( Handle, Address );
|
||||
}
|
||||
else if (!strcasecmp( Type, "UNIXserver" ))
|
||||
{
|
||||
if ((Name = (char*)TempMember->GetMemStr( "Socket/Name", NULL ))) {
|
||||
sprintf( Path, "Address/%s/Address", Name );
|
||||
Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get AddressList Address value
|
||||
}
|
||||
else {
|
||||
Address = (char*)TempMember->GetMemStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||
}
|
||||
SetUnixHandle( Handle, ctUNIXserver, Address );
|
||||
}
|
||||
else if (!strcasecmp( Type, "UNIXclient" ))
|
||||
{
|
||||
if ((Name = (char*)TempMember->GetMemStr( "Socket/Name", NULL ))) {
|
||||
sprintf( Path, "Address/%s/Address", Name );
|
||||
Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get AddressList Address value
|
||||
}
|
||||
else {
|
||||
Address = (char*)TempMember->GetMemStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||
}
|
||||
SetUnixHandle( Handle, ctUNIXclient, Address );
|
||||
}
|
||||
else if (!strcasecmp( Type, "UDP" ))
|
||||
{
|
||||
if ((Name = (char*)TempMember->GetMemStr( "Socket/Name", NULL ))) {
|
||||
sprintf( Path, "Address/%s/Address", Name );
|
||||
Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get AddressList Address value
|
||||
sprintf( Path, "Address/%s/Port", Name );
|
||||
Port = (char*)DataTree->GetMemStr( Path, "0", true ); // Get AddressList Port value
|
||||
}
|
||||
else {
|
||||
Address = (char*)TempMember->GetMemStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||
Port = (char*)TempMember->GetMemStr( "Socket/Port", "0", true ); // Get default Port value
|
||||
}
|
||||
Delay = TempMember->GetMemInt( "Socket/ResolveDelay", 0, true );
|
||||
SetSocketHandle( Handle, ctUDPsock, Address, strlcase(Port), Delay );
|
||||
}
|
||||
else if (!strcasecmp( Type, "TCPserver" ))
|
||||
{
|
||||
if ((Name = (char*)TempMember->GetMemStr( "Socket/Name", NULL ))) {
|
||||
@@ -160,7 +198,7 @@ bool CSelectableCore::LoadConfigData()
|
||||
Port = (char*)TempMember->GetMemStr( "Socket/Port", "0", true ); // Get default Port value
|
||||
}
|
||||
Delay = TempMember->GetMemInt( "Socket/ResolveDelay", 0, true );
|
||||
SetSocketHandle( Handle, ctServer, Address, strlcase(Port), Delay );
|
||||
SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Delay );
|
||||
}
|
||||
else if (!strcasecmp( Type, "TCPclient" ))
|
||||
{
|
||||
@@ -175,7 +213,7 @@ bool CSelectableCore::LoadConfigData()
|
||||
Port = (char*)TempMember->GetMemStr( "Socket/Port", "0", true ); // Get default Port value
|
||||
}
|
||||
Delay = TempMember->GetMemInt( "Socket/ResolveDelay", 0, true );
|
||||
SetSocketHandle( Handle, ctClient, Address, strlcase(Port), Delay );
|
||||
SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), Delay );
|
||||
}
|
||||
else if (!strcasecmp( Type, "ForkPipe" )) {
|
||||
Address = (char*)TempMember->GetMemStr( "Fork/ExecPath", NULL, true ); // Get default value
|
||||
@@ -396,11 +434,39 @@ bool CSelectableCore::SetForkPipeHandle( THandle * Handle, const char * ExecPath
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle || !FileName ||
|
||||
!((Type == ctUNIXserver) || (Type == ctUNIXclient) || (Type == ctUNIXremote)) ||
|
||||
!((Handle->Type == ctNone) || (Handle->Type == Type)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set Type
|
||||
Handle->Type = Type;
|
||||
|
||||
// Clear File Name
|
||||
if (Handle->Path) {
|
||||
free( Handle->Path );
|
||||
}
|
||||
|
||||
// Set name
|
||||
Handle->Path = (char*)malloc( strlen(FileName)+1 );
|
||||
strcpy( Handle->Path, FileName );
|
||||
|
||||
// Log event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Set as %s [%s]", Name, Handle->Name, ConnectTypeName[Type], FileName );
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle || ((Handle->Type != ctNone) && (Handle->Type != ctServer) && (Handle->Type != ctClient) && (Handle->Type != ctRemoteClient)) ||
|
||||
!((Type == ctServer) || (Type == ctClient) || (Type == ctRemoteClient)) || !HostName || !PortName ) {
|
||||
if (!Handle || !HostName || !PortName ||
|
||||
!((Type == ctUDPsock) || (Type == ctTCPserver) || (Type == ctTCPclient) || (Type == ctTCPremote)) ||
|
||||
!((Handle->Type == ctNone) || (Handle->Type == Type)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -419,8 +485,10 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
|
||||
// Set HostName & Port
|
||||
Handle->HostName = (char*)malloc( strlen(HostName)+1 );
|
||||
strcpy( Handle->HostName, HostName );
|
||||
|
||||
Handle->PortName = (char*)malloc( strlen(PortName)+1 );
|
||||
strcpy( Handle->PortName, PortName );
|
||||
|
||||
Handle->AddressList = NULL;
|
||||
Handle->AddressInfo = NULL;
|
||||
|
||||
@@ -651,7 +719,7 @@ int CSelectableCore::OpenForkPipe( THandle * Handle )
|
||||
if (!Handle->Path || !*(Handle->Path))
|
||||
{
|
||||
// Log event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Invalid path for Exec", Name, Handle->Name );
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - No path specified for Exec", Name, Handle->Name );
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -727,7 +795,268 @@ int CSelectableCore::OpenForkPipe( THandle * Handle )
|
||||
ChangeState( Handle, csOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
||||
{
|
||||
socklen_t addr_len;
|
||||
struct sockaddr_un address;
|
||||
|
||||
// Validate
|
||||
if (Handle->Type != ctUNIXserver) {
|
||||
return false;
|
||||
} else if (Handle->State == csOpen) {
|
||||
return Handle->FD;
|
||||
}
|
||||
|
||||
// Remove old socket
|
||||
if (unlink( Handle->Path ) && (errno != ENOENT)) {
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to remove old UNIX Server socket [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create socket
|
||||
if ((Handle->FD = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to create new UNIX Server socket [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Set non-blocking flag
|
||||
int flags = fcntl( Handle->FD, F_GETFL, 0 );
|
||||
fcntl( Handle->FD, F_SETFL, flags | O_NONBLOCK );
|
||||
|
||||
// Name Socket
|
||||
memset( &address, 0, sizeof(struct sockaddr_un) );
|
||||
address.sun_family = AF_UNIX;
|
||||
strcpy( address.sun_path, Handle->Path );
|
||||
addr_len = sizeof(address);
|
||||
|
||||
// Bind socket
|
||||
if (bind( Handle->FD, (struct sockaddr*)&address, addr_len ) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to bind UNIX Server socket [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
close( Handle->FD );
|
||||
Handle->FD = -1;
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Create que for 5 connections
|
||||
if (listen( Handle->FD, 5 ) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to listen on UNIX Server socket [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
close( Handle->FD );
|
||||
Handle->FD = -1;
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server binded and listening [%s]", Name, Handle->Name, Handle->Path );
|
||||
|
||||
// Add to Select Lists
|
||||
if (Selector) {
|
||||
Selector->Add( Handle->FD, true, false, Handle, this );
|
||||
}
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
||||
{
|
||||
socklen_t addr_len;
|
||||
struct sockaddr_un address;
|
||||
|
||||
// Check state
|
||||
if (Handle->State == csOpen) {
|
||||
// Already open
|
||||
return Handle->FD;
|
||||
}
|
||||
|
||||
if (Handle->State != csWaitingtoOpen)
|
||||
{
|
||||
// Create socket
|
||||
if ((Handle->FD = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to create new UNIX Client socket [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Set non-blocking flag
|
||||
int flags = fcntl( Handle->FD, F_GETFL, 0 );
|
||||
fcntl( Handle->FD, F_SETFL, flags | O_NONBLOCK );
|
||||
|
||||
// Name Socket
|
||||
memset( &address, 0, sizeof(struct sockaddr_un) );
|
||||
address.sun_family = AF_UNIX;
|
||||
strcpy( address.sun_path, Handle->Path );
|
||||
addr_len = sizeof(address);
|
||||
|
||||
// Try to connect to address
|
||||
if (!connect( Handle->FD, (struct sockaddr*)&address, addr_len ))
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Client waiting to connect [%s]", Name, Handle->Name, Handle->Path );
|
||||
|
||||
// Add to Select Lists
|
||||
if (Selector) {
|
||||
Selector->Add( Handle->FD, true, true, Handle, this );
|
||||
}
|
||||
|
||||
// Set status
|
||||
ChangeState( Handle, csWaitingtoOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Client could not connect [%s] (%s)", Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||
|
||||
// Remove from Select List
|
||||
if (Selector) {
|
||||
Selector->Remove( Handle->FD, true, true );
|
||||
}
|
||||
|
||||
// Close socket
|
||||
close( Handle->FD );
|
||||
ChangeState( Handle, csFailed );
|
||||
Handle->AddressFailed = true;
|
||||
|
||||
// Reset Handle
|
||||
Handle->FD = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Client connected [%s]", Name, Handle->Name, Handle->Path );
|
||||
|
||||
// Add to Select Lists
|
||||
if (Selector) {
|
||||
Selector->Add( Handle->FD, true, true, Handle, this );
|
||||
}
|
||||
|
||||
// Set status
|
||||
ChangeState( Handle, csOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenUNIXremoteSocket( THandle * Handle )
|
||||
{
|
||||
THandle ** RemoteClient;
|
||||
int ClientFD;
|
||||
char ClientName[100];
|
||||
|
||||
socklen_t addr_len;
|
||||
struct sockaddr_un address;
|
||||
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check Handle type
|
||||
if (Handle->Type == ctUNIXserver)
|
||||
{
|
||||
// Accept connection on current socket
|
||||
addr_len = sizeof( address );
|
||||
if ((ClientFD = accept( Handle->FD, (struct sockaddr *)&address, &addr_len)) == -1)
|
||||
{
|
||||
// Log Event
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server failed to accept blocking connection (%s)", Name, Handle->Name, strerror(errno) );
|
||||
}
|
||||
else {
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server failed to accept connection (%s)", Name, Handle->Name, strerror(errno) );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set non-blocking flag
|
||||
int flags = fcntl( ClientFD, F_GETFL, 0 );
|
||||
fcntl( ClientFD, F_SETFL, flags | O_NONBLOCK );
|
||||
|
||||
// Get end of client list
|
||||
RemoteClient = &FirstHandle;
|
||||
while (*RemoteClient) {
|
||||
RemoteClient = &((*RemoteClient)->Next);
|
||||
}
|
||||
|
||||
// Create Remote Client Handle
|
||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||
*RemoteClient = CreateHandle( ClientName, false );
|
||||
if (!SetUnixHandle( *RemoteClient, ctUNIXremote, Handle->Path )) {
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server failed to configure Remote UNIX Client connection (%s)", Name, Handle->Name, strerror(errno) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy Parent Buffer setup
|
||||
SetInBuffer( *RemoteClient, ((Handle->InBuffer)? Handle->InBuffer->Size() : 0),
|
||||
Handle->InTimeout, Handle->InMarker, Handle->InMarkerLen );
|
||||
SetOutBuffer( *RemoteClient, ((Handle->OutBuffer)? Handle->OutBuffer->Size() : 0) );
|
||||
|
||||
// Set Key parameters
|
||||
(*RemoteClient)->FD = ClientFD;
|
||||
(*RemoteClient)->Parent = Handle;
|
||||
(*RemoteClient)->State = csWaitingtoOpen;
|
||||
|
||||
// Reset Timer
|
||||
SetStartTime( &((*RemoteClient)->LastAction) );
|
||||
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server accepted Remote Client connection [%s]", Name, Handle->Name, (*RemoteClient)->Path );
|
||||
|
||||
// Add to Select Lists
|
||||
if (Selector) {
|
||||
Selector->Add( (*RemoteClient)->FD, true, true, *RemoteClient, this );
|
||||
}
|
||||
|
||||
return (*RemoteClient)->FD;
|
||||
}
|
||||
else if (Handle->Type == ctUNIXremote)
|
||||
{
|
||||
// Check state
|
||||
if (Handle->State == csOpen)
|
||||
{
|
||||
// Already open
|
||||
return Handle->FD;
|
||||
}
|
||||
else if (Handle->State == csWaitingtoOpen)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Remote UNIX Client connected [%s]", Name, Handle->Name, Handle->Path );
|
||||
|
||||
// Update state
|
||||
ChangeState( Handle, csOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
||||
@@ -816,7 +1145,95 @@ bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenServerSocket( THandle * Handle, bool DelayResolve )
|
||||
int CSelectableCore::OpenUDPsocket( THandle * Handle, bool DelayResolve )
|
||||
{
|
||||
// Socket options
|
||||
struct linger ServerLinger_opt;
|
||||
ServerLinger_opt.l_onoff = 1;
|
||||
ServerLinger_opt.l_linger = 5;
|
||||
|
||||
int Reuse_opt = 1;
|
||||
int KeepAlive_opt = 1;
|
||||
|
||||
// Validate Handle
|
||||
if (Handle->Type != ctUDPsock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve Host & Port Names
|
||||
if (!ResolveAddress( Handle, DelayResolve ))
|
||||
return -1;
|
||||
|
||||
// Create socket
|
||||
if ((Handle->FD = socket( Handle->AddressInfo->ai_family, Handle->AddressInfo->ai_socktype, Handle->AddressInfo->ai_protocol )) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to create UDP Server socket [%s:%s] (%s)", Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Configure connection
|
||||
if ((setsockopt( Handle->FD, SOL_SOCKET, SO_LINGER, &ServerLinger_opt, sizeof(ServerLinger_opt)) == -1) ||
|
||||
(setsockopt( Handle->FD, SOL_SOCKET, SO_REUSEADDR, &Reuse_opt, sizeof(Reuse_opt)) == -1))
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Could not set socket options [%s:%s] (%s)", Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csFailed );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set non-blocking flag
|
||||
int flags = fcntl( Handle->FD, F_GETFL, 0 );
|
||||
fcntl( Handle->FD, F_SETFL, flags | O_NONBLOCK );
|
||||
|
||||
// Bind socket
|
||||
if (bind( Handle->FD, Handle->AddressInfo->ai_addr, Handle->AddressInfo->ai_addrlen ) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to bind UDP Server socket [%s:%s] (%s)", Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
close( Handle->FD );
|
||||
Handle->FD = -1;
|
||||
ChangeState( Handle, csFailed );
|
||||
Handle->AddressFailed = true;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Create que for 5 connections
|
||||
if (listen( Handle->FD, 5 ) < 0)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Failed to listen on UDP Server socket [%s:%s] (%s)", Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||
|
||||
// Set state
|
||||
close( Handle->FD );
|
||||
Handle->FD = -1;
|
||||
ChangeState( Handle, csFailed );
|
||||
Handle->AddressFailed = true;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UDP Server binded and listening [%s:%s]", Name, Handle->Name, Handle->HostName, Handle->PortName );
|
||||
|
||||
// Add to Select Lists
|
||||
if (Selector) {
|
||||
Selector->Add( Handle->FD, true, false, Handle, this );
|
||||
}
|
||||
|
||||
// Set state
|
||||
ChangeState( Handle, csOpen );
|
||||
return Handle->FD;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayResolve )
|
||||
{
|
||||
// Socket options
|
||||
struct linger ServerLinger_opt;
|
||||
@@ -830,7 +1247,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle, bool DelayResolve )
|
||||
int TCPcnt_opt = 3;
|
||||
|
||||
// Validate Handle
|
||||
if (Handle->Type != ctServer) {
|
||||
if (Handle->Type != ctTCPserver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -921,7 +1338,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle, bool DelayResolve )
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
int CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
||||
{
|
||||
THandle ** RemoteClient;
|
||||
int ClientFD;
|
||||
@@ -938,7 +1355,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
}
|
||||
|
||||
// Check Handle type
|
||||
if (Handle->Type == ctServer)
|
||||
if (Handle->Type == ctTCPserver)
|
||||
{
|
||||
// Accept connection on current socket
|
||||
addr_len = sizeof( address );
|
||||
@@ -972,7 +1389,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
// Create Remote Client Handle
|
||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||
*RemoteClient = CreateHandle( ClientName, false );
|
||||
if (!SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, ClientPort, 0 )) {
|
||||
if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0 )) {
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - TCP Server failed to configure Remote TCP Client connection (%s)", Name, Handle->Name, strerror(errno) );
|
||||
return -1;
|
||||
}
|
||||
@@ -1000,7 +1417,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
|
||||
return (*RemoteClient)->FD;
|
||||
}
|
||||
else if (Handle->Type == ctRemoteClient)
|
||||
else if (Handle->Type == ctTCPremote)
|
||||
{
|
||||
// Check state
|
||||
if (Handle->State == csOpen)
|
||||
@@ -1011,7 +1428,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
else if (Handle->State == csWaitingtoOpen)
|
||||
{
|
||||
// Log Event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Remote TCP Client connection open [%s]", Name, Handle->Name, Handle->HostName );
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Remote TCP Client connected [%s]", Name, Handle->Name, Handle->HostName );
|
||||
|
||||
// Update state
|
||||
ChangeState( Handle, csOpen );
|
||||
@@ -1022,7 +1439,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OpenClientSocket( THandle * Handle, bool DelayResolve )
|
||||
int CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayResolve )
|
||||
{
|
||||
// Socket options
|
||||
int KeepAlive_opt = 1;
|
||||
@@ -1144,14 +1561,26 @@ int CSelectableCore::Open( THandle * Handle, bool DelayResolve )
|
||||
case ctForkPipe :
|
||||
FD = OpenForkPipe( Handle );
|
||||
break;
|
||||
case ctServer :
|
||||
FD = OpenServerSocket( Handle, DelayResolve );
|
||||
case ctUNIXserver :
|
||||
FD = OpenUNIXserverSocket( Handle );
|
||||
break;
|
||||
case ctClient :
|
||||
FD = OpenClientSocket( Handle, DelayResolve );
|
||||
case ctUNIXclient :
|
||||
FD = OpenUNIXclientSocket( Handle );
|
||||
break;
|
||||
case ctRemoteClient :
|
||||
FD = OpenRemoteClientSocket( Handle );
|
||||
case ctUNIXremote :
|
||||
FD = OpenUNIXremoteSocket( Handle );
|
||||
break;
|
||||
case ctUDPsock :
|
||||
FD = OpenUDPsocket( Handle, DelayResolve );
|
||||
break;
|
||||
case ctTCPserver :
|
||||
FD = OpenTCPserverSocket( Handle, DelayResolve );
|
||||
break;
|
||||
case ctTCPclient :
|
||||
FD = OpenTCPclientSocket( Handle, DelayResolve );
|
||||
break;
|
||||
case ctTCPremote :
|
||||
FD = OpenTCPremoteSocket( Handle );
|
||||
break;
|
||||
default:
|
||||
FD = -1;
|
||||
@@ -1175,7 +1604,7 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
||||
return false;
|
||||
|
||||
// Close Children
|
||||
if (Handle->Type == ctServer)
|
||||
if ((Handle->Type == ctTCPserver) || (Handle->Type == ctUNIXserver))
|
||||
{
|
||||
ChildHandle = FirstHandle;
|
||||
while (ChildHandle)
|
||||
@@ -1223,15 +1652,31 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Forked Pipe %s", Name, Handle->Name, ((Fail)? "failed" : "closed"));
|
||||
break;
|
||||
|
||||
case ctServer:
|
||||
case ctUNIXserver:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Server %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path );
|
||||
break;
|
||||
|
||||
case ctUNIXclient:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Client connection %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path );
|
||||
break;
|
||||
|
||||
case ctUNIXremote:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UNIX Remote Client connection %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path );
|
||||
break;
|
||||
|
||||
case ctUDPsock:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - UDP Socket connection %s [%s:%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->HostName, Handle->PortName );
|
||||
break;
|
||||
|
||||
case ctTCPserver:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - TCP Server %s [%s:%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->HostName, Handle->PortName );
|
||||
break;
|
||||
|
||||
case ctRemoteClient:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Remote TCP Client connection %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->HostName );
|
||||
case ctTCPremote:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - TCP Remote Client connection %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->HostName );
|
||||
break;
|
||||
|
||||
case ctClient:
|
||||
case ctTCPclient:
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - TCP Client connection %s [%s:%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->HostName, Handle->PortName );
|
||||
break;
|
||||
|
||||
@@ -1268,10 +1713,14 @@ bool CSelectableCore::Read( THandle * Handle )
|
||||
if (Log) Log->Message( LogLevel, dlHigh, "%s: Handle '%s' - Read Event", Name, Handle->Name );
|
||||
|
||||
// Check for closing/opening event on Socket
|
||||
if (Handle->Type == ctServer)
|
||||
if ((Handle->Type == ctTCPserver) || (Handle->Type == ctUNIXserver))
|
||||
{
|
||||
// Incoming client request
|
||||
ClientFD = OpenRemoteClientSocket( Handle );
|
||||
if (Handle->Type == ctTCPserver) {
|
||||
ClientFD = OpenTCPremoteSocket( Handle );
|
||||
} else if (Handle->Type == ctUNIXserver) {
|
||||
ClientFD = OpenUNIXremoteSocket( Handle );
|
||||
}
|
||||
if (ClientFD == -1) {
|
||||
return false;
|
||||
}
|
||||
@@ -1284,15 +1733,20 @@ bool CSelectableCore::Read( THandle * Handle )
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((Handle->Type == ctRemoteClient) || (Handle->Type == ctClient))
|
||||
else if ((Handle->Type == ctTCPremote) || (Handle->Type == ctTCPclient) ||
|
||||
(Handle->Type == ctUNIXremote) || (Handle->Type == ctUNIXclient) )
|
||||
{
|
||||
// Check if socket ready (non-block open in progress)
|
||||
if (Handle->State == csWaitingtoOpen)
|
||||
{
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
OpenRemoteClientSocket( Handle );
|
||||
} else if (Handle->Type == ctClient) {
|
||||
OpenClientSocket( Handle, true );
|
||||
if (Handle->Type == ctTCPremote) {
|
||||
OpenTCPremoteSocket( Handle );
|
||||
} else if (Handle->Type == ctTCPclient) {
|
||||
OpenTCPclientSocket( Handle, true );
|
||||
} else if (Handle->Type == ctUNIXremote) {
|
||||
OpenUNIXremoteSocket( Handle );
|
||||
} else if (Handle->Type == ctUNIXclient) {
|
||||
OpenUNIXclientSocket( Handle );
|
||||
}
|
||||
// Reset Timer (for auto-close)
|
||||
SetStartTime( &(Handle->LastAction) );
|
||||
@@ -1314,7 +1768,7 @@ bool CSelectableCore::Read( THandle * Handle )
|
||||
Close( Handle, false );
|
||||
|
||||
// Destroy Client
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctTCPremote)) {
|
||||
RemoveHandle( Handle );
|
||||
}
|
||||
return false;
|
||||
@@ -1402,10 +1856,14 @@ bool CSelectableCore::Write( THandle * Handle )
|
||||
if (Handle->State == csWaitingtoOpen)
|
||||
{
|
||||
// Complete socket open process
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
OpenRemoteClientSocket( Handle );
|
||||
} else if (Handle->Type == ctClient) {
|
||||
OpenClientSocket( Handle, true );
|
||||
if (Handle->Type == ctTCPremote) {
|
||||
OpenTCPremoteSocket( Handle );
|
||||
} else if (Handle->Type == ctTCPclient) {
|
||||
OpenTCPclientSocket( Handle, true );
|
||||
} else if (Handle->Type == ctUNIXremote) {
|
||||
OpenUNIXremoteSocket( Handle );
|
||||
} else if (Handle->Type == ctUNIXclient) {
|
||||
OpenUNIXclientSocket( Handle );
|
||||
}
|
||||
// Reset Timer (for auto-close)
|
||||
SetStartTime( &(Handle->LastAction) );
|
||||
@@ -1477,7 +1935,7 @@ bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force )
|
||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Handle '%s' - IN-T:", Name, Handle->Name );
|
||||
|
||||
// Write buffer to Outputs
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||
Output( Handle->Parent->Channel, Data, Len );
|
||||
} else {
|
||||
Output( Handle->Channel, Data, Len );
|
||||
@@ -1496,7 +1954,7 @@ bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force )
|
||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Handle '%s' - IN-M:", Name, Handle->Name );
|
||||
|
||||
// Write buffer to Outputs
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||
Output( Handle->Parent->Channel, Data, Len );
|
||||
} else {
|
||||
Output( Handle->Channel, Data, Len );
|
||||
@@ -1666,7 +2124,7 @@ int CSelectableCore::OutputHandle( THandle * Handle, const char * Data, int Len
|
||||
Len = strlen( Data );
|
||||
}
|
||||
|
||||
if (Handle->Type == ctServer)
|
||||
if ((Handle->Type == ctTCPserver) || (Handle->Type == ctUNIXserver))
|
||||
{
|
||||
// Cannot write to server socket, so Update Remote Client connections individually
|
||||
ChildHandle = FirstHandle;
|
||||
@@ -1775,7 +2233,7 @@ bool CSelectableCore::Process()
|
||||
}
|
||||
|
||||
// Check for auto close (but not on servers)
|
||||
if ((Handle->State == csOpen) && (Handle->Type != ctServer) && Handle->AutoManage && !Handle->Persistent)
|
||||
if ((Handle->State == csOpen) && (Handle->Type != ctTCPserver) && (Handle->Type != ctUNIXserver) && Handle->AutoManage && !Handle->Persistent)
|
||||
{
|
||||
// Close port after timeout
|
||||
if (Timeout( Handle->LastAction, Handle->CloseTimeout )) {
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Types required for connections
|
||||
typedef enum { ctNone = 0, ctSerial = 1, ctLinePrinter = 2, ctServer = 3, ctRemoteClient = 4, ctClient = 5, ctForkPipe = 6 } EConnectType;
|
||||
const char ConnectTypeName[][15] = { "None", "SerialPort", "ParallelPort", "Server", "RemoteClient", "Client", "ForkPipe" };
|
||||
typedef enum { ctNone = 0, ctSerial = 1, ctLinePrinter = 2, ctForkPipe = 3, ctUNIXserver = 4, ctUNIXclient = 5, ctUNIXremote = 6,
|
||||
ctUDPsock = 7, ctTCPserver = 8, ctTCPremote = 9, ctTCPclient = 10 } EConnectType;
|
||||
const char ConnectTypeName[][20] = { "None", "Serial", "LinePrinter", "ForkPipe", "UNIXserver", "UNIXclient", "UNIXremote", "UDPsock", "TCPserver", "TCPremote", "TCPclient" };
|
||||
|
||||
typedef enum { csNone = 0, csOpenRequest = 1, csWaitingtoOpen = 2, csOpen = 3, csDataWaiting = 4, csClosed = 5, csFailed = 6 } EConnectState;
|
||||
const char ConnectStateName[][15] = { "None", "OpenRequest", "WaitingToOpen", "Open", "DataWaiting", "Closed", "Failed" };
|
||||
@@ -84,7 +85,7 @@ struct SHandle {
|
||||
long CloseTimeout; // millisecs of no traffic before closing socket
|
||||
|
||||
// Callback functions
|
||||
FHandleCallback StateCallback[ 6 ];
|
||||
FHandleCallback StateCallback[ 7 ];
|
||||
|
||||
// Type specific parameters
|
||||
char * Path; // Port (file)name or Exec path
|
||||
@@ -209,14 +210,18 @@ protected:
|
||||
|
||||
int OpenLinePrinterPort( THandle * Handle );
|
||||
|
||||
// ForkPipe Operations
|
||||
// File Socket Operations
|
||||
int OpenForkPipe( THandle * Handle );
|
||||
int OpenUNIXserverSocket( THandle * Handle );
|
||||
int OpenUNIXclientSocket( THandle * Handle );
|
||||
int OpenUNIXremoteSocket( THandle * Handle );
|
||||
|
||||
// Socket Operations
|
||||
bool ResolveAddress( THandle * Handle, bool DelayResolve );
|
||||
int OpenServerSocket( THandle * Handle, bool DelayResolve );
|
||||
int OpenRemoteClientSocket( THandle * Handle );
|
||||
int OpenClientSocket( THandle * Handle, bool DelayResolve );
|
||||
int OpenUDPsocket( THandle * Handle, bool DelayResolve );
|
||||
int OpenTCPserverSocket( THandle * Handle, bool DelayResolve );
|
||||
int OpenTCPremoteSocket( THandle * Handle );
|
||||
int OpenTCPclientSocket( THandle * Handle, bool DelayResolve );
|
||||
|
||||
// Mutual Operations
|
||||
int ReadFromFD( int FD, char * Data, int MaxLen );
|
||||
@@ -270,6 +275,7 @@ public:
|
||||
bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait );
|
||||
bool SetLinePrinterHandle( THandle * Handle, const char * FileName );
|
||||
bool SetForkPipeHandle( THandle * Handle, const char * ExecPath );
|
||||
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName );
|
||||
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay );
|
||||
bool ClearHandle( THandle * Handle );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user