xref: /haiku/src/kits/app/Messenger.cpp (revision 8780db592a950c2cc94870a7d03474568b596934)
15edcfe96SAxel Dörfler /*
25edcfe96SAxel Dörfler  * Copyright 2001-2005, Haiku.
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 
105edcfe96SAxel Dörfler #include <AppMisc.h>
115edcfe96SAxel Dörfler #include <MessageUtils.h>
125edcfe96SAxel Dörfler #include "ObjectLocker.h"
135edcfe96SAxel Dörfler #include "TokenSpace.h"
1452a38012Sejakowatz 
1552a38012Sejakowatz #include <Application.h>
1652a38012Sejakowatz #include <Handler.h>
1752a38012Sejakowatz #include <Looper.h>
18e1f41e5dSIngo Weinhold #include <LooperList.h>
1952a38012Sejakowatz #include <Message.h>
20bdbd1cb4SMichael Lotz #include <MessagePrivate.h>
2152a38012Sejakowatz #include <Messenger.h>
2252a38012Sejakowatz #include <OS.h>
233b044715SIngo Weinhold #include <Roster.h>
2494b98dffSIngo Weinhold #include <TokenSpace.h>
2552a38012Sejakowatz 
265edcfe96SAxel Dörfler #include <new>
275edcfe96SAxel Dörfler #include <stdio.h>
285edcfe96SAxel Dörfler #include <string.h>
2952a38012Sejakowatz 
30cf10934eSMichael Lotz 
315edcfe96SAxel Dörfler // debugging
325edcfe96SAxel Dörfler //#define DBG(x) x
335edcfe96SAxel Dörfler #define DBG(x)
345edcfe96SAxel Dörfler #define OUT	printf
3552a38012Sejakowatz 
3652a38012Sejakowatz using BPrivate::gDefaultTokens;
3737faaadeSIngo Weinhold using BPrivate::gLooperList;
3837faaadeSIngo Weinhold using BPrivate::BLooperList;
3937faaadeSIngo Weinhold using BPrivate::BObjectLocker;
4052a38012Sejakowatz 
4152a38012Sejakowatz enum {
4252a38012Sejakowatz 	NOT_IMPLEMENTED	= B_ERROR,
4352a38012Sejakowatz };
4452a38012Sejakowatz 
4552a38012Sejakowatz 
4652a38012Sejakowatz /*!	\brief Creates an unitialized BMessenger.
4752a38012Sejakowatz */
4852a38012Sejakowatz BMessenger::BMessenger()
494ceb1e51SAxel Dörfler 	:
504ceb1e51SAxel Dörfler 	fPort(-1),
5194b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
524ceb1e51SAxel Dörfler 	fTeam(-1)
5352a38012Sejakowatz {
5452a38012Sejakowatz }
5552a38012Sejakowatz 
564ceb1e51SAxel Dörfler 
5752a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the already
5852a38012Sejakowatz 	running application identified by its signature and/or team ID.
5952a38012Sejakowatz 
6052a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
6152a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
6252a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
6352a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
6452a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
6552a38012Sejakowatz 
6652a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
6752a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
6852a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
6952a38012Sejakowatz 		   the result of the initialization is written.
7052a38012Sejakowatz */
7152a38012Sejakowatz BMessenger::BMessenger(const char *signature, team_id team, status_t *result)
724ceb1e51SAxel Dörfler 	:
734ceb1e51SAxel Dörfler 	fPort(-1),
7494b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
754ceb1e51SAxel Dörfler 	fTeam(-1)
7652a38012Sejakowatz {
774ceb1e51SAxel Dörfler 	_InitData(signature, team, result);
7852a38012Sejakowatz }
7952a38012Sejakowatz 
804ceb1e51SAxel Dörfler 
8152a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the local
8252a38012Sejakowatz 	BHandler and/or BLooper.
8352a38012Sejakowatz 
8452a38012Sejakowatz 	When a \c NULL handler is supplied, the preferred handler in the given
8552a38012Sejakowatz 	looper is targeted. If no looper is supplied the looper the given handler
8652a38012Sejakowatz 	belongs to is used -- that means in particular, that the handler must
8752a38012Sejakowatz 	already belong to a looper. If both are supplied the handler must actually
8852a38012Sejakowatz 	belong to looper.
8952a38012Sejakowatz 
9052a38012Sejakowatz 	\param handler The target handler. May be \c NULL.
9152a38012Sejakowatz 	\param looper The target looper. May be \c NULL.
9252a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
9352a38012Sejakowatz 		   the result of the initialization is written.
9452a38012Sejakowatz */
9552a38012Sejakowatz BMessenger::BMessenger(const BHandler* handler, const BLooper* looper,
964ceb1e51SAxel Dörfler 	status_t* _result)
974ceb1e51SAxel Dörfler 	:
984ceb1e51SAxel Dörfler 	fPort(-1),
9994b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
1004ceb1e51SAxel Dörfler 	fTeam(-1)
10152a38012Sejakowatz {
10252a38012Sejakowatz 	status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
10352a38012Sejakowatz 	if (error == B_OK) {
10452a38012Sejakowatz 		if (handler) {
10552a38012Sejakowatz 			// BHandler is given, check/retrieve the looper.
10652a38012Sejakowatz 			if (looper) {
10752a38012Sejakowatz 				if (handler->Looper() != looper)
10852a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
10952a38012Sejakowatz 			} else {
11052a38012Sejakowatz 				looper = handler->Looper();
11152a38012Sejakowatz 				if (looper == NULL)
11252a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
11352a38012Sejakowatz 			}
11437faaadeSIngo Weinhold 		}
11552a38012Sejakowatz 		// set port, token,...
11652a38012Sejakowatz 		if (error == B_OK) {
11737faaadeSIngo Weinhold 			BObjectLocker<BLooperList> locker(gLooperList);
11837faaadeSIngo Weinhold 			if (locker.IsLocked() && gLooperList.IsLooperValid(looper)) {
11952a38012Sejakowatz 				fPort = looper->fMsgPort;
12094b98dffSIngo Weinhold 				fHandlerToken = (handler
12194b98dffSIngo Weinhold 					? _get_object_token_(handler) : B_PREFERRED_TOKEN);
12237faaadeSIngo Weinhold 				fTeam = looper->Team();
12337faaadeSIngo Weinhold 			} else
12437faaadeSIngo Weinhold 				error = B_BAD_VALUE;
12552a38012Sejakowatz 		}
12652a38012Sejakowatz 	}
1274ceb1e51SAxel Dörfler 	if (_result)
1284ceb1e51SAxel Dörfler 		*_result = error;
12952a38012Sejakowatz }
13052a38012Sejakowatz 
1314ceb1e51SAxel Dörfler 
13252a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to have the same target
13352a38012Sejakowatz 	as the supplied messemger.
13452a38012Sejakowatz 
13552a38012Sejakowatz 	\param from The messenger to be copied.
13652a38012Sejakowatz */
13752a38012Sejakowatz BMessenger::BMessenger(const BMessenger& from)
1384ceb1e51SAxel Dörfler 	:
1394ceb1e51SAxel Dörfler 	fPort(from.fPort),
14052a38012Sejakowatz 	fHandlerToken(from.fHandlerToken),
1414ceb1e51SAxel Dörfler 	fTeam(from.fTeam)
14252a38012Sejakowatz {
14352a38012Sejakowatz }
14452a38012Sejakowatz 
1454ceb1e51SAxel Dörfler 
14652a38012Sejakowatz /*!	\brief Frees all resources associated with this object.
14752a38012Sejakowatz */
14852a38012Sejakowatz BMessenger::~BMessenger()
14952a38012Sejakowatz {
15052a38012Sejakowatz }
15152a38012Sejakowatz 
15252a38012Sejakowatz 
1534ceb1e51SAxel Dörfler //	#pragma mark - Target
15452a38012Sejakowatz 
1554ceb1e51SAxel Dörfler 
15652a38012Sejakowatz /*!	\brief Returns whether or not the messenger's target lives within the team
15752a38012Sejakowatz 	of the caller.
15852a38012Sejakowatz 
15952a38012Sejakowatz 	\return \c true, if the object is properly initialized and its target
16052a38012Sejakowatz 			lives within the caller's team, \c false otherwise.
16152a38012Sejakowatz */
16252a38012Sejakowatz bool
16352a38012Sejakowatz BMessenger::IsTargetLocal() const
16452a38012Sejakowatz {
16552a38012Sejakowatz 	thread_info info;
1664ceb1e51SAxel Dörfler 	return get_thread_info(find_thread(NULL), &info) == B_OK
1674ceb1e51SAxel Dörfler 		&& fTeam == info.team;
16852a38012Sejakowatz }
16952a38012Sejakowatz 
1704ceb1e51SAxel Dörfler 
17152a38012Sejakowatz /*!	\brief Returns the handler and looper targeted by the messenger, if the
17252a38012Sejakowatz 	target is local.
17352a38012Sejakowatz 
17452a38012Sejakowatz 	The handler is returned directly, the looper by reference. If both are
17552a38012Sejakowatz 	\c NULL, the object is either not properly initialized, the target
17652a38012Sejakowatz 	objects have been deleted or the target is remote. If only the returned
17752a38012Sejakowatz 	handler is \c NULL, either the looper's preferred handler is targeted or
17852a38012Sejakowatz 	the handler has been deleted.
17952a38012Sejakowatz 
18052a38012Sejakowatz 	\param looper A pointer to a pre-allocated BLooper pointer into which
18152a38012Sejakowatz 		   the pointer to the targeted looper is written.
18252a38012Sejakowatz 	\return The BHandler targeted by the messenger.
18352a38012Sejakowatz */
18452a38012Sejakowatz BHandler *
1854ceb1e51SAxel Dörfler BMessenger::Target(BLooper** _looper) const
18652a38012Sejakowatz {
18752a38012Sejakowatz 	BHandler *handler = NULL;
1884ceb1e51SAxel Dörfler 	if (IsTargetLocal() && fHandlerToken > B_NULL_TOKEN) {
18952a38012Sejakowatz 		gDefaultTokens.GetToken(fHandlerToken, B_HANDLER_TOKEN,
19052a38012Sejakowatz 			(void**)&handler);
1914ceb1e51SAxel Dörfler 		if (_looper)
1924ceb1e51SAxel Dörfler 			*_looper = BPrivate::gLooperList.LooperForPort(fPort);
1934ceb1e51SAxel Dörfler 	} else if (_looper)
1944ceb1e51SAxel Dörfler 		*_looper = NULL;
1954ceb1e51SAxel Dörfler 
19652a38012Sejakowatz 	return handler;
19752a38012Sejakowatz }
19852a38012Sejakowatz 
1994ceb1e51SAxel Dörfler 
20052a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
20152a38012Sejakowatz 
20252a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
20352a38012Sejakowatz 	Target() and calling BLooper::Lock() on the looper afterwards.
20452a38012Sejakowatz 
20552a38012Sejakowatz 	\see BLooper::Lock() for details.
20652a38012Sejakowatz 
20752a38012Sejakowatz 	\return \c true, if the looper could be locked sucessfully, \c false, if
20852a38012Sejakowatz 			the messenger is not properly initialized, the target is remote,
20952a38012Sejakowatz 			or the targeted looper is invalid.
21052a38012Sejakowatz */
21152a38012Sejakowatz bool
21252a38012Sejakowatz BMessenger::LockTarget() const
21352a38012Sejakowatz {
21452a38012Sejakowatz 	BLooper *looper = NULL;
21552a38012Sejakowatz 	Target(&looper);
2164ceb1e51SAxel Dörfler 	return looper && looper->Lock();
21752a38012Sejakowatz }
21852a38012Sejakowatz 
2194ceb1e51SAxel Dörfler 
22052a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
22152a38012Sejakowatz 
22252a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
22352a38012Sejakowatz 	Target() and calling BLooper::LockWithTimeout() on the looper afterwards.
22452a38012Sejakowatz 
22552a38012Sejakowatz 	\see BLooper::LockWithTimeout() for details.
22652a38012Sejakowatz 
22752a38012Sejakowatz 	\return
22852a38012Sejakowatz 	- \c B_OK, if the looper could be locked sucessfully,
22952a38012Sejakowatz 	- \c B_BAD_VALUE, if the messenger is not properly initialized,
23052a38012Sejakowatz 	  the target is remote, or the targeted looper is invalid,
23152a38012Sejakowatz 	- other error codes returned by BLooper::LockWithTimeout().
23252a38012Sejakowatz */
23352a38012Sejakowatz status_t
23452a38012Sejakowatz BMessenger::LockTargetWithTimeout(bigtime_t timeout) const
23552a38012Sejakowatz {
23652a38012Sejakowatz 	BLooper *looper = NULL;
23752a38012Sejakowatz 	Target(&looper);
2384ceb1e51SAxel Dörfler 	status_t error = looper ? B_OK : B_BAD_VALUE;
23952a38012Sejakowatz 	if (error == B_OK)
24052a38012Sejakowatz 		error = looper->LockWithTimeout(timeout);
2414ceb1e51SAxel Dörfler 
24252a38012Sejakowatz 	return error;
24352a38012Sejakowatz }
24452a38012Sejakowatz 
24552a38012Sejakowatz 
2464ceb1e51SAxel Dörfler //	#pragma mark - Message sending
24752a38012Sejakowatz 
24852a38012Sejakowatz // SendMessage
24952a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
25052a38012Sejakowatz 
2517e24e06eSIngo Weinhold 	The method does not wait for a reply. The message is sent asynchronously.
25252a38012Sejakowatz 
25352a38012Sejakowatz 	\param command The what field of the message to deliver.
25452a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
25552a38012Sejakowatz 		   May be \c NULL.
25652a38012Sejakowatz 	\return
25752a38012Sejakowatz 	- \c B_OK: Everything went fine.
25852a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
25952a38012Sejakowatz 	  target doesn't exist anymore.
26052a38012Sejakowatz */
26152a38012Sejakowatz status_t
26252a38012Sejakowatz BMessenger::SendMessage(uint32 command, BHandler *replyTo) const
26352a38012Sejakowatz {
26452a38012Sejakowatz 	BMessage message(command);
26552a38012Sejakowatz 	return SendMessage(&message, replyTo);
26652a38012Sejakowatz }
26752a38012Sejakowatz 
26852a38012Sejakowatz // SendMessage
26952a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
27052a38012Sejakowatz 
27152a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
27252a38012Sejakowatz 	of \a message.
27352a38012Sejakowatz 
2747e24e06eSIngo Weinhold 	The method does not wait for a reply. The message is sent asynchronously.
27552a38012Sejakowatz 
27652a38012Sejakowatz 	\param message The message to be sent.
27752a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
27852a38012Sejakowatz 		   May be \c NULL.
27952a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
28052a38012Sejakowatz 	\return
28152a38012Sejakowatz 	- \c B_OK: Everything went fine.
28252a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
28352a38012Sejakowatz 	  target doesn't exist anymore.
28452a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
28552a38012Sejakowatz 	  port was full when trying to deliver the message.
28652a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
28752a38012Sejakowatz 	  message.
28852a38012Sejakowatz */
28952a38012Sejakowatz status_t
29052a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BHandler *replyTo,
29152a38012Sejakowatz 						bigtime_t timeout) const
29252a38012Sejakowatz {
29352a38012Sejakowatz DBG(OUT("BMessenger::SendMessage2(%.4s)\n", (char*)&message->what));
29452a38012Sejakowatz 	status_t error = (message ? B_OK : B_BAD_VALUE);
29552a38012Sejakowatz 	if (error == B_OK) {
29652a38012Sejakowatz 		BMessenger replyMessenger(replyTo);
297717a24b7SIngo Weinhold 		error = SendMessage(message, replyMessenger, timeout);
29852a38012Sejakowatz 	}
29952a38012Sejakowatz DBG(OUT("BMessenger::SendMessage2() done: %lx\n", error));
30052a38012Sejakowatz 	return error;
30152a38012Sejakowatz }
30252a38012Sejakowatz 
30352a38012Sejakowatz // SendMessage
30452a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
30552a38012Sejakowatz 
30652a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
30752a38012Sejakowatz 	of \a message.
30852a38012Sejakowatz 
3097e24e06eSIngo Weinhold 	The method does not wait for a reply. The message is sent asynchronously.
31052a38012Sejakowatz 
31152a38012Sejakowatz 	\param message The message to be sent.
31252a38012Sejakowatz 	\param replyTo A messenger specifying the target for a reply to \a message.
31352a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
31452a38012Sejakowatz 	\return
31552a38012Sejakowatz 	- \c B_OK: Everything went fine.
31652a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
31752a38012Sejakowatz 	  target doesn't exist anymore.
31852a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
31952a38012Sejakowatz 	  port was full when trying to deliver the message.
32052a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
32152a38012Sejakowatz 	  message.
32252a38012Sejakowatz */
32352a38012Sejakowatz status_t
32452a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessenger replyTo,
32552a38012Sejakowatz 						bigtime_t timeout) const
32652a38012Sejakowatz {
3270d0f1600SJérôme Duval 	if (!message)
3280d0f1600SJérôme Duval 		return B_BAD_VALUE;
3290d0f1600SJérôme Duval 
330cf10934eSMichael Lotz 	return BMessage::Private(message).SendMessage(fPort, fHandlerToken,
3314ceb1e51SAxel Dörfler 		timeout, false, replyTo);
33252a38012Sejakowatz }
33352a38012Sejakowatz 
33452a38012Sejakowatz // SendMessage
33552a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
33652a38012Sejakowatz 	waits for a reply.
33752a38012Sejakowatz 
33852a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
33952a38012Sejakowatz 	\a reply. If the target doesn't send a reply, the \c what field of
34052a38012Sejakowatz 	\a reply is set to \c B_NO_REPLY.
34152a38012Sejakowatz 
34252a38012Sejakowatz 	\param command The what field of the message to deliver.
34352a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
34452a38012Sejakowatz 		   message will be copied.
34552a38012Sejakowatz 	\return
34652a38012Sejakowatz 	- \c B_OK: Everything went fine.
34752a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
34852a38012Sejakowatz 	  target doesn't exist anymore.
34952a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
35052a38012Sejakowatz */
35152a38012Sejakowatz status_t
35252a38012Sejakowatz BMessenger::SendMessage(uint32 command, BMessage *reply) const
35352a38012Sejakowatz {
35452a38012Sejakowatz 	BMessage message(command);
35552a38012Sejakowatz 	return SendMessage(&message, reply);
35652a38012Sejakowatz }
35752a38012Sejakowatz 
35852a38012Sejakowatz // SendMessage
35952a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
36052a38012Sejakowatz 	waits for a reply.
36152a38012Sejakowatz 
36252a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
36352a38012Sejakowatz 	of \a message.
36452a38012Sejakowatz 
36552a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
36652a38012Sejakowatz 	\a reply. If the target doesn't send a reply or if a reply timeout occurs,
36752a38012Sejakowatz 	the \c what field of \a reply is set to \c B_NO_REPLY.
36852a38012Sejakowatz 
36952a38012Sejakowatz 	\param message The message to be sent.
37052a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
37152a38012Sejakowatz 		   message will be copied.
37252a38012Sejakowatz 	\param deliveryTimeout A timeout for the delivery of the message.
37352a38012Sejakowatz 	\param replyTimeout A timeout for waiting for the reply.
37452a38012Sejakowatz 	\return
37552a38012Sejakowatz 	- \c B_OK: Everything went fine.
37652a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
37752a38012Sejakowatz 	  target doesn't exist anymore.
37852a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
37952a38012Sejakowatz 	  port was full when trying to deliver the message.
38052a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
38152a38012Sejakowatz 	  message.
38252a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
38352a38012Sejakowatz */
38452a38012Sejakowatz status_t
38552a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessage *reply,
38652a38012Sejakowatz 	bigtime_t deliveryTimeout, bigtime_t replyTimeout) const
38752a38012Sejakowatz {
388*8780db59SAxel Dörfler 	if (message == NULL || reply == NULL)
389*8780db59SAxel Dörfler 		return B_BAD_VALUE;
390*8780db59SAxel Dörfler 
391*8780db59SAxel Dörfler 	status_t error = BMessage::Private(message).SendMessage(fPort, fTeam,
3924ceb1e51SAxel Dörfler 		fHandlerToken, reply, deliveryTimeout, replyTimeout);
393bdbd1cb4SMichael Lotz 
3948f1dc17dSIngo Weinhold 	// Map this error for now:
3958f1dc17dSIngo Weinhold 	if (error == B_BAD_TEAM_ID)
3968f1dc17dSIngo Weinhold 		error = B_BAD_PORT_ID;
397*8780db59SAxel Dörfler 
39852a38012Sejakowatz 	return error;
39952a38012Sejakowatz }
40052a38012Sejakowatz 
40152a38012Sejakowatz 
4024ceb1e51SAxel Dörfler //	#pragma mark - Operators and misc
40352a38012Sejakowatz 
4044ceb1e51SAxel Dörfler 
40552a38012Sejakowatz /*!	\brief Makes this BMessenger a copy of the supplied one.
40652a38012Sejakowatz 
40752a38012Sejakowatz 	\param from the messenger to be copied.
40852a38012Sejakowatz 	\return A reference to this object.
40952a38012Sejakowatz */
41052a38012Sejakowatz BMessenger &
41152a38012Sejakowatz BMessenger::operator=(const BMessenger &from)
41252a38012Sejakowatz {
41352a38012Sejakowatz 	if (this != &from) {
41452a38012Sejakowatz 		fPort = from.fPort;
41552a38012Sejakowatz 		fHandlerToken = from.fHandlerToken;
41652a38012Sejakowatz 		fTeam = from.fTeam;
41752a38012Sejakowatz 	}
4188f1dc17dSIngo Weinhold 	return *this;
41952a38012Sejakowatz }
42052a38012Sejakowatz 
4214ceb1e51SAxel Dörfler 
42252a38012Sejakowatz /*!	\brief Returns whether this and the supplied messenger have the same
42352a38012Sejakowatz 	target.
42452a38012Sejakowatz 
42552a38012Sejakowatz 	\param other The other messenger.
42652a38012Sejakowatz 	\return \c true, if the messengers have the same target or if both aren't
42752a38012Sejakowatz 			properly initialzed, \c false otherwise.
42852a38012Sejakowatz */
42952a38012Sejakowatz bool
43052a38012Sejakowatz BMessenger::operator==(const BMessenger &other) const
43152a38012Sejakowatz {
4328f1dc17dSIngo Weinhold 	// Note: The fTeam fields are not compared.
4334ceb1e51SAxel Dörfler 	return fPort == other.fPort
4344ceb1e51SAxel Dörfler 		&& fHandlerToken == other.fHandlerToken;
43552a38012Sejakowatz }
43652a38012Sejakowatz 
4374ceb1e51SAxel Dörfler 
43852a38012Sejakowatz /*!	\brief Returns whether the messenger's target looper does still exist.
43952a38012Sejakowatz 
44052a38012Sejakowatz 	It is not checked whether the target handler is also still existing.
44152a38012Sejakowatz 
44252a38012Sejakowatz 	\return \c true, if the messenger's target looper does still exist,
44352a38012Sejakowatz 			\c false otherwise.
44452a38012Sejakowatz */
44552a38012Sejakowatz bool
44652a38012Sejakowatz BMessenger::IsValid() const
44752a38012Sejakowatz {
44852a38012Sejakowatz 	port_info info;
4494ceb1e51SAxel Dörfler 	return fPort >= 0 && get_port_info(fPort, &info) == B_OK;
45052a38012Sejakowatz }
45152a38012Sejakowatz 
4524ceb1e51SAxel Dörfler 
45352a38012Sejakowatz /*!	\brief Returns the ID of the team the messenger's target lives in.
45452a38012Sejakowatz 
45552a38012Sejakowatz 	\return The team of the messenger's target.
45652a38012Sejakowatz */
45752a38012Sejakowatz team_id
45852a38012Sejakowatz BMessenger::Team() const
45952a38012Sejakowatz {
46052a38012Sejakowatz 	return fTeam;
46152a38012Sejakowatz }
46252a38012Sejakowatz 
46352a38012Sejakowatz 
4644ceb1e51SAxel Dörfler //	#pragma mark - Private or reserved
46552a38012Sejakowatz 
4664ceb1e51SAxel Dörfler 
4674afc60d3SIngo Weinhold /*!	\brief Sets the messenger's team, target looper port and handler token.
46852a38012Sejakowatz 
4694ceb1e51SAxel Dörfler 	To target the preferred handler, use B_PREFERRED_TOKEN as token.
47052a38012Sejakowatz 
47152a38012Sejakowatz 	\param team The target's team.
47252a38012Sejakowatz 	\param port The target looper port.
47352a38012Sejakowatz 	\param token The target handler token.
47452a38012Sejakowatz */
4754afc60d3SIngo Weinhold void
4764ceb1e51SAxel Dörfler BMessenger::_SetTo(team_id team, port_id port, int32 token)
47752a38012Sejakowatz {
47852a38012Sejakowatz 	fTeam = team;
47952a38012Sejakowatz 	fPort = port;
4804ceb1e51SAxel Dörfler 	fHandlerToken = token;
48152a38012Sejakowatz }
48252a38012Sejakowatz 
4834ceb1e51SAxel Dörfler 
48452a38012Sejakowatz /*!	\brief Initializes the BMessenger object's data given the signature and/or
48552a38012Sejakowatz 	team ID of a target.
48652a38012Sejakowatz 
48752a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
48852a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
48952a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
49052a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
49152a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
49252a38012Sejakowatz 
49352a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
49452a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
49552a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
49652a38012Sejakowatz 		   the result of the initialization is written.
49752a38012Sejakowatz */
49852a38012Sejakowatz void
4994ceb1e51SAxel Dörfler BMessenger::_InitData(const char* signature, team_id team, status_t* _result)
50052a38012Sejakowatz {
5013b044715SIngo Weinhold 	status_t error = B_OK;
5029e9f5a1aSIngo Weinhold 	// get an app_info
5039e9f5a1aSIngo Weinhold 	app_info info;
5043b044715SIngo Weinhold 	if (team < 0) {
5059e9f5a1aSIngo Weinhold 		// no team ID given
5063b044715SIngo Weinhold 		if (signature) {
5079e9f5a1aSIngo Weinhold 			error = be_roster->GetAppInfo(signature, &info);
5089e9f5a1aSIngo Weinhold 			team = info.team;
509672c1ea9SIngo Weinhold 			// B_ERROR means that no application with the given signature
510672c1ea9SIngo Weinhold 			// is running. But we are supposed to return B_BAD_VALUE.
511672c1ea9SIngo Weinhold 			if (error == B_ERROR)
5123b044715SIngo Weinhold 				error = B_BAD_VALUE;
513672c1ea9SIngo Weinhold 		} else
514672c1ea9SIngo Weinhold 			error = B_BAD_TYPE;
5159e9f5a1aSIngo Weinhold 	} else {
5169e9f5a1aSIngo Weinhold 		// a team ID is given
5173b044715SIngo Weinhold 		error = be_roster->GetRunningAppInfo(team, &info);
5189e9f5a1aSIngo Weinhold 		// Compare the returned signature with the supplied one.
5191771f7aeSAxel Dörfler 		if (error == B_OK && signature && strcasecmp(signature, info.signature))
520672c1ea9SIngo Weinhold 			error = B_MISMATCHED_VALUES;
5219e9f5a1aSIngo Weinhold 	}
5229e9f5a1aSIngo Weinhold 	// check whether the app flags say B_ARGV_ONLY
523672c1ea9SIngo Weinhold 	if (error == B_OK && (info.flags & B_ARGV_ONLY)) {
524c9f4f5e1SIngo Weinhold 		error = B_BAD_TYPE;
525672c1ea9SIngo Weinhold 		// Set the team ID nevertheless -- that's what Be's implementation
526672c1ea9SIngo Weinhold 		// does. Don't know, if that is a bug, but at least it doesn't harm.
527672c1ea9SIngo Weinhold 		fTeam = team;
528672c1ea9SIngo Weinhold 	}
5293b044715SIngo Weinhold 	// init our members
5303b044715SIngo Weinhold 	if (error == B_OK) {
5313b044715SIngo Weinhold 		fTeam = team;
5323b044715SIngo Weinhold 		fPort = info.port;
53394b98dffSIngo Weinhold 		fHandlerToken = B_PREFERRED_TOKEN;
53452a38012Sejakowatz 	}
53552a38012Sejakowatz 
5364ceb1e51SAxel Dörfler 	// return the error
5374ceb1e51SAxel Dörfler 	if (_result)
5384ceb1e51SAxel Dörfler 		*_result = error;
5394ceb1e51SAxel Dörfler }
5404ceb1e51SAxel Dörfler 
5414ceb1e51SAxel Dörfler 
54252a38012Sejakowatz /*!	\brief Returns whether the first one of two BMessengers is less than the
54352a38012Sejakowatz 	second one.
54452a38012Sejakowatz 
54552a38012Sejakowatz 	This method defines an order on BMessengers based on their member
5468f1dc17dSIngo Weinhold 	variables \c fPort, \c fHandlerToken and \c fPreferredTarget.
5478f1dc17dSIngo Weinhold 
54852a38012Sejakowatz 	\param a The first messenger.
54952a38012Sejakowatz 	\param b The second messenger.
55052a38012Sejakowatz 	\return \c true, if \a a is less than \a b, \c false otherwise.
55152a38012Sejakowatz */
55252a38012Sejakowatz bool
5534afc60d3SIngo Weinhold operator<(const BMessenger &_a, const BMessenger &_b)
55452a38012Sejakowatz {
5554afc60d3SIngo Weinhold 	BMessenger::Private a(const_cast<BMessenger&>(_a));
5564afc60d3SIngo Weinhold 	BMessenger::Private b(const_cast<BMessenger&>(_b));
5574afc60d3SIngo Weinhold 
5588f1dc17dSIngo Weinhold 	// significance:
5598f1dc17dSIngo Weinhold 	// 1. fPort
5608f1dc17dSIngo Weinhold 	// 2. fHandlerToken
5618f1dc17dSIngo Weinhold 	// 3. fPreferredTarget
5628f1dc17dSIngo Weinhold 	// fTeam is insignificant
5634afc60d3SIngo Weinhold 	return (a.Port() < b.Port()
5644afc60d3SIngo Weinhold 			|| a.Port() == b.Port()
5654afc60d3SIngo Weinhold 				&& (a.Token() < b.Token()
5664afc60d3SIngo Weinhold 					|| a.Token() == b.Token()
5674afc60d3SIngo Weinhold 						&& !a.IsPreferredTarget()
5684afc60d3SIngo Weinhold 						&& b.IsPreferredTarget()));
56952a38012Sejakowatz }
57052a38012Sejakowatz 
5714ceb1e51SAxel Dörfler 
57252a38012Sejakowatz /*!	\brief Returns whether two BMessengers have not the same target.
57352a38012Sejakowatz 
57452a38012Sejakowatz 	\param a The first messenger.
57552a38012Sejakowatz 	\param b The second messenger.
57652a38012Sejakowatz 	\return \c false, if \a a and \a b have the same targets or are both not
57752a38012Sejakowatz 			properly initialized, \c true otherwise.
57852a38012Sejakowatz */
57952a38012Sejakowatz bool
58052a38012Sejakowatz operator!=(const BMessenger &a, const BMessenger &b)
58152a38012Sejakowatz {
58252a38012Sejakowatz 	return !(a == b);
58352a38012Sejakowatz }
58452a38012Sejakowatz 
585