xref: /haiku/src/kits/app/Messenger.cpp (revision cd511790d7245773e881991381870596bb525903)
15edcfe96SAxel Dörfler /*
2930a139dSRene Gollent  * Copyright 2001-2011, 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>
112b2ec438SIngo Weinhold #include <AutoLocker.h>
125edcfe96SAxel Dörfler #include <MessageUtils.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;
3952a38012Sejakowatz 
4052a38012Sejakowatz enum {
4152a38012Sejakowatz 	NOT_IMPLEMENTED	= B_ERROR,
4252a38012Sejakowatz };
4352a38012Sejakowatz 
4452a38012Sejakowatz 
4552a38012Sejakowatz /*!	\brief Creates an unitialized BMessenger.
4652a38012Sejakowatz */
4752a38012Sejakowatz BMessenger::BMessenger()
484ceb1e51SAxel Dörfler 	:
494ceb1e51SAxel Dörfler 	fPort(-1),
5094b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
514ceb1e51SAxel Dörfler 	fTeam(-1)
5252a38012Sejakowatz {
5352a38012Sejakowatz }
5452a38012Sejakowatz 
554ceb1e51SAxel Dörfler 
5652a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the already
5752a38012Sejakowatz 	running application identified by its signature and/or team ID.
5852a38012Sejakowatz 
5952a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
6052a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
6152a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
6252a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
6352a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
6452a38012Sejakowatz 
6552a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
6652a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
6752a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
6852a38012Sejakowatz 		   the result of the initialization is written.
6952a38012Sejakowatz */
7052a38012Sejakowatz BMessenger::BMessenger(const char *signature, team_id team, status_t *result)
714ceb1e51SAxel Dörfler 	:
724ceb1e51SAxel Dörfler 	fPort(-1),
7394b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
744ceb1e51SAxel Dörfler 	fTeam(-1)
7552a38012Sejakowatz {
764ceb1e51SAxel Dörfler 	_InitData(signature, team, result);
7752a38012Sejakowatz }
7852a38012Sejakowatz 
794ceb1e51SAxel Dörfler 
8052a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the local
8152a38012Sejakowatz 	BHandler and/or BLooper.
8252a38012Sejakowatz 
8352a38012Sejakowatz 	When a \c NULL handler is supplied, the preferred handler in the given
8452a38012Sejakowatz 	looper is targeted. If no looper is supplied the looper the given handler
8552a38012Sejakowatz 	belongs to is used -- that means in particular, that the handler must
8652a38012Sejakowatz 	already belong to a looper. If both are supplied the handler must actually
8752a38012Sejakowatz 	belong to looper.
8852a38012Sejakowatz 
8952a38012Sejakowatz 	\param handler The target handler. May be \c NULL.
9052a38012Sejakowatz 	\param looper The target looper. May be \c NULL.
9152a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
9252a38012Sejakowatz 		   the result of the initialization is written.
9352a38012Sejakowatz */
9452a38012Sejakowatz BMessenger::BMessenger(const BHandler* handler, const BLooper* looper,
954ceb1e51SAxel Dörfler 	status_t* _result)
964ceb1e51SAxel Dörfler 	:
974ceb1e51SAxel Dörfler 	fPort(-1),
9894b98dffSIngo Weinhold 	fHandlerToken(B_NULL_TOKEN),
994ceb1e51SAxel Dörfler 	fTeam(-1)
10052a38012Sejakowatz {
10152a38012Sejakowatz 	status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
10252a38012Sejakowatz 	if (error == B_OK) {
10352a38012Sejakowatz 		if (handler) {
10452a38012Sejakowatz 			// BHandler is given, check/retrieve the looper.
10552a38012Sejakowatz 			if (looper) {
10652a38012Sejakowatz 				if (handler->Looper() != looper)
10752a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
10852a38012Sejakowatz 			} else {
10952a38012Sejakowatz 				looper = handler->Looper();
11052a38012Sejakowatz 				if (looper == NULL)
11152a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
11252a38012Sejakowatz 			}
11337faaadeSIngo Weinhold 		}
11452a38012Sejakowatz 		// set port, token,...
11552a38012Sejakowatz 		if (error == B_OK) {
1162b2ec438SIngo Weinhold 			AutoLocker<BLooperList> locker(gLooperList);
11737faaadeSIngo Weinhold 			if (locker.IsLocked() && gLooperList.IsLooperValid(looper)) {
11852a38012Sejakowatz 				fPort = looper->fMsgPort;
11994b98dffSIngo Weinhold 				fHandlerToken = (handler
12094b98dffSIngo Weinhold 					? _get_object_token_(handler) : B_PREFERRED_TOKEN);
12137faaadeSIngo Weinhold 				fTeam = looper->Team();
12237faaadeSIngo Weinhold 			} else
12337faaadeSIngo Weinhold 				error = B_BAD_VALUE;
12452a38012Sejakowatz 		}
12552a38012Sejakowatz 	}
1264ceb1e51SAxel Dörfler 	if (_result)
1274ceb1e51SAxel Dörfler 		*_result = error;
12852a38012Sejakowatz }
12952a38012Sejakowatz 
1304ceb1e51SAxel Dörfler 
13152a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to have the same target
13252a38012Sejakowatz 	as the supplied messemger.
13352a38012Sejakowatz 
13452a38012Sejakowatz 	\param from The messenger to be copied.
13552a38012Sejakowatz */
13652a38012Sejakowatz BMessenger::BMessenger(const BMessenger& from)
1374ceb1e51SAxel Dörfler 	:
1384ceb1e51SAxel Dörfler 	fPort(from.fPort),
13952a38012Sejakowatz 	fHandlerToken(from.fHandlerToken),
1404ceb1e51SAxel Dörfler 	fTeam(from.fTeam)
14152a38012Sejakowatz {
14252a38012Sejakowatz }
14352a38012Sejakowatz 
1444ceb1e51SAxel Dörfler 
14552a38012Sejakowatz /*!	\brief Frees all resources associated with this object.
14652a38012Sejakowatz */
14752a38012Sejakowatz BMessenger::~BMessenger()
14852a38012Sejakowatz {
14952a38012Sejakowatz }
15052a38012Sejakowatz 
15152a38012Sejakowatz 
1524ceb1e51SAxel Dörfler //	#pragma mark - Target
15352a38012Sejakowatz 
1544ceb1e51SAxel Dörfler 
15552a38012Sejakowatz /*!	\brief Returns whether or not the messenger's target lives within the team
15652a38012Sejakowatz 	of the caller.
15752a38012Sejakowatz 
15852a38012Sejakowatz 	\return \c true, if the object is properly initialized and its target
15952a38012Sejakowatz 			lives within the caller's team, \c false otherwise.
16052a38012Sejakowatz */
16152a38012Sejakowatz bool
16252a38012Sejakowatz BMessenger::IsTargetLocal() const
16352a38012Sejakowatz {
1644cad5abaSAxel Dörfler 	return BPrivate::current_team() == fTeam;
16552a38012Sejakowatz }
16652a38012Sejakowatz 
1674ceb1e51SAxel Dörfler 
16852a38012Sejakowatz /*!	\brief Returns the handler and looper targeted by the messenger, if the
16952a38012Sejakowatz 	target is local.
17052a38012Sejakowatz 
17152a38012Sejakowatz 	The handler is returned directly, the looper by reference. If both are
17252a38012Sejakowatz 	\c NULL, the object is either not properly initialized, the target
17352a38012Sejakowatz 	objects have been deleted or the target is remote. If only the returned
17452a38012Sejakowatz 	handler is \c NULL, either the looper's preferred handler is targeted or
17552a38012Sejakowatz 	the handler has been deleted.
17652a38012Sejakowatz 
17752a38012Sejakowatz 	\param looper A pointer to a pre-allocated BLooper pointer into which
17852a38012Sejakowatz 		   the pointer to the targeted looper is written.
17952a38012Sejakowatz 	\return The BHandler targeted by the messenger.
18052a38012Sejakowatz */
18152a38012Sejakowatz BHandler *
1824ceb1e51SAxel Dörfler BMessenger::Target(BLooper** _looper) const
18352a38012Sejakowatz {
18452a38012Sejakowatz 	BHandler *handler = NULL;
18594f814b3SJérôme Duval 	if (IsTargetLocal()
18694f814b3SJérôme Duval 		&& (fHandlerToken > B_NULL_TOKEN
18794f814b3SJérôme Duval 			|| fHandlerToken == B_PREFERRED_TOKEN)) {
18852a38012Sejakowatz 		gDefaultTokens.GetToken(fHandlerToken, B_HANDLER_TOKEN,
18952a38012Sejakowatz 			(void**)&handler);
1904ceb1e51SAxel Dörfler 		if (_looper)
1914ceb1e51SAxel Dörfler 			*_looper = BPrivate::gLooperList.LooperForPort(fPort);
1924ceb1e51SAxel Dörfler 	} else if (_looper)
1934ceb1e51SAxel Dörfler 		*_looper = NULL;
1944ceb1e51SAxel Dörfler 
19552a38012Sejakowatz 	return handler;
19652a38012Sejakowatz }
19752a38012Sejakowatz 
1984ceb1e51SAxel Dörfler 
19952a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
20052a38012Sejakowatz 
20152a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
20252a38012Sejakowatz 	Target() and calling BLooper::Lock() on the looper afterwards.
20352a38012Sejakowatz 
20452a38012Sejakowatz 	\see BLooper::Lock() for details.
20552a38012Sejakowatz 
20652a38012Sejakowatz 	\return \c true, if the looper could be locked sucessfully, \c false, if
20752a38012Sejakowatz 			the messenger is not properly initialized, the target is remote,
20852a38012Sejakowatz 			or the targeted looper is invalid.
20952a38012Sejakowatz */
21052a38012Sejakowatz bool
21152a38012Sejakowatz BMessenger::LockTarget() const
21252a38012Sejakowatz {
21352a38012Sejakowatz 	BLooper *looper = NULL;
21452a38012Sejakowatz 	Target(&looper);
215*cd511790SAxel Dörfler 	if (looper != NULL && looper->Lock()) {
216930a139dSRene Gollent 		if (looper->fMsgPort == fPort)
217930a139dSRene Gollent 			return true;
218*cd511790SAxel Dörfler 
219930a139dSRene Gollent 		looper->Unlock();
220930a139dSRene Gollent 		return false;
221930a139dSRene Gollent 	}
222930a139dSRene Gollent 
223930a139dSRene Gollent 	return false;
22452a38012Sejakowatz }
22552a38012Sejakowatz 
2264ceb1e51SAxel Dörfler 
22752a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
22852a38012Sejakowatz 
22952a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
23052a38012Sejakowatz 	Target() and calling BLooper::LockWithTimeout() on the looper afterwards.
23152a38012Sejakowatz 
23252a38012Sejakowatz 	\see BLooper::LockWithTimeout() for details.
23352a38012Sejakowatz 
23452a38012Sejakowatz 	\return
23552a38012Sejakowatz 	- \c B_OK, if the looper could be locked sucessfully,
23652a38012Sejakowatz 	- \c B_BAD_VALUE, if the messenger is not properly initialized,
23752a38012Sejakowatz 	  the target is remote, or the targeted looper is invalid,
23852a38012Sejakowatz 	- other error codes returned by BLooper::LockWithTimeout().
23952a38012Sejakowatz */
24052a38012Sejakowatz status_t
24152a38012Sejakowatz BMessenger::LockTargetWithTimeout(bigtime_t timeout) const
24252a38012Sejakowatz {
24352a38012Sejakowatz 	BLooper *looper = NULL;
24452a38012Sejakowatz 	Target(&looper);
245*cd511790SAxel Dörfler 	if (looper == NULL)
246*cd511790SAxel Dörfler 		return B_BAD_VALUE;
247*cd511790SAxel Dörfler 
248*cd511790SAxel Dörfler 	status_t error = looper->LockWithTimeout(timeout);
2494ceb1e51SAxel Dörfler 
25087aa57e8SRene Gollent 	if (error == B_OK && looper->fMsgPort != fPort) {
25187aa57e8SRene Gollent 		looper->Unlock();
252930a139dSRene Gollent 		return B_BAD_PORT_ID;
25387aa57e8SRene Gollent 	}
254930a139dSRene Gollent 
25552a38012Sejakowatz 	return error;
25652a38012Sejakowatz }
25752a38012Sejakowatz 
25852a38012Sejakowatz 
2594ceb1e51SAxel Dörfler //	#pragma mark - Message sending
26052a38012Sejakowatz 
261*cd511790SAxel Dörfler 
26269666c91SIngo Weinhold /*! \brief Delivers a BMessage synchronously to the messenger's target,
26369666c91SIngo Weinhold 		   without waiting for a reply.
26452a38012Sejakowatz 
26569666c91SIngo Weinhold 	If the target's message port is full, the method waits indefinitely, until
26669666c91SIngo Weinhold 	space becomes available in the port. After delivery the method returns
26769666c91SIngo Weinhold 	immediately. It does not wait until the target processes the message or
26869666c91SIngo Weinhold 	even sends a reply.
26952a38012Sejakowatz 
27052a38012Sejakowatz 	\param command The what field of the message to deliver.
27152a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
27252a38012Sejakowatz 		   May be \c NULL.
27352a38012Sejakowatz 	\return
27452a38012Sejakowatz 	- \c B_OK: Everything went fine.
27552a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
27652a38012Sejakowatz 	  target doesn't exist anymore.
27752a38012Sejakowatz */
27852a38012Sejakowatz status_t
27952a38012Sejakowatz BMessenger::SendMessage(uint32 command, BHandler *replyTo) const
28052a38012Sejakowatz {
28152a38012Sejakowatz 	BMessage message(command);
28252a38012Sejakowatz 	return SendMessage(&message, replyTo);
28352a38012Sejakowatz }
28452a38012Sejakowatz 
285*cd511790SAxel Dörfler 
28669666c91SIngo Weinhold /*! \brief Delivers a BMessage synchronously to the messenger's target,
28769666c91SIngo Weinhold 		   without waiting for a reply.
28852a38012Sejakowatz 
28952a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
29052a38012Sejakowatz 	of \a message.
29152a38012Sejakowatz 
29269666c91SIngo Weinhold 	If the target's message port is full, the method waits until space becomes
29369666c91SIngo Weinhold 	available in the port or the specified timeout occurs (whichever happens
29469666c91SIngo Weinhold 	first). After delivery the method returns immediately. It does not wait
29569666c91SIngo Weinhold 	until the target processes the message or even sends a reply.
29652a38012Sejakowatz 
29752a38012Sejakowatz 	\param message The message to be sent.
29852a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
29952a38012Sejakowatz 		   May be \c NULL.
30052a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
30152a38012Sejakowatz 	\return
30252a38012Sejakowatz 	- \c B_OK: Everything went fine.
30352a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
30452a38012Sejakowatz 	  target doesn't exist anymore.
30552a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
30652a38012Sejakowatz 	  port was full when trying to deliver the message.
30752a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
30852a38012Sejakowatz 	  message.
30952a38012Sejakowatz */
31052a38012Sejakowatz status_t
31152a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BHandler *replyTo,
31252a38012Sejakowatz 	bigtime_t timeout) const
31352a38012Sejakowatz {
31452a38012Sejakowatz 	DBG(OUT("BMessenger::SendMessage2(%.4s)\n", (char*)&message->what));
31552a38012Sejakowatz 	status_t error = (message ? B_OK : B_BAD_VALUE);
31652a38012Sejakowatz 	if (error == B_OK) {
31752a38012Sejakowatz 		BMessenger replyMessenger(replyTo);
318717a24b7SIngo Weinhold 		error = SendMessage(message, replyMessenger, timeout);
31952a38012Sejakowatz 	}
32052a38012Sejakowatz 	DBG(OUT("BMessenger::SendMessage2() done: %lx\n", error));
32152a38012Sejakowatz 	return error;
32252a38012Sejakowatz }
32352a38012Sejakowatz 
324*cd511790SAxel Dörfler 
32569666c91SIngo Weinhold /*! \brief Delivers a BMessage synchronously to the messenger's target,
32669666c91SIngo Weinhold 		   without waiting for a reply.
32752a38012Sejakowatz 
32852a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
32952a38012Sejakowatz 	of \a message.
33052a38012Sejakowatz 
33169666c91SIngo Weinhold 	If the target's message port is full, the method waits until space becomes
33269666c91SIngo Weinhold 	available in the port or the specified timeout occurs (whichever happens
33369666c91SIngo Weinhold 	first). After delivery the method returns immediately. It does not wait
33469666c91SIngo Weinhold 	until the target processes the message or even sends a reply.
33552a38012Sejakowatz 
33652a38012Sejakowatz 	\param message The message to be sent.
33752a38012Sejakowatz 	\param replyTo A messenger specifying the target for a reply to \a message.
33852a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
33952a38012Sejakowatz 	\return
34052a38012Sejakowatz 	- \c B_OK: Everything went fine.
34152a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
34252a38012Sejakowatz 	  target doesn't exist anymore.
34352a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
34452a38012Sejakowatz 	  port was full when trying to deliver the message.
34552a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
34652a38012Sejakowatz 	  message.
34752a38012Sejakowatz */
34852a38012Sejakowatz status_t
34952a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessenger replyTo,
35052a38012Sejakowatz 	bigtime_t timeout) const
35152a38012Sejakowatz {
3520d0f1600SJérôme Duval 	if (!message)
3530d0f1600SJérôme Duval 		return B_BAD_VALUE;
3540d0f1600SJérôme Duval 
3559dbe170aSAxel Dörfler 	return BMessage::Private(message).SendMessage(fPort, fTeam, fHandlerToken,
3564ceb1e51SAxel Dörfler 		timeout, false, replyTo);
35752a38012Sejakowatz }
35852a38012Sejakowatz 
359*cd511790SAxel Dörfler 
36052a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
36152a38012Sejakowatz 	waits for a reply.
36252a38012Sejakowatz 
36352a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
36452a38012Sejakowatz 	\a reply. If the target doesn't send a reply, the \c what field of
36552a38012Sejakowatz 	\a reply is set to \c B_NO_REPLY.
36652a38012Sejakowatz 
36752a38012Sejakowatz 	\param command The what field of the message to deliver.
36852a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
36952a38012Sejakowatz 		   message will be copied.
37052a38012Sejakowatz 	\return
37152a38012Sejakowatz 	- \c B_OK: Everything went fine.
37252a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
37352a38012Sejakowatz 	  target doesn't exist anymore.
37452a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
37552a38012Sejakowatz */
37652a38012Sejakowatz status_t
37752a38012Sejakowatz BMessenger::SendMessage(uint32 command, BMessage *reply) const
37852a38012Sejakowatz {
37952a38012Sejakowatz 	BMessage message(command);
38052a38012Sejakowatz 	return SendMessage(&message, reply);
38152a38012Sejakowatz }
38252a38012Sejakowatz 
383*cd511790SAxel Dörfler 
38452a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
38552a38012Sejakowatz 	waits for a reply.
38652a38012Sejakowatz 
38752a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
38852a38012Sejakowatz 	of \a message.
38952a38012Sejakowatz 
39052a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
39152a38012Sejakowatz 	\a reply. If the target doesn't send a reply or if a reply timeout occurs,
39252a38012Sejakowatz 	the \c what field of \a reply is set to \c B_NO_REPLY.
39352a38012Sejakowatz 
39452a38012Sejakowatz 	\param message The message to be sent.
39552a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
39652a38012Sejakowatz 		   message will be copied.
39752a38012Sejakowatz 	\param deliveryTimeout A timeout for the delivery of the message.
39852a38012Sejakowatz 	\param replyTimeout A timeout for waiting for the reply.
39952a38012Sejakowatz 	\return
40052a38012Sejakowatz 	- \c B_OK: Everything went fine.
40152a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
40252a38012Sejakowatz 	  target doesn't exist anymore.
40352a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
40452a38012Sejakowatz 	  port was full when trying to deliver the message.
40552a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
40652a38012Sejakowatz 	  message.
40752a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
40852a38012Sejakowatz */
40952a38012Sejakowatz status_t
41052a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessage *reply,
41152a38012Sejakowatz 	bigtime_t deliveryTimeout, bigtime_t replyTimeout) const
41252a38012Sejakowatz {
4138780db59SAxel Dörfler 	if (message == NULL || reply == NULL)
4148780db59SAxel Dörfler 		return B_BAD_VALUE;
4158780db59SAxel Dörfler 
4168780db59SAxel Dörfler 	status_t error = BMessage::Private(message).SendMessage(fPort, fTeam,
4174ceb1e51SAxel Dörfler 		fHandlerToken, reply, deliveryTimeout, replyTimeout);
418bdbd1cb4SMichael Lotz 
4198f1dc17dSIngo Weinhold 	// Map this error for now:
4208f1dc17dSIngo Weinhold 	if (error == B_BAD_TEAM_ID)
4218f1dc17dSIngo Weinhold 		error = B_BAD_PORT_ID;
4228780db59SAxel Dörfler 
42352a38012Sejakowatz 	return error;
42452a38012Sejakowatz }
42552a38012Sejakowatz 
42652a38012Sejakowatz 
4274ceb1e51SAxel Dörfler //	#pragma mark - Operators and misc
42852a38012Sejakowatz 
4294ceb1e51SAxel Dörfler 
43052a38012Sejakowatz /*!	\brief Makes this BMessenger a copy of the supplied one.
43152a38012Sejakowatz 
43252a38012Sejakowatz 	\param from the messenger to be copied.
43352a38012Sejakowatz 	\return A reference to this object.
43452a38012Sejakowatz */
43552a38012Sejakowatz BMessenger &
43652a38012Sejakowatz BMessenger::operator=(const BMessenger &from)
43752a38012Sejakowatz {
43852a38012Sejakowatz 	if (this != &from) {
43952a38012Sejakowatz 		fPort = from.fPort;
44052a38012Sejakowatz 		fHandlerToken = from.fHandlerToken;
44152a38012Sejakowatz 		fTeam = from.fTeam;
44252a38012Sejakowatz 	}
4438f1dc17dSIngo Weinhold 	return *this;
44452a38012Sejakowatz }
44552a38012Sejakowatz 
4464ceb1e51SAxel Dörfler 
44752a38012Sejakowatz /*!	\brief Returns whether this and the supplied messenger have the same
44852a38012Sejakowatz 	target.
44952a38012Sejakowatz 
45052a38012Sejakowatz 	\param other The other messenger.
45152a38012Sejakowatz 	\return \c true, if the messengers have the same target or if both aren't
45252a38012Sejakowatz 			properly initialzed, \c false otherwise.
45352a38012Sejakowatz */
45452a38012Sejakowatz bool
45552a38012Sejakowatz BMessenger::operator==(const BMessenger &other) const
45652a38012Sejakowatz {
4578f1dc17dSIngo Weinhold 	// Note: The fTeam fields are not compared.
4584ceb1e51SAxel Dörfler 	return fPort == other.fPort
4594ceb1e51SAxel Dörfler 		&& fHandlerToken == other.fHandlerToken;
46052a38012Sejakowatz }
46152a38012Sejakowatz 
4624ceb1e51SAxel Dörfler 
46352a38012Sejakowatz /*!	\brief Returns whether the messenger's target looper does still exist.
46452a38012Sejakowatz 
46552a38012Sejakowatz 	It is not checked whether the target handler is also still existing.
46652a38012Sejakowatz 
46752a38012Sejakowatz 	\return \c true, if the messenger's target looper does still exist,
46852a38012Sejakowatz 			\c false otherwise.
46952a38012Sejakowatz */
47052a38012Sejakowatz bool
47152a38012Sejakowatz BMessenger::IsValid() const
47252a38012Sejakowatz {
47352a38012Sejakowatz 	port_info info;
4744ceb1e51SAxel Dörfler 	return fPort >= 0 && get_port_info(fPort, &info) == B_OK;
47552a38012Sejakowatz }
47652a38012Sejakowatz 
4774ceb1e51SAxel Dörfler 
47852a38012Sejakowatz /*!	\brief Returns the ID of the team the messenger's target lives in.
47952a38012Sejakowatz 
48052a38012Sejakowatz 	\return The team of the messenger's target.
48152a38012Sejakowatz */
48252a38012Sejakowatz team_id
48352a38012Sejakowatz BMessenger::Team() const
48452a38012Sejakowatz {
48552a38012Sejakowatz 	return fTeam;
48652a38012Sejakowatz }
48752a38012Sejakowatz 
48852a38012Sejakowatz 
4894ceb1e51SAxel Dörfler //	#pragma mark - Private or reserved
49052a38012Sejakowatz 
4914ceb1e51SAxel Dörfler 
4924afc60d3SIngo Weinhold /*!	\brief Sets the messenger's team, target looper port and handler token.
49352a38012Sejakowatz 
4944ceb1e51SAxel Dörfler 	To target the preferred handler, use B_PREFERRED_TOKEN as token.
49552a38012Sejakowatz 
49652a38012Sejakowatz 	\param team The target's team.
49752a38012Sejakowatz 	\param port The target looper port.
49852a38012Sejakowatz 	\param token The target handler token.
49952a38012Sejakowatz */
5004afc60d3SIngo Weinhold void
5014ceb1e51SAxel Dörfler BMessenger::_SetTo(team_id team, port_id port, int32 token)
50252a38012Sejakowatz {
50352a38012Sejakowatz 	fTeam = team;
50452a38012Sejakowatz 	fPort = port;
5054ceb1e51SAxel Dörfler 	fHandlerToken = token;
50652a38012Sejakowatz }
50752a38012Sejakowatz 
5084ceb1e51SAxel Dörfler 
50952a38012Sejakowatz /*!	\brief Initializes the BMessenger object's data given the signature and/or
51052a38012Sejakowatz 	team ID of a target.
51152a38012Sejakowatz 
51252a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
51352a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
51452a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
51552a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
51652a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
51752a38012Sejakowatz 
51852a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
51952a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
52052a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
52152a38012Sejakowatz 		   the result of the initialization is written.
52252a38012Sejakowatz */
52352a38012Sejakowatz void
5244ceb1e51SAxel Dörfler BMessenger::_InitData(const char* signature, team_id team, status_t* _result)
52552a38012Sejakowatz {
5263b044715SIngo Weinhold 	status_t error = B_OK;
5279e9f5a1aSIngo Weinhold 	// get an app_info
5289e9f5a1aSIngo Weinhold 	app_info info;
5293b044715SIngo Weinhold 	if (team < 0) {
5309e9f5a1aSIngo Weinhold 		// no team ID given
5313b044715SIngo Weinhold 		if (signature) {
5329e9f5a1aSIngo Weinhold 			error = be_roster->GetAppInfo(signature, &info);
5339e9f5a1aSIngo Weinhold 			team = info.team;
534672c1ea9SIngo Weinhold 			// B_ERROR means that no application with the given signature
535672c1ea9SIngo Weinhold 			// is running. But we are supposed to return B_BAD_VALUE.
536672c1ea9SIngo Weinhold 			if (error == B_ERROR)
5373b044715SIngo Weinhold 				error = B_BAD_VALUE;
538672c1ea9SIngo Weinhold 		} else
539672c1ea9SIngo Weinhold 			error = B_BAD_TYPE;
5409e9f5a1aSIngo Weinhold 	} else {
5419e9f5a1aSIngo Weinhold 		// a team ID is given
5423b044715SIngo Weinhold 		error = be_roster->GetRunningAppInfo(team, &info);
5439e9f5a1aSIngo Weinhold 		// Compare the returned signature with the supplied one.
5441771f7aeSAxel Dörfler 		if (error == B_OK && signature && strcasecmp(signature, info.signature))
545672c1ea9SIngo Weinhold 			error = B_MISMATCHED_VALUES;
5469e9f5a1aSIngo Weinhold 	}
5479e9f5a1aSIngo Weinhold 	// check whether the app flags say B_ARGV_ONLY
548672c1ea9SIngo Weinhold 	if (error == B_OK && (info.flags & B_ARGV_ONLY)) {
549c9f4f5e1SIngo Weinhold 		error = B_BAD_TYPE;
550672c1ea9SIngo Weinhold 		// Set the team ID nevertheless -- that's what Be's implementation
551672c1ea9SIngo Weinhold 		// does. Don't know, if that is a bug, but at least it doesn't harm.
552672c1ea9SIngo Weinhold 		fTeam = team;
553672c1ea9SIngo Weinhold 	}
5543b044715SIngo Weinhold 	// init our members
5553b044715SIngo Weinhold 	if (error == B_OK) {
5563b044715SIngo Weinhold 		fTeam = team;
5573b044715SIngo Weinhold 		fPort = info.port;
55894b98dffSIngo Weinhold 		fHandlerToken = B_PREFERRED_TOKEN;
55952a38012Sejakowatz 	}
56052a38012Sejakowatz 
5614ceb1e51SAxel Dörfler 	// return the error
5624ceb1e51SAxel Dörfler 	if (_result)
5634ceb1e51SAxel Dörfler 		*_result = error;
5644ceb1e51SAxel Dörfler }
5654ceb1e51SAxel Dörfler 
5664ceb1e51SAxel Dörfler 
56752a38012Sejakowatz /*!	\brief Returns whether the first one of two BMessengers is less than the
56852a38012Sejakowatz 	second one.
56952a38012Sejakowatz 
57052a38012Sejakowatz 	This method defines an order on BMessengers based on their member
5718f1dc17dSIngo Weinhold 	variables \c fPort, \c fHandlerToken and \c fPreferredTarget.
5728f1dc17dSIngo Weinhold 
57352a38012Sejakowatz 	\param a The first messenger.
57452a38012Sejakowatz 	\param b The second messenger.
57552a38012Sejakowatz 	\return \c true, if \a a is less than \a b, \c false otherwise.
57652a38012Sejakowatz */
57752a38012Sejakowatz bool
5784afc60d3SIngo Weinhold operator<(const BMessenger &_a, const BMessenger &_b)
57952a38012Sejakowatz {
5804afc60d3SIngo Weinhold 	BMessenger::Private a(const_cast<BMessenger&>(_a));
5814afc60d3SIngo Weinhold 	BMessenger::Private b(const_cast<BMessenger&>(_b));
5824afc60d3SIngo Weinhold 
5838f1dc17dSIngo Weinhold 	// significance:
5848f1dc17dSIngo Weinhold 	// 1. fPort
5858f1dc17dSIngo Weinhold 	// 2. fHandlerToken
5868f1dc17dSIngo Weinhold 	// 3. fPreferredTarget
5878f1dc17dSIngo Weinhold 	// fTeam is insignificant
5884afc60d3SIngo Weinhold 	return (a.Port() < b.Port()
5896eb09230SMichael Lotz 			|| (a.Port() == b.Port()
5904afc60d3SIngo Weinhold 				&& (a.Token() < b.Token()
5916eb09230SMichael Lotz 					|| (a.Token() == b.Token()
5924afc60d3SIngo Weinhold 						&& !a.IsPreferredTarget()
5936eb09230SMichael Lotz 						&& b.IsPreferredTarget()))));
59452a38012Sejakowatz }
59552a38012Sejakowatz 
5964ceb1e51SAxel Dörfler 
59752a38012Sejakowatz /*!	\brief Returns whether two BMessengers have not the same target.
59852a38012Sejakowatz 
59952a38012Sejakowatz 	\param a The first messenger.
60052a38012Sejakowatz 	\param b The second messenger.
60152a38012Sejakowatz 	\return \c false, if \a a and \a b have the same targets or are both not
60252a38012Sejakowatz 			properly initialized, \c true otherwise.
60352a38012Sejakowatz */
60452a38012Sejakowatz bool
60552a38012Sejakowatz operator!=(const BMessenger &a, const BMessenger &b)
60652a38012Sejakowatz {
60752a38012Sejakowatz 	return !(a == b);
60852a38012Sejakowatz }
609