Skip to content

Commit

Permalink
Return result Messages from Server methods
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcusTomlinson committed Feb 10, 2024
1 parent 12be569 commit f9bd1be
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 56 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, ubuntu-20.04, windows-2022]
os: [macos-12, ubuntu-20.04, windows-2022]

steps:
- if: matrix.os == 'windows-2022'
Expand All @@ -26,11 +26,6 @@ jobs:
name: Configure MSVC (Windows)
uses: ilammy/msvc-dev-cmd@v1

- if: matrix.os == 'macos-11'
name: Configure Xcode (MacOS)
run: |
sudo xcode-select -s /Applications/Xcode_11.7.app/Contents/Developer
- name: Configure Python
uses: actions/setup-python@v4
with:
Expand Down
48 changes: 19 additions & 29 deletions src/IpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,11 @@ class ServerImpl final
#endif
}

bool Listen( const std::function<Message( const Message& header, const Message& message )>& callback )
Message Listen( const std::function<Message( const Message& header, const Message& message )>& callback )
{
if ( serverSocket == INVALID_SOCKET )
{
callback( Message( "", true ), Message( initError, true ) );
return false;
return Message( initError, true );
}

// Accept a connection
Expand All @@ -139,17 +138,13 @@ class ServerImpl final

if ( select( (int)serverSocket + 1, &fd, nullptr, nullptr, &timeout ) <= 0 )
{
callback( Message( "", true ),
Message( "select() failed (error: " + std::to_string( lastError() ) + ")", true ) );
return false;
return Message( "select() failed (error: " + std::to_string( lastError() ) + ")", true );
}

SOCKET clientSocket = accept( serverSocket, NULL, NULL );
if ( clientSocket == INVALID_SOCKET )
{
callback( Message( "", true ),
Message( "accept() failed (error: " + std::to_string( lastError() ) + ")", true ) );
return false;
return Message( "accept() failed (error: " + std::to_string( lastError() ) + ")", true );
}

#ifdef _WIN32
Expand All @@ -167,65 +162,60 @@ class ServerImpl final
auto recvHeaderBytes = Receive( clientSocket );
if ( recvHeaderBytes.empty() )
{
if ( lastError() != 0 && lastError() != EINVAL )
if ( lastError() == 0 || lastError() == EINVAL )
{
callback( Message( "", true ),
Message( "header recv() failed (error: " + std::to_string( lastError() ) + ")", true ) );
closesocket( clientSocket );
return Message( "" );
}

closesocket( clientSocket );
return false;
return Message( "header recv() failed (error: " + std::to_string( lastError() ) + ")", true );
}

// Send ack
if ( !Send( clientSocket, std::vector<unsigned char>{ 1 } ) )
{
callback( Message( "", true ),
Message( "ack send() failed (error: " + std::to_string( lastError() ) + ")", true ) );
closesocket( clientSocket );
return false;
return Message( "ack send() failed (error: " + std::to_string( lastError() ) + ")", true );
}

// Receive message data
auto recvMessageBytes = Receive( clientSocket );
if ( recvMessageBytes.empty() )
{
callback( Message( "", true ),
Message( "message recv() failed (error: " + std::to_string( lastError() ) + ")", true ) );
closesocket( clientSocket );
return false;
return Message( "message recv() failed (error: " + std::to_string( lastError() ) + ")", true );
}

// Send some data
auto sendMessage = callback( recvHeaderBytes, recvMessageBytes );
if ( !Send( clientSocket, sendMessage ) )
{
callback( Message( "", true ),
Message( "response send() failed (error: " + std::to_string( lastError() ) + ")", true ) );
closesocket( clientSocket );
return false;
return Message( "response send() failed (error: " + std::to_string( lastError() ) + ")", true );
}

closesocket( clientSocket );
return true;
return Message( "" );
}

bool StopListening() const
Message StopListening() const
{
SOCKET clientSocket = socket( AF_UNIX, SOCK_STREAM, PF_UNSPEC );
if ( clientSocket == INVALID_SOCKET )
{
return false;
return Message( "socket() failed (error: " + std::to_string( lastError() ) + ")", true );
}

if ( connect( clientSocket, reinterpret_cast<const sockaddr*>( &socketAddr ), sizeof( socketAddr ) ) ==
SOCKET_ERROR )
{
closesocket( clientSocket );
return false;
return Message( "connect() failed (error: " + std::to_string( lastError() ) + ")", true );
}

closesocket( clientSocket );
return true;
return Message( "" );
}

static bool Send( SOCKET clientSocket, const Message& message )
Expand Down Expand Up @@ -295,12 +285,12 @@ Server::Server( const std::filesystem::path& socketPath )

Server::~Server() = default;

bool Server::Listen( const std::function<Message( const Message& header, const Message& message )>& callback )
Message Server::Listen( const std::function<Message( const Message& header, const Message& message )>& callback )
{
return p->Listen( callback );
}

bool Server::StopListening()
Message Server::StopListening()
{
return p->StopListening();
}
6 changes: 4 additions & 2 deletions src/IpcServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ class Server final
Server& operator=( const Server& ) = delete;

// Listen() blocks for just one client message, run it in a loop in it's own thread
bool Listen( const std::function<Message( const Message& header, const Message& message )>& callback );
// (Use IsError() on the return Message to determine if the call was successful)
Message Listen( const std::function<Message( const Message& header, const Message& message )>& callback );

// StopListening() should be called from a different thread to Listen() to unblock it
bool StopListening();
// (Use IsError() on the return Message to determine if the call was successful)
Message StopListening();

private:
std::unique_ptr<Private::ServerImpl> p;
Expand Down
27 changes: 8 additions & 19 deletions tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ TEST( Ipc, SameProcess )
auto listenThread = std::thread(
[&server]
{
ASSERT_TRUE( server.Listen( RecvCallback ) );
ASSERT_TRUE( server.Listen( RecvCallback ) );
ASSERT_FALSE( server.Listen( RecvCallback ).IsError() );
ASSERT_FALSE( server.Listen( RecvCallback ).IsError() );
} );

Ipc::Client client( c_serverSocket );
Expand All @@ -91,8 +91,8 @@ TEST( Ipc, SeparateProcess )
{
Ipc::Server server( c_serverSocket );
ready.set_value();
ASSERT_TRUE( server.Listen( RecvCallback ) );
ASSERT_TRUE( server.Listen( RecvCallback ) );
ASSERT_FALSE( server.Listen( RecvCallback ).IsError() );
ASSERT_FALSE( server.Listen( RecvCallback ).IsError() );
} )
.detach();
ready.get_future().wait();
Expand Down Expand Up @@ -125,7 +125,7 @@ TEST( Ipc, SeparateProcess )
TEST( Ipc, StopListening )
{
Ipc::Server server( c_serverSocket );
auto listenThread = std::thread( [&server] { ASSERT_FALSE( server.Listen( RecvCallback ) ); } );
auto listenThread = std::thread( [&server] { ASSERT_FALSE( server.Listen( RecvCallback ).IsError() ); } );

server.StopListening();

Expand All @@ -141,20 +141,9 @@ TEST( Ipc, PathTooLong )
// Server
Ipc::Server server( longPath );

bool callbackCalled = false;

ASSERT_FALSE( server.Listen(
[&longPath, &callbackCalled]( const Ipc::Message& header, const Ipc::Message& message ) -> Ipc::Message
{
callbackCalled = true;
EXPECT_TRUE( header.IsError() );
EXPECT_TRUE( header.AsString().empty() );
EXPECT_TRUE( message.IsError() );
EXPECT_EQ( message.AsString(), std::string( "socket path too long: " ) + longPath );
return Ipc::Message( "" );
} ) );

ASSERT_TRUE( callbackCalled );
auto result = server.Listen( RecvCallback );
ASSERT_TRUE( result.IsError() );
ASSERT_EQ( result.AsString(), std::string( "socket path too long: " ) + longPath );

// Client
Ipc::Client client( longPath );
Expand Down

0 comments on commit f9bd1be

Please sign in to comment.