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:
Ingo Weinhold 2002-07-21 14:48:09 +00:00
parent 01f8c701b9
commit 40c28b75d4
4 changed files with 270 additions and 0 deletions

View 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;
}

View 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

View File

@ -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;

View File

@ -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