1
2 /*-
3 *
4 * New BSD License 2006
5 *
6 * Copyright (c) 2006, Jorgen Lundman
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * 1 Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2 Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * 3 Neither the name of the stuff nor the names of its contributors
20 * may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 // $Id: connections.c,v 1.13 2006/06/30 01:22:58 lundman Exp $
38 // Temporary connection space holder
39 // Jorgen Lundman November 5th, 1999
40
41
42 // As we get new connections, we need a few values and information to be
43 // stored with them. This is an example on how this could be achieved.
44 // Currently it is a simple linked list of nodes, one for each connection.
45 // Eventually, this with belong to a high connection database information
46 // module.
47
48 // This module is more complicated to the casual reader than it really needs
49 // to be, but that is so that it can be as modular as possible.
50 // Although if you really want to achieve this, the linked list would have
51 // just nodes of "next" and "data" (void *) totally hiding data from this
52 // layer, as well as, hiding the implementation from the data-layer.
53
54 #include <stdio.h> // for defn of NULL
55 #include <stdlib.h> // malloc
56 #include <string.h> // memset
57 #include <time.h>
58
59 #include "connections.h"
60 //#include "misc.h"
61
62 // The start to the linked list, it's static as only we may touch it.
63 THREAD_SAFE static connection_t *connections_head = NULL;
64
65
66 // The main buffer size variable, so that we can change it on load.
67 unsigned int buffer_size = BUFFER_SIZE_DEFAULT;
68
69
70
71 #include "lion.h" // Only for DEBUG define!!
72
73
74
75 //
76 // Allocate and return a fresh Connection Holder.
77 //
78 // IN: void
79 // OUT: pointer to a new node, added to the main linked list.
80 //
connections_new(void)81 connection_t *connections_new(void)
82 {
83 connection_t *result;
84
85 // printf(" head is at %p pointing to %p\n", &connections_head, connections_head);
86
87 result = (connection_t *) malloc(sizeof (connection_t));
88
89 if (!result) {
90
91 perror("connections_new: malloc:");
92 exit(1); // FIXME.
93
94 }
95
96 #ifdef DEBUG_VERBOSE
97 printf("Allocated new Connection %p\n", result);
98 #endif
99
100 // clear it
101 memset(result, 0, sizeof(*result));
102
103
104 // Add it to linked list
105 result->next = connections_head;
106 connections_head = result;
107
108
109 // Allocate input buffer
110 result->buffer = (char *) malloc(buffer_size);
111
112 if (!result->buffer) {
113
114 perror("connections_new: buffer area malloc:");
115 exit(1); // FIXME.
116
117 }
118
119
120 // Allocate output buffer
121 result->obuffer = (char *) malloc(buffer_size);
122
123 if (!result->obuffer) {
124
125 perror("connections_new: buffer area malloc:");
126 exit(1); // FIXME.
127
128 }
129
130 // Clear the buffers to avoid UMR
131 memset(result->buffer, 0, buffer_size);
132 memset(result->obuffer, 0, buffer_size);
133
134 result->inbuffer_size = buffer_size;
135 result->outbuffer_size = buffer_size;
136
137
138 result->return_code = -1; // -1 == unknown
139
140
141 // That's all, return it.
142 return result;
143
144 }
145
146
147 //
148 // Free a connection node, and remove it from the linked list.
149 //
150 // IN: connection ptr to be freed
151 // OUT: void
152 //
connections_free(connection_t * node)153 void connections_free(connection_t *node)
154 {
155 connection_t *runner, *prev;
156
157 /* assert(!node); */
158 if (node->trace)
159 fprintf(trace_file, "%p: connections_free (node released)\n", node);
160
161 if (node->trace)
162 lion_disable_trace(node);
163
164
165 // Free the buffer if it was allocated
166
167 if (node->buffer) {
168
169 free( node->buffer );
170 node->buffer = NULL;
171
172 }
173
174 if (node->obuffer) {
175
176 free( node->obuffer );
177 node->obuffer = NULL;
178
179 }
180
181 #ifdef DEBUG_VERBOSE
182 printf("[releasing input/output buffers size %d / %d]\n",
183 node->inbuffer_size,
184 node->outbuffer_size);
185 #endif
186
187
188 for (prev = NULL, runner = connections_head;
189 runner;
190 prev = runner, runner = runner->next) {
191
192
193 if (runner == node) { // This is the one to remove
194
195 if (!prev) {
196
197 // If no previous node, then it's at the start of the list
198
199 connections_head = runner->next;
200
201 } else {
202
203 // In the middle somewhere
204
205 prev->next = runner->next;
206
207 }
208
209 break; // Stop spinning in the for-loop.
210
211 } // if runner == node
212
213 } // for
214
215
216 #ifdef DEBUG_VERBOSE
217 printf("Releasing %p\n", node);
218 #endif
219
220 #ifdef DEBUG
221 memset(node, -1, sizeof(*node));
222 #endif
223
224
225 // Release it
226 free( node );
227
228 }
229
230
231
232
233
234 //
235 // Find a particular node, or, iterate the list.
236 //
237 // IN: comparison function, expected to return 0 on match
238 // IN: two optional arguments that are simply passed on
239 // OUT: pointer to matching node, or NULL if end reached
240 //
connections_find(int (* compare)(connection_t *,void *,void *),void * optarg1,void * optarg2)241 connection_t *connections_find( int (*compare)(connection_t *, void *, void *),
242 void *optarg1, void *optarg2)
243 {
244 connection_t *runner;
245
246 for (runner = connections_head; runner; runner = runner->next) {
247
248 if (!compare(runner, optarg1, optarg2)) {
249
250 // Found it, apparently
251 return runner;
252
253 }
254
255 }
256
257 // Didn't find it
258 return NULL;
259
260 }
261
262
263
264
265
connections_dupe(connection_t * dst,connection_t * src)266 void connections_dupe(connection_t *dst, connection_t *src)
267 {
268 // Copy over anything we need.
269 #define NODE_DUPE(X) dst->X = src->X
270 NODE_DUPE(type);
271 NODE_DUPE(socket);
272 NODE_DUPE(status);
273 NODE_DUPE(binary);
274 NODE_DUPE(disable_read);
275 NODE_DUPE(user_data);
276 NODE_DUPE(rate_in);
277 NODE_DUPE(rate_out);
278 NODE_DUPE(time_start);
279 NODE_DUPE(event_handler);
280 #ifdef WIN32
281 NODE_DUPE(mutex);
282 NODE_DUPE(file_socket);
283 NODE_DUPE(start_address);
284 #endif
285 // More to come
286 #undef NODE_DUPE
287 }
288
289
connections_cycle(void)290 void connections_cycle( void )
291 {
292 connection_t *runner;
293
294 for (runner = connections_head; runner; runner = runner->next) {
295
296 if (!runner->next) { // Last node.
297
298 if ( connections_head != runner ) { // Not the only thing in list.
299
300 // Find the last node, assign it to have a ->next pointing to
301 // the first node in the list.
302 runner->next = connections_head;
303
304 // Then we need to save the first node's ->next to re assign
305 runner = connections_head->next;
306
307 // Set first node (now last) ->next to be NULL, EOL.
308 connections_head->next = NULL;
309
310 // Re-assign the front of the list to point to 2nd node.
311 connections_head = runner;
312
313 // and stop
314 return;
315
316 }
317
318 }
319
320 }
321
322 }
323