Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / mp / mp_mp.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
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_mp.C /main/7 1999/09/21 08:43:02 mgreess $                                                       
28 /*
29  *
30  * mp_mp.cc -- Server and client state object for the Message Passer
31  *
32  * Copyright (c) 1990,1992 by Sun Microsystems, Inc.
33  */
34
35 #include "mp/mp_global.h"
36 #include "mp/mp_mp.h"
37 #include "mp/mp_file.h"
38 #include "mp/mp_session.h"
39 #include "mp/mp_c_session.h"
40 #include "mp/mp_procid.h"
41 #include "mp/mp_rpc_client.h"
42 #include "mp/mp_xdr_functions.h"
43 #include "util/tt_base64.h"
44 #include "util/tt_port.h"
45 #include "util/tt_path.h"
46 #include "api/c/api_error.h"
47 #include <errno.h>
48 #include <sys/resource.h>
49 #include <malloc.h>
50 #include "tt_options.h"
51
52 #if defined(_AIX)
53 /* AIX's FD_ZERO macro uses bzero() without declaring it. */
54 #include <strings.h>
55 #endif
56
57 // 
58 // This file contains methods for the _Tt_mp object which is an object
59 // whose only function is to serve as a placeholder for global
60 // data/objects relevant to the message-passer routines. Another major
61 // use is to hold the various object caches that map object ids to a
62 // single object of the given class.
63 //
64 // Really, the _Tt_mp object as we see it here should go away, being
65 // replaced by _Tt_c_mp, which should represent the client's idea
66 // of the ttsession server it's connected to, and _Tt_s_mp, which
67 // represents the global state of a ttsession server.
68 // 
69
70 //
71 // Global pointer to *the* _Tt_mp object. There should only be one
72 // _Tt_mp object per tooltalk client.
73 //
74 _Tt_mp          *_tt_mp = (_Tt_mp *)0;
75
76 //
77 // Constructs a _Tt_mp object in the indicated mode.
78 //
79 _Tt_mp::
80 _Tt_mp()
81 {
82         _flags = 0;
83         FD_ZERO(&_session_fds);
84         _session_cache = new _Tt_session_table(_tt_session_address);
85         active_messages = 0;
86         _current_message_id = _current_pattern_id = 0;
87         active_procs = new _Tt_procid_table(_tt_procid_id, 50);
88 }
89
90 _Tt_mp::
91 ~_Tt_mp()
92 {
93 }
94
95
96
97 // 
98 // Returns the value of a counter and then increments the counter. Used
99 // to make different messages sent by the same sender unique.
100 //
101 int _Tt_mp::
102 generate_message_id()
103 {
104         return(_current_message_id++);
105 }
106
107
108 // 
109 // Returns the value of a counter and then increments the counter. Used
110 // to make different patterns registered by the same sender unique.
111 //
112 int _Tt_mp::
113 generate_pattern_id()
114 {
115         return(_current_pattern_id++);
116 }
117
118
119
120
121 // 
122 // Finds the _Tt_file object associated with the network pathname <path>.
123 // Optionally creates the _Tt_file object.  Returns:
124 //      TT_OK           but: if (! createIfNot), then fp.is_null() is possible
125 //      TT_ERR_FILE
126 //      TT_ERR_PATH
127 //      TT_ERR_DBAVAIL
128 //      TT_ERR_DBEXIST
129 //      TT_ERR_INTERNAL can mean ENOMEM
130 // 
131 Tt_status
132 _Tt_mp::find_file(
133         _Tt_string      path,
134         _Tt_file_ptr   &file,
135         int             createIfNot
136 )
137 {
138         _Tt_string network_path;
139         if (_tt_is_network_path(path)) {
140                 network_path = path;
141         }
142         else {
143                 network_path = _Tt_db_file::getNetworkPath(path);
144         }
145
146         if (_file_cache.is_null()) {
147                 if (!createIfNot) {
148                         return TT_OK;
149                 }
150                 else {
151                         _file_cache = new _Tt_file_table(_Tt_file::networkPath_);
152                         if (_file_cache.is_null()) {
153                                 return TT_ERR_NOMEM;
154                         }
155                 }
156         }
157         else {
158                 file = _file_cache->lookup( network_path );
159                 if (! file.is_null()) {
160                         return TT_OK;
161                 }
162         }
163
164         // If we get to this point, the file is not in the cache
165
166         Tt_status status = TT_OK;
167         if (createIfNot) {
168                 file = new _Tt_file( path );
169                 if (file.is_null()) {
170                         return TT_ERR_NOMEM;
171                 }
172                 _Tt_db_results dbStatus = file->getDBResults();
173                 status = _tt_get_api_error( dbStatus, _TT_API_FILE );
174                 if (status == TT_OK) {
175                         _file_cache->insert( file );
176                 } else if (status == TT_ERR_INTERNAL) {
177                         _tt_syslog( 0, LOG_ERR,
178                                     "_Tt_db_file::_Tt_db_file(): %d", dbStatus);
179                 }
180         }
181         return status;
182 }
183
184 void _Tt_mp::remove_file(_Tt_string path)
185 {
186         _Tt_string network_path = _Tt_db_file::getNetworkPath(path);
187         _file_cache->remove(network_path);
188 }
189
190 void _Tt_mp::
191 remove_session(_Tt_string id)
192 {
193         _session_cache->remove(id);
194 }
195
196
197 // 
198 // Attempts to find the _Tt_session object associated with the given
199 // session id. If not found and create_ifnot is 1 then a new session is
200 // created and initialized. When it is initialized, the auto_start
201 // parameter is examined. If it is 1 then the new session will be
202 // initialized with the c_init method that will do an auto-start of the
203 // session if it isn't running. Otherwise, the "client_session_init"
204 // method is used which just tries to connect to a running session.
205 //
206 // Note that the server does use _Tt_c_session since servers can
207 // act as clients for one another when passing file scoped messages.
208 // 
209 Tt_status _Tt_mp::
210 find_session(_Tt_string id, _Tt_session_ptr &sp,
211              int create_ifnot, int auto_start)
212 {
213         Tt_status result = TT_OK;
214
215         _Tt_session_ptr         s;
216         if (_session_cache->lookup(id,s)) {
217                 sp = s;
218                 result = TT_OK;
219         } else {
220                 // If this is a session address, try the X session ID
221                 // XXX - this is a kludge to deal with X session
222                 // IDs  now  that we use addres_strings as the lookup
223                 // key.  This should be removed if/when we expunge
224                 // our internal use of X session IDs.
225                 _Tt_session_table_cursor sc(_session_cache);
226
227                 while (sc.next()) {
228                         if (sc->has_id(id)) {
229                                 sp = *sc;
230
231                                 // Note: we return right here!
232                                 return TT_OK;
233                         }
234                 }
235         }
236
237         if (! create_ifnot || id.len() <= 0) {
238                 result = TT_ERR_SESSION;
239         } else {
240                 _Tt_c_session_ptr s = new _Tt_c_session();
241
242                 result = s->set_id(id);
243                 if (result != TT_OK) return result;
244
245                 if (auto_start) result = s->c_init();
246                 if (result != TT_OK) return result;
247
248                 if (result == TT_OK) result = s->client_session_init();
249                 if (result != TT_OK) return result;
250
251                 _session_cache->insert(s);
252                 sp = s;
253                 result = TT_OK;
254         }
255         return result;
256 }
257
258
259 void _Tt_mp::
260 save_session_fd(int fd)
261 {
262         FD_SET(fd, &_session_fds);
263 }
264
265
266 int _Tt_mp::
267 find_session_by_fd(int fd, _Tt_session_ptr &sp)
268 {
269         _Tt_rpc_client_ptr              rpc_client;
270         _Tt_session_table_cursor        sc(_session_cache);
271
272         while (sc.next()) {
273                 rpc_client = sc->_rpc_client;
274                 if (rpc_client->socket() == fd) {
275                         sp = *sc;
276                         return(1);
277                 }
278         }
279         return(0);
280 }
281
282
283 void _Tt_mp::
284 check_if_sessions_alive()
285 {
286         fd_set                  s_fds;
287         int                     fd, maxfds, n;
288         timeval                 tmout;
289         _Tt_session_ptr         s;
290         _Tt_string              id;
291
292         tmout.tv_sec = 0;
293         tmout.tv_usec = 0;
294         s_fds = _session_fds;
295         maxfds = _tt_getdtablesize();
296         n = select(maxfds, (fd_set *) 0, &s_fds, (fd_set *) 0, &tmout);
297
298         if (n < 0) {
299                 return;
300         }
301         fd = 0;
302         while (n > 0) {
303                 if (FD_ISSET(fd, &s_fds)) {
304                         if (! find_session_by_fd(fd, s)) {
305                                 FD_CLR(fd, &_session_fds);
306                         } else if (s->ping() != TT_OK) {
307                                 id = s->process_tree_id();
308                                 _tt_mp->remove_session(id);
309                                 FD_CLR(fd, &_session_fds);
310                         }
311                         n--;
312                 }
313                 fd++;
314         }
315 }