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
122 : _pattern_id(), _object(), _file(), _op(),
123 _otype(), _sender_ptype(), _handler_ptype(),
124 _api_id(), _status_string()
126 : _pattern_id(NULL), _object(NULL), _file(NULL), _op(NULL),
127 _otype(NULL), _sender_ptype(NULL), _handler_ptype(NULL),
128 _api_id(NULL), _status_string(NULL)
137 // Destroys a message object.
142 // note _sender and _handler may be circular references
143 // so we explicitly set them to 0 to produce any garbage
145 _sender = (_Tt_procid *)0;
146 _handler = (_Tt_procid *)0;
147 _session = (_Tt_session *)0;
153 // Returns 1 if m is equal to this message. Message equality can be
154 // determined by logically concatenating the message sender with the
158 is_equal(const _Tt_message_ptr &m)
163 if (m->_sender.is_null() && _sender.is_null()) {
165 } else if (m->_sender.is_null() || _sender.is_null()) {
168 return(m->_sender->id() == _sender->id());
175 // XDR encodes/decodes a message.
177 // Because xdr'ing a message is crucial to the message-passing
178 // performance the way messages are xdr'ed is a little more complicated
179 // than other xdr methods.
181 // The main optimization that is done is to have an integer field,
182 // _ptr_guards, is a collection of bit fields. If a particular bit is
183 // turned on then this means that the corresponding message field is
184 // being sent/received from the xdr stream. These bit fields obey the
185 // following naming convention, if _ptr_guards&_TT_MSK_<field> is true
186 // then <field> is being sent/received from the xdr stream. Note that
187 // this means that this optimization can only apply to at most 32
190 // This scheme is an optimization if it allows us to send less
191 // information for a given message. The way it does this is by allowing
192 // "default" values to not be sent. For example, if a typical value of
193 // the _scope field is TT_SESSION then rather than send this value every
194 // time, we just leave the bit turned off and have the other end just use
195 // the default value if it notices the bit is turned off. Another way
196 // we can avoid sending the entire message is if it is known that
197 // certain fields won't be required. For example, when a handler
198 // replies to a message, it is unnecessary to send back the entire
199 // list of arguments since, by definition, only the TT_OUT and
200 // TT_INOUT arguments can change.
202 // There are certain methods that are called just before a message is
203 // going to be xdr'ed that set up the _ptr_guards field to turn on the
204 // proper set of flags. These methods are:
206 // _Tt_c_message::set_return_handler_flags
208 // Optimizes message xdr for the case of a handler replying to a
211 // _Tt_s_message::set_return_sender_flags
213 // Optimizes message xdr for the case of a message being returned
214 // to its original sender.
216 // _Tt_s_message::set_send_handler_flags
218 // Optimizes message xdr for the case of sending a message to a
221 // The way these methods work is by setting the _ptr_guards field to some
222 // value other than 0 that has the proper flag bits turned on. Then this
223 // method checks for _ptr_guards being 0. If it is then it just uses the
224 // value of _full_msg_guards which is an always up-to-date set of flags
225 // of message fields that need to get xdr'ed in the default case. If
226 // _ptr_guards is not 0 then that value gets used instead of the default.
227 // Another detail of this mechanism is that the _flags field may
228 // sometimes have the _TT_MSG_UPDATE_XDR_MODE flag turned on. If this is
229 // the case then this indicates that when encoding the message only the
230 // arguments contained in the _out_args list are to be used rather than
231 // the ones in the _args list. This is because the args in _out_args are
232 // only the TT_OUT and TT_INOUT arguments.
237 if (xdrs->x_op == XDR_DECODE) {
240 if (xdrs->x_op == XDR_ENCODE && _ptr_guards==0) {
241 _flags &= ~(1<<_TT_MSG_UPDATE_XDR_MODE);
242 _ptr_guards = _full_msg_guards;
246 if (! xdr_int(xdrs, &_ptr_guards)) {
250 int need_2_set_id = 0;
251 if (_ptr_guards&_TT_MSK_ID) {
252 if (xdrs->x_op == XDR_DECODE) {
254 if (! xdr_int(xdrs, &id_2_set)) {
258 if (! xdr_int(xdrs, &_id)) {
263 if (_ptr_guards&_TT_MSK_MESSAGE_CLASS) {
264 if (! xdr_int(xdrs, (int *)&_message_class)) {
268 if (_ptr_guards&_TT_MSK_STATE) {
269 if (! xdr_int(xdrs, (int *)&_state)) {
272 } else { // XXXX only if XDR_DECODE, right? et al!
275 if (_ptr_guards&_TT_MSK_PARADIGM) {
276 if (! xdr_int(xdrs, (int *)&_paradigm)) {
280 if (_ptr_guards&_TT_MSK_SCOPE) {
281 if (! xdr_int(xdrs, (int *)&_scope)) {
284 } else if (_tt_global->xdr_version() > 1) {
287 if (_ptr_guards&_TT_MSK_RELIABILITY) {
288 if (! xdr_int(xdrs, (int *)&_reliability)) {
292 if (_ptr_guards&_TT_MSK_OPNUM) {
293 if (! xdr_int(xdrs, &_opnum)) {
297 if (_ptr_guards&_TT_MSK_STATUS) {
298 if (! xdr_int(xdrs,&_status)) {
302 // Even though in Solaris 2.x uid_t and gid_t are typedef'd as
303 // u_long, the compiler complains if they are not explicitly
305 if (_ptr_guards&_TT_MSK_UID) {
306 if (xdrs->x_op == XDR_DECODE) {
310 if (! xdr_u_int(xdrs, &_uid)) {
314 if (! xdr_u_long(xdrs,(u_long *) &_uid)) {
319 if (_ptr_guards&_TT_MSK_GID) {
320 if (xdrs->x_op == XDR_DECODE) {
324 if (! xdr_u_int(xdrs, &_gid)) {
328 if (! xdr_u_long(xdrs,(u_long *) &_gid)) {
334 if (_ptr_guards&_TT_MSK_SESSION) {
335 if (xdrs->x_op == XDR_DECODE) {
336 _session = new _Tt_session();
338 if (! _session->xdr(xdrs)) {
341 } else if (xdrs->x_op == XDR_DECODE) {
342 _session = _tt_mp->initial_session;
345 if (_ptr_guards&_TT_MSK_SENDER) {
346 if (xdrs->x_op == XDR_DECODE) {
347 _sender = new _Tt_procid();
349 if (! _sender->xdr(xdrs)) {
352 } else if (! _tt_mp->in_server()) {
353 // Since we know we're not in the server, we know that
354 // _tt_c_mp is valid.
355 _sender = _tt_c_mp->default_procid();
357 // _set_id() only works if _handler is set
363 switch (_tt_global->xdr_version()) {
365 // version 1 tooltalk always xdr's a _Tt_procid_ptr
366 if (! _handler.xdr(xdrs)) {
372 if (xdrs->x_op == XDR_DECODE) {
374 // XXX holtz: Also do this for other fields?
375 // If not, *this is a hybrid message that
376 // is dangerous to look at until you use it
377 // to update_message().
381 if (_ptr_guards&_TT_MSK_HANDLER) {
382 if (xdrs->x_op == XDR_DECODE) {
383 _handler = new _Tt_procid();
385 if (! _handler->xdr(xdrs)) {
391 if (_ptr_guards&_TT_MSK_FILE) {
392 if (! _file->xdr(xdrs)) {
397 if (_ptr_guards&_TT_MSK_OBJECT) {
398 if (! _object->xdr(xdrs)) {
403 if (_ptr_guards&_TT_MSK_OP) {
404 if (! _op->xdr(xdrs)) {
409 if (_ptr_guards&_TT_MSK_ARGS) {
410 if (xdrs->x_op == XDR_ENCODE) {
411 if (_flags&(1<<_TT_MSG_UPDATE_XDR_MODE)) {
413 // if this flag is turned on then only
414 // send arguments from the _out_args
415 // field rather than the _args field.
417 if (_out_args.is_null()) {
418 _out_args = new _Tt_arg_list();
420 if (! _out_args->xdr(xdrs)) {
424 if (! _args->xdr(xdrs)) {
430 SET_GUARD(_full_msg_guards, 0, _TT_MSK_ARGS);
432 if (! _args->xdr(xdrs)) {
437 if (_ptr_guards&_TT_MSK_FLAGS) {
438 if (! xdr_int(xdrs, &_flags)) {
441 if (xdrs->x_op == XDR_DECODE) {
442 // Assume non-remote, until we learn otherwise
443 _flags &= ~(1<<_TT_MSG_IS_REMOTE);
446 if (_ptr_guards&_TT_MSK_OTYPE) {
447 if (! _otype->xdr(xdrs)) {
452 if (_ptr_guards&_TT_MSK_SENDER_PTYPE) {
453 if (! _sender_ptype->xdr(xdrs)) {
457 if (_ptr_guards&_TT_MSK_HANDLER_PTYPE) {
458 if (! _handler_ptype->xdr(xdrs)) {
462 if (_ptr_guards&_TT_MSK_PATTERN_ID) {
463 if (! _pattern_id->xdr(xdrs)) {
467 if (_ptr_guards&_TT_MSK_RSESSIONS) {
468 if (xdrs->x_op == XDR_DECODE) {
469 _rsessions = new _Tt_string_list();
471 if (! _rsessions->xdr(xdrs)) {
475 if (_ptr_guards&_TT_MSK_STATUS_STRING) {
476 if (! _status_string->xdr(xdrs)) {
481 // Because of the bitmask, we don't worry about
482 // xdr versioning here, and in effect pretend that
483 // _TT_MSK_CONTEXTS has been defined from day 1.
485 if (_ptr_guards&_TT_MSK_CONTEXTS) {
486 if (! _contexts->xdr(xdrs)) {
493 if (_ptr_guards&_TT_MSK_OFFEREES) {
495 // TT_OFFERS are more rare than contexts, so
496 // we allocate the lists lazily to save memory.
498 if (_abstainers.is_null()) {
499 _abstainers = new _Tt_procid_list;
501 if (! _abstainers->xdr(xdrs)) {
504 if (_accepters.is_null()) {
505 _accepters = new _Tt_procid_list;
507 if (! _accepters->xdr(xdrs)) {
510 if (_rejecters.is_null()) {
511 _rejecters = new _Tt_procid_list;
513 if (! _rejecters->xdr(xdrs)) {
518 if (xdrs->x_op == XDR_DECODE) {
519 // Now we want to update _full_msg_guards from
520 // _ptr_guards appropiately. We must choose to do this
521 // either by assignment or by or'ing the fields.
522 // Assignment is required if this is a new message
523 // because _full_msg_guards may contain fields that
524 // are 1 when they need to be 0 (see
525 // _Tt_message::_Tt_message). (and or'ing won't
526 // help). We can tell that the message coming in is a
527 // new message by checking whether the paradigm and
528 // state field is being sent. This is a gross hack but
529 // unfortunately when the need for it was discovered
530 // there was no other way to test for this in a
531 // binary-compatible way with previous versions. Note
532 // that the paradigm (known as "address" in the
533 // documentation) doesn't ever change once its been
534 // created so it should never be the case that sending
535 // the message to a recipient in other than the
536 // defualt xdr mode should require sending the
539 if (_ptr_guards&(_TT_MSK_PARADIGM|_TT_MSK_STATE)) {
540 _full_msg_guards = _ptr_guards;
542 _full_msg_guards |= _ptr_guards;
552 // m represents the same message as this but perhaps with updated
553 // information. This method handles updating this message with the
554 // appropiate values in m.
557 update_message(const _Tt_message_ptr &m)
560 int mguards = m->_full_msg_guards;
562 _full_msg_guards |= mguards;
563 if (!_tt_mp->in_server()) {
564 if (mguards&_TT_MSK_STATE) {
565 set_state(m->_state);
567 if (mguards&_TT_MSK_RELIABILITY) {
568 set_reliability(m->_reliability);
573 if (mguards&_TT_MSK_SCOPE) {
580 if (mguards&_TT_MSK_PATTERN_ID) {
581 if (m->_pattern_id.len()) {
582 _pattern_id = m->_pattern_id;
585 if (mguards&_TT_MSK_HANDLER) {
586 _handler = m->_handler;
588 if (mguards&_TT_MSK_HANDLER_PTYPE) {
589 _handler_ptype = m->_handler_ptype;
591 if (mguards&_TT_MSK_OPNUM) {
592 set_opnum(m->opnum());
595 if (mguards&_TT_MSK_STATUS) {
596 _status = m->_status;
598 if (mguards & _TT_MSK_STATUS_STRING) {
599 set_status_string(m->_status_string);
601 if (mguards & _TT_MSK_OFFEREES) {
603 // We could just snare references and share the lists,
604 // but if the given message is ttsession's static
605 // wire buffer, then the lists will probably be changing.
607 _abstainers = new _Tt_procid_list( *m->_abstainers );
608 _accepters = new _Tt_procid_list( *m->_accepters );
609 _rejecters = new _Tt_procid_list( *m->_rejecters );
615 // update object and file
618 if (mguards&_TT_MSK_OBJECT) {
619 _object = m->_object;
621 if (mguards&_TT_MSK_FILE) {
624 if (mguards&_TT_MSK_CONTEXTS) {
625 // All contexts are INOUT, and extra can
626 // be added by the handler.
627 _contexts = new _Tt_msg_context_list( *m->_contexts );
629 if (mguards&_TT_MSK_ARGS) {
630 margc = _args->count();
631 if (margc && m->_args->count()) {
634 // update arguments with new values
637 _Tt_arg_list_cursor argc;
638 _Tt_arg_list_cursor nargc;
641 nargc.reset(m->_args);
642 while (argc.next()) {
643 switch (argc->mode()) {
647 argc->update_value(*nargc);
652 if (!_tt_mp->in_server() &&
653 _message_class==TT_NOTICE &&
655 m->_full_msg_guards = 0;
666 if (is_awaiting_reply()) {
667 set_awaiting_reply( 0 );
671 m->_full_msg_guards = 0;
672 // XXX holtz 20 Jul 94 Why change given message?
676 _Tt_msg_context_ptr _Tt_message::
677 context(const char *slotname) const
679 _Tt_msg_context_list_cursor contextC( _contexts );
680 while (contextC.next()) {
681 if (contextC->slotName() == slotname) {
689 _Tt_msg_context_ptr _Tt_message::
692 if ((i >= 0) && (i < _contexts->count())) {
693 return (*_contexts)[ i ];
700 contextsCount() const
702 if (_contexts.is_null()) {
705 return _contexts->count();
710 // Returns the id of the pattern that matched this message (ie. that
711 // caused it to be delivered). This id will be null if the message
712 // matched a ptype pattern rather than a dynamic pattern.
714 _Tt_string & _Tt_message::
722 // Sets the pattern id of a messsage and turns on the corresponding bit
723 // field in _full_msg_guards if non-empty.
726 set_pattern_id(_Tt_string id)
729 SET_GUARD(_full_msg_guards, _pattern_id.len(), _TT_MSK_PATTERN_ID);
735 // Function wrapper used to invoke the xdr method on a message when
736 // interfacing to the C RPC routines.
739 tt_xdr_message(XDR *xdrs, _Tt_message_ptr *msgp)
741 return((*msgp).xdr(xdrs));
765 const _Tt_string & _Tt_message::
772 Tt_status _Tt_message::
773 set_message_class(Tt_class mclass)
775 _message_class = mclass;
780 Tt_status _Tt_message::
781 set_state(Tt_state state)
789 Tt_status _Tt_message::
790 set_paradigm(Tt_address p)
799 // Sets the scope of a message. Note that if we're a post-version-1
800 // client then we also turn on the corresponding flag in _full_msg_guards
801 // if this is a non-TT_SESSION scope.
803 Tt_status _Tt_message::
804 set_scope(Tt_scope s)
807 // XXX: The xdr_version() only shadows to the sessions xdr version when an
808 // RPC call is in progress. set_scope() can be called by
809 // tt_message_scope_set() at which time the xdr version is not setup
813 SET_GUARD(_full_msg_guards,1,_TT_MSK_SCOPE);
819 // Sets the file field of a message and turn on the corresponding bit in
820 // _full_msg_guards if non-empty.
822 Tt_status _Tt_message::
823 set_file(_Tt_string f)
829 SET_GUARD(_full_msg_guards, 1, _TT_MSK_FILE);
835 // Sets the session field in a message and turns on the corresponding bit
836 // field in _full_msg_guards if non-null.
838 Tt_status _Tt_message::
839 set_session(_Tt_session_ptr &s)
842 SET_GUARD(_full_msg_guards,(! _session.is_null()), _TT_MSK_SESSION);
849 // Sets the op field in a message and turns on the corresponding bit
850 // field in _full_msg_guards if non-null.
852 Tt_status _Tt_message::
856 SET_GUARD(_full_msg_guards, _op.len(), _TT_MSK_OP);
863 // Sets the opnum field in a message and turns on the corresponding
864 // bit field in _full_msg_guards if not equal to -1 (the default).
866 Tt_status _Tt_message::
870 SET_GUARD(_full_msg_guards, _opnum != -1, _TT_MSK_OPNUM);
877 // Adds an argument to a message. Turns on the bit field for _args in
878 // _full_msg_guards since we know the list is non-empty.
880 Tt_status _Tt_message::
881 add_arg(_Tt_arg_ptr &arg)
885 SET_GUARD(_full_msg_guards, 1, _TT_MSK_ARGS);
891 // Adds a TT_OUT or TT_INOUT argument to the _out_args list. This is used
892 // by _Tt_message::xdr when the _TT_MSG_UPDATE_XDR flag is turned on.
895 add_out_arg(_Tt_arg_ptr &arg)
897 if (_out_args.is_null()) {
898 _out_args = new _Tt_arg_list();
900 switch (arg->mode()) {
903 // a parallel list of just out arguments is kept since
904 // whenever it is known that the receiver of a message
905 // is only seeing an update of the message, only the
906 // out arguments need to be sent.
907 _out_args->append(arg);
908 SET_GUARD(_full_msg_guards, 1, _TT_MSK_ARGS);
918 // Adds a context to a message. Turns on the bit field for _contexts in
919 // _full_msg_guards since we know the list is non-empty.
921 Tt_status _Tt_message::
922 add_context(_Tt_msg_context_ptr &context)
924 _contexts->append_ordered(context);
926 SET_GUARD(_full_msg_guards, 1, _TT_MSK_CONTEXTS);
932 // Sets the object field in a message and turns on the corresponding bit
933 // field in _full_msg_guards.
935 Tt_status _Tt_message::
936 set_object(_Tt_string oid)
939 SET_GUARD(_full_msg_guards, _object.len(), _TT_MSK_OBJECT);
944 Tt_status _Tt_message::
945 set_otype(_Tt_string ot)
948 SET_GUARD(_full_msg_guards, _otype.len(), _TT_MSK_OTYPE);
954 Tt_status _Tt_message::
955 set_sender(_Tt_procid_ptr &s)
958 SET_GUARD(_full_msg_guards, (! _sender.is_null()), _TT_MSK_SENDER);
964 Tt_status _Tt_message::
965 unset_handler_procid(void)
967 _handler = (_Tt_procid *) 0;
968 SET_GUARD(_full_msg_guards, 0, _TT_MSK_HANDLER);
973 Tt_status _Tt_message::
974 set_handler_procid(const _Tt_procid_ptr &h)
977 SET_GUARD(_full_msg_guards, (! _handler.is_null()), _TT_MSK_HANDLER);
983 Tt_status _Tt_message::
984 add_voter(const _Tt_procid_ptr &voter, Tt_state vote)
986 if (voter.is_null() || (_message_class != TT_OFFER)) {
989 if (_abstainers.is_null()) {
990 _abstainers = new _Tt_procid_list;
992 if (_abstainers.is_null()) {
995 if (_accepters.is_null()) {
996 _accepters = new _Tt_procid_list;
998 if (_accepters.is_null()) {
1001 if (_rejecters.is_null()) {
1002 _rejecters = new _Tt_procid_list;
1004 if (_rejecters.is_null()) {
1005 return TT_ERR_NOMEM;
1009 _accepters->append( voter );
1012 _rejecters->append( voter );
1015 _abstainers->append( voter );
1018 // Not a vote; bail out.
1021 SET_GUARD(_full_msg_guards, 1, _TT_MSK_OFFEREES);
1026 Tt_status _Tt_message::
1027 set_sender_ptype(_Tt_string s)
1030 SET_GUARD(_full_msg_guards,_sender_ptype.len(), _TT_MSK_SENDER_PTYPE);
1036 Tt_status _Tt_message::
1037 set_handler_ptype(_Tt_string h)
1040 SET_GUARD(_full_msg_guards,_handler_ptype.len(),_TT_MSK_HANDLER_PTYPE);
1046 Tt_status _Tt_message::
1047 set_reliability(Tt_disposition r)
1050 SET_GUARD(_full_msg_guards, _reliability != TT_DISCARD,
1051 _TT_MSK_RELIABILITY);
1058 // Sets the id of a message which is used to uniquely identify the
1059 // message within the sending process. The id is also used when queueing
1060 // the message. This implies that the message contains enough
1061 // information that is unique so that the queued message will never be
1062 // misinterpreted to be another message. This uniqueness is achieved by
1063 // combining the sender procid with the message id. This works because
1064 // the prefix of the sender procid is unique and the message id then
1065 // distinguishes the message among other messages the process has sent.
1067 Tt_status _Tt_message::
1070 return _set_id(_tt_mp->generate_message_id());
1073 Tt_status _Tt_message::
1078 sprintf( buf, "%d ", _id );
1080 if (sender().is_null()) {
1083 _api_id = _api_id.cat( sender()->id() );
1088 * Sets this to be a super message (send to parent type)
1093 _flags |= (1<<_TT_MSG_IS_SUPER);
1096 _Tt_string & _Tt_message::
1099 return(_status_string);
1103 Tt_status _Tt_message::
1104 set_status_string(_Tt_string st)
1106 _status_string = st;
1107 SET_GUARD(_full_msg_guards,_status_string.len(),_TT_MSK_STATUS_STRING);
1114 // This method will identify this message as a "start" message if flag is
1115 // 1. Otherwise it clears the flag associated with this. When turning the
1116 // flag on we set the status field to TT_WRN_START_MESSAGE because the
1117 // tooltalk client needs to check for this value to know that this is a
1118 // start message. When turning the flag off we have to set the status to
1119 // TT_OK but only if it is still TT_WRN_START_MESSAGE (otherwise we end
1120 // up stomping on a status code set by the client.).
1123 set_start_message(int flag)
1126 set_status((int)TT_WRN_START_MESSAGE);
1127 _flags |= (1<<_TT_MSG_IS_START_MSG);
1129 if (_status == (int)TT_WRN_START_MESSAGE) {
1130 SET_GUARD(_full_msg_guards,1,_TT_MSK_STATUS);
1133 _flags &= ~(1<<_TT_MSG_IS_START_MSG);
1139 // Returns 1 if this is a start message. Version 1 clients didn't
1140 // implement the _TT_MSG_IS_START_MSG flag so the only way to tell with
1141 // them is if the _status field is TT_WRN_START_MESSAGE.
1144 is_start_message() const
1146 return(_status == TT_WRN_START_MESSAGE ||
1147 (_flags&(1<<_TT_MSG_IS_START_MSG)));
1151 set_awaiting_reply(int flag)
1154 _flags |= (1<<_TT_MSG_AWAITING_REPLY);
1156 _flags &= ~(1<<_TT_MSG_AWAITING_REPLY);
1161 is_awaiting_reply() const
1163 return (_flags&(1<<_TT_MSG_AWAITING_REPLY));
1167 Tt_status _Tt_message::
1170 // _status is used in the special case of a start message
1171 if (st == (int)TT_OK && _status == TT_WRN_START_MESSAGE) {
1175 SET_GUARD(_full_msg_guards,1,_TT_MSK_STATUS);
1181 // Sets the _handler field of a message for the special case of an
1182 // observer replying to a start message. This special case is
1183 // distinguished by turning on the _TT_MSG_OBSERVER flag.
1186 set_observer_procid(const _Tt_procid_ptr &p)
1188 _flags |= (1<<_TT_MSG_OBSERVER);
1194 // Clears the _TT_MSG_OBSERVER flag and sets the _handler field back to
1198 clr_observer_procid()
1200 _flags &= ~(1<<_TT_MSG_OBSERVER);
1201 _handler = (_Tt_procid *)0;
1206 _tt_procid_list_print(const _Tt_ostream &os,
1207 const _Tt_procid_list_ptr &procs, const char *label)
1209 if ((! procs.is_null()) && (procs->count() > 0)) {
1210 os << label << ":\n";
1211 _Tt_string indent = os.indent();
1212 os.set_indent( indent.cat( "\t" ));
1213 _Tt_procid_list_cursor procC( procs );
1214 while (procC.next()) {
1217 os.set_indent( indent );
1223 // Prints out a message to os.
1226 print(const _Tt_ostream &os) const
1228 _Tt_arg_list_cursor arg_cursor;
1230 os << _tt_enumname(state()) << " ";
1231 os << _tt_enumname(_paradigm) << " ";
1232 os << _tt_enumname(_message_class) << " ";
1233 os << "(" << _tt_enumname(reliability()) << " in ";
1234 os << _tt_enumname(scope()) << "): ";
1235 os << (int)_status << " == " << (Tt_status)_status << "\n";
1237 os << "id:\t\t" << _api_id << "\n";
1238 os << "op:\t\t" << _op << "\n";
1239 if (_args->count() > 0) {
1241 _Tt_string indent = os.indent();
1242 os.set_indent( indent.cat( "\t" ));
1243 _Tt_arg_list_cursor argC( _args );
1244 while (argC.next()) {
1247 os.set_indent( indent );
1249 if (_contexts->count() > 0) {
1250 os << "contexts:\n";
1251 _Tt_string indent = os.indent();
1252 os.set_indent( indent.cat( "\t" ));
1253 _Tt_msg_context_list_cursor contextC( _contexts );
1254 while (contextC.next()) {
1255 contextC->print( os );
1257 os.set_indent( indent );
1259 if (_status_string.len() > 0) {
1260 os << "status_string:\t" << _status_string << "\n";
1262 if (! _session.is_null()) {
1263 os << "session:\t" << _session->address_string() << "\n";
1265 if (_file.len() > 0) {
1266 os << "file:\t\t" << _tt_network_path_to_local_path(_file)
1269 if (_object.len() > 0) {
1270 os << "object:\t\t" << _object << "\n";
1272 if (_otype.len() > 0) {
1273 os << "otype:\t\t" << _otype << "\n";
1275 if (! _sender.is_null()) {
1276 os << "sender:\t\t[" << _uid << "/" << _gid << "] ";
1277 _sender->print( os );
1279 if (_sender_ptype.len() > 0) {
1280 os << "sender_ptype:\t" << _sender_ptype << "\n";
1282 if (_pattern_id.len() > 0) {
1283 os << "pattern:\t" << _pattern_id << "\n";
1285 if (opnum() != -1) {
1286 os << "opnum:\t\t" << opnum() << "\n";
1288 if (! _handler.is_null()) {
1290 _handler->print( os );
1292 if (_handler_ptype.len() > 0) {
1293 os << "handler_ptype:\t" << _handler_ptype << "\n";
1295 _tt_procid_list_print( os, _accepters, "accepters" );
1296 _tt_procid_list_print( os, _rejecters, "rejecters" );
1297 _tt_procid_list_print( os, _abstainers, "abstainers" );