15edcfe96SAxel Dörfler/*
2d3206115SAxel Dörfler * Copyright 2001-2015 Haiku, Inc. All rights reserved.
35edcfe96SAxel Dörfler * Distributed under the terms of the MIT License.
45edcfe96SAxel Dörfler *
55edcfe96SAxel Dörfler * Authors:
65edcfe96SAxel Dörfler *		Ingo Weinhold (bonefish@users.sf.net)
75edcfe96SAxel Dörfler */
852a38012Sejakowatz
952a38012Sejakowatz
10d3206115SAxel Dörfler#include <Messenger.h>
11d3206115SAxel Dörfler
12d3206115SAxel Dörfler#include <new>
13d3206115SAxel Dörfler#include <stdio.h>
14d3206115SAxel Dörfler#include <strings.h>
155edcfe96SAxel Dörfler
1652a38012Sejakowatz#include <Application.h>
17d3206115SAxel Dörfler#include <AutoLocker.h>
1852a38012Sejakowatz#include <Handler.h>
1952a38012Sejakowatz#include <Looper.h>
2052a38012Sejakowatz#include <Message.h>
2152a38012Sejakowatz#include <OS.h>
223b044715SIngo Weinhold#include <Roster.h>
2352a38012Sejakowatz
24d3206115SAxel Dörfler#include <AppMisc.h>
25d3206115SAxel Dörfler#include <LaunchRoster.h>
26d3206115SAxel Dörfler#include <LooperList.h>
27d3206115SAxel Dörfler#include <MessagePrivate.h>
28d3206115SAxel Dörfler#include <MessageUtils.h>
29d3206115SAxel Dörfler#include <TokenSpace.h>
3052a38012Sejakowatz
3152a38012Sejakowatz
325edcfe96SAxel Dörfler// debugging
335edcfe96SAxel Dörfler//#define DBG(x) x
345edcfe96SAxel Dörfler#define DBG(x)
355edcfe96SAxel Dörfler#define OUT	printf
3652a38012Sejakowatz
3752a38012Sejakowatzusing BPrivate::gDefaultTokens;
3837faaadeSIngo Weinholdusing BPrivate::gLooperList;
3937faaadeSIngo Weinholdusing BPrivate::BLooperList;
4052a38012Sejakowatz
4152a38012Sejakowatz
4252a38012SejakowatzBMessenger::BMessenger()
434ceb1e51SAxel Dörfler	:
444ceb1e51SAxel Dörfler	fPort(-1),
454ceb1e51SAxel Dörfler	fHandlerToken(B_NULL_TOKEN),
464ceb1e51SAxel Dörfler	fTeam(-1)
4752a38012Sejakowatz{
4852a38012Sejakowatz}
4952a38012Sejakowatz
504ceb1e51SAxel Dörfler
516fd09955SJohn ScipioneBMessenger::BMessenger(const char* signature, team_id team, status_t* result)
524ceb1e51SAxel Dörfler	:
534ceb1e51SAxel Dörfler	fPort(-1),
544ceb1e51SAxel Dörfler	fHandlerToken(B_NULL_TOKEN),
554ceb1e51SAxel Dörfler	fTeam(-1)
5652a38012Sejakowatz{
574ceb1e51SAxel Dörfler	_InitData(signature, team, result);
5852a38012Sejakowatz}
5952a38012Sejakowatz
604ceb1e51SAxel Dörfler
614ceb1e51SAxel DörflerBMessenger::BMessenger(const BHandler* handler, const BLooper* looper,
624ceb1e51SAxel Dörfler	status_t* _result)
634ceb1e51SAxel Dörfler	:
644ceb1e51SAxel Dörfler	fPort(-1),
654ceb1e51SAxel Dörfler	fHandlerToken(B_NULL_TOKEN),
664ceb1e51SAxel Dörfler	fTeam(-1)
6752a38012Sejakowatz{
686de47836SMichael Lotz	_InitData(handler, looper, _result);
6952a38012Sejakowatz}
7052a38012Sejakowatz
714ceb1e51SAxel Dörfler
726fd09955SJohn ScipioneBMessenger::BMessenger(const BMessenger& other)
734ceb1e51SAxel Dörfler	:
746fd09955SJohn Scipione	fPort(other.fPort),
756fd09955SJohn Scipione	fHandlerToken(other.fHandlerToken),
766fd09955SJohn Scipione	fTeam(other.fTeam)
7752a38012Sejakowatz{
7852a38012Sejakowatz}
7952a38012Sejakowatz
804ceb1e51SAxel Dörfler
8152a38012SejakowatzBMessenger::~BMessenger()
8252a38012Sejakowatz{
8352a38012Sejakowatz}
8452a38012Sejakowatz
8552a38012Sejakowatz
864ceb1e51SAxel Dörfler//	#pragma mark - Target
874ceb1e51SAxel Dörfler
8852a38012Sejakowatz
8952a38012Sejakowatzbool
9052a38012SejakowatzBMessenger::IsTargetLocal() const
9152a38012Sejakowatz{
924cad5abaSAxel Dörfler	return BPrivate::current_team() == fTeam;
9352a38012Sejakowatz}
9452a38012Sejakowatz
954ceb1e51SAxel Dörfler
966fd09955SJohn ScipioneBHandler*
974ceb1e51SAxel DörflerBMessenger::Target(BLooper** _looper) const
9852a38012Sejakowatz{
996fd09955SJohn Scipione	BHandler* handler = NULL;
100cd511790SAxel Dörfler	if (IsTargetLocal()
10194f814b3SJérôme Duval		&& (fHandlerToken > B_NULL_TOKEN
10294f814b3SJérôme Duval			|| fHandlerToken == B_PREFERRED_TOKEN)) {
1034ceb1e51SAxel Dörfler		gDefaultTokens.GetToken(fHandlerToken, B_HANDLER_TOKEN,
1044ceb1e51SAxel Dörfler			(void**)&handler);
1054ceb1e51SAxel Dörfler		if (_looper)
1064ceb1e51SAxel Dörfler			*_looper = BPrivate::gLooperList.LooperForPort(fPort);
1074ceb1e51SAxel Dörfler	} else if (_looper)
1084ceb1e51SAxel Dörfler		*_looper = NULL;
1094ceb1e51SAxel Dörfler
11052a38012Sejakowatz	return handler;
11152a38012Sejakowatz}
11252a38012Sejakowatz
1134ceb1e51SAxel Dörfler
11452a38012Sejakowatzbool
11552a38012SejakowatzBMessenger::LockTarget() const
11652a38012Sejakowatz{
1176fd09955SJohn Scipione	BLooper* looper = NULL;
11852a38012Sejakowatz	Target(&looper);
119cd511790SAxel Dörfler	if (looper != NULL && looper->Lock()) {
120930a139dSRene Gollent		if (looper->fMsgPort == fPort)
121930a139dSRene Gollent			return true;
122cd511790SAxel Dörfler
123cd511790SAxel Dörfler		looper->Unlock();
124cd511790SAxel Dörfler		return false;
125930a139dSRene Gollent	}
126930a139dSRene Gollent
127930a139dSRene Gollent	return false;
12852a38012Sejakowatz}
12952a38012Sejakowatz
1304ceb1e51SAxel Dörfler
13152a38012Sejakowatzstatus_t
13252a38012SejakowatzBMessenger::LockTargetWithTimeout(bigtime_t timeout) const
13352a38012Sejakowatz{
1346fd09955SJohn Scipione	BLooper* looper = NULL;
13552a38012Sejakowatz	Target(&looper);
136cd511790SAxel Dörfler	if (looper == NULL)
137cd511790SAxel Dörfler		return B_BAD_VALUE;
138cd511790SAxel Dörfler
1396fd09955SJohn Scipione	status_t result = looper->LockWithTimeout(timeout);
140cd511790SAxel Dörfler
1416fd09955SJohn Scipione	if (result == B_OK && looper->fMsgPort != fPort) {
14287aa57e8SRene Gollent		looper->Unlock();
143930a139dSRene Gollent		return B_BAD_PORT_ID;
14487aa57e8SRene Gollent	}
1454ceb1e51SAxel Dörfler
1466fd09955SJohn Scipione	return result;
14752a38012Sejakowatz}
14852a38012Sejakowatz
14952a38012Sejakowatz
1504ceb1e51SAxel Dörfler//	#pragma mark - Message sending
15152a38012Sejakowatz
152cd511790SAxel Dörfler
15352a38012Sejakowatzstatus_t
1546fd09955SJohn ScipioneBMessenger::SendMessage(uint32 command, BHandler* replyTo) const
15552a38012Sejakowatz{
15652a38012Sejakowatz	BMessage message(command);
15752a38012Sejakowatz	return SendMessage(&message, replyTo);
15852a38012Sejakowatz}
15952a38012Sejakowatz
160cd511790SAxel Dörfler
16152a38012Sejakowatzstatus_t
1626fd09955SJohn ScipioneBMessenger::SendMessage(BMessage* message, BHandler* replyTo,
163cd511790SAxel Dörfler	bigtime_t timeout) const
16452a38012Sejakowatz{
165cd511790SAxel Dörfler	DBG(OUT("BMessenger::SendMessage2(%.4s)\n", (char*)&message->what));
1666fd09955SJohn Scipione
1676fd09955SJohn Scipione	status_t result = message != NULL ? B_OK : B_BAD_VALUE;
1686fd09955SJohn Scipione	if (result == B_OK) {
16952a38012Sejakowatz		BMessenger replyMessenger(replyTo);
1706fd09955SJohn Scipione		result = SendMessage(message, replyMessenger, timeout);
17152a38012Sejakowatz	}
1726fd09955SJohn Scipione
1736fd09955SJohn Scipione	DBG(OUT("BMessenger::SendMessage2() done: %lx\n", result));
1746fd09955SJohn Scipione
1756fd09955SJohn Scipione	return result;
17652a38012Sejakowatz}
17752a38012Sejakowatz
178cd511790SAxel Dörfler
17952a38012Sejakowatzstatus_t
1806fd09955SJohn ScipioneBMessenger::SendMessage(BMessage* message, BMessenger replyTo,
181cd511790SAxel Dörfler	bigtime_t timeout) const
18252a38012Sejakowatz{
1836fd09955SJohn Scipione	if (message == NULL)
1840d0f1600SJérôme Duval		return B_BAD_VALUE;
1850d0f1600SJérôme Duval
1869dbe170aSAxel Dörfler	return BMessage::Private(message).SendMessage(fPort, fTeam, fHandlerToken,
1874ceb1e51SAxel Dörfler		timeout, false, replyTo);
18852a38012Sejakowatz}
18952a38012Sejakowatz
190cd511790SAxel Dörfler
19152a38012Sejakowatzstatus_t
1926fd09955SJohn ScipioneBMessenger::SendMessage(uint32 command, BMessage* reply) const
19352a38012Sejakowatz{
19452a38012Sejakowatz	BMessage message(command);
1956fd09955SJohn Scipione
19652a38012Sejakowatz	return SendMessage(&message, reply);
19752a38012Sejakowatz}
19852a38012Sejakowatz
199cd511790SAxel Dörfler
20052a38012Sejakowatzstatus_t
2016fd09955SJohn ScipioneBMessenger::SendMessage(BMessage* message, BMessage* reply,
2024ceb1e51SAxel Dörfler	bigtime_t deliveryTimeout, bigtime_t replyTimeout) const
20352a38012Sejakowatz{
2048780db59SAxel Dörfler	if (message == NULL || reply == NULL)
2058780db59SAxel Dörfler		return B_BAD_VALUE;
2068780db59SAxel Dörfler
2076fd09955SJohn Scipione	status_t result = BMessage::Private(message).SendMessage(fPort, fTeam,
2088780db59SAxel Dörfler		fHandlerToken, reply, deliveryTimeout, replyTimeout);
2098780db59SAxel Dörfler
2106fd09955SJohn Scipione	// map this result for now
2116fd09955SJohn Scipione	if (result == B_BAD_TEAM_ID)
2126fd09955SJohn Scipione		result = B_BAD_PORT_ID;
213bdbd1cb4SMichael Lotz
2146fd09955SJohn Scipione	return result;
21552a38012Sejakowatz}
21652a38012Sejakowatz
21752a38012Sejakowatz
2184ceb1e51SAxel Dörfler//	#pragma mark - Operators and misc
2194ceb1e51SAxel Dörfler
22052a38012Sejakowatz
2216de47836SMichael Lotzstatus_t
2226fd09955SJohn ScipioneBMessenger::SetTo(const char* signature, team_id team)
2236de47836SMichael Lotz{
2246de47836SMichael Lotz	status_t result = B_OK;
2256de47836SMichael Lotz	_InitData(signature, team, &result);
2266fd09955SJohn Scipione
2276de47836SMichael Lotz	return result;
2286de47836SMichael Lotz}
2296de47836SMichael Lotz
2306de47836SMichael Lotz
2316de47836SMichael Lotzstatus_t
2326de47836SMichael LotzBMessenger::SetTo(const BHandler* handler, const BLooper* looper)
2336de47836SMichael Lotz{
2346de47836SMichael Lotz	status_t result = B_OK;
2356de47836SMichael Lotz	_InitData(handler, looper, &result);
2366fd09955SJohn Scipione
2376de47836SMichael Lotz	return result;
2386de47836SMichael Lotz}
2396de47836SMichael Lotz
2406de47836SMichael Lotz
2416fd09955SJohn ScipioneBMessenger&
2426fd09955SJohn ScipioneBMessenger::operator=(const BMessenger& other)
24352a38012Sejakowatz{
2446fd09955SJohn Scipione	if (this != &other) {
2456fd09955SJohn Scipione		fPort = other.fPort;
2466fd09955SJohn Scipione		fHandlerToken = other.fHandlerToken;
2476fd09955SJohn Scipione		fTeam = other.fTeam;
24852a38012Sejakowatz	}
2496fd09955SJohn Scipione
2508f1dc17dSIngo Weinhold	return *this;
25152a38012Sejakowatz}
25252a38012Sejakowatz
2534ceb1e51SAxel Dörfler
25452a38012Sejakowatzbool
2556fd09955SJohn ScipioneBMessenger::operator==(const BMessenger& other) const
25652a38012Sejakowatz{
2578f1dc17dSIngo Weinhold	// Note: The fTeam fields are not compared.
2586fd09955SJohn Scipione	return fPort == other.fPort && fHandlerToken == other.fHandlerToken;
25952a38012Sejakowatz}
26052a38012Sejakowatz
2614ceb1e51SAxel Dörfler
26252a38012Sejakowatzbool
26352a38012SejakowatzBMessenger::IsValid() const
26452a38012Sejakowatz{
26552a38012Sejakowatz	port_info info;
2664ceb1e51SAxel Dörfler	return fPort >= 0 && get_port_info(fPort, &info) == B_OK;
26752a38012Sejakowatz}
26852a38012Sejakowatz
2694ceb1e51SAxel Dörfler
27052a38012Sejakowatzteam_id
27152a38012SejakowatzBMessenger::Team() const
27252a38012Sejakowatz{
27352a38012Sejakowatz	return fTeam;
27452a38012Sejakowatz}
27552a38012Sejakowatz
27652a38012Sejakowatz
2773e8daeb7SIngo Weinholduint32
2783e8daeb7SIngo WeinholdBMessenger::HashValue() const
2793e8daeb7SIngo Weinhold{
2803e8daeb7SIngo Weinhold	return fPort * 19 + fHandlerToken;
2813e8daeb7SIngo Weinhold}
2823e8daeb7SIngo Weinhold
2833e8daeb7SIngo Weinhold
2844ceb1e51SAxel Dörfler//	#pragma mark - Private or reserved
2854ceb1e51SAxel Dörfler
28652a38012Sejakowatz
2876fd09955SJohn Scipione/*!	Sets the messenger's team, target looper port and handler token.
28852a38012Sejakowatz
2896fd09955SJohn Scipione	To target the preferred handler, use \c B_PREFERRED_TOKEN as token.
29052a38012Sejakowatz
29152a38012Sejakowatz	\param team The target's team.
29252a38012Sejakowatz	\param port The target looper port.
29352a38012Sejakowatz	\param token The target handler token.
29452a38012Sejakowatz*/
2954afc60d3SIngo Weinholdvoid
2964ceb1e51SAxel DörflerBMessenger::_SetTo(team_id team, port_id port, int32 token)
29752a38012Sejakowatz{
29852a38012Sejakowatz	fTeam = team;
29952a38012Sejakowatz	fPort = port;
3004ceb1e51SAxel Dörfler	fHandlerToken = token;
30152a38012Sejakowatz}
30252a38012Sejakowatz
3034ceb1e51SAxel Dörfler
3046fd09955SJohn Scipione/*!	Initializes the BMessenger object's data given the signature and/or
30552a38012Sejakowatz	team ID of a target.
30652a38012Sejakowatz
30752a38012Sejakowatz	When only a signature is given, and multiple instances of the application
30852a38012Sejakowatz	are running it is undeterminate which one is chosen as the target. In case
30952a38012Sejakowatz	only a team ID is passed, the target application is identified uniquely.
31052a38012Sejakowatz	If both are supplied, the application identified by the team ID must have
31152a38012Sejakowatz	a matching signature, otherwise the initilization fails.
31252a38012Sejakowatz
31352a38012Sejakowatz	\param signature The target application's signature. May be \c NULL.
31452a38012Sejakowatz	\param team The target application's team ID. May be < 0.
31552a38012Sejakowatz	\param result An optional pointer to a pre-allocated status_t into which
31652a38012Sejakowatz		   the result of the initialization is written.
31752a38012Sejakowatz*/
31852a38012Sejakowatzvoid
3194ceb1e51SAxel DörflerBMessenger::_InitData(const char* signature, team_id team, status_t* _result)
32052a38012Sejakowatz{
3216fd09955SJohn Scipione	status_t result = B_OK;
3226fd09955SJohn Scipione
3239e9f5a1aSIngo Weinhold	// get an app_info
3249e9f5a1aSIngo Weinhold	app_info info;
3253b044715SIngo Weinhold	if (team < 0) {
3269e9f5a1aSIngo Weinhold		// no team ID given
3276fd09955SJohn Scipione		if (signature != NULL) {
328d3206115SAxel Dörfler			// Try existing launch communication data first
329d3206115SAxel Dörfler			BMessage data;
330d3206115SAxel Dörfler			if (BLaunchRoster().GetData(signature, data) == B_OK) {
331d3206115SAxel Dörfler				info.port = data.GetInt32("port", -1);
332d3206115SAxel Dörfler				team = data.GetInt32("team", -5);
333d3206115SAxel Dörfler			}
334d3206115SAxel Dörfler			if (info.port < 0) {
335d3206115SAxel Dörfler				result = be_roster->GetAppInfo(signature, &info);
336d3206115SAxel Dörfler				team = info.team;
337d3206115SAxel Dörfler				// B_ERROR means that no application with the given signature
338d3206115SAxel Dörfler				// is running. But we are supposed to return B_BAD_VALUE.
339d3206115SAxel Dörfler				if (result == B_ERROR)
340d3206115SAxel Dörfler					result = B_BAD_VALUE;
341d3206115SAxel Dörfler			} else
342d3206115SAxel Dörfler				info.flags = 0;
3433b044715SIngo Weinhold		} else
3446fd09955SJohn Scipione			result = B_BAD_TYPE;
3459e9f5a1aSIngo Weinhold	} else {
3469e9f5a1aSIngo Weinhold		// a team ID is given
3476fd09955SJohn Scipione		result = be_roster->GetRunningAppInfo(team, &info);
3489e9f5a1aSIngo Weinhold		// Compare the returned signature with the supplied one.
3496fd09955SJohn Scipione		if (result == B_OK && signature != NULL
3506fd09955SJohn Scipione			&& strcasecmp(signature, info.signature) != 0) {
3516fd09955SJohn Scipione			result = B_MISMATCHED_VALUES;
3526fd09955SJohn Scipione		}
3539e9f5a1aSIngo Weinhold	}
3549e9f5a1aSIngo Weinhold	// check whether the app flags say B_ARGV_ONLY
3556fd09955SJohn Scipione	if (result == B_OK && (info.flags & B_ARGV_ONLY) != 0) {
3566fd09955SJohn Scipione		result = B_BAD_TYPE;
357672c1ea9SIngo Weinhold		// Set the team ID nevertheless -- that's what Be's implementation
358672c1ea9SIngo Weinhold		// does. Don't know, if that is a bug, but at least it doesn't harm.
359672c1ea9SIngo Weinhold		fTeam = team;
360672c1ea9SIngo Weinhold	}
3613b044715SIngo Weinhold	// init our members
3626fd09955SJohn Scipione	if (result == B_OK) {
3633b044715SIngo Weinhold		fTeam = team;
3643b044715SIngo Weinhold		fPort = info.port;
36594b98dffSIngo Weinhold		fHandlerToken = B_PREFERRED_TOKEN;
3663b044715SIngo Weinhold	}
3674ceb1e51SAxel Dörfler
3686fd09955SJohn Scipione	// return the result
3696fd09955SJohn Scipione	if (_result != NULL)
3706fd09955SJohn Scipione		*_result = result;
37152a38012Sejakowatz}
37252a38012Sejakowatz
3734ceb1e51SAxel Dörfler
3746fd09955SJohn Scipione/*!	Initializes the BMessenger to target the local BHandler and/or BLooper.
3756de47836SMichael Lotz
3766de47836SMichael Lotz	When a \c NULL handler is supplied, the preferred handler in the given
3776de47836SMichael Lotz	looper is targeted. If no looper is supplied the looper the given handler
3786de47836SMichael Lotz	belongs to is used -- that means in particular, that the handler must
3796de47836SMichael Lotz	already belong to a looper. If both are supplied the handler must actually
3806de47836SMichael Lotz	belong to looper.
3816de47836SMichael Lotz
3826de47836SMichael Lotz	\param handler The target handler. May be \c NULL.
3836de47836SMichael Lotz	\param looper The target looper. May be \c NULL.
3846de47836SMichael Lotz	\param result An optional pointer to a pre-allocated status_t into which
3856fd09955SJohn Scipione	       the result of the initialization is written.
3866de47836SMichael Lotz*/
3876de47836SMichael Lotzvoid
3886de47836SMichael LotzBMessenger::_InitData(const BHandler* handler, const BLooper* looper,
3896de47836SMichael Lotz	status_t* _result)
3906de47836SMichael Lotz{
391d2e51939SJérôme Duval	status_t result = (handler != NULL || looper != NULL) ? B_OK : B_BAD_VALUE;
3926fd09955SJohn Scipione	if (result == B_OK) {
3936fd09955SJohn Scipione		if (handler != NULL) {
3946de47836SMichael Lotz			// BHandler is given, check/retrieve the looper.
3956fd09955SJohn Scipione			if (looper != NULL) {
3966de47836SMichael Lotz				if (handler->Looper() != looper)
3976fd09955SJohn Scipione					result = B_MISMATCHED_VALUES;
3986de47836SMichael Lotz			} else {
3996de47836SMichael Lotz				looper = handler->Looper();
4006de47836SMichael Lotz				if (looper == NULL)
4016fd09955SJohn Scipione					result = B_MISMATCHED_VALUES;
4026de47836SMichael Lotz			}
4036de47836SMichael Lotz		}
4046fd09955SJohn Scipione
4056de47836SMichael Lotz		// set port, token,...
4066fd09955SJohn Scipione		if (result == B_OK) {
4076de47836SMichael Lotz			AutoLocker<BLooperList> locker(gLooperList);
4086de47836SMichael Lotz			if (locker.IsLocked() && gLooperList.IsLooperValid(looper)) {
4096de47836SMichael Lotz				fPort = looper->fMsgPort;
4106fd09955SJohn Scipione				fHandlerToken = handler != NULL
4116fd09955SJohn Scipione					? _get_object_token_(handler)
4126fd09955SJohn Scipione					: B_PREFERRED_TOKEN;
4136de47836SMichael Lotz				fTeam = looper->Team();
4146de47836SMichael Lotz			} else
4156fd09955SJohn Scipione				result = B_BAD_VALUE;
4166de47836SMichael Lotz		}
4176de47836SMichael Lotz	}
4186fd09955SJohn Scipione
4196fd09955SJohn Scipione	if (_result != NULL)
4206fd09955SJohn Scipione		*_result = result;
4216de47836SMichael Lotz}
4226de47836SMichael Lotz
4236de47836SMichael Lotz
424fd3c25a9SJohn Scipione//	#pragma mark - Operator functions
42552a38012Sejakowatz
4268f1dc17dSIngo Weinhold
42752a38012Sejakowatzbool
4286fd09955SJohn Scipioneoperator<(const BMessenger& _a, const BMessenger& _b)
42952a38012Sejakowatz{
4304afc60d3SIngo Weinhold	BMessenger::Private a(const_cast<BMessenger&>(_a));
4314afc60d3SIngo Weinhold	BMessenger::Private b(const_cast<BMessenger&>(_b));
4324afc60d3SIngo Weinhold
4338f1dc17dSIngo Weinhold	// significance:
4348f1dc17dSIngo Weinhold	// 1. fPort
4358f1dc17dSIngo Weinhold	// 2. fHandlerToken
4368f1dc17dSIngo Weinhold	// 3. fPreferredTarget
4378f1dc17dSIngo Weinhold	// fTeam is insignificant
4384afc60d3SIngo Weinhold	return (a.Port() < b.Port()
4396eb09230SMichael Lotz			|| (a.Port() == b.Port()
4404afc60d3SIngo Weinhold				&& (a.Token() < b.Token()
4416eb09230SMichael Lotz					|| (a.Token() == b.Token()
4424afc60d3SIngo Weinhold						&& !a.IsPreferredTarget()
4436eb09230SMichael Lotz						&& b.IsPreferredTarget()))));
44452a38012Sejakowatz}
44552a38012Sejakowatz
4464ceb1e51SAxel Dörfler
44752a38012Sejakowatzbool
4486fd09955SJohn Scipioneoperator!=(const BMessenger& a, const BMessenger& b)
44952a38012Sejakowatz{
45052a38012Sejakowatz	return !(a == b);
45152a38012Sejakowatz}
452