ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/uplink.C
Revision: 1.2
Committed: Sat Jul 21 01:29:13 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * uplink.C: Uplink management.
3 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
4 pippijn 1.1 *
5     * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6     */
7    
8     static char const rcsid[] = "$Id";
9    
10     #include "atheme.h"
11     #include "datastream.h"
12     #include "uplink.h"
13    
14     list_t uplinks;
15     uplink_t *curr_uplink;
16    
17     static BlockHeap *uplink_heap;
18    
19     static void uplink_close (connection_t *cptr);
20    
21     void
22     init_uplinks (void)
23     {
24     uplink_heap = BlockHeapCreate (sizeof (uplink_t), 4);
25     if (!uplink_heap)
26     {
27     slog (LG_INFO, "init_uplinks(): block allocator failed.");
28     exit (EXIT_FAILURE);
29     }
30     }
31    
32     uplink_t *
33     uplink_add (char *name, char *host, char *password, char *vhost, int port)
34     {
35     uplink_t *u;
36     node_t *n;
37    
38     slog (LG_DEBUG, "uplink_add(): %s -> %s:%d", me.name, name, port);
39    
40     if ((u = uplink_find (name)))
41     {
42     if (u->flags & UPF_ILLEGAL)
43     {
44     u->flags &= ~UPF_ILLEGAL;
45     free (u->name);
46     free (u->host);
47     free (u->pass);
48     free (u->vhost);
49     }
50     else
51     {
52     slog (LG_INFO, "Duplicate uplink %s.", name);
53     return NULL;
54     }
55     }
56     else
57     {
58     u = static_cast<uplink_t *> (BlockHeapAlloc (uplink_heap));
59     n = node_create ();
60     u->node = n;
61     node_add (u, n, &uplinks);
62     cnt.uplink++;
63     }
64    
65     u->name = sstrdup (name);
66     u->host = sstrdup (host);
67     u->pass = sstrdup (password);
68     if (vhost)
69     u->vhost = sstrdup (vhost);
70     else
71     u->vhost = sstrdup ("0.0.0.0");
72     u->port = port;
73    
74     return u;
75     }
76    
77     void
78     uplink_delete (uplink_t *u)
79     {
80     node_t *n = node_find (u, &uplinks);
81    
82     free (u->name);
83     free (u->host);
84     free (u->pass);
85     free (u->vhost);
86    
87     node_del (n, &uplinks);
88     node_free (n);
89    
90     BlockHeapFree (uplink_heap, u);
91     cnt.uplink--;
92     }
93    
94     uplink_t *
95     uplink_find (char *name)
96     {
97     node_t *n;
98    
99     LIST_FOREACH (n, uplinks.head)
100     {
101     uplink_t *u = static_cast<uplink_t *> (n->data);
102    
103     if (!strcasecmp (u->name, name))
104     return u;
105     }
106    
107     return NULL;
108     }
109    
110     void
111     uplink_connect (void)
112     {
113     uplink_t *u;
114    
115     if (curr_uplink == NULL)
116     {
117     if (uplinks.head == NULL)
118     {
119     slog (LG_ERROR, "uplink_connect(): no uplinks configured, exiting. Make sure to have at least one uplink{} block in your configuration file.");
120     exit (EXIT_FAILURE);
121     }
122     curr_uplink = static_cast<uplink_t *> (uplinks.head->data);
123     slog (LG_INFO, "uplink_connect(): connecting to first entry %s[%s]:%d.", curr_uplink->name, curr_uplink->host, curr_uplink->port);
124     }
125     else if (curr_uplink->node->next)
126     {
127     u = static_cast<uplink_t *> (curr_uplink->node->next->data);
128    
129     curr_uplink = u;
130     slog (LG_INFO, "uplink_connect(): trying alternate uplink %s[%s]:%d", curr_uplink->name, curr_uplink->host, curr_uplink->port);
131     }
132     else
133     {
134     curr_uplink = static_cast<uplink_t *> (uplinks.head->data);
135     slog (LG_INFO, "uplink_connect(): trying again first entry %s[%s]:%d", curr_uplink->name, curr_uplink->host, curr_uplink->port);
136     }
137    
138     u = curr_uplink;
139    
140     curr_uplink->conn = connection_open_tcp (u->host, u->vhost, u->port, recvq_put, sendq_flush);
141     if (curr_uplink->conn != NULL)
142     curr_uplink->conn->close_handler = uplink_close;
143     else
144     event_add_once ("reconn", reconn, NULL, me.recontime);
145     }
146    
147     /*
148     * uplink_close()
149     *
150     * inputs:
151     * connection pointer of current uplink
152     * triggered by callback close_handler
153     *
154     * outputs:
155     * none
156     *
157     * side effects:
158     * reconnection is scheduled
159     * uplink marked dead
160     * uplink deleted if it had been removed from configuration
161     */
162     static void
163     uplink_close (connection_t *cptr)
164     {
165     channel_t *c;
166     dictionary_iteration_state_t state;
167    
168     event_add_once ("reconn", reconn, NULL, me.recontime);
169    
170     me.connected = false;
171    
172     if (curr_uplink->flags & UPF_ILLEGAL)
173     {
174     slog (LG_INFO, "uplink_close(): %s was removed from configuration, deleting", curr_uplink->name);
175     uplink_delete (curr_uplink);
176     if (uplinks.head == NULL)
177     {
178     slog (LG_ERROR, "uplink_close(): last uplink deleted, exiting.");
179     exit (EXIT_FAILURE);
180     }
181     curr_uplink = static_cast<uplink_t *> (uplinks.head->data);
182     }
183     curr_uplink->conn = NULL;
184    
185     slog (LG_DEBUG, "uplink_close(): ----------------------- clearing -----------------------");
186    
187     /* we have to kill everything.
188     * we do not clear users here because when you delete a server,
189     * it deletes its users
190     */
191     if (me.actual != NULL)
192     server_delete (me.actual);
193     me.actual = NULL;
194     /* remove all the channels left */
195     DICTIONARY_FOREACH (c, channel_t, &state, chanlist)
196     {
197     channel_delete (c);
198     }
199     /* this leaves me.me and all users on it (i.e. services) */
200    
201     slog (LG_DEBUG, "uplink_close(): ------------------------- done -------------------------");
202     }