2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: mp_message.C /main/4 1998/04/09 17:52:22 mgreess $
30 * @(#)mp_message.C 1.52 93/09/07
32 * Tool Talk Message Passer (MP) - mp_message.cc
34 * Copyright (c) 1990,1992 by Sun Microsystems, Inc.
36 #include <util/tt_global_env.h>
37 // Strictly, mp_message should not include the client-only mp structure.
38 // But we have just one client-only call buried in the xdr method,
39 // and splitting that out would be too hard (having different xdr
40 // methods for the server and the client would be madness!)
41 #include <mp/mp_c_global.h>
42 #include <mp/mp_c_mp.h>
43 #include <mp/mp_arg.h>
44 #include <mp/mp_msg_context.h>
45 #include <mp/mp_message.h>
46 #include <mp/mp_pattern.h>
47 #include <mp/mp_procid.h>
48 #include <mp/mp_session.h>
49 #include <util/tt_enumname.h>
53 // Base constructor for a message. ::xdr() relies on this
54 // to reset everything because _Tt_s_mp keeps a global
55 // _Tt_message as a buffer for reading messages off the wire,
56 // instead of constructing a new one each time. XXX I refuse
57 // to believe that constructing a new one cannot be made cheap.
65 _paradigm = TT_ADDRESS_LAST;
66 _scope = TT_SCOPE_NONE;
67 _reliability = TT_DISCARD;
84 _args = new _Tt_arg_list;
86 _contexts = new _Tt_msg_context_list;
89 _gid = _tt_global->gid;
90 _uid = _tt_global->uid;
91 // Set the default set of fields to be sent by
92 // _Tt_message::xdr. Note that it is important for
93 // _TT_MSK_PARADIGM and _TT_MSK_STATE to be part of this set
94 // (see relevant comments in _Tt_message::xdr).
95 _full_msg_guards = (_TT_MSK_ID |
96 _TT_MSK_MESSAGE_CLASS |
104 _message_class = TT_CLASS_UNDEFINED;
111 // Default constructor.
114 // XXX: Make sure all _Tt_strings do *not* point to
115 // _tt_global->universal_null_string for messages,
116 // because otherwise svc_getargs will clobber the
121 : _pattern_id(NULL), _object(NULL), _file(NULL), _op(NULL),
122 _otype(NULL), _sender_ptype(NULL), _handler_ptype(NULL),
123 _api_id(NULL), _status_string(NULL)
131 // Destroys a message object.
136 // note _sender and _handler may be circular references
137 // so we explicitly set them to 0 to produce any garbage
139 _sender = (_Tt_procid *)0;
140 _handler = (_Tt_procid *)0;
141 _session = (_Tt_session *)0;
147 // Returns 1 if m is equal to this message. Message equality can be
148 // determined by logically concatenating the message sender with the
152 is_equal(const _Tt_message_ptr &m)
157 if (m->_sender.is_null() && _sender.is_null()) {
159 } else if (m->_sender.is_null() || _sender.is_null()) {
162 return(m->_sender->id() == _sender->id());
169 // XDR encodes/decodes a message.
171 // Because xdr'ing a message is crucial to the message-passing
172 // performance the way messages are xdr'ed is a little more complicated
173 // than other xdr methods.
175 // The main optimization that is done is to have an integer field,
176 // _ptr_guards, is a collection of bit fields. If a particular bit is
177 // turned on then this means that the corresponding message field is
178 // being sent/received from the xdr stream. These bit fields obey the
179 // following naming convention, if _ptr_guards&_TT_MSK_<field> is true
180 // then <field> is being sent/received from the xdr stream. Note that
181 // this means that this optimization can only apply to at most 32
184 // This scheme is an optimization if it allows us to send less
185 // information for a given message. The way it does this is by allowing
186 // "default" values to not be sent. For example, if a typical value of
187 // the _scope field is TT_SESSION then rather than send this value every
188 // time, we just leave the bit turned off and have the other end just use
189 // the default value if it notices the bit is turned off. Another way
190 // we can avoid sending the entire message is if it is known that
191 // certain fields won't be required. For example, when a handler
192 // replies to a message, it is unnecessary to send back the entire
193 // list of arguments since, by definition, only the TT_OUT and
194 // TT_INOUT arguments can change.
196 // There are certain methods that are called just before a message is
197 // going to be xdr'ed that set up the _ptr_guards field to turn on the
198 // proper set of flags. These methods are:
200 // _Tt_c_message::set_return_handler_flags
202 // Optimizes message xdr for the case of a handler replying to a
205 // _Tt_s_message::set_return_sender_flags
207 // Optimizes message xdr for the case of a message being returned
208 // to its original sender.
210 // _Tt_s_message::set_send_handler_flags
212 // Optimizes message xdr for the case of sending a message to a
215 // The way these methods work is by setting the _ptr_guards field to some
216 // value other than 0 that has the proper flag bits turned on. Then this
217 // method checks for _ptr_guards being 0. If it is then it just uses the
218 // value of _full_msg_guards which is an always up-to-date set of flags
219 // of message fields that need to get xdr'ed in the default case. If
220 // _ptr_guards is not 0 then that value gets used instead of the default.
221 // Another detail of this mechanism is that the _flags field may
222 // sometimes have the _TT_MSG_UPDATE_XDR_MODE flag turned on. If this is
223 // the case then this indicates that when encoding the message only the
224 // arguments contained in the _out_args list are to be used rather than
225 // the ones in the _args list. This is because the args in _out_args are
226 // only the TT_OUT and TT_INOUT arguments.
231 if (xdrs->x_op == XDR_DECODE) {
234 if (xdrs->x_op == XDR_ENCODE && _ptr_guards==0) {
235 _flags &= ~(1<<_TT_MSG_UPDATE_XDR_MODE);
236 _ptr_guards = _full_msg_guards;
240 if (! xdr_int(xdrs, &_ptr_guards)) {
244 int need_2_set_id = 0;
245 if (_ptr_guards&_TT_MSK_ID) {
246 if (xdrs->x_op == XDR_DECODE) {
248 if (! xdr_int(xdrs, &id_2_set)) {
252 if (! xdr_int(xdrs, &_id)) {
257 if (_ptr_guards&_TT_MSK_MESSAGE_CLASS) {
258 if (! xdr_int(xdrs, (int *)&_message_class)) {
262 if (_ptr_guards&_TT_MSK_STATE) {
263 if (! xdr_int(xdrs, (int *)&_state)) {
266 } else { // XXXX only if XDR_DECODE, right? et al!
269 if (_ptr_guards&_TT_MSK_PARADIGM) {
270 if (! xdr_int(xdrs, (int *)&_paradigm)) {
274 if (_ptr_guards&_TT_MSK_SCOPE) {
275 if (! xdr_int(xdrs, (int *)&_scope)) {
278 } else if (_tt_global->xdr_version() > 1) {
281 if (_ptr_guards&_TT_MSK_RELIABILITY) {
282 if (! xdr_int(xdrs, (int *)&_reliability)) {
286 if (_ptr_guards&_TT_MSK_OPNUM) {
287 if (! xdr_int(xdrs, &_opnum)) {
291 if (_ptr_guards&_TT_MSK_STATUS) {
292 if (! xdr_int(xdrs,&_status)) {
296 // Even though in Solaris 2.x uid_t and gid_t are typedef'd as
297 // u_long, the compiler complains if they are not explicitly
299 if (_ptr_guards&_TT_MSK_UID) {
300 if (xdrs->x_op == XDR_DECODE) {
304 if (! xdr_u_int(xdrs, &_uid)) {
308 if (! xdr_u_long(xdrs,(u_long *) &_uid)) {
313 if (_ptr_guards&_TT_MSK_GID) {
314 if (xdrs->x_op == XDR_DECODE) {
318 if (! xdr_u_int(xdrs, &_gid)) {
322 if (! xdr_u_long(xdrs,(u_long *) &_gid)) {
328 if (_ptr_guards&_TT_MSK_SESSION) {
329 if (xdrs->x_op == XDR_DECODE) {
330 _session = new _Tt_session();
332 if (! _session->xdr(xdrs)) {
335 } else if (xdrs->x_op == XDR_DECODE) {
336 _session = _tt_mp->initial_session;
339 if (_ptr_guards&_TT_MSK_SENDER) {
340 if (xdrs->x_op == XDR_DECODE) {
341 _sender = new _Tt_procid();
343 if (! _sender->xdr(xdrs)) {
346 } else if (! _tt_mp->in_server()) {
347 // Since we know we're not in the server, we know that
348 // _tt_c_mp is valid.
349 _sender = _tt_c_mp->default_procid();
351 // _set_id() only works if _handler is set
357 switch (_tt_global->xdr_version()) {
359 // version 1 tooltalk always xdr's a _Tt_procid_ptr
360 if (! _handler.xdr(xdrs)) {
366 if (xdrs->x_op == XDR_DECODE) {
368 // XXX holtz: Also do this for other fields?
369 // If not, *this is a hybrid message that
370 // is dangerous to look at until you use it
371 // to update_message().
375 if (_ptr_guards&_TT_MSK_HANDLER) {
376 if (xdrs->x_op == XDR_DECODE) {
377 _handler = new _Tt_procid();
379 if (! _handler->xdr(xdrs)) {
385 if (_ptr_guards&_TT_MSK_FILE) {
386 if (! _file->xdr(xdrs)) {
391 if (_ptr_guards&_TT_MSK_OBJECT) {
392 if (! _object->xdr(xdrs)) {
397 if (_ptr_guards&_TT_MSK_OP) {
398 if (! _op->xdr(xdrs)) {
403 if (_ptr_guards&_TT_MSK_ARGS) {
404 if (xdrs->x_op == XDR_ENCODE) {
405 if (_flags&(1<<_TT_MSG_UPDATE_XDR_MODE)) {
407 // if this flag is turned on then only
408 // send arguments from the _out_args
409 // field rather than the _args field.
411 if (_out_args.is_null()) {
412 _out_args = new _Tt_arg_list();
414 if (! _out_args->xdr(xdrs)) {
418 if (! _args->xdr(xdrs)) {
424 SET_GUARD(_full_msg_guards, 0, _TT_MSK_ARGS);
426 if (! _args->xdr(xdrs)) {
431 if (_ptr_guards&_TT_MSK_FLAGS) {
432 if (! xdr_int(xdrs, &_flags)) {
435 if (xdrs->x_op == XDR_DECODE) {
436 // Assume non-remote, until we learn otherwise
437 _flags &= ~(1<<_TT_MSG_IS_REMOTE);
440 if (_ptr_guards&_TT_MSK_OTYPE) {
441 if (! _otype->xdr(xdrs)) {
446 if (_ptr_guards&_TT_MSK_SENDER_PTYPE) {
447 if (! _sender_ptype->xdr(xdrs)) {
451 if (_ptr_guards&_TT_MSK_HANDLER_PTYPE) {
452 if (! _handler_ptype->xdr(xdrs)) {
456 if (_ptr_guards&_TT_MSK_PATTERN_ID) {
457 if (! _pattern_id->xdr(xdrs)) {
461 if (_ptr_guards&_TT_MSK_RSESSIONS) {
462 if (xdrs->x_op == XDR_DECODE) {
463 _rsessions = new _Tt_string_list();
465 if (! _rsessions->xdr(xdrs)) {
469 if (_ptr_guards&_TT_MSK_STATUS_STRING) {
470 if (! _status_string->xdr(xdrs)) {
475 // Because of the bitmask, we don't worry about
476 // xdr versioning here, and in effect pretend that
477 // _TT_MSK_CONTEXTS has been defined from day 1.
479 if (_ptr_guards&_TT_MSK_CONTEXTS) {
480 if (! _contexts->xdr(xdrs)) {
487 if (_ptr_guards&_TT_MSK_OFFEREES) {
489 // TT_OFFERS are more rare than contexts, so
490 // we allocate the lists lazily to save memory.
492 if (_abstainers.is_null()) {
493 _abstainers = new _Tt_procid_list;
495 if (! _abstainers->xdr(xdrs)) {
498 if (_accepters.is_null()) {
499 _accepters = new _Tt_procid_list;
501 if (! _accepters->xdr(xdrs)) {
504 if (_rejecters.is_null()) {
505 _rejecters = new _Tt_procid_list;
507 if (! _rejecters->xdr(xdrs)) {
512 if (xdrs->x_op == XDR_DECODE) {
513 // Now we want to update _full_msg_guards from
514 // _ptr_guards appropiately. We must choose to do this
515 // either by assignment or by or'ing the fields.
516 // Assignment is required if this is a new message
517 // because _full_msg_guards may contain fields that
518 // are 1 when they need to be 0 (see
519 // _Tt_message::_Tt_message). (and or'ing won't
520 // help). We can tell that the message coming in is a
521 // new message by checking whether the paradigm and
522 // state field is being sent. This is a gross hack but
523 // unfortunately when the need for it was discovered
524 // there was no other way to test for this in a
525 // binary-compatible way with previous versions. Note
526 // that the paradigm (known as "address" in the
527 // documentation) doesn't ever change once its been
528 // created so it should never be the case that sending
529 // the message to a recipient in other than the
530 // defualt xdr mode should require sending the
533 if (_ptr_guards&(_TT_MSK_PARADIGM|_TT_MSK_STATE)) {
534 _full_msg_guards = _ptr_guards;
536 _full_msg_guards |= _ptr_guards;
546 // m represents the same message as this but perhaps with updated
547 // information. This method handles updating this message with the
548 // appropiate values in m.
551 update_message(const _Tt_message_ptr &m)
554 int mguards = m->_full_msg_guards;
556 _full_msg_guards |= mguards;
557 if (!_tt_mp->in_server()) {
558 if (mguards&_TT_MSK_STATE) {
559 set_state(m->_state);
561 if (mguards&_TT_MSK_RELIABILITY) {
562 set_reliability(m->_reliability);
567 if (mguards&_TT_MSK_SCOPE) {
574 if (mguards&_TT_MSK_PATTERN_ID) {
575 if (m->_pattern_id.len()) {
576 _pattern_id = m->_pattern_id;
579 if (mguards&_TT_MSK_HANDLER) {
580 _handler = m->_handler;
582 if (mguards&_TT_MSK_HANDLER_PTYPE) {
583 _handler_ptype = m->_handler_ptype;
585 if (mguards&_TT_MSK_OPNUM) {
586 set_opnum(m->opnum());
589 if (mguards&_TT_MSK_STATUS) {
590 _status = m->_status;
592 if (mguards & _TT_MSK_STATUS_STRING) {
593 set_status_string(m->_status_string);
595 if (mguards & _TT_MSK_OFFEREES) {
597 // We could just snare references and share the lists,
598 // but if the given message is ttsession's static
599 // wire buffer, then the lists will probably be changing.
601 _abstainers = new _Tt_procid_list( *m->_abstainers );
602 _accepters = new _Tt_procid_list( *m->_accepters );
603 _rejecters = new _Tt_procid_list( *m->_rejecters );
609 // update object and file
612 if (mguards&_TT_MSK_OBJECT) {
613 _object = m->_object;
615 if (mguards&_TT_MSK_FILE) {
618 if (mguards&_TT_MSK_CONTEXTS) {
619 // All contexts are INOUT, and extra can
620 // be added by the handler.
621 _contexts = new _Tt_msg_context_list( *m->_contexts );
623 if (mguards&_TT_MSK_ARGS) {
624 margc = _args->count();
625 if (margc && m->_args->count()) {
628 // update arguments with new values
631 _Tt_arg_list_cursor argc;
632 _Tt_arg_list_cursor nargc;
635 nargc.reset(m->_args);
636 while (argc.next()) {
637 switch (argc->mode()) {
641 argc->update_value(*nargc);
646 if (!_tt_mp->in_server() &&
647 _message_class==TT_NOTICE &&
649 m->_full_msg_guards = 0;
660 if (is_awaiting_reply()) {
661 set_awaiting_reply( 0 );
665 m->_full_msg_guards = 0;
666 // XXX holtz 20 Jul 94 Why change given message?
670 _Tt_msg_context_ptr _Tt_message::
671 context(const char *slotname) const
673 _Tt_msg_context_list_cursor contextC( _contexts );
674 while (contextC.next()) {
675 if (contextC->slotName() == slotname) {
683 _Tt_msg_context_ptr _Tt_message::
686 if ((i >= 0) && (i < _contexts->count())) {
687 return (*_contexts)[ i ];
694 contextsCount() const
696 if (_contexts.is_null()) {
699 return _contexts->count();
704 // Returns the id of the pattern that matched this message (ie. that
705 // caused it to be delivered). This id will be null if the message
706 // matched a ptype pattern rather than a dynamic pattern.
708 _Tt_string & _Tt_message::
716 // Sets the pattern id of a messsage and turns on the corresponding bit
717 // field in _full_msg_guards if non-empty.
720 set_pattern_id(_Tt_string id)
723 SET_GUARD(_full_msg_guards, _pattern_id.len(), _TT_MSK_PATTERN_ID);
729 // Function wrapper used to invoke the xdr method on a message when
730 // interfacing to the C RPC routines.
733 tt_xdr_message(XDR *xdrs, _Tt_message_ptr *msgp)
735 return((*msgp).xdr(xdrs));
759 const _Tt_string & _Tt_message::
766 Tt_status _Tt_message::
767 set_message_class(Tt_class mclass)
769 _message_class = mclass;
774 Tt_status _Tt_message::
775 set_state(Tt_state state)
783 Tt_status _Tt_message::
784 set_paradigm(Tt_address p)
793 // Sets the scope of a message. Note that if we're a post-version-1
794 // client then we also turn on the corresponding flag in _full_msg_guards
795 // if this is a non-TT_SESSION scope.
797 Tt_status _Tt_message::
798 set_scope(Tt_scope s)
801 // XXX: The xdr_version() only shadows to the sessions xdr version when an
802 // RPC call is in progress. set_scope() can be called by
803 // tt_message_scope_set() at which time the xdr version is not setup
807 SET_GUARD(_full_msg_guards,1,_TT_MSK_SCOPE);
813 // Sets the file field of a message and turn on the corresponding bit in
814 // _full_msg_guards if non-empty.
816 Tt_status _Tt_message::
817 set_file(_Tt_string f)
823 SET_GUARD(_full_msg_guards, 1, _TT_MSK_FILE);
829 // Sets the session field in a message and turns on the corresponding bit
830 // field in _full_msg_guards if non-null.
832 Tt_status _Tt_message::
833 set_session(_Tt_session_ptr &s)
836 SET_GUARD(_full_msg_guards,(! _session.is_null()), _TT_MSK_SESSION);
843 // Sets the op field in a message and turns on the corresponding bit
844 // field in _full_msg_guards if non-null.
846 Tt_status _Tt_message::
850 SET_GUARD(_full_msg_guards, _op.len(), _TT_MSK_OP);
857 // Sets the opnum field in a message and turns on the corresponding
858 // bit field in _full_msg_guards if not equal to -1 (the default).
860 Tt_status _Tt_message::
864 SET_GUARD(_full_msg_guards, _opnum != -1, _TT_MSK_OPNUM);
871 // Adds an argument to a message. Turns on the bit field for _args in
872 // _full_msg_guards since we know the list is non-empty.
874 Tt_status _Tt_message::
875 add_arg(_Tt_arg_ptr &arg)
879 SET_GUARD(_full_msg_guards, 1, _TT_MSK_ARGS);
885 // Adds a TT_OUT or TT_INOUT argument to the _out_args list. This is used
886 // by _Tt_message::xdr when the _TT_MSG_UPDATE_XDR flag is turned on.
889 add_out_arg(_Tt_arg_ptr &arg)
891 if (_out_args.is_null()) {
892 _out_args = new _Tt_arg_list();
894 switch (arg->mode()) {
897 // a parallel list of just out arguments is kept since
898 // whenever it is known that the receiver of a message
899 // is only seeing an update of the message, only the
900 // out arguments need to be sent.
901 _out_args->append(arg);
902 SET_GUARD(_full_msg_guards, 1, _TT_MSK_ARGS);
912 // Adds a context to a message. Turns on the bit field for _contexts in
913 // _full_msg_guards since we know the list is non-empty.
915 Tt_status _Tt_message::
916 add_context(_Tt_msg_context_ptr &context)
918 _contexts->append_ordered(context);
920 SET_GUARD(_full_msg_guards, 1, _TT_MSK_CONTEXTS);
926 // Sets the object field in a message and turns on the corresponding bit
927 // field in _full_msg_guards.
929 Tt_status _Tt_message::
930 set_object(_Tt_string oid)
933 SET_GUARD(_full_msg_guards, _object.len(), _TT_MSK_OBJECT);
938 Tt_status _Tt_message::
939 set_otype(_Tt_string ot)
942 SET_GUARD(_full_msg_guards, _otype.len(), _TT_MSK_OTYPE);
948 Tt_status _Tt_message::
949 set_sender(_Tt_procid_ptr &s)
952 SET_GUARD(_full_msg_guards, (! _sender.is_null()), _TT_MSK_SENDER);
958 Tt_status _Tt_message::
959 unset_handler_procid(void)
961 _handler = (_Tt_procid *) 0;
962 SET_GUARD(_full_msg_guards, 0, _TT_MSK_HANDLER);
967 Tt_status _Tt_message::
968 set_handler_procid(const _Tt_procid_ptr &h)
971 SET_GUARD(_full_msg_guards, (! _handler.is_null()), _TT_MSK_HANDLER);
977 Tt_status _Tt_message::
978 add_voter(const _Tt_procid_ptr &voter, Tt_state vote)
980 if (voter.is_null() || (_message_class != TT_OFFER)) {
983 if (_abstainers.is_null()) {
984 _abstainers = new _Tt_procid_list;
986 if (_abstainers.is_null()) {
989 if (_accepters.is_null()) {
990 _accepters = new _Tt_procid_list;
992 if (_accepters.is_null()) {
995 if (_rejecters.is_null()) {
996 _rejecters = new _Tt_procid_list;
998 if (_rejecters.is_null()) {
1003 _accepters->append( voter );
1006 _rejecters->append( voter );
1009 _abstainers->append( voter );
1012 // Not a vote; bail out.
1015 SET_GUARD(_full_msg_guards, 1, _TT_MSK_OFFEREES);
1020 Tt_status _Tt_message::
1021 set_sender_ptype(_Tt_string s)
1024 SET_GUARD(_full_msg_guards,_sender_ptype.len(), _TT_MSK_SENDER_PTYPE);
1030 Tt_status _Tt_message::
1031 set_handler_ptype(_Tt_string h)
1034 SET_GUARD(_full_msg_guards,_handler_ptype.len(),_TT_MSK_HANDLER_PTYPE);
1040 Tt_status _Tt_message::
1041 set_reliability(Tt_disposition r)
1044 SET_GUARD(_full_msg_guards, _reliability != TT_DISCARD,
1045 _TT_MSK_RELIABILITY);
1052 // Sets the id of a message which is used to uniquely identify the
1053 // message within the sending process. The id is also used when queueing
1054 // the message. This implies that the message contains enough
1055 // information that is unique so that the queued message will never be
1056 // misinterpreted to be another message. This uniqueness is achieved by
1057 // combining the sender procid with the message id. This works because
1058 // the prefix of the sender procid is unique and the message id then
1059 // distinguishes the message among other messages the process has sent.
1061 Tt_status _Tt_message::
1064 return _set_id(_tt_mp->generate_message_id());
1067 Tt_status _Tt_message::
1072 sprintf( buf, "%d ", _id );
1074 if (sender().is_null()) {
1077 _api_id = _api_id.cat( sender()->id() );
1082 * Sets this to be a super message (send to parent type)
1087 _flags |= (1<<_TT_MSG_IS_SUPER);
1090 _Tt_string & _Tt_message::
1093 return(_status_string);
1097 Tt_status _Tt_message::
1098 set_status_string(_Tt_string st)
1100 _status_string = st;
1101 SET_GUARD(_full_msg_guards,_status_string.len(),_TT_MSK_STATUS_STRING);
1108 // This method will identify this message as a "start" message if flag is
1109 // 1. Otherwise it clears the flag associated with this. When turning the
1110 // flag on we set the status field to TT_WRN_START_MESSAGE because the
1111 // tooltalk client needs to check for this value to know that this is a
1112 // start message. When turning the flag off we have to set the status to
1113 // TT_OK but only if it is still TT_WRN_START_MESSAGE (otherwise we end
1114 // up stomping on a status code set by the client.).
1117 set_start_message(int flag)
1120 set_status((int)TT_WRN_START_MESSAGE);
1121 _flags |= (1<<_TT_MSG_IS_START_MSG);
1123 if (_status == (int)TT_WRN_START_MESSAGE) {
1124 SET_GUARD(_full_msg_guards,1,_TT_MSK_STATUS);
1127 _flags &= ~(1<<_TT_MSG_IS_START_MSG);
1133 // Returns 1 if this is a start message. Version 1 clients didn't
1134 // implement the _TT_MSG_IS_START_MSG flag so the only way to tell with
1135 // them is if the _status field is TT_WRN_START_MESSAGE.
1138 is_start_message() const
1140 return(_status == TT_WRN_START_MESSAGE ||
1141 (_flags&(1<<_TT_MSG_IS_START_MSG)));
1145 set_awaiting_reply(int flag)
1148 _flags |= (1<<_TT_MSG_AWAITING_REPLY);
1150 _flags &= ~(1<<_TT_MSG_AWAITING_REPLY);
1155 is_awaiting_reply() const
1157 return (_flags&(1<<_TT_MSG_AWAITING_REPLY));
1161 Tt_status _Tt_message::
1164 // _status is used in the special case of a start message
1165 if (st == (int)TT_OK && _status == TT_WRN_START_MESSAGE) {
1169 SET_GUARD(_full_msg_guards,1,_TT_MSK_STATUS);
1175 // Sets the _handler field of a message for the special case of an
1176 // observer replying to a start message. This special case is
1177 // distinguished by turning on the _TT_MSG_OBSERVER flag.
1180 set_observer_procid(const _Tt_procid_ptr &p)
1182 _flags |= (1<<_TT_MSG_OBSERVER);
1188 // Clears the _TT_MSG_OBSERVER flag and sets the _handler field back to
1192 clr_observer_procid()
1194 _flags &= ~(1<<_TT_MSG_OBSERVER);
1195 _handler = (_Tt_procid *)0;
1200 _tt_procid_list_print(const _Tt_ostream &os,
1201 const _Tt_procid_list_ptr &procs, const char *label)
1203 if ((! procs.is_null()) && (procs->count() > 0)) {
1204 os << label << ":\n";
1205 _Tt_string indent = os.indent();
1206 os.set_indent( indent.cat( "\t" ));
1207 _Tt_procid_list_cursor procC( procs );
1208 while (procC.next()) {
1211 os.set_indent( indent );
1217 // Prints out a message to os.
1220 print(const _Tt_ostream &os) const
1222 _Tt_arg_list_cursor arg_cursor;
1224 os << _tt_enumname(state()) << " ";
1225 os << _tt_enumname(_paradigm) << " ";
1226 os << _tt_enumname(_message_class) << " ";
1227 os << "(" << _tt_enumname(reliability()) << " in ";
1228 os << _tt_enumname(scope()) << "): ";
1229 os << (int)_status << " == " << (Tt_status)_status << "\n";
1231 os << "id:\t\t" << _api_id << "\n";
1232 os << "op:\t\t" << _op << "\n";
1233 if (_args->count() > 0) {
1235 _Tt_string indent = os.indent();
1236 os.set_indent( indent.cat( "\t" ));
1237 _Tt_arg_list_cursor argC( _args );
1238 while (argC.next()) {
1241 os.set_indent( indent );
1243 if (_contexts->count() > 0) {
1244 os << "contexts:\n";
1245 _Tt_string indent = os.indent();
1246 os.set_indent( indent.cat( "\t" ));
1247 _Tt_msg_context_list_cursor contextC( _contexts );
1248 while (contextC.next()) {
1249 contextC->print( os );
1251 os.set_indent( indent );
1253 if (_status_string.len() > 0) {
1254 os << "status_string:\t" << _status_string << "\n";
1256 if (! _session.is_null()) {
1257 os << "session:\t" << _session->address_string() << "\n";
1259 if (_file.len() > 0) {
1260 os << "file:\t\t" << _tt_network_path_to_local_path(_file)
1263 if (_object.len() > 0) {
1264 os << "object:\t\t" << _object << "\n";
1266 if (_otype.len() > 0) {
1267 os << "otype:\t\t" << _otype << "\n";
1269 if (! _sender.is_null()) {
1270 os << "sender:\t\t[" << _uid << "/" << _gid << "] ";
1271 _sender->print( os );
1273 if (_sender_ptype.len() > 0) {
1274 os << "sender_ptype:\t" << _sender_ptype << "\n";
1276 if (_pattern_id.len() > 0) {
1277 os << "pattern:\t" << _pattern_id << "\n";
1279 if (opnum() != -1) {
1280 os << "opnum:\t\t" << opnum() << "\n";
1282 if (! _handler.is_null()) {
1284 _handler->print( os );
1286 if (_handler_ptype.len() > 0) {
1287 os << "handler_ptype:\t" << _handler_ptype << "\n";
1289 _tt_procid_list_print( os, _accepters, "accepters" );
1290 _tt_procid_list_print( os, _rejecters, "rejecters" );
1291 _tt_procid_list_print( os, _abstainers, "abstainers" );