ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/uplink.C
Revision: 1.3
Committed: Sat Jul 21 13:23:22 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
- added rcsid to some files
- more documentation tweaks
- made most protocol commands local to phandler.C
- added ircd metadata (inspircd only for now)
- added inspircd swhois support

File Contents

# Content
1 /*
2 * uplink.C: Uplink management.
3 * Rights to this code are documented in doc/pod/license.pod.
4 *
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 }