// SMTarget.cpp #include #include #include #include #include #include #include #include #include "SMTarget.h" #include "SMLooper.h" #include "SMRemoteTargetApp.h" using namespace std; // SMTarget // constructor SMTarget::SMTarget() { } // destructor SMTarget::~SMTarget() { } // Init void SMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) { } // Handler BHandler * SMTarget::Handler() { return NULL; } // Messenger BMessenger SMTarget::Messenger() { return BMessenger(); } // DeliverySuccess bool SMTarget::DeliverySuccess() { return false; } // LocalSMTarget // constructor LocalSMTarget::LocalSMTarget(bool preferred) : SMTarget(), fHandler(NULL), fLooper(NULL) { // create looper and handler fLooper = new SMLooper; fLooper->Run(); if (!preferred) { fHandler = new SMHandler; CHK(fLooper->Lock()); fLooper->AddHandler(fHandler); fLooper->Unlock(); } } // destructor LocalSMTarget::~LocalSMTarget() { if (fLooper) { fLooper->Lock(); if (fHandler) { fLooper->RemoveHandler(fHandler); delete fHandler; } fLooper->Quit(); } } // Init void LocalSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) { fLooper->SetReplyDelay(replyDelay); fLooper->BlockUntil(unblockTime); } // Handler BHandler * LocalSMTarget::Handler() { return fHandler; } // Messenger BMessenger LocalSMTarget::Messenger() { return BMessenger(fHandler, fLooper); } // DeliverySuccess bool 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;