Added class RemoteSMTarget that starts application SMRemoteTargetApp and communicates with it via ports. The remote app runs a looper with an optional handler.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@365 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
// SMRemoteTargetApp.cpp
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include "SMRemoteTargetApp.h"
|
||||||
|
#include "SMLooper.h"
|
||||||
|
|
||||||
|
// debugging
|
||||||
|
//#define DBG(x) x
|
||||||
|
#define DBG(x)
|
||||||
|
#define OUT printf
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
DBG(OUT("REMOTE: main()\n"));
|
||||||
|
assert(argc > 1);
|
||||||
|
const char *portName = argv[1];
|
||||||
|
bool preferred = (argc > 2 && !strcmp(argv[2], "preferred"));
|
||||||
|
// create local port
|
||||||
|
port_id localPort = create_port(5, "SMRemoteTargetApp port");
|
||||||
|
assert(localPort >= 0);
|
||||||
|
DBG(OUT("REMOTE: local port created\n"));
|
||||||
|
// create looper/handler
|
||||||
|
SMHandler *handler = NULL;
|
||||||
|
SMLooper *looper = new SMLooper;
|
||||||
|
looper->Run();
|
||||||
|
if (!preferred) {
|
||||||
|
handler = new SMHandler;
|
||||||
|
assert(looper->Lock());
|
||||||
|
looper->AddHandler(handler);
|
||||||
|
looper->Unlock();
|
||||||
|
}
|
||||||
|
DBG(OUT("REMOTE: looper/handler created\n"));
|
||||||
|
// find remote port
|
||||||
|
DBG(OUT("REMOTE: find remote port `%s'\n", portName));
|
||||||
|
port_id remotePort = find_port(portName);
|
||||||
|
assert(remotePort >= 0);
|
||||||
|
DBG(OUT("REMOTE: found remote port\n"));
|
||||||
|
// send init message
|
||||||
|
smrt_init initData;
|
||||||
|
initData.port = localPort;
|
||||||
|
initData.messenger = BMessenger(handler, looper);
|
||||||
|
assert(write_port(remotePort, SMRT_INIT, &initData, sizeof(smrt_init))
|
||||||
|
== B_OK);
|
||||||
|
DBG(OUT("REMOTE: init message sent\n"));
|
||||||
|
// loop until quit message
|
||||||
|
bool running = true;
|
||||||
|
while (running) {
|
||||||
|
char buffer[sizeof(smrt_get_ready)];
|
||||||
|
int32 code;
|
||||||
|
ssize_t readSize = read_port(localPort, &code, buffer, sizeof(buffer));
|
||||||
|
if (readSize < 0)
|
||||||
|
running = readSize;
|
||||||
|
DBG(OUT("REMOTE: read port: %.4s\n", (char*)&code));
|
||||||
|
switch (code) {
|
||||||
|
case SMRT_GET_READY:
|
||||||
|
{
|
||||||
|
DBG(OUT("REMOTE: SMRT_GET_READY\n"));
|
||||||
|
assert(readSize == sizeof(smrt_get_ready));
|
||||||
|
smrt_get_ready &data = *(smrt_get_ready*)buffer;
|
||||||
|
looper->SetReplyDelay(data.reply_delay);
|
||||||
|
looper->BlockUntil(data.unblock_time);
|
||||||
|
DBG(OUT("REMOTE: SMRT_GET_READY done\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMRT_DELIVERY_SUCCESS_REQUEST:
|
||||||
|
{
|
||||||
|
DBG(OUT("REMOTE: SMRT_DELIVERY_SUCCESS_REQUEST\n"));
|
||||||
|
assert(readSize == 0);
|
||||||
|
smrt_delivery_success data;
|
||||||
|
data.success = looper->DeliverySuccess();
|
||||||
|
assert(write_port(remotePort, SMRT_DELIVERY_SUCCESS_REPLY,
|
||||||
|
&data, sizeof(smrt_delivery_success))
|
||||||
|
== B_OK);
|
||||||
|
DBG(OUT("REMOTE: SMRT_DELIVERY_SUCCESS_REQUEST done\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMRT_QUIT:
|
||||||
|
DBG(OUT("REMOTE: QUIT\n"));
|
||||||
|
default:
|
||||||
|
if (code != SMRT_QUIT)
|
||||||
|
DBG(OUT("REMOTE: UNKNOWN COMMAND!\n"));
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// delete looper/handler
|
||||||
|
if (looper) {
|
||||||
|
looper->Lock();
|
||||||
|
if (handler) {
|
||||||
|
looper->RemoveHandler(handler);
|
||||||
|
delete handler;
|
||||||
|
}
|
||||||
|
looper->Quit();
|
||||||
|
}
|
||||||
|
DBG(OUT("REMOTE: looper/handler deleted\n"));
|
||||||
|
// delete local port
|
||||||
|
delete_port(localPort);
|
||||||
|
DBG(OUT("REMOTE: main() done\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// SMRemoteTargetApp.h
|
||||||
|
|
||||||
|
#ifndef SM_REMOTE_TARGET_APP_H
|
||||||
|
#define SM_REMOTE_TARGET_APP_H
|
||||||
|
|
||||||
|
#include <Messenger.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SMRT_INIT = 'init',
|
||||||
|
SMRT_QUIT = 'quit',
|
||||||
|
SMRT_GET_READY = 'gtrd',
|
||||||
|
SMRT_DELIVERY_SUCCESS_REQUEST = 'dsrq',
|
||||||
|
SMRT_DELIVERY_SUCCESS_REPLY = 'dsre',
|
||||||
|
};
|
||||||
|
|
||||||
|
struct smrt_init {
|
||||||
|
port_id port;
|
||||||
|
BMessenger messenger;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct smrt_delivery_success {
|
||||||
|
bool success;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct smrt_get_ready {
|
||||||
|
bigtime_t unblock_time;
|
||||||
|
bigtime_t reply_delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SM_REMOTE_TARGET_APP_H
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
// SMTarget.cpp
|
// SMTarget.cpp
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <TestShell.h>
|
||||||
#include <TestUtils.h>
|
#include <TestUtils.h>
|
||||||
#include <cppunit/TestAssert.h>
|
#include <cppunit/TestAssert.h>
|
||||||
|
|
||||||
#include "SMTarget.h"
|
#include "SMTarget.h"
|
||||||
#include "SMLooper.h"
|
#include "SMLooper.h"
|
||||||
|
#include "SMRemoteTargetApp.h"
|
||||||
|
|
||||||
// SMTarget
|
// SMTarget
|
||||||
|
|
||||||
@@ -107,3 +114,104 @@ LocalSMTarget::DeliverySuccess()
|
|||||||
return fLooper->DeliverySuccess();
|
return fLooper->DeliverySuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RemoteSMTarget
|
||||||
|
|
||||||
|
static const char *kSMRemotePortName = "BMessenger_SMRemoteTarget";
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
RemoteSMTarget::RemoteSMTarget(bool preferred)
|
||||||
|
: SMTarget(),
|
||||||
|
fLocalPort(-1),
|
||||||
|
fRemotePort(-1),
|
||||||
|
fTarget()
|
||||||
|
{
|
||||||
|
// create unused port name
|
||||||
|
int32 id = atomic_add(&fID, 1);
|
||||||
|
string portName(kSMRemotePortName);
|
||||||
|
BString idString;
|
||||||
|
idString << id;
|
||||||
|
portName += idString.String();
|
||||||
|
// create local port
|
||||||
|
fLocalPort = create_port(5, portName.c_str());
|
||||||
|
CHK(fLocalPort >= 0);
|
||||||
|
// execute the remote app
|
||||||
|
BString unescapedTestDir(BTestShell::GlobalTestDir());
|
||||||
|
unescapedTestDir.CharacterEscape(" \t\n!\"'`$&()?*+{}[]<>|", '\\');
|
||||||
|
string remoteApp(unescapedTestDir.String());
|
||||||
|
remoteApp += "/kits/app/SMRemoteTargetApp ";
|
||||||
|
remoteApp += portName;
|
||||||
|
if (preferred)
|
||||||
|
remoteApp += " preferred";
|
||||||
|
else
|
||||||
|
remoteApp += " specific";
|
||||||
|
remoteApp += " &";
|
||||||
|
system(remoteApp.c_str());
|
||||||
|
// wait for the remote app to send its init data
|
||||||
|
smrt_init initData;
|
||||||
|
CHK(_GetReply(SMRT_INIT, &initData, sizeof(smrt_init)) == B_OK);
|
||||||
|
fRemotePort = initData.port;
|
||||||
|
fTarget = initData.messenger;
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
RemoteSMTarget::~RemoteSMTarget()
|
||||||
|
{
|
||||||
|
_SendRequest(SMRT_QUIT);
|
||||||
|
delete_port(fLocalPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
void
|
||||||
|
RemoteSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay)
|
||||||
|
{
|
||||||
|
smrt_get_ready data;
|
||||||
|
data.unblock_time = unblockTime;
|
||||||
|
data.reply_delay = replyDelay;
|
||||||
|
CHK(_SendRequest(SMRT_GET_READY, &data, sizeof(smrt_get_ready)) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Messenger
|
||||||
|
BMessenger
|
||||||
|
RemoteSMTarget::Messenger()
|
||||||
|
{
|
||||||
|
return fTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverySuccess
|
||||||
|
bool
|
||||||
|
RemoteSMTarget::DeliverySuccess()
|
||||||
|
{
|
||||||
|
CHK(_SendRequest(SMRT_DELIVERY_SUCCESS_REQUEST) == B_OK);
|
||||||
|
smrt_delivery_success data;
|
||||||
|
CHK(_GetReply(SMRT_DELIVERY_SUCCESS_REPLY, &data,
|
||||||
|
sizeof(smrt_delivery_success)) == B_OK);
|
||||||
|
return data.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _SendRequest
|
||||||
|
status_t
|
||||||
|
RemoteSMTarget::_SendRequest(int32 code, const void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
return write_port(fRemotePort, code, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _GetReply
|
||||||
|
status_t
|
||||||
|
RemoteSMTarget::_GetReply(int32 expectedCode, void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
int32 code;
|
||||||
|
ssize_t readSize = read_port(fLocalPort, &code, buffer, size);
|
||||||
|
if (readSize < 0)
|
||||||
|
error = readSize;
|
||||||
|
else if ((uint32)readSize != size)
|
||||||
|
error = B_ERROR;
|
||||||
|
else if (code != expectedCode)
|
||||||
|
error = B_ERROR;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID
|
||||||
|
int32 RemoteSMTarget::fID = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -39,4 +39,29 @@ private:
|
|||||||
SMLooper *fLooper;
|
SMLooper *fLooper;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// RemoteSMTarget
|
||||||
|
class RemoteSMTarget : public SMTarget {
|
||||||
|
public:
|
||||||
|
RemoteSMTarget(bool preferred);
|
||||||
|
virtual ~RemoteSMTarget();
|
||||||
|
|
||||||
|
virtual void Init(bigtime_t unblockTime, bigtime_t replyDelay);
|
||||||
|
|
||||||
|
virtual BMessenger Messenger();
|
||||||
|
|
||||||
|
virtual bool DeliverySuccess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SendRequest(int32 code, const void *buffer = NULL,
|
||||||
|
size_t size = 0);
|
||||||
|
status_t _GetReply(int32 code, void *buffer, size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
port_id fLocalPort;
|
||||||
|
port_id fRemotePort;
|
||||||
|
BMessenger fTarget;
|
||||||
|
|
||||||
|
static int32 fID;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SM_TARGET_H
|
#endif // SM_TARGET_H
|
||||||
|
|||||||
Reference in New Issue
Block a user