[go: up one dir, main page]

File: sid.c

package info (click to toggle)
uhub 0.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,016 kB
  • sloc: ansic: 12,630; xml: 588; sh: 356; perl: 233; makefile: 60
file content (154 lines) | stat: -rw-r--r-- 3,685 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * uhub - A tiny ADC p2p connection hub
 * Copyright (C) 2007-2009, Jan Vidar Krey
 *
 * This program 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "uhub.h"

const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

char* sid_to_string(sid_t sid_)
{
	static char t_sid[5];
	sid_t sid = (sid_ & 0xFFFFF); /*  20 bits only */
	sid_t A, B, C, D = 0;
	D     = (sid % 32);
	sid   = (sid - D) / 32;
	C     = (sid % 32);
	sid   = (sid - C) / 32;
	B     = (sid % 32);
	sid   = (sid - B) / 32;
	A     = (sid % 32);
	t_sid[0] = BASE32_ALPHABET[A];
	t_sid[1] = BASE32_ALPHABET[B];
	t_sid[2] = BASE32_ALPHABET[C];
	t_sid[3] = BASE32_ALPHABET[D];
	t_sid[4] = 0;
	return t_sid;
}


sid_t string_to_sid(const char* sid)
{
	sid_t nsid = 0;
	sid_t n, x;
	sid_t factors[] = { 32768, 1024, 32, 1};
	
	if (!sid || strlen(sid) != 4) return 0;

	for (n = 0; n < 4; n++) {
		for (x = 0; x < strlen(BASE32_ALPHABET); x++)
			if (sid[n] == BASE32_ALPHABET[x]) break;
		if (x == 32) return 0;
		nsid += x * factors[n];
	}
	return nsid;
}

/*
 * Session IDs are heavily reused, since they are a fairly scarce
 * resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
 * value and 'AAAA' (0) is reserved for the hub.
 *
 * Initialize with sid_initialize(), which sets min and max to one, and count to 0.
 *
 * When allocating a session ID:
 * - If 'count' is less than the pool size (max-min), then allocate within the pool
 * - Increase the pool size (see below)
 * - If unable to do that, hub is really full - don't let anyone in!
 *
 * When freeing a session ID:
 * - If the session ID being freed is 'max', then decrease the pool size by one.
 *
 */

struct sid_pool
{
	sid_t min;
	sid_t max;
	sid_t count;
	struct hub_user** map;
};


struct sid_pool* sid_pool_create(sid_t max)
{
	struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
	if (!pool)
		return 0;

	pool->min = 1;
	pool->max = max + 1;
	pool->count = 0;
	pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
	if (!pool->map)
	{
		hub_free(pool);
		return 0;
	}
	pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */

#ifdef DEBUG_SID
	LOG_DUMP("SID_POOL:  max=%d", (int) pool->max);
#endif
	return pool;
}

void sid_pool_destroy(struct sid_pool* pool)
{
#ifdef DEBUG_SID
	LOG_DUMP("SID_POOL:  destroying, current allocs=%d", (int) pool->count);
#endif
	hub_free(pool->map);
	hub_free(pool);
}

sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{
	if (pool->count >= (pool->max - pool->min))
	{
#ifdef DEBUG_SID
		LOG_DUMP("SID_POOL:  alloc, sid pool is full.");
#endif
		return 0;
	}

	sid_t n = (++pool->count);
	for (; (pool->map[n % pool->max]); n++) ;

#ifdef DEBUG_SID
	LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
#endif
	pool->map[n] = user;
	return n;
}

void sid_free(struct sid_pool* pool, sid_t sid)
{
#ifdef DEBUG_SID
	LOG_DUMP("SID_FREE:  %d", (int) sid);
#endif
	pool->map[sid] = 0;
	pool->count--;
}

struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
{
	if (!sid || (sid >= pool->max))
		return 0;
	return pool->map[sid];
}