diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 96aeeb1..e78636a 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -101,10 +102,10 @@ bool CSelectableCore::LoadConfigData() { if ((Name = (char*)TempMember->GetMemStr( "Port/Name", NULL ))) { sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get address list value + Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get address list value } else { - Address = (char*)TempMember->GetMemStr( "Port/Address", NULL, true ); // Get default value + Address = (char*)TempMember->GetMemStr( "Port/Address", NULL, true ); // Get default value } SetSerialHandle( Handle, Address ); @@ -140,13 +141,50 @@ bool CSelectableCore::LoadConfigData() { if ((Name = (char*)TempMember->GetMemStr( "Port/Name", NULL ))) { sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get address list value + Address = (char*)DataTree->GetMemStr( Path, NULL, true ); // Get address list value } else { - Address = (char*)TempMember->GetMemStr( "Port/Address", NULL, true ); // Get default value + Address = (char*)TempMember->GetMemStr( "Port/Address", NULL, true ); // Get default value } 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 ))) { @@ -156,11 +194,11 @@ bool CSelectableCore::LoadConfigData() 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 + 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, ctServer, Address, strlcase(Port), Delay ); + SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Delay ); } else if (!strcasecmp( Type, "TCPclient" )) { @@ -171,14 +209,14 @@ bool CSelectableCore::LoadConfigData() 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 + 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, 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 + Address = (char*)TempMember->GetMemStr( "Fork/ExecPath", NULL, true ); // Get default value SetForkPipeHandle( Handle, Address ); } @@ -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 )) { diff --git a/SelectableCore.h b/SelectableCore.h index b9bd9e1..e6a4f99 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -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 );