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:
parent
01f8c701b9
commit
40c28b75d4
107
src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp
Normal file
107
src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
30
src/tests/kits/app/bmessenger/SMRemoteTargetApp.h
Normal file
30
src/tests/kits/app/bmessenger/SMRemoteTargetApp.h
Normal file
@ -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
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <TestShell.h>
|
||||
#include <TestUtils.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
|
||||
#include "SMTarget.h"
|
||||
#include "SMLooper.h"
|
||||
#include "SMRemoteTargetApp.h"
|
||||
|
||||
// SMTarget
|
||||
|
||||
@ -107,3 +114,104 @@ LocalSMTarget::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;
|
||||
};
|
||||
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user