#include <Messenger.h>
#include <new>
#include <stdio.h>
#include <strings.h>
#include <Application.h>
#include <AutoLocker.h>
#include <Handler.h>
#include <Looper.h>
#include <Message.h>
#include <OS.h>
#include <Roster.h>
#include <AppMisc.h>
#include <LaunchRoster.h>
#include <LooperList.h>
#include <MessagePrivate.h>
#include <MessageUtils.h>
#include <TokenSpace.h>
#define DBG(x)
#define OUT printf
using BPrivate::gDefaultTokens;
using BPrivate::gLooperList;
using BPrivate::BLooperList;
BMessenger::BMessenger()
:
fPort(-1),
fHandlerToken(B_NULL_TOKEN),
fTeam(-1)
{
}
BMessenger::BMessenger(const char* signature, team_id team, status_t* result)
:
fPort(-1),
fHandlerToken(B_NULL_TOKEN),
fTeam(-1)
{
_InitData(signature, team, result);
}
BMessenger::BMessenger(const BHandler* handler, const BLooper* looper,
status_t* _result)
:
fPort(-1),
fHandlerToken(B_NULL_TOKEN),
fTeam(-1)
{
_InitData(handler, looper, _result);
}
BMessenger::BMessenger(const BMessenger& other)
:
fPort(other.fPort),
fHandlerToken(other.fHandlerToken),
fTeam(other.fTeam)
{
}
BMessenger::~BMessenger()
{
}
bool
BMessenger::IsTargetLocal() const
{
return BPrivate::current_team() == fTeam;
}
BHandler*
BMessenger::Target(BLooper** _looper) const
{
BHandler* handler = NULL;
if (IsTargetLocal()
&& (fHandlerToken > B_NULL_TOKEN
|| fHandlerToken == B_PREFERRED_TOKEN)) {
gDefaultTokens.GetToken(fHandlerToken, B_HANDLER_TOKEN,
(void**)&handler);
if (_looper)
*_looper = BPrivate::gLooperList.LooperForPort(fPort);
} else if (_looper)
*_looper = NULL;
return handler;
}
bool
BMessenger::LockTarget() const
{
BLooper* looper = NULL;
Target(&looper);
if (looper != NULL && looper->Lock()) {
if (looper->fMsgPort == fPort)
return true;
looper->Unlock();
return false;
}
return false;
}
status_t
BMessenger::LockTargetWithTimeout(bigtime_t timeout) const
{
BLooper* looper = NULL;
Target(&looper);
if (looper == NULL)
return B_BAD_VALUE;
status_t result = looper->LockWithTimeout(timeout);
if (result == B_OK && looper->fMsgPort != fPort) {
looper->Unlock();
return B_BAD_PORT_ID;
}
return result;
}
status_t
BMessenger::SendMessage(uint32 command, BHandler* replyTo) const
{
BMessage message(command);
return SendMessage(&message, replyTo);
}
status_t
BMessenger::SendMessage(BMessage* message, BHandler* replyTo,
bigtime_t timeout) const
{
DBG(OUT("BMessenger::SendMessage2(%.4s)\n", (char*)&message->what));
status_t result = message != NULL ? B_OK : B_BAD_VALUE;
if (result == B_OK) {
BMessenger replyMessenger(replyTo);
result = SendMessage(message, replyMessenger, timeout);
}
DBG(OUT("BMessenger::SendMessage2() done: %lx\n", result));
return result;
}
status_t
BMessenger::SendMessage(BMessage* message, BMessenger replyTo,
bigtime_t timeout) const
{
if (message == NULL)
return B_BAD_VALUE;
return BMessage::Private(message).SendMessage(fPort, fTeam, fHandlerToken,
timeout, false, replyTo);
}
status_t
BMessenger::SendMessage(uint32 command, BMessage* reply) const
{
BMessage message(command);
return SendMessage(&message, reply);
}
status_t
BMessenger::SendMessage(BMessage* message, BMessage* reply,
bigtime_t deliveryTimeout, bigtime_t replyTimeout) const
{
if (message == NULL || reply == NULL)
return B_BAD_VALUE;
status_t result = BMessage::Private(message).SendMessage(fPort, fTeam,
fHandlerToken, reply, deliveryTimeout, replyTimeout);
if (result == B_BAD_TEAM_ID)
result = B_BAD_PORT_ID;
return result;
}
status_t
BMessenger::SetTo(const char* signature, team_id team)
{
status_t result = B_OK;
_InitData(signature, team, &result);
return result;
}
status_t
BMessenger::SetTo(const BHandler* handler, const BLooper* looper)
{
status_t result = B_OK;
_InitData(handler, looper, &result);
return result;
}
BMessenger&
BMessenger::operator=(const BMessenger& other)
{
if (this != &other) {
fPort = other.fPort;
fHandlerToken = other.fHandlerToken;
fTeam = other.fTeam;
}
return *this;
}
bool
BMessenger::operator==(const BMessenger& other) const
{
return fPort == other.fPort && fHandlerToken == other.fHandlerToken;
}
bool
BMessenger::IsValid() const
{
port_info info;
return fPort >= 0 && get_port_info(fPort, &info) == B_OK;
}
team_id
BMessenger::Team() const
{
return fTeam;
}
uint32
BMessenger::HashValue() const
{
return fPort * 19 + fHandlerToken;
}
void
BMessenger::_SetTo(team_id team, port_id port, int32 token)
{
fTeam = team;
fPort = port;
fHandlerToken = token;
}
void
BMessenger::_InitData(const char* signature, team_id team, status_t* _result)
{
status_t result = B_OK;
app_info info;
if (team < 0) {
if (signature != NULL) {
BMessage data;
if (BLaunchRoster().GetData(signature, data) == B_OK) {
info.port = data.GetInt32("port", -1);
team = data.GetInt32("team", -5);
}
if (info.port < 0) {
result = be_roster->GetAppInfo(signature, &info);
team = info.team;
if (result == B_ERROR)
result = B_BAD_VALUE;
} else
info.flags = 0;
} else
result = B_BAD_TYPE;
} else {
result = be_roster->GetRunningAppInfo(team, &info);
if (result == B_OK && signature != NULL
&& strcasecmp(signature, info.signature) != 0) {
result = B_MISMATCHED_VALUES;
}
}
if (result == B_OK && (info.flags & B_ARGV_ONLY) != 0) {
result = B_BAD_TYPE;
fTeam = team;
}
if (result == B_OK) {
fTeam = team;
fPort = info.port;
fHandlerToken = B_PREFERRED_TOKEN;
}
if (_result != NULL)
*_result = result;
}
void
BMessenger::_InitData(const BHandler* handler, const BLooper* looper,
status_t* _result)
{
status_t result = (handler != NULL || looper != NULL) ? B_OK : B_BAD_VALUE;
if (result == B_OK) {
if (handler != NULL) {
if (looper != NULL) {
if (handler->Looper() != looper)
result = B_MISMATCHED_VALUES;
} else {
looper = handler->Looper();
if (looper == NULL)
result = B_MISMATCHED_VALUES;
}
}
if (result == B_OK) {
AutoLocker<BLooperList> locker(gLooperList);
if (locker.IsLocked() && gLooperList.IsLooperValid(looper)) {
fPort = looper->fMsgPort;
fHandlerToken = handler != NULL
? _get_object_token_(handler)
: B_PREFERRED_TOKEN;
fTeam = looper->Team();
} else
result = B_BAD_VALUE;
}
}
if (_result != NULL)
*_result = result;
}
bool
operator<(const BMessenger& _a, const BMessenger& _b)
{
BMessenger::Private a(const_cast<BMessenger&>(_a));
BMessenger::Private b(const_cast<BMessenger&>(_b));
return (a.Port() < b.Port()
|| (a.Port() == b.Port()
&& (a.Token() < b.Token()
|| (a.Token() == b.Token()
&& !a.IsPreferredTarget()
&& b.IsPreferredTarget()))));
}
bool
operator!=(const BMessenger& a, const BMessenger& b)
{
return !(a == b);
}