Skip to content

Commit

Permalink
[tests] Splitting ListenCallback test into 3 separate tests (#2556).
Browse files Browse the repository at this point in the history
Fixed proper setup/teardown.
  • Loading branch information
ethouris authored Nov 28, 2022
1 parent 6d62096 commit 053f179
Showing 1 changed file with 159 additions and 74 deletions.
233 changes: 159 additions & 74 deletions test/test_listen_callback.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <gtest/gtest.h>
#include <thread>
#include <chrono>
#include <string>
#include <map>
Expand All @@ -10,107 +11,134 @@
#include "srt.h"
#include "utilities.h"


srt_listen_callback_fn SrtTestListenCallback;

/**
* This test makes a service and a client connecting to it.
* The service sets up a callback function on the listener.
* The listener sets up different passwords depending on the user.
* The test tests:
* - correct connection with correct password
* - rejected connection with wrong password
* - rejected connection on nonexistent user
*/
TEST(Core, ListenCallback) {

using namespace std;

ASSERT_EQ(srt_startup(), 0);
class ListenerCallback
: public testing::Test
{
protected:
ListenerCallback()
{
// initialization code here
}

// Create server on 127.0.0.1:5555
~ListenerCallback()
{
// cleanup any pending stuff, but no exceptions allowed
}
public:

const SRTSOCKET server_sock = srt_create_socket();
ASSERT_GT(server_sock, 0); // socket_id should be > 0
SRTSOCKET server_sock, client_sock;
std::thread accept_thread;
sockaddr_in sa;
sockaddr* psa;

sockaddr_in bind_sa;
memset(&bind_sa, 0, sizeof bind_sa);
bind_sa.sin_family = AF_INET;
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &bind_sa.sin_addr), 1);
bind_sa.sin_port = htons(5555);
void SetUp()
{
ASSERT_EQ(srt_startup(), 0);

ASSERT_NE(srt_bind(server_sock, (sockaddr*)&bind_sa, sizeof bind_sa), -1);
ASSERT_NE(srt_listen(server_sock, 5), -1);
(void)srt_listen_callback(server_sock, &SrtTestListenCallback, NULL);
// Create server on 127.0.0.1:5555

// Create client to connect to the above server
SRTSOCKET client_sock;
sockaddr_in sa;
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(5555);
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1);
sockaddr* psa = (sockaddr*)&sa;
server_sock = srt_create_socket();
ASSERT_GT(server_sock, 0); // socket_id should be > 0

sockaddr_in bind_sa;
memset(&bind_sa, 0, sizeof bind_sa);
bind_sa.sin_family = AF_INET;
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &bind_sa.sin_addr), 1);
bind_sa.sin_port = htons(5555);

cerr << "TEST 1: Connect to an encrypted socket correctly (should succeed)\n";
ASSERT_NE(srt_bind(server_sock, (sockaddr*)&bind_sa, sizeof bind_sa), -1);
ASSERT_NE(srt_listen(server_sock, 5), -1);
(void)srt_listen_callback(server_sock, &SrtTestListenCallback, NULL);

client_sock = srt_create_socket();
ASSERT_GT(client_sock, 0); // socket_id should be > 0
accept_thread = std::thread([this] { this->AcceptLoop(); });

string username_spec = "#!::u=admin";
string password = "thelocalmanager";
// Prepare client socket

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
#if SRT_ENABLE_ENCRYPTION
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);
#endif
client_sock = srt_create_socket();
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(5555);
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1);
psa = (sockaddr*)&sa;

// EXPECTED RESULT: connected successfully
EXPECT_NE(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
ASSERT_GT(client_sock, 0); // socket_id should be > 0

// Close the socket
EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
auto awhile = std::chrono::milliseconds(20);
std::this_thread::sleep_for(awhile);
}

void AcceptLoop()
{
// Setup EID in order to pick up either readiness or error.
// THis is only to make a formal response side, nothing here is to be tested.

cerr << "TEST 2: Connect with a wrong password (should reject the handshake)\n";
#if SRT_ENABLE_ENCRYPTION
client_sock = srt_create_socket();
ASSERT_GT(client_sock, 0); // socket_id should be > 0
int eid = srt_epoll_create();

password = "thelokalmanager"; // (typo :D)
// Subscribe to R | E

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);
int re = SRT_EPOLL_IN | SRT_EPOLL_ERR;
srt_epoll_add_usock(eid, server_sock, &re);

// EXPECTED RESULT: connection rejected
EXPECT_EQ(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
SRT_EPOLL_EVENT results[2];

// Close the socket
EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
#endif
for (;;)
{
auto state = srt_getsockstate(server_sock);
if (int(state) > int(SRTS_CONNECTED))
{
std::cout << "[T] Listener socket closed, exitting\n";
break;
}

std::cout << "[T] Waiting for epoll to accept\n";
int res = srt_epoll_uwait(eid, results, 2, 1000);
if (res == 1)
{
if (results[0].events == SRT_EPOLL_IN)
{
int acp = srt_accept(server_sock, NULL, NULL);
if (acp == SRT_ERROR)
{
std::cout << "[T] Accept failed, so exitting\n";
break;
}
srt_close(acp);
continue;
}

// Then it can only be SRT_EPOLL_ERR, which
// can be done by having the socket closed
break;
}

cerr << "TEST 3: Connect with wrong username (should exit on exception)\n";
client_sock = srt_create_socket();
ASSERT_GT(client_sock, 0); // socket_id should be > 0
if (res == 0) // probably timeout, just repeat
{
std::cout << "[T] (NOTE: epoll timeout, still waiting)\n";
continue;
}
}

username_spec = "#!::u=haivision";
password = "thelocalmanager"; // (typo :D)
srt_epoll_release(eid);
}

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
#if SRT_ENABLE_ENCRYPTION
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);
#endif
void TearDown()
{
std::cout << "TeadDown: closing all sockets\n";
// Close the socket
EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
EXPECT_EQ(srt_close(server_sock), SRT_SUCCESS);

// EXPECTED RESULT: connection rejected
EXPECT_EQ(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
// After that, the thread should exit
std::cout << "TearDown: joining accept thread\n";
accept_thread.join();
std::cout << "TearDown: SRT exit\n";

// Close the socket
EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
srt_cleanup();
}

(void)srt_cleanup();
}
};

int SrtTestListenCallback(void* opaq, SRTSOCKET ns SRT_ATR_UNUSED, int hsversion, const struct sockaddr* peeraddr, const char* streamid)
{
Expand Down Expand Up @@ -193,3 +221,60 @@ int SrtTestListenCallback(void* opaq, SRTSOCKET ns SRT_ATR_UNUSED, int hsversion
}


/**
* This test makes a service and a client connecting to it.
* The service sets up a callback function on the listener.
* The listener sets up different passwords depending on the user.
* The test tests:
* - correct connection with correct password (SecureSuccess)
* - rejected connection with wrong password (FauxPass)
* - rejected connection on nonexistent user (FauxUser)
*/

using namespace std;


TEST_F(ListenerCallback, SecureSuccess)
{
string username_spec = "#!::u=admin";
string password = "thelocalmanager";

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
#if SRT_ENABLE_ENCRYPTION
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);
#endif

// EXPECTED RESULT: connected successfully
EXPECT_NE(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
}

#if SRT_ENABLE_ENCRYPTION
TEST_F(ListenerCallback, FauxPass)
{
string username_spec = "#!::u=admin";
string password = "thelokalmanager"; // (typo :D)

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);

// EXPECTED RESULT: connection rejected
EXPECT_EQ(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
}
#endif

TEST_F(ListenerCallback, FauxUser)
{
string username_spec = "#!::u=haivision";
string password = "thelocalmanager"; // (typo :D)

ASSERT_NE(srt_setsockflag(client_sock, SRTO_STREAMID, username_spec.c_str(), username_spec.size()), -1);
#if SRT_ENABLE_ENCRYPTION
ASSERT_NE(srt_setsockflag(client_sock, SRTO_PASSPHRASE, password.c_str(), password.size()), -1);
#endif

// EXPECTED RESULT: connection rejected
EXPECT_EQ(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);
}



0 comments on commit 053f179

Please sign in to comment.