internal-connections.c 9.88 KB
Newer Older
Linus Tolke's avatar
Linus Tolke committed
1
/*
2
 * $Id: internal-connections.c,v 0.47 2001/12/22 17:00:18 ceder Exp $
Per Cederqvist's avatar
Per Cederqvist committed
3
 * Copyright (C) 1991-1994, 1996-2000  Lysator Academic Computer Association.
Linus Tolke's avatar
Linus Tolke committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * This file is part of the LysKOM server.
 * 
 * LysKOM is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 1, or (at your option) 
 * any later version.
 * 
 * LysKOM is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with LysKOM; see the file COPYING.  If not, write to
 * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
 * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
 * MA 02139, USA.
 *
 * Please mail bug reports to bug-lyskom@lysator.liu.se. 
 */
Per Cederqvist's avatar
Per Cederqvist committed
25
26
27
28
29
30
/*
 * internal-connections.c
 *
 * Abstract routines on the data type Connection.
 */

David Byers's avatar
David Byers committed
31
32
33
34
35

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

Per Cederqvist's avatar
Per Cederqvist committed
36
37
38
#include <stdio.h>
#include <time.h>
#include <setjmp.h>
Per Cederqvist's avatar
Per Cederqvist committed
39
#include <sys/types.h>
Per Cederqvist's avatar
Per Cederqvist committed
40

Per Cederqvist's avatar
Per Cederqvist committed
41
#include "exp.h"
Per Cederqvist's avatar
Per Cederqvist committed
42
43
#include "s-string.h"
#include "kom-types.h"
Per Cederqvist's avatar
Per Cederqvist committed
44
#include "com.h"
45
#include "async.h"
Per Cederqvist's avatar
Per Cederqvist committed
46
47
#include "connections.h"
#include "internal-connections.h"
David Byers's avatar
David Byers committed
48
#include "kom-config.h"
Per Cederqvist's avatar
Per Cederqvist committed
49
50
#include "server/smalloc.h"
#include "lyskomd.h"
51
#include "log.h"
52
#include "async.h"
53
#include "kom-memory.h"
54
#include "server-time.h"
Per Cederqvist's avatar
Per Cederqvist committed
55

56
57
58
59
/* We don't need the defensive checks in this file.  They have been
   tested enough the last few years.  They also consume a lot of CPU. */
#define NDEFENSIVE_CHECKS 1

Per Cederqvist's avatar
Per Cederqvist committed
60
INTERNAL  Connection  *all_connections   = NULL;
61
INTERNAL  Session_no   no_of_connection_attempts = 0;
Per Cederqvist's avatar
Per Cederqvist committed
62
63
64
65
66

/* Used in get_conn_by_number to speed things up. */

INTERNAL  Connection  *last_conn = NULL;

67
68
static int  no_of_allocated_connections = 0;

69
70
71
static void
init_connection(Connection *conn)
{
72
    enum async default_want_async[] = ASYNC_DEFAULT_MESSAGES;
73
74
    int i;
    
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    conn->magic = 0;
    conn->prev = NULL;
    conn->next = NULL;
    conn->pers_no = 0;
    conn->person = NULL;
    conn->session_start = NO_TIME;
    conn->cwc = 0;
    conn->what_am_i_doing = EMPTY_STRING;
    conn->ena_level = 0;
    conn->username = EMPTY_STRING;
    conn->hostname = EMPTY_STRING;
    conn->ident_user = EMPTY_STRING;
    conn->client_name = EMPTY_STRING;
    conn->client_version = EMPTY_STRING;
89
90
91
92
93
94
95
96
    conn->flags.invisible = FALSE;
    conn->flags.user_active_used = FALSE;
    conn->flags.user_absent = FALSE;
    conn->flags.reserved3 = FALSE;
    conn->flags.reserved4 = FALSE;
    conn->flags.reserved5 = FALSE;
    conn->flags.reserved6 = FALSE;
    conn->flags.reserved7 = FALSE;
97
    conn->username_valid = FALSE;
98
    conn->isc_session = NULL;
99
100
101
102
    conn->protocol = '\0';
    conn->parse_pos = 0;
    conn->fnc_parse_pos = 0;
    conn->array_parse_pos = 0;
103
    conn->array_parse_index = 0;
David Byers's avatar
David Byers committed
104
    conn->array_parse_parsed_length = 0;
105
106
    conn->struct_parse_pos = 0;
    conn->string_parse_pos = 0;
David Byers's avatar
David Byers committed
107
108
109
    conn->hunt_parse_pos = 0;
    conn->array_hunt_num = 0;
    conn->array_hunt_depth = 0;
110
111
112
113
114
115
116
117
118
    conn->ref_no = 0;
    conn->function = call_fnc_login_old;
    conn->num0 = 0;
    conn->num1 = 0;
    conn->num2 = 0;
    conn->num3 = 0;
    conn->c_string0 = EMPTY_STRING;
    conn->c_string1 = EMPTY_STRING;
    conn->string0 = EMPTY_STRING;
David Byers's avatar
David Byers committed
119
120
    conn->misc_info_list.no_of_misc = 0;
    conn->misc_info_list.misc = NULL;
121
    conn->aux_item.data = EMPTY_STRING;
122
    conn->dummy_aux_item.data = EMPTY_STRING;
123
124
    conn->aux_item_list.items = NULL;
    conn->aux_item_list.length = 0;
125
126
127
128
    conn->c_local_text_no_p = NULL;
    conn->unparsed = EMPTY_STRING;
    conn->first_to_parse = 0;
    conn->more_to_parse = FALSE;
129
    conn->active_time = current_time;
130
131
    conn->session_no = 0;

132
133
134
135
136
137
    conn->info.pers_pres_conf = 0;
    conn->info.conf_pres_conf = 0;
    conn->info.motd_conf = 0;
    conn->info.kom_news_conf = 0;
    conn->info.motd_of_lyskom = 0;
    conn->info.version = 0;
138
139
140
    conn->info.highest_aux_no = 0;
    conn->info.aux_item_list.length = 0;
    conn->info.aux_item_list.items = NULL;
141

142
143
144
145
    conn->num_list.length = 0;
    conn->num_list.data = NULL;

    for (i = 0; i < ay_dummy_last; i++)
146
        conn->want_async[i] = FALSE;
147
148
    
    for (i = 0;
David Byers's avatar
David Byers committed
149
         (size_t)i < sizeof(default_want_async)/sizeof(*default_want_async);
150
         i++)
151
        conn->want_async[default_want_async[i]] = TRUE;
152

153
154
155
    init_priv_bits(&conn->priv_bits);
    init_conf_type(&conn->conf_type);
    init_struct_tm(&conn->time);
David Byers's avatar
David Byers committed
156
    init_personal_flags(&conn->pers_flags);
157
158
159
}

static Connection *
Per Cederqvist's avatar
Per Cederqvist committed
160
161
162
163
164
alloc_connection(void)
{
    Connection *res;
    
    res = smalloc ( sizeof(Connection) );
165
    init_connection(res);
166
    ++no_of_allocated_connections;
Per Cederqvist's avatar
Per Cederqvist committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    return res;
}

EXPORT  Connection *
new_client(void)
{
    Connection		*c;

    c = alloc_connection();

    c->magic = CONN_MAGIC_ALLOC;
    
    if (all_connections != NULL)
    {
	all_connections->prev->next = c;
	c->prev = all_connections->prev;
	all_connections->prev = c;
	c->next = all_connections;
    }
    else
    {
	c->prev = c;
	c->next = c;
    }

    all_connections = c;
    
    c->session_no = ++no_of_connection_attempts;
195
    c->protocol = '\0';      /* Reserved to mean 'no protocol specified yet' */
Per Cederqvist's avatar
Per Cederqvist committed
196
197
198
    c->unparsed = EMPTY_STRING;
    c->first_to_parse = 0;
    c->more_to_parse = TRUE;
199
    c->active_time = current_time;
Per Cederqvist's avatar
Per Cederqvist committed
200
201
    c->pers_no = 0;
    c->person = NULL;
202
    c->session_start = current_time;
Per Cederqvist's avatar
Per Cederqvist committed
203
204
205
206
    c->cwc = 0;
    c->what_am_i_doing = EMPTY_STRING;
    c->ena_level = 0;
    c->username = EMPTY_STRING;
207
    c->ident_user = EMPTY_STRING;
208
209
    c->client_name = EMPTY_STRING;
    c->client_version = EMPTY_STRING;
210
211
212
213
214
215
216
217
    c->flags.invisible = FALSE;
    c->flags.user_active_used = FALSE;
    c->flags.user_absent = FALSE;
    c->flags.reserved3 = FALSE;
    c->flags.reserved4 = FALSE;
    c->flags.reserved5 = FALSE;
    c->flags.reserved6 = FALSE;
    c->flags.reserved7 = FALSE;
218
    c->username_valid = FALSE;
219

Per Cederqvist's avatar
Per Cederqvist committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    return c;
}

/*
 * Only used from logout_client
 */
EXPORT  void
kill_client(Connection *cp)    
{
    if ( all_connections == NULL )
	restart_kom("kill_client(): No clients in all_connections list\n");
    
    if (all_connections == all_connections->next)
    {
	if (all_connections->prev != all_connections)
	    restart_kom("kill_client(): all_connections corrupt (LINK)\n");

	if (all_connections != cp)
	    restart_kom("kill_client(): all_connections corrupt (SINGLE)\n");
      
	all_connections = NULL;
    }
    else
    {
	if (cp->prev == NULL || cp->next == NULL)
	    restart_kom("kill_client(): all_connections corrupt (NULL)\n");
      
	cp->prev->next = cp->next;
	cp->next->prev = cp->prev;
	
	if (all_connections == cp)
	    all_connections = cp->next;
    }

    if ( last_conn == cp )
	last_conn = NULL;

    cp->magic = CONN_MAGIC_FREE;
258
259
260
261
262

    s_clear(&cp->unparsed);
    s_clear(&cp->what_am_i_doing);
    s_clear(&cp->username);
    s_clear(&cp->hostname);
263
    s_clear(&cp->ident_user);
264
265
    s_clear(&cp->client_name);
    s_clear(&cp->client_version);
266

267
    if ( cp->isc_session != NULL )
268
    {
David Byers's avatar
David Byers committed
269
270
	kom_log("kill_client(): client %ld has isc_session != NULL.\n",
                cp->session_no);
271
272
273
274
275
    }

    if ( !s_empty(cp->c_string0) || !s_empty(cp->c_string1)
	|| !s_empty(cp->string0) )
    {
David Byers's avatar
David Byers committed
276
	kom_log("kill_client(): unexpected string remains.\n");
277
278
    }

David Byers's avatar
David Byers committed
279
    if ( cp->misc_info_list.misc != NULL || cp->c_local_text_no_p != NULL )
David Byers's avatar
David Byers committed
280
	kom_log("kill_client(): unexpected remaining data.\n");
281

282
283
284
285
286
287
    if (!s_empty(cp->aux_item.data))
	kom_log("kill_client(): unexpected aux_item string remains.\n");

    if (!s_empty(cp->dummy_aux_item.data))
	kom_log("kill_client(): unexpected dummy_aux_item string remains.\n");
	
288
    /* FIXME (bug 149): Check for remaining data in aux-item structures */
David Byers's avatar
David Byers committed
289

Per Cederqvist's avatar
Per Cederqvist committed
290
    sfree(cp);
291
    --no_of_allocated_connections;
Per Cederqvist's avatar
Per Cederqvist committed
292
293
}

294
#ifndef NDEFENSIVE_CHECKS
Per Cederqvist's avatar
Per Cederqvist committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

INTERNAL  void
check_conn_exists(Connection *foo)
{
    /* Check that foo really is active. */

    Connection *c = all_connections;
    Bool found = FALSE;

    do
    {
	if ( c == foo )
	    found = TRUE;

	c = c->next;
    }
    while ( c != all_connections && found == FALSE );

    if ( found == FALSE )
314
	restart_kom("%s: foo == %ld not found in all_connections.\n", 
Per Cederqvist's avatar
Per Cederqvist committed
315
316
		    "get_conn_by_number",
		    last_conn->session_no);
Per Cederqvist's avatar
Per Cederqvist committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
}

#endif

/*
 * Session_nos must NOT be recycled, or this code might break!
 */
EXPORT  Connection *
get_conn_by_number (Session_no session_no)
{
    Connection *end;

    if ( last_conn == NULL )
	last_conn = all_connections;
    else if ( all_connections == NULL )
    {
333
	restart_kom("get_conn_by_number(%ld): last_conn = %ld %s",
Per Cederqvist's avatar
Per Cederqvist committed
334
335
336
		    session_no,
		    last_conn->session_no,
		    "and all_connections == NULL");
Per Cederqvist's avatar
Per Cederqvist committed
337
    }
338
#ifndef NDEFENSIVE_CHECKS
Per Cederqvist's avatar
Per Cederqvist committed
339
340
341
342
343
344
    else
	check_conn_exists(last_conn);
#endif

    end = last_conn;

345
    if (session_no == 0)
David Byers's avatar
Server    
David Byers committed
346
347
348
349
350
    {
        if (active_connection == NULL)
        {
            restart_kom("get_conn_by_number: No session-no and no active connection");
        }
351
        session_no = active_connection->session_no;
David Byers's avatar
Server    
David Byers committed
352
    }
353

Per Cederqvist's avatar
Per Cederqvist committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
    do
    {
	if ( last_conn->session_no == session_no )
	    return last_conn;

	last_conn = last_conn->next;
    }
    while ( last_conn != end);

    return NULL;
}


EXPORT  Session_no
traverse_connections (Session_no session_no)
{
    Connection *prev = NULL;

    if ( all_connections == NULL )
	return 0;

375
376
377
378
    if (session_no == 0)
        prev = NULL;
    else
        prev = get_conn_by_number ( session_no );
Per Cederqvist's avatar
Per Cederqvist committed
379
380
381
382
383
384
385
386
387
388

    /* prev is NULL if session_no is 0, or if session_no was logged out. */

    if ( prev == NULL )
	return all_connections->session_no;
    else if ( prev->next == all_connections )
	return 0;		/* Full circle. */
    else
	return prev->next->session_no;
}
389
390
391
392

void
dump_allocated_connections(FILE *fp)
{
Per Cederqvist's avatar
Per Cederqvist committed
393
394
    fprintf(fp, "---%s:\n\tConnections:      %d\n",
	    __FILE__,
395
	    no_of_allocated_connections);
Per Cederqvist's avatar
Per Cederqvist committed
396
397
    fprintf(fp, "\tConnection attempts:	%lu\n",
	    (unsigned long)no_of_connection_attempts);
398
}