Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downgrade to base64 for snooped blobs #1828

Merged
merged 3 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion indiserver/indiserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ class MsgQueue: public Collectable

void setFds(int rFd, int wFd);

bool acceptSharedBuffers() const
virtual bool acceptSharedBuffers() const
{
return useSharedBuffer;
}
Expand Down Expand Up @@ -747,6 +747,12 @@ class DvrInfo: public MsgQueue

/* Reference to all active drivers */
static ConcurrentSet<DvrInfo> drivers;

// decoding of attached blobs from driver is not supported ATM. Be conservative here
virtual bool acceptSharedBuffers() const
{
return false;
}
};

class LocalDvrInfo: public DvrInfo
Expand Down
40 changes: 22 additions & 18 deletions integs/DriverMock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,34 @@
#include "DriverMock.h"
#include "utils.h"


class FakeDriverListener {
std::string abstractPath;
bool ready = false;
public:
int serverConnection;
void setup() {
if (ready) return;
ready = true;
// Create a socket that will not have the clo on exec flag ?
abstractPath = "/tmp/fakedriver-test";
setenv("FAKEDRIVER_ADDRESS", abstractPath.c_str(), 1);

serverConnection = unixSocketListen(abstractPath);
}
};

static FakeDriverListener driverListener;


void DriverMock::setup()
{
// Create a socket that will not have the clo on exec flag ?
abstractPath = "/tmp/fakedriver-test";
setenv("FAKEDRIVER_ADDRESS", abstractPath.c_str(), 1);

serverConnection = unixSocketListen(abstractPath);
driverListener.setup();
}

void DriverMock::waitEstablish()
{
driverConnection = socketAccept(serverConnection);
driverConnection = socketAccept(driverListener.serverConnection);
unixSocketRecvFds(driverConnection, 2, driverFds);
cnx.setFds(driverFds[0], driverFds[1]);
}
Expand All @@ -55,19 +71,8 @@ void DriverMock::ping()
cnx.expectXml("<pingReply uid=\"flush\"/>");
}


void DriverMock::unsetup()
{
if (serverConnection != -1)
{
close(serverConnection);
serverConnection = -1;
}
}

DriverMock::DriverMock()
{
serverConnection = -1;
driverConnection = -1;
driverFds[0] = -1;
driverFds[1] = -1;
Expand All @@ -76,5 +81,4 @@ DriverMock::DriverMock()
DriverMock::~DriverMock()
{
terminateDriver();
unsetup();
}
3 changes: 0 additions & 3 deletions integs/DriverMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
*/
class DriverMock
{
std::string abstractPath;
int serverConnection;
int driverConnection;

int driverFds[2];
Expand All @@ -42,7 +40,6 @@ class DriverMock

// Start the listening socket that will receive driver upon their starts
void setup();
void unsetup();

void waitEstablish();

Expand Down
49 changes: 49 additions & 0 deletions integs/IndiServerController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,35 @@

#include <system_error>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "utils.h"
#include "IndiServerController.h"


#define TEST_TCP_PORT 17624
#define TEST_UNIX_SOCKET "/tmp/indi-test-server"
#define TEST_INDI_FIFO "/tmp/indi-test-fifo"
#define STRINGIFY_TOK(x) #x
#define TO_STRING(x) STRINGIFY_TOK(x)

IndiServerController::IndiServerController() {
fifo = false;
}

IndiServerController::~IndiServerController() {
// Abort any pending indi server
kill();
join();
}


void IndiServerController::setFifo(bool fifo) {
this->fifo = fifo;
}

void IndiServerController::start(const std::vector<std::string> & args) {
ProcessController::start("../indiserver/indiserver", args);
}
Expand All @@ -38,11 +57,41 @@ void IndiServerController::startDriver(const std::string & path) {
args.push_back("-u");
args.push_back(TEST_UNIX_SOCKET);
#endif

if (fifo) {
unlink(TEST_INDI_FIFO);
if (mkfifo(TEST_INDI_FIFO, 0600) == -1) {
throw std::system_error(errno, std::generic_category(), "mkfifo");
}
args.push_back("-f");
args.push_back(TEST_INDI_FIFO);
}
args.push_back(path);

start(args);
}

void IndiServerController::addDriver(const std::string & driver) {
if (!fifo) {
throw new std::runtime_error("Fifo is not enabled - cannot add driver");
}

int fifoFd = open(TEST_INDI_FIFO, O_WRONLY);
if (fifoFd == -1) {
throw std::system_error(errno, std::generic_category(), "opening fifo");
}

std::string cmd = "start " + driver +"\n";
int wr = write(fifoFd, cmd.data(), cmd.length());
if (wr == -1) {
auto e = errno;
close(fifoFd);
throw std::system_error(e, std::generic_category(), "write to fifo");
}

close(fifoFd);
}

std::string IndiServerController::getUnixSocketPath() const {
return TEST_UNIX_SOCKET;
}
Expand Down
7 changes: 6 additions & 1 deletion integs/IndiServerController.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@
*/
class IndiServerController : public ProcessController
{

bool fifo;
public:
IndiServerController();
~IndiServerController();
void setFifo(bool enable);
void start(const std::vector<std::string> & args);

void startDriver(const std::string & driver);

void addDriver(const std::string & path);

std::string getUnixSocketPath() const;
int getTcpPort() const;
};
Expand Down
9 changes: 8 additions & 1 deletion integs/ProcessController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void ProcessController::start(const std::string & path, const std::vector<std::s
}
if (pid == 0) {
std::string error = "exec " + path;

// TODO : Close all file descriptor
execv(fullArgs[0], (char * const *) fullArgs);

// Child goes here....
Expand All @@ -103,6 +103,13 @@ void ProcessController::waitProcessEnd(int exitCode) {
expectExitCode(exitCode);
}

void ProcessController::kill() {
if (pid == -1) {
return;
}
::kill(pid, SIGKILL);
}

void ProcessController::join() {
if (pid == -1) {
return;
Expand Down
1 change: 1 addition & 0 deletions integs/ProcessController.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ProcessController {
void expectAlive();
void expectExitCode(int e);
void join();
void kill();

void waitProcessEnd(int expectedExitCode);

Expand Down
118 changes: 113 additions & 5 deletions integs/TestIndiserverSingleDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,51 @@ TEST(IndiserverSingleDriver, ReplyToPing)
}


void startFakeDev1(IndiServerController &indiServer, DriverMock &fakeDriver)
static void startFakeDev(IndiServerController &indiServer)
{
setupSigPipe();

fakeDriver.setup();

std::string fakeDriverPath = getTestExePath("fakedriver");

// Start indiserver with one instance, repeat 0
indiServer.startDriver(fakeDriverPath);
fprintf(stderr, "indiserver started\n");
}


static void establishDriver(IndiServerController &indiServer, DriverMock &fakeDriver, const std::string & name) {
(void)indiServer;
fakeDriver.waitEstablish();
fprintf(stderr, "fake driver started\n");

fakeDriver.cnx.expectXml("<getProperties version='1.7'/>");
fprintf(stderr, "getProperties received\n");

// Give one props to the driver
fakeDriver.cnx.send("<defBLOBVector device='fakedev1' name='testblob' label='test label' group='test_group' state='Idle' perm='ro' timeout='100' timestamp='2018-01-01T00:00:00'>\n");
fakeDriver.cnx.send("<defBLOBVector device='" + name + "' name='testblob' label='test label' group='test_group' state='Idle' perm='ro' timeout='100' timestamp='2018-01-01T00:00:00'>\n");
fakeDriver.cnx.send("<defBLOB name='content' label='content'/>\n");
fakeDriver.cnx.send("</defBLOBVector>\n");
}

static void startFakeDev1(IndiServerController &indiServer, DriverMock &fakeDriver)
{
fakeDriver.setup();
startFakeDev(indiServer);
establishDriver(indiServer, fakeDriver, "fakeDev1");
}

static void addDriver(IndiServerController &indiServer, DriverMock &fakeDriver, const std::string & name)
{
fakeDriver.setup();

std::string fakeDriverPath = getTestExePath("fakedriver");

indiServer.addDriver(fakeDriverPath);

establishDriver(indiServer, fakeDriver, name);
}


void connectFakeDev1Client(IndiServerController &, DriverMock &fakeDriver, IndiClientMock &indiClient)
{
fprintf(stderr, "Client asks properties\n");
Expand Down Expand Up @@ -314,6 +335,43 @@ TEST(IndiserverSingleDriver, ForwardBase64BlobToIPClient)
}


TEST(IndiserverSingleDriver, SnoopDriverPropertie)
{
// This tests snooping simple property from driver to driver
DriverMock fakeDriver;
IndiServerController indiServer;
indiServer.setFifo(true);
startFakeDev1(indiServer, fakeDriver);

DriverMock snoopDriver;
addDriver(indiServer, snoopDriver, "snoopDriver");

fakeDriver.ping();
snoopDriver.ping();

snoopDriver.cnx.send("<getProperties version='1.7' device='fakedev1' name='testnumber1'/>\n");

snoopDriver.ping();
fakeDriver.ping();

fakeDriver.cnx.send("<defNumberVector device='fakedev1' name='testnumber1' label='test label' group='test_group' state='Idle' perm='rw' timeout='100' timestamp='2018-01-01T00:00:00'>\n");
fakeDriver.cnx.send("<defNumber name='content' label='content' min='0' max='100' step='1'>50</defNumber>\n");
fakeDriver.cnx.send("</defNumberVector>\n");

snoopDriver.cnx.expectXml("<defNumberVector device='fakedev1' name='testnumber1' label='test label' group='test_group' state='Idle' perm='rw' timeout='100' timestamp='2018-01-01T00:00:00'>");
snoopDriver.cnx.expectXml("<defNumber name='content' label='content' min='0' max='100' step='1'>");
snoopDriver.cnx.expect("\n50");
snoopDriver.cnx.expectXml("</defNumber>");
snoopDriver.cnx.expectXml("</defNumberVector>");

fakeDriver.terminateDriver();
snoopDriver.terminateDriver();

indiServer.kill();
indiServer.join();
}


#define DUMMY_BLOB_SIZE 64

#ifdef ENABLE_INDI_SHARED_MEMORY
Expand Down Expand Up @@ -363,7 +421,7 @@ TEST(IndiserverSingleDriver, ForwardBase64BlobToUnixClient)

void driverSendAttachedBlob(DriverMock &fakeDriver, ssize_t size)
{
fprintf(stderr, "Driver send new blob value - without actual attachment\n");
fprintf(stderr, "Driver send new blob value as attachment\n");

// Allocate more memory than asked (simulate kernel BSD kernel rounding up)
ssize_t physical_size=0x10000;
Expand Down Expand Up @@ -482,4 +540,54 @@ TEST(IndiserverSingleDriver, ForwardAttachedBlobToIPClient)
indiServer.waitProcessEnd(1);
}


TEST(IndiserverSingleDriver, ForwardAttachedBlobToDriver)
{
// This tests attached blob pass through
DriverMock fakeDriver;
IndiServerController indiServer;
indiServer.setFifo(true);
startFakeDev1(indiServer, fakeDriver);

DriverMock snoopDriver;
addDriver(indiServer, snoopDriver, "snoopDriver");

fakeDriver.ping();
snoopDriver.ping();

snoopDriver.cnx.send("<getProperties version='1.7' device='fakedev1' name='testblob'/>\n");
snoopDriver.cnx.send("<enableBLOB device='fakedev1' name='testblob'>Also</enableBLOB>\n");
snoopDriver.ping();

ssize_t size = 32;
driverSendAttachedBlob(fakeDriver, size);

#if 0
// Until proper support by drivers, indiserver converts to base64 for that path
snoopDriver.cnx.allowBufferReceive(true);
snoopDriver.cnx.expectXml("<setBLOBVector device='fakedev1' name='testblob' timestamp='2018-01-01T00:01:00'>");
snoopDriver.cnx.expectXml("<oneBLOB name='content' size='32' format='.fits' attached='true'/>\n");
snoopDriver.cnx.expectXml("</setBLOBVector>");

SharedBuffer receivedFd;
snoopDriver.cnx.expectBuffer(receivedFd);
snoopDriver.cnx.allowBufferReceive(false);
EXPECT_GE( receivedFd.getSize(), 32);
#else
snoopDriver.cnx.expectXml("<setBLOBVector device='fakedev1' name='testblob' timestamp='2018-01-01T00:01:00'>");
snoopDriver.cnx.expectXml("<oneBLOB name='content' size='32' format='.fits'>\n");
snoopDriver.cnx.expect("\nMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=");
snoopDriver.cnx.expectXml("</oneBLOB>\n");
snoopDriver.cnx.expectXml("</setBLOBVector>");
#endif

fakeDriver.terminateDriver();
snoopDriver.terminateDriver();
// fakeSnooper.terminateDriver();
// Exit code 1 is expected when driver stopped
indiServer.kill();
indiServer.join();
}


#endif
Loading