ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/pxys2-2.0.0/pxyservd/src/session.c
Revision: 3252
Committed: Wed Apr 2 20:41:43 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 7746 byte(s)
Log Message:
- Imported pxys2-2.0.0

File Contents

# Content
1 /* Copyright (C) 2003, 2004 Stephane Thiell
2 *
3 * This file is part of pxyservd (from pxys)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20 #define RCSID "$Id: session.c,v 1.4 2004/01/10 18:15:36 mbuna Exp $"
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "session.h"
27
28 #include <peak/peak.h>
29
30 #include <assert.h>
31 #include <signal.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36
37 #include "cfgloader.h"
38 #include "debug.h"
39 #include "evreg.h"
40 #include "irc_auth.h"
41 #include "irc_init.h"
42 #include "irc_network.h" /* irc_network_squit_downlink() */
43 #include "irc_parser.h"
44 #include "irc_send.h"
45
46 #include "scan.h" /* scan_init() */
47
48 peak_stream gIRCStream; /* IRC Stream reference - global */
49
50 time_t link_timestamp;
51
52 static CHubLink *hubLink;
53 static peak_timer timer_recon;
54
55 #define LINK_STATUS_DISCONNECTED 0
56 #define LINK_STATUS_CONNECTED 1
57 #define LINK_STATUS_SQUITTED 2
58 static int link_status = LINK_STATUS_DISCONNECTED;
59
60 static void session_init(void);
61 static int session_try_hub(void);
62 static int session_open(CHubLink *hublink);
63
64 static void session_stream_event(peak_stream s, int type, void *context);
65 static void session_stream_error(peak_stream s, int error_type, void *context);
66 static void session_timer_recon(peak_timer ti, void *context);
67
68 /* Initialize session module, create reconnect timer and interruptions
69 * notification object for handling signals.
70 */
71 static void
72 session_init()
73 {
74 /* It's wise to use a reconnection timer for several reasons. We use it as a
75 * starter too here (it will be called immediately when the task starts).
76 */
77 timer_recon = peak_timer_create(0, -1, session_timer_recon, NULL);
78 peak_task_timer_add(peak_task_self(), timer_recon);
79 }
80
81 static int
82 session_try_hub()
83 {
84 int i;
85
86 for (i = 0; i < gConfig->nhubs; i++)
87 {
88 /* The first hub in the configuration file has got the highest priority
89 */
90 hubLink = cfgloader_next_hublink(hubLink);
91 assert(hubLink != NULL);
92
93 /* Try to establish connection */
94 if (session_open(hubLink) == 0)
95 break;
96 }
97 cfgloader_retain_hublink(hubLink); /* Be sure we won't dispose this hub */
98 return 0;
99 }
100
101 static int
102 session_open(CHubLink *hublink)
103 {
104 struct sockaddr_in sin;
105
106 Debug((DL_BASIC, "session_open"));
107
108 memset(&sin, 0, sizeof(struct sockaddr_in));
109 sin.sin_family = AF_INET;
110 sin.sin_addr = hublink->hub.address;
111 sin.sin_port = htons((unsigned short)hublink->hub.port);
112
113 /* Create socket stream */
114 gIRCStream = peak_stream_socket_create((struct sockaddr *)&sin,
115 sizeof(sin),
116 PEAK_STREAM_OPT_LINEMODE,
117 session_stream_event,
118 NULL);
119 if (!gIRCStream)
120 {
121 Debug((DL_BASIC, "session_open: peak_stream_socket_create failed!"));
122 return -1;
123 }
124
125 if (hublink->hub.bind_address.s_addr != INADDR_ANY)
126 {
127 struct sockaddr_in local_sin;
128 memset(&local_sin, 0, sizeof(local_sin));
129 local_sin.sin_family = AF_INET;
130 local_sin.sin_addr = hublink->hub.bind_address;
131 local_sin.sin_port = htons(0);
132
133 peak_stream_set_address(gIRCStream, (struct sockaddr *)&local_sin,
134 sizeof(local_sin));
135 }
136
137 peak_stream_set_buffered(gIRCStream, 1, MSGBUF_SIZE,
138 gConfig->server.sendq,
139 session_stream_error);
140
141 /* Tell peak library that a connection should be established... */
142 if (peak_stream_connect(gIRCStream) != 0)
143 {
144 Debug((DL_BASIC, "session_open: peak_stream_connect failed!"));
145 peak_release(gIRCStream);
146 return -1;
147 }
148
149 /* Schedule connection stream with our current task */
150 peak_stream_schedule(gIRCStream, peak_task_self());
151 return 0;
152 }
153
154 static void
155 session_close()
156 {
157 gIRCStream = NULL;
158
159 irc_network_squit_downlink();
160
161 assert(irc_network_get_remote_server_count() == 0);
162
163 peak_timer_configure(timer_recon, 30, -1); /* First, wait a bit. */
164 peak_task_timer_add(peak_task_self(), timer_recon);
165
166 irc_reinit(); /* Then, reinit IRC modules */
167 evreg_finalize();
168 evreg_init();
169 }
170
171 static void
172 session_stream_event(peak_stream s, int type, void *context)
173 {
174 switch (type)
175 {
176 case PEAK_STREAM_EVT_OPEN:
177 link_status = LINK_STATUS_CONNECTED;
178 link_timestamp = peak_time();
179 irc_auth(hubLink->hub.password);
180 break;
181 case PEAK_STREAM_EVT_READ:
182 if (link_status == LINK_STATUS_CONNECTED)
183 irc_parser_parse_line(peak_stream_get_line(s));
184 break;
185 case PEAK_STREAM_EVT_WRITE:
186 /* In buffered mode, it means "write completed"...
187 * Anyway we don't use it at all for now.
188 */
189 break;
190 case PEAK_STREAM_EVT_END:
191 Debug((DL_BASIC, "[EOF] end from server"));
192 link_status = LINK_STATUS_DISCONNECTED;
193 peak_release(s);
194 session_close();
195 break;
196 case PEAK_STREAM_EVT_ERROR:
197 Debug((DL_BASIC, "[ERR] stream error with server"));
198 link_status = LINK_STATUS_DISCONNECTED;
199 peak_release(s);
200 session_close();
201 break;
202 default:
203 fprintf(stderr, "type=%d\n", type);
204 assert(0);
205 break;
206 }
207 }
208
209 static void
210 session_stream_error(peak_stream s, int error_type, void *context)
211 {
212 Debug((DL_BASIC, "session_stream_error: MAX SENDQ EXCEEDED (%d)",
213 error_type));
214 if (link_status == LINK_STATUS_CONNECTED)
215 {
216 send_squit("Max SendQ Exceeded");
217 link_status = LINK_STATUS_SQUITTED;
218 peak_timer_configure(timer_recon, 5, -1);
219 peak_task_timer_add(peak_task_self(), timer_recon);
220 }
221 }
222
223 static void
224 session_timer_recon(peak_timer ti, void *context)
225 {
226 Debug((DL_BASIC, "session_recon: trying to reconnect pxyservd"));
227
228 if (link_status == LINK_STATUS_SQUITTED)
229 {
230 peak_stream_disconnect(gIRCStream); /* Enough! */
231 peak_timer_configure(timer_recon, 5, -1); /* Wait, again. */
232 return;
233 }
234
235 assert(link_status == LINK_STATUS_DISCONNECTED);
236
237 session_try_hub();
238 peak_task_timer_remove(peak_task_self(), timer_recon);
239 }
240
241 /* Public methods */
242 void
243 session_run(void)
244 {
245 session_init(); /* Setup some things like auto reconnection timer */
246 evreg_init(); /* EVREG management */
247 irc_init(); /* Initialize IRC modules */
248 scan_init(); /* Initialize scan stuffs and PCKP/UDP server */
249
250 /* Run task event loop
251 */
252 Debug((DL_BASIC, "Running task..."));
253 peak_task_run(peak_task_self());
254 Debug((DL_BASIC, "Exiting from peak_task_run"));
255 }
256
257 void
258 session_reload(void)
259 {
260 Debug((DL_BASIC, "session_cfg_reload: reloading configuration file..."));
261 hubLink = NULL; /* reset hub list as it's gonna change */
262
263 /* TODO */
264
265 #if 0
266 scan_finalize();
267 scan_init(session_runloop);
268 #endif
269 }
270
271 void
272 session_stop(const char *message)
273 {
274 Debug((DL_BASIC, "session_stop (%s)", message));
275 send_squit(message); /* can put in sendq but we don't care */
276 peak_task_break(peak_task_self());
277 }