aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xcs/connection.c
blob: 3b5747de6842ddd749e397c84a7dfff503353e45 (plain)
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
155
156
157
/*
 * connection.c
 *
 * State associated with a client connection to xcs.
 *
 * Copyright (c) 2004, Andrew Warfield
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xcs.h"

connection_t *connection_list = NULL;

#define CONNECTED(_c) (((_c)->ctrl_fd != -1) || ((_c)->data_fd != -1))

connection_t *get_con_by_session(unsigned long session_id)
{
    connection_t **c, *ent = NULL;
    
    c = &connection_list;
    
    DPRINTF("looking for id: %lu : %lu\n", session_id, (*c)->id);
    
    while (*c != NULL) 
    {
        if ((*c)->id == session_id) 
            return (*c);
        c = &(*c)->next;
    }
    
    return ent;
}

connection_t *connection_new()
{
    connection_t *con;
    
    con = (connection_t *)malloc(sizeof(connection_t));
    if (con == NULL)
    {
        DPRINTF("couldn't allocate a new connection\n");
        return NULL;
    }
    
    con->bindings = NULL;
    con->data_fd = -1;
    con->ctrl_fd = -1;
    
    /* connections need a unique session id. 
     * - this approach probably gets fixed later, but for the moment
     * is unique, and clearly identifies a connection.
     */
    con->id = (unsigned long)con;
    
    /* add it to the connection list */
    con->next = connection_list;
    connection_list = con;
    
    return (con);
}

void connection_free(connection_t *con)
{
    /* first free all subscribed bindings: */
    
    while (con->bindings != NULL)
        xcs_unbind(con, con->bindings->key.port, con->bindings->key.type);
    
    /* now free the connection. */
    free(con);
}
    
int connection_add_binding(connection_t *con, binding_key_t *key)
{
    binding_key_ent_t *key_ent;
    
    key_ent = (binding_key_ent_t *)malloc(sizeof(binding_key_ent_t));
    if (key_ent == NULL)
    {
        DPRINTF("couldn't alloc key in connection_add_binding\n");
        return -1;    
    }
    
    key_ent->key = *key;
    key_ent->next = con->bindings;
    con->bindings = key_ent;
    
    return 0;
}

int connection_remove_binding(connection_t *con, binding_key_t *key)
{
    binding_key_ent_t *key_ent;
    binding_key_ent_t **curs = &con->bindings;
    
    while ((*curs != NULL) && (!BINDING_KEYS_EQUAL(&(*curs)->key, key)))
        curs = &(*curs)->next;
    
    if (*curs != NULL) {
        key_ent = *curs;
        *curs = (*curs)->next;
        free(key_ent);
    }
    
    return 0;   
}


int connection_has_binding(connection_t *con, binding_key_t *key)
{
    binding_key_ent_t *ent;
    int ret = 0;
    
    ent = con->bindings;
    
    while (ent != NULL) 
    {
        if (BINDING_KEYS_EQUAL(key, &ent->key))
        {
            ret = 1;
            break;
        }
        ent = ent->next;
    }
    
    return ret;
}


void gc_connection_list(void)
{
    connection_t **c, *ent = NULL;
    struct timeval now, delta;

    c = &connection_list;
    gettimeofday(&now, NULL);

    while ( *c != NULL )
    {
        if ( !CONNECTED(*c) )
        {
            timersub(&now, &(*c)->disconnect_time, &delta);
            if ( delta.tv_sec >= XCS_SESSION_TIMEOUT )
            {
                DPRINTF("        : Freeing connection %lu after %lds\n", 
                     (*c)->id, delta.tv_sec);
                ent = *c;
                *c = (*c)->next;
                connection_free(ent);
                continue;
            }
        }
        c = &(*c)->next;
    }
}