xref: /haiku/src/kits/app/Messenger.cpp (revision e1f41e5d5305e74fb9cc97d68f92a72513909883)
152a38012Sejakowatz  //------------------------------------------------------------------------------
252a38012Sejakowatz //	Copyright (c) 2001-2002, OpenBeOS
352a38012Sejakowatz //
452a38012Sejakowatz //	Permission is hereby granted, free of charge, to any person obtaining a
552a38012Sejakowatz //	copy of this software and associated documentation files (the "Software"),
652a38012Sejakowatz //	to deal in the Software without restriction, including without limitation
752a38012Sejakowatz //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
852a38012Sejakowatz //	and/or sell copies of the Software, and to permit persons to whom the
952a38012Sejakowatz //	Software is furnished to do so, subject to the following conditions:
1052a38012Sejakowatz //
1152a38012Sejakowatz //	The above copyright notice and this permission notice shall be included in
1252a38012Sejakowatz //	all copies or substantial portions of the Software.
1352a38012Sejakowatz //
1452a38012Sejakowatz //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1552a38012Sejakowatz //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1652a38012Sejakowatz //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1752a38012Sejakowatz //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1852a38012Sejakowatz //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1952a38012Sejakowatz //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2052a38012Sejakowatz //	DEALINGS IN THE SOFTWARE.
2152a38012Sejakowatz //
2252a38012Sejakowatz //	File Name:		Messenger.h
2352a38012Sejakowatz //	Author:			Ingo Weinhold (bonefish@users.sf.net)
2452a38012Sejakowatz //	Description:	BMessenger delivers messages to local or remote targets.
2552a38012Sejakowatz //------------------------------------------------------------------------------
2652a38012Sejakowatz 
2752a38012Sejakowatz // debugging
2852a38012Sejakowatz //#define DBG(x) x
2952a38012Sejakowatz #define DBG(x)
3052a38012Sejakowatz #define OUT	printf
3152a38012Sejakowatz 
3252a38012Sejakowatz // Standard Includes -----------------------------------------------------------
3352a38012Sejakowatz #include <new>
3452a38012Sejakowatz #include <stdio.h>
3552a38012Sejakowatz 
3652a38012Sejakowatz // System Includes -------------------------------------------------------------
3752a38012Sejakowatz #include <Application.h>
3852a38012Sejakowatz #include <Handler.h>
3952a38012Sejakowatz #include <Looper.h>
40*e1f41e5dSIngo Weinhold #include <LooperList.h>
4152a38012Sejakowatz #include <Message.h>
4252a38012Sejakowatz #include <Messenger.h>
4352a38012Sejakowatz #include <OS.h>
4452a38012Sejakowatz 
4552a38012Sejakowatz // Project Includes ------------------------------------------------------------
4652a38012Sejakowatz #include "TokenSpace.h"
4752a38012Sejakowatz 
4852a38012Sejakowatz // Local Includes --------------------------------------------------------------
4952a38012Sejakowatz 
5052a38012Sejakowatz // Local Defines ---------------------------------------------------------------
5152a38012Sejakowatz 
5252a38012Sejakowatz // Globals ---------------------------------------------------------------------
5352a38012Sejakowatz 
5452a38012Sejakowatz using BPrivate::gDefaultTokens;
5552a38012Sejakowatz 
5652a38012Sejakowatz enum {
5752a38012Sejakowatz 	NOT_IMPLEMENTED	= B_ERROR,
5852a38012Sejakowatz };
5952a38012Sejakowatz 
6052a38012Sejakowatz // _get_object_token_
6152a38012Sejakowatz /*!	Return the token of a BHandler.
6252a38012Sejakowatz 
6352a38012Sejakowatz 	\param handler The BHandler.
6452a38012Sejakowatz 	\return the token.
6552a38012Sejakowatz 
6652a38012Sejakowatz 	\todo Think about a better place for this function.
6752a38012Sejakowatz */
6852a38012Sejakowatz inline
6952a38012Sejakowatz int32
7052a38012Sejakowatz _get_object_token_(const BHandler* handler)
7152a38012Sejakowatz {
7252a38012Sejakowatz 	return handler->fToken;
7352a38012Sejakowatz }
7452a38012Sejakowatz 
7552a38012Sejakowatz // _set_message_target_
7652a38012Sejakowatz /*!	\brief Sets the target of a message.
7752a38012Sejakowatz 
7852a38012Sejakowatz 	\param message The message.
7952a38012Sejakowatz 	\param token The target handler token.
8052a38012Sejakowatz 	\param preferred Indicates whether to use the looper's preferred handler.
8152a38012Sejakowatz */
8252a38012Sejakowatz inline
8352a38012Sejakowatz void
8452a38012Sejakowatz _set_message_target_(BMessage *message, int32 token, bool preferred)
8552a38012Sejakowatz {
8652a38012Sejakowatz 	message->fTarget = token;
8752a38012Sejakowatz 	message->fPreferred = preferred;
8852a38012Sejakowatz }
8952a38012Sejakowatz 
9052a38012Sejakowatz // _set_message_reply_
9152a38012Sejakowatz /*!	\brief Sets a message's reply target.
9252a38012Sejakowatz 
9352a38012Sejakowatz 	\param message The message.
9452a38012Sejakowatz 	\param messenger The reply messenger.
9552a38012Sejakowatz */
9652a38012Sejakowatz inline
9752a38012Sejakowatz void
9852a38012Sejakowatz _set_message_reply_(BMessage *message, BMessenger messenger)
9952a38012Sejakowatz {
10052a38012Sejakowatz 	message->fReplyTo.port = messenger.fPort;
10152a38012Sejakowatz 	message->fReplyTo.target = messenger.fHandlerToken;
10252a38012Sejakowatz 	message->fReplyTo.team = messenger.fTeam;
10352a38012Sejakowatz 	message->fReplyTo.preferred = messenger.fPreferredTarget;
10452a38012Sejakowatz }
10552a38012Sejakowatz 
10652a38012Sejakowatz // constructor
10752a38012Sejakowatz /*!	\brief Creates an unitialized BMessenger.
10852a38012Sejakowatz */
10952a38012Sejakowatz BMessenger::BMessenger()
11052a38012Sejakowatz 		  : fPort(-1),
11152a38012Sejakowatz 			fHandlerToken(-1),
11252a38012Sejakowatz 			fTeam(-1),
11352a38012Sejakowatz 			fPreferredTarget(false)
11452a38012Sejakowatz {
11552a38012Sejakowatz }
11652a38012Sejakowatz 
11752a38012Sejakowatz // constructor
11852a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the already
11952a38012Sejakowatz 	running application identified by its signature and/or team ID.
12052a38012Sejakowatz 
12152a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
12252a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
12352a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
12452a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
12552a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
12652a38012Sejakowatz 
12752a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
12852a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
12952a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
13052a38012Sejakowatz 		   the result of the initialization is written.
13152a38012Sejakowatz */
13252a38012Sejakowatz BMessenger::BMessenger(const char *signature, team_id team, status_t *result)
13352a38012Sejakowatz 		  : fPort(-1),
13452a38012Sejakowatz 			fHandlerToken(-1),
13552a38012Sejakowatz 			fTeam(-1),
13652a38012Sejakowatz 			fPreferredTarget(false)
13752a38012Sejakowatz {
13852a38012Sejakowatz 	InitData(signature, team, result);
13952a38012Sejakowatz }
14052a38012Sejakowatz 
14152a38012Sejakowatz // constructor
14252a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to target the local
14352a38012Sejakowatz 	BHandler and/or BLooper.
14452a38012Sejakowatz 
14552a38012Sejakowatz 	When a \c NULL handler is supplied, the preferred handler in the given
14652a38012Sejakowatz 	looper is targeted. If no looper is supplied the looper the given handler
14752a38012Sejakowatz 	belongs to is used -- that means in particular, that the handler must
14852a38012Sejakowatz 	already belong to a looper. If both are supplied the handler must actually
14952a38012Sejakowatz 	belong to looper.
15052a38012Sejakowatz 
15152a38012Sejakowatz 	\param handler The target handler. May be \c NULL.
15252a38012Sejakowatz 	\param looper The target looper. May be \c NULL.
15352a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
15452a38012Sejakowatz 		   the result of the initialization is written.
15552a38012Sejakowatz */
15652a38012Sejakowatz BMessenger::BMessenger(const BHandler *handler, const BLooper *looper,
15752a38012Sejakowatz 					   status_t *result)
15852a38012Sejakowatz 		  : fPort(-1),
15952a38012Sejakowatz 			fHandlerToken(-1),
16052a38012Sejakowatz 			fTeam(-1),
16152a38012Sejakowatz 			fPreferredTarget(false)
16252a38012Sejakowatz {
16352a38012Sejakowatz 	status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
16452a38012Sejakowatz 	if (error == B_OK) {
16552a38012Sejakowatz 		if (handler) {
16652a38012Sejakowatz 			// BHandler is given, check/retrieve the looper.
16752a38012Sejakowatz 			if (looper) {
16852a38012Sejakowatz 				if (handler->Looper() != looper)
16952a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
17052a38012Sejakowatz 			} else {
17152a38012Sejakowatz 				looper = handler->Looper();
17252a38012Sejakowatz 				if (looper == NULL)
17352a38012Sejakowatz 					error = B_MISMATCHED_VALUES;
17452a38012Sejakowatz 			}
17552a38012Sejakowatz 			// set port, token,...
17652a38012Sejakowatz 			if (error == B_OK) {
17752a38012Sejakowatz 				fPort = looper->fMsgPort;
17852a38012Sejakowatz 				fHandlerToken = _get_object_token_(handler);
17952a38012Sejakowatz 				fPreferredTarget = false;
18052a38012Sejakowatz 			}
18152a38012Sejakowatz 		} else {	// handler == NULL (=> looper != NULL)
18252a38012Sejakowatz 			fPort = looper->fMsgPort;
18352a38012Sejakowatz 			fHandlerToken = false;
18452a38012Sejakowatz 			fPreferredTarget = true;
18552a38012Sejakowatz 		}
18652a38012Sejakowatz 		// get and set the team ID
18752a38012Sejakowatz 		if (error == B_OK) {
18852a38012Sejakowatz 			thread_info info;
18952a38012Sejakowatz 			error = get_thread_info(find_thread(NULL), &info);
19052a38012Sejakowatz 			if (error == B_OK)
19152a38012Sejakowatz 				fTeam = info.team;
19252a38012Sejakowatz 		}
19352a38012Sejakowatz 	}
19452a38012Sejakowatz 	if (result)
19552a38012Sejakowatz 		*result = error;
19652a38012Sejakowatz }
19752a38012Sejakowatz 
19852a38012Sejakowatz // copy constructor
19952a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to have the same target
20052a38012Sejakowatz 	as the supplied messemger.
20152a38012Sejakowatz 
20252a38012Sejakowatz 	\param from The messenger to be copied.
20352a38012Sejakowatz */
20452a38012Sejakowatz BMessenger::BMessenger(const BMessenger &from)
20552a38012Sejakowatz 		  : fPort(from.fPort),
20652a38012Sejakowatz 			fHandlerToken(from.fHandlerToken),
20752a38012Sejakowatz 			fTeam(from.fTeam),
20852a38012Sejakowatz 			fPreferredTarget(from.fPreferredTarget)
20952a38012Sejakowatz {
21052a38012Sejakowatz }
21152a38012Sejakowatz 
21252a38012Sejakowatz // destructor
21352a38012Sejakowatz /*!	\brief Frees all resources associated with this object.
21452a38012Sejakowatz */
21552a38012Sejakowatz BMessenger::~BMessenger()
21652a38012Sejakowatz {
21752a38012Sejakowatz }
21852a38012Sejakowatz 
21952a38012Sejakowatz 
22052a38012Sejakowatz // Target
22152a38012Sejakowatz 
22252a38012Sejakowatz // IsTargetLocal
22352a38012Sejakowatz /*!	\brief Returns whether or not the messenger's target lives within the team
22452a38012Sejakowatz 	of the caller.
22552a38012Sejakowatz 
22652a38012Sejakowatz 	\return \c true, if the object is properly initialized and its target
22752a38012Sejakowatz 			lives within the caller's team, \c false otherwise.
22852a38012Sejakowatz */
22952a38012Sejakowatz bool
23052a38012Sejakowatz BMessenger::IsTargetLocal() const
23152a38012Sejakowatz {
23252a38012Sejakowatz 	thread_info info;
23352a38012Sejakowatz 	return (get_thread_info(find_thread(NULL), &info) == B_OK
23452a38012Sejakowatz 			&& fTeam == info.team);
23552a38012Sejakowatz }
23652a38012Sejakowatz 
23752a38012Sejakowatz // Target
23852a38012Sejakowatz /*!	\brief Returns the handler and looper targeted by the messenger, if the
23952a38012Sejakowatz 	target is local.
24052a38012Sejakowatz 
24152a38012Sejakowatz 	The handler is returned directly, the looper by reference. If both are
24252a38012Sejakowatz 	\c NULL, the object is either not properly initialized, the target
24352a38012Sejakowatz 	objects have been deleted or the target is remote. If only the returned
24452a38012Sejakowatz 	handler is \c NULL, either the looper's preferred handler is targeted or
24552a38012Sejakowatz 	the handler has been deleted.
24652a38012Sejakowatz 
24752a38012Sejakowatz 	\param looper A pointer to a pre-allocated BLooper pointer into which
24852a38012Sejakowatz 		   the pointer to the targeted looper is written.
24952a38012Sejakowatz 	\return The BHandler targeted by the messenger.
25052a38012Sejakowatz */
25152a38012Sejakowatz BHandler *
25252a38012Sejakowatz BMessenger::Target(BLooper **looper) const
25352a38012Sejakowatz {
25452a38012Sejakowatz 	BHandler *handler = NULL;
25552a38012Sejakowatz 	if (IsTargetLocal()) {
25652a38012Sejakowatz 		if (!fPreferredTarget) {
25752a38012Sejakowatz 			gDefaultTokens.GetToken(fHandlerToken, B_HANDLER_TOKEN,
25852a38012Sejakowatz 									(void**)&handler);
25952a38012Sejakowatz 		}
260*e1f41e5dSIngo Weinhold 		if (looper)
261*e1f41e5dSIngo Weinhold 			*looper = BPrivate::gLooperList.LooperForPort(fPort);
26252a38012Sejakowatz 	} else if (looper)
26352a38012Sejakowatz 		*looper = NULL;
26452a38012Sejakowatz 	return handler;
26552a38012Sejakowatz }
26652a38012Sejakowatz 
26752a38012Sejakowatz // LockTarget
26852a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
26952a38012Sejakowatz 
27052a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
27152a38012Sejakowatz 	Target() and calling BLooper::Lock() on the looper afterwards.
27252a38012Sejakowatz 
27352a38012Sejakowatz 	\see BLooper::Lock() for details.
27452a38012Sejakowatz 
27552a38012Sejakowatz 	\return \c true, if the looper could be locked sucessfully, \c false, if
27652a38012Sejakowatz 			the messenger is not properly initialized, the target is remote,
27752a38012Sejakowatz 			or the targeted looper is invalid.
27852a38012Sejakowatz */
27952a38012Sejakowatz bool
28052a38012Sejakowatz BMessenger::LockTarget() const
28152a38012Sejakowatz {
28252a38012Sejakowatz 	BLooper *looper = NULL;
28352a38012Sejakowatz 	Target(&looper);
28452a38012Sejakowatz 	return (looper && looper->Lock());
28552a38012Sejakowatz }
28652a38012Sejakowatz 
28752a38012Sejakowatz // LockTargetWithTimeout
28852a38012Sejakowatz /*!	\brief Locks the BLooper targeted by the messenger, if the target is local.
28952a38012Sejakowatz 
29052a38012Sejakowatz 	This method is a shorthand for retrieving the targeted looper via
29152a38012Sejakowatz 	Target() and calling BLooper::LockWithTimeout() on the looper afterwards.
29252a38012Sejakowatz 
29352a38012Sejakowatz 	\see BLooper::LockWithTimeout() for details.
29452a38012Sejakowatz 
29552a38012Sejakowatz 	\return
29652a38012Sejakowatz 	- \c B_OK, if the looper could be locked sucessfully,
29752a38012Sejakowatz 	- \c B_BAD_VALUE, if the messenger is not properly initialized,
29852a38012Sejakowatz 	  the target is remote, or the targeted looper is invalid,
29952a38012Sejakowatz 	- other error codes returned by BLooper::LockWithTimeout().
30052a38012Sejakowatz */
30152a38012Sejakowatz status_t
30252a38012Sejakowatz BMessenger::LockTargetWithTimeout(bigtime_t timeout) const
30352a38012Sejakowatz {
30452a38012Sejakowatz 	BLooper *looper = NULL;
30552a38012Sejakowatz 	Target(&looper);
30652a38012Sejakowatz 	status_t error = (looper ? B_OK : B_BAD_VALUE);
30752a38012Sejakowatz 	if (error == B_OK)
30852a38012Sejakowatz 		error = looper->LockWithTimeout(timeout);
30952a38012Sejakowatz 	return error;
31052a38012Sejakowatz }
31152a38012Sejakowatz 
31252a38012Sejakowatz 
31352a38012Sejakowatz // Message sending
31452a38012Sejakowatz 
31552a38012Sejakowatz // SendMessage
31652a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
31752a38012Sejakowatz 
31852a38012Sejakowatz 	The method does not wait for a reply. It is sent asynchronously.
31952a38012Sejakowatz 
32052a38012Sejakowatz 	\param command The what field of the message to deliver.
32152a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
32252a38012Sejakowatz 		   May be \c NULL.
32352a38012Sejakowatz 	\return
32452a38012Sejakowatz 	- \c B_OK: Everything went fine.
32552a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
32652a38012Sejakowatz 	  target doesn't exist anymore.
32752a38012Sejakowatz */
32852a38012Sejakowatz status_t
32952a38012Sejakowatz BMessenger::SendMessage(uint32 command, BHandler *replyTo) const
33052a38012Sejakowatz {
33152a38012Sejakowatz 	BMessage message(command);
33252a38012Sejakowatz 	return SendMessage(&message, replyTo);
33352a38012Sejakowatz }
33452a38012Sejakowatz 
33552a38012Sejakowatz // SendMessage
33652a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
33752a38012Sejakowatz 
33852a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
33952a38012Sejakowatz 	of \a message.
34052a38012Sejakowatz 
34152a38012Sejakowatz 	The method does not wait for a reply. It is sent asynchronously.
34252a38012Sejakowatz 
34352a38012Sejakowatz 	\param message The message to be sent.
34452a38012Sejakowatz 	\param replyTo The handler to which a reply to the message shall be sent.
34552a38012Sejakowatz 		   May be \c NULL.
34652a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
34752a38012Sejakowatz 	\return
34852a38012Sejakowatz 	- \c B_OK: Everything went fine.
34952a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
35052a38012Sejakowatz 	  target doesn't exist anymore.
35152a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
35252a38012Sejakowatz 	  port was full when trying to deliver the message.
35352a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
35452a38012Sejakowatz 	  message.
35552a38012Sejakowatz */
35652a38012Sejakowatz status_t
35752a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BHandler *replyTo,
35852a38012Sejakowatz 						bigtime_t timeout) const
35952a38012Sejakowatz {
36052a38012Sejakowatz DBG(OUT("BMessenger::SendMessage2(%.4s)\n", (char*)&message->what));
36152a38012Sejakowatz 	// TODO: Verify the reply behavior.
36252a38012Sejakowatz 	status_t error = (message ? B_OK : B_BAD_VALUE);
36352a38012Sejakowatz 	if (error == B_OK) {
36452a38012Sejakowatz 		BMessenger replyMessenger(replyTo);
36552a38012Sejakowatz 		bool wantsReply = replyTo;
36652a38012Sejakowatz 		error = message->_send_(fPort, fHandlerToken, fPreferredTarget,
36752a38012Sejakowatz 								timeout, wantsReply, replyMessenger);
36852a38012Sejakowatz 	}
36952a38012Sejakowatz DBG(OUT("BMessenger::SendMessage2() done: %lx\n", error));
37052a38012Sejakowatz 	return error;
37152a38012Sejakowatz }
37252a38012Sejakowatz 
37352a38012Sejakowatz // SendMessage
37452a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target.
37552a38012Sejakowatz 
37652a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
37752a38012Sejakowatz 	of \a message.
37852a38012Sejakowatz 
37952a38012Sejakowatz 	The method does not wait for a reply. It is sent asynchronously.
38052a38012Sejakowatz 
38152a38012Sejakowatz 	\param message The message to be sent.
38252a38012Sejakowatz 	\param replyTo A messenger specifying the target for a reply to \a message.
38352a38012Sejakowatz 	\param timeout A timeout for the delivery of the message.
38452a38012Sejakowatz 	\return
38552a38012Sejakowatz 	- \c B_OK: Everything went fine.
38652a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
38752a38012Sejakowatz 	  target doesn't exist anymore.
38852a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
38952a38012Sejakowatz 	  port was full when trying to deliver the message.
39052a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
39152a38012Sejakowatz 	  message.
39252a38012Sejakowatz */
39352a38012Sejakowatz status_t
39452a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessenger replyTo,
39552a38012Sejakowatz 						bigtime_t timeout) const
39652a38012Sejakowatz {
39752a38012Sejakowatz 	// TODO: Verify the reply behavior.
39852a38012Sejakowatz 	status_t error = (message ? B_OK : B_BAD_VALUE);
39952a38012Sejakowatz 	if (error == B_OK) {
40052a38012Sejakowatz 		error = message->_send_(fPort, fHandlerToken, fPreferredTarget,
40152a38012Sejakowatz 								timeout, true, replyTo);
40252a38012Sejakowatz 	}
40352a38012Sejakowatz 	return error;
40452a38012Sejakowatz }
40552a38012Sejakowatz 
40652a38012Sejakowatz // SendMessage
40752a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
40852a38012Sejakowatz 	waits for a reply.
40952a38012Sejakowatz 
41052a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
41152a38012Sejakowatz 	\a reply. If the target doesn't send a reply, the \c what field of
41252a38012Sejakowatz 	\a reply is set to \c B_NO_REPLY.
41352a38012Sejakowatz 
41452a38012Sejakowatz 	\param command The what field of the message to deliver.
41552a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
41652a38012Sejakowatz 		   message will be copied.
41752a38012Sejakowatz 	\return
41852a38012Sejakowatz 	- \c B_OK: Everything went fine.
41952a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
42052a38012Sejakowatz 	  target doesn't exist anymore.
42152a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
42252a38012Sejakowatz */
42352a38012Sejakowatz status_t
42452a38012Sejakowatz BMessenger::SendMessage(uint32 command, BMessage *reply) const
42552a38012Sejakowatz {
42652a38012Sejakowatz 	BMessage message(command);
42752a38012Sejakowatz 	return SendMessage(&message, reply);
42852a38012Sejakowatz }
42952a38012Sejakowatz 
43052a38012Sejakowatz // SendMessage
43152a38012Sejakowatz /*! \brief Delivers a BMessage synchronously to the messenger's target and
43252a38012Sejakowatz 	waits for a reply.
43352a38012Sejakowatz 
43452a38012Sejakowatz 	A copy of the supplied message is sent and the caller retains ownership
43552a38012Sejakowatz 	of \a message.
43652a38012Sejakowatz 
43752a38012Sejakowatz 	The method does wait for a reply. The reply message is copied into
43852a38012Sejakowatz 	\a reply. If the target doesn't send a reply or if a reply timeout occurs,
43952a38012Sejakowatz 	the \c what field of \a reply is set to \c B_NO_REPLY.
44052a38012Sejakowatz 
44152a38012Sejakowatz 	\param message The message to be sent.
44252a38012Sejakowatz 	\param reply A pointer to a pre-allocated BMessage into which the reply
44352a38012Sejakowatz 		   message will be copied.
44452a38012Sejakowatz 	\param deliveryTimeout A timeout for the delivery of the message.
44552a38012Sejakowatz 	\param replyTimeout A timeout for waiting for the reply.
44652a38012Sejakowatz 	\return
44752a38012Sejakowatz 	- \c B_OK: Everything went fine.
44852a38012Sejakowatz 	- \c B_BAD_PORT_ID: The messenger is not properly initialized or its
44952a38012Sejakowatz 	  target doesn't exist anymore.
45052a38012Sejakowatz 	- \c B_WOULD_BLOCK: A delivery timeout of 0 was supplied and the target
45152a38012Sejakowatz 	  port was full when trying to deliver the message.
45252a38012Sejakowatz 	- \c B_TIMED_OUT: The timeout expired while trying to deliver the
45352a38012Sejakowatz 	  message.
45452a38012Sejakowatz 	- \c B_NO_MORE_PORTS: All reply ports are in use.
45552a38012Sejakowatz */
45652a38012Sejakowatz status_t
45752a38012Sejakowatz BMessenger::SendMessage(BMessage *message, BMessage *reply,
45852a38012Sejakowatz 						bigtime_t deliveryTimeout, bigtime_t replyTimeout) const
45952a38012Sejakowatz {
46052a38012Sejakowatz 	status_t error = (message ? B_OK : B_BAD_VALUE);
46152a38012Sejakowatz 	if (error) {
46252a38012Sejakowatz 		error = message->send_message(fPort, fTeam, fHandlerToken,
46352a38012Sejakowatz 									  fPreferredTarget, reply, deliveryTimeout,
46452a38012Sejakowatz 									  replyTimeout);
46552a38012Sejakowatz 	}
46652a38012Sejakowatz 	return error;
46752a38012Sejakowatz }
46852a38012Sejakowatz 
46952a38012Sejakowatz 
47052a38012Sejakowatz // Operators and misc
47152a38012Sejakowatz 
47252a38012Sejakowatz // =
47352a38012Sejakowatz /*!	\brief Makes this BMessenger a copy of the supplied one.
47452a38012Sejakowatz 
47552a38012Sejakowatz 	\param from the messenger to be copied.
47652a38012Sejakowatz 	\return A reference to this object.
47752a38012Sejakowatz */
47852a38012Sejakowatz BMessenger &
47952a38012Sejakowatz BMessenger::operator=(const BMessenger &from)
48052a38012Sejakowatz {
48152a38012Sejakowatz 	if (this != &from) {
48252a38012Sejakowatz 		fPort = from.fPort;
48352a38012Sejakowatz 		fHandlerToken = from.fHandlerToken;
48452a38012Sejakowatz 		fTeam = from.fTeam;
48552a38012Sejakowatz 		fPreferredTarget = from.fPreferredTarget;
48652a38012Sejakowatz 	}
48752a38012Sejakowatz }
48852a38012Sejakowatz 
48952a38012Sejakowatz // ==
49052a38012Sejakowatz /*!	\brief Returns whether this and the supplied messenger have the same
49152a38012Sejakowatz 	target.
49252a38012Sejakowatz 
49352a38012Sejakowatz 	\param other The other messenger.
49452a38012Sejakowatz 	\return \c true, if the messengers have the same target or if both aren't
49552a38012Sejakowatz 			properly initialzed, \c false otherwise.
49652a38012Sejakowatz */
49752a38012Sejakowatz bool
49852a38012Sejakowatz BMessenger::operator==(const BMessenger &other) const
49952a38012Sejakowatz {
50052a38012Sejakowatz 	return (fPort == other.fPort
50152a38012Sejakowatz 			&& fHandlerToken == other.fHandlerToken
50252a38012Sejakowatz 			&& fTeam == other.fTeam
50352a38012Sejakowatz 			&& fPreferredTarget == other.fPreferredTarget);
50452a38012Sejakowatz }
50552a38012Sejakowatz 
50652a38012Sejakowatz // IsValid
50752a38012Sejakowatz /*!	\brief Returns whether the messenger's target looper does still exist.
50852a38012Sejakowatz 
50952a38012Sejakowatz 	It is not checked whether the target handler is also still existing.
51052a38012Sejakowatz 
51152a38012Sejakowatz 	\return \c true, if the messenger's target looper does still exist,
51252a38012Sejakowatz 			\c false otherwise.
51352a38012Sejakowatz */
51452a38012Sejakowatz bool
51552a38012Sejakowatz BMessenger::IsValid() const
51652a38012Sejakowatz {
51752a38012Sejakowatz 	port_info info;
51852a38012Sejakowatz 	return (fPort >= 0 && get_port_info(fPort, &info) == B_OK);
51952a38012Sejakowatz }
52052a38012Sejakowatz 
52152a38012Sejakowatz // Team
52252a38012Sejakowatz /*!	\brief Returns the ID of the team the messenger's target lives in.
52352a38012Sejakowatz 
52452a38012Sejakowatz 	\return The team of the messenger's target.
52552a38012Sejakowatz */
52652a38012Sejakowatz team_id
52752a38012Sejakowatz BMessenger::Team() const
52852a38012Sejakowatz {
52952a38012Sejakowatz 	return fTeam;
53052a38012Sejakowatz }
53152a38012Sejakowatz 
53252a38012Sejakowatz 
53352a38012Sejakowatz //----- Private or reserved -----------------------------------------
53452a38012Sejakowatz 
53552a38012Sejakowatz // constructor
53652a38012Sejakowatz /*!	\brief Creates a BMessenger and initializes it to team, target looper port
53752a38012Sejakowatz 	and handler token.
53852a38012Sejakowatz 
53952a38012Sejakowatz 	If \a preferred is \c true, \a token is ignored.
54052a38012Sejakowatz 
54152a38012Sejakowatz 	\param team The target's team.
54252a38012Sejakowatz 	\param port The target looper port.
54352a38012Sejakowatz 	\param token The target handler token.
54452a38012Sejakowatz 	\param preferred \c true to rather use the looper's preferred handler
54552a38012Sejakowatz 		   instead of the one specified by \a token.
54652a38012Sejakowatz */
54752a38012Sejakowatz BMessenger::BMessenger(team_id team, port_id port, int32 token, bool preferred)
54852a38012Sejakowatz 		  : fPort(-1),
54952a38012Sejakowatz 			fHandlerToken(-1),
55052a38012Sejakowatz 			fTeam(-1),
55152a38012Sejakowatz 			fPreferredTarget(false)
55252a38012Sejakowatz {
55352a38012Sejakowatz 	fTeam = team;
55452a38012Sejakowatz 	fPort = port;
55552a38012Sejakowatz 	fHandlerToken = token;
55652a38012Sejakowatz 	fPreferredTarget = preferred;
55752a38012Sejakowatz }
55852a38012Sejakowatz 
55952a38012Sejakowatz // InitData
56052a38012Sejakowatz /*!	\brief Initializes the BMessenger object's data given the signature and/or
56152a38012Sejakowatz 	team ID of a target.
56252a38012Sejakowatz 
56352a38012Sejakowatz 	When only a signature is given, and multiple instances of the application
56452a38012Sejakowatz 	are running it is undeterminate which one is chosen as the target. In case
56552a38012Sejakowatz 	only a team ID is passed, the target application is identified uniquely.
56652a38012Sejakowatz 	If both are supplied, the application identified by the team ID must have
56752a38012Sejakowatz 	a matching signature, otherwise the initilization fails.
56852a38012Sejakowatz 
56952a38012Sejakowatz 	\param signature The target application's signature. May be \c NULL.
57052a38012Sejakowatz 	\param team The target application's team ID. May be < 0.
57152a38012Sejakowatz 	\param result An optional pointer to a pre-allocated status_t into which
57252a38012Sejakowatz 		   the result of the initialization is written.
57352a38012Sejakowatz 
57452a38012Sejakowatz 	\todo Implement!
57552a38012Sejakowatz */
57652a38012Sejakowatz void
57752a38012Sejakowatz BMessenger::InitData(const char *signature, team_id team, status_t *result)
57852a38012Sejakowatz {
57952a38012Sejakowatz 	if (result)
58052a38012Sejakowatz 		*result = NOT_IMPLEMENTED;
58152a38012Sejakowatz }
58252a38012Sejakowatz 
58352a38012Sejakowatz // <
58452a38012Sejakowatz /*!	\brief Returns whether the first one of two BMessengers is less than the
58552a38012Sejakowatz 	second one.
58652a38012Sejakowatz 
58752a38012Sejakowatz 	This method defines an order on BMessengers based on their member
58852a38012Sejakowatz 	variables \c fPort, \c fHandlerToken, \c fTeam and \c fPreferredTarget.
58952a38012Sejakowatz s
59052a38012Sejakowatz 	\param a The first messenger.
59152a38012Sejakowatz 	\param b The second messenger.
59252a38012Sejakowatz 	\return \c true, if \a a is less than \a b, \c false otherwise.
59352a38012Sejakowatz */
59452a38012Sejakowatz bool
59552a38012Sejakowatz operator<(const BMessenger &a, const BMessenger &b)
59652a38012Sejakowatz {
59752a38012Sejakowatz 	return (a.fPort < b.fPort
59852a38012Sejakowatz 			|| (a.fPort == b.fPort
59952a38012Sejakowatz 				&& a.fHandlerToken < b.fHandlerToken
60052a38012Sejakowatz 				|| (a.fHandlerToken == b.fHandlerToken
60152a38012Sejakowatz 					&& a.fTeam < b.fTeam
60252a38012Sejakowatz 					|| (a.fTeam == b.fTeam
60352a38012Sejakowatz 						&& a.fPreferredTarget == false
60452a38012Sejakowatz 						&& b.fPreferredTarget == true))));
60552a38012Sejakowatz }
60652a38012Sejakowatz 
60752a38012Sejakowatz // !=
60852a38012Sejakowatz /*!	\brief Returns whether two BMessengers have not the same target.
60952a38012Sejakowatz 
61052a38012Sejakowatz 	\param a The first messenger.
61152a38012Sejakowatz 	\param b The second messenger.
61252a38012Sejakowatz 	\return \c false, if \a a and \a b have the same targets or are both not
61352a38012Sejakowatz 			properly initialized, \c true otherwise.
61452a38012Sejakowatz */
61552a38012Sejakowatz bool
61652a38012Sejakowatz operator!=(const BMessenger &a, const BMessenger &b)
61752a38012Sejakowatz {
61852a38012Sejakowatz 	return !(a == b);
61952a38012Sejakowatz }
62052a38012Sejakowatz 
621