2086
|
1 /*
|
|
2 * libyay
|
|
3 *
|
|
4 * Copyright (C) 2001 Eric Warmenhoven <warmenhoven@yahoo.com>
|
|
5 *
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
9 * (at your option) any later version.
|
|
10 *
|
|
11 * This program is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 * GNU General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License
|
|
17 * along with this program; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 *
|
|
20 */
|
|
21
|
|
22 #include "internal.h"
|
|
23
|
|
24 void (*yahoo_socket_notify)(struct yahoo_session *, int, int, gboolean) = NULL;
|
|
25 void (*yahoo_print)(struct yahoo_session *, int, const char *) = NULL;
|
|
26 int (*yahoo_connector)(struct yahoo_session *, const char *, int, gpointer) = NULL;
|
|
27
|
|
28 struct yahoo_session *yahoo_new()
|
|
29 {
|
|
30 struct yahoo_session *sess;
|
|
31
|
|
32 if (!(sess = g_new0(struct yahoo_session, 1)))
|
|
33 return NULL;
|
|
34
|
|
35 return sess;
|
|
36 }
|
|
37
|
|
38 void yahoo_set_proxy(struct yahoo_session *session, int proxy_type, char *proxy_host, int proxy_port)
|
|
39 {
|
|
40 if (!session || !proxy_type || !proxy_host)
|
|
41 return;
|
|
42
|
|
43 session->proxy_type = proxy_type;
|
|
44 session->proxy_host = g_strdup(proxy_host);
|
|
45 session->proxy_port = proxy_port;
|
|
46 }
|
|
47
|
|
48 static int yahoo_connect_host(struct yahoo_session *sess, const char *host, int port, int *statusret)
|
|
49 {
|
|
50 struct sockaddr_in sa;
|
|
51 struct hostent *hp;
|
|
52 int fd;
|
|
53
|
|
54 if (!(hp = gethostbyname(host))) {
|
|
55 YAHOO_PRINT(sess, YAHOO_LOG_WARNING, "Resolve error");
|
|
56 if (statusret)
|
|
57 *statusret = (h_errno | YAHOO_CONN_STATUS_RESOLVERR);
|
|
58 return -1;
|
|
59 }
|
|
60
|
|
61 memset(&sa, 0, sizeof(struct sockaddr_in));
|
|
62 sa.sin_port = htons(port);
|
|
63 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
|
|
64 sa.sin_family = hp->h_addrtype;
|
|
65
|
|
66 fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
|
|
67
|
|
68 fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
69
|
|
70 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
|
|
71 if ((errno == EINPROGRESS) || (errno == EINTR)) {
|
|
72 YAHOO_PRINT(sess, YAHOO_LOG_NOTICE, "Connect would block");
|
|
73 if (statusret)
|
|
74 *statusret |= YAHOO_CONN_STATUS_INPROGRESS;
|
|
75 return fd;
|
|
76 }
|
|
77 close(fd);
|
|
78 fd = -1;
|
|
79 }
|
|
80
|
|
81 return fd;
|
|
82 }
|
|
83
|
|
84 int yahoo_connected(struct yahoo_session *session, gpointer data, int fd)
|
|
85 {
|
|
86 struct yahoo_conn *conn = data;
|
|
87
|
|
88 if (fd < 0) {
|
|
89 YAHOO_PRINT(session, YAHOO_LOG_WARNING, "connect failed");
|
|
90 session->connlist = g_list_remove(session->connlist, conn);
|
|
91 g_free(conn);
|
|
92 return 0;
|
|
93 }
|
|
94
|
|
95 YAHOO_PRINT(session, YAHOO_LOG_NOTICE, "connect succeeded");
|
|
96 conn->socket = fd;
|
|
97 conn->connected = TRUE;
|
|
98 if (conn->type == YAHOO_CONN_TYPE_AUTH) {
|
|
99 if (session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)
|
|
100 (*session->callbacks[YAHOO_HANDLE_AUTHCONNECT].function)(session);
|
|
101 } else if (conn->type == YAHOO_CONN_TYPE_MAIN) {
|
|
102 if (session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)
|
|
103 (*session->callbacks[YAHOO_HANDLE_MAINCONNECT].function)(session);
|
|
104 } else if (conn->type == YAHOO_CONN_TYPE_DUMB) {
|
|
105 YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "sending to buddy list host");
|
|
106 yahoo_write(session, conn, conn->txqueue, strlen(conn->txqueue));
|
|
107 g_free(conn->txqueue);
|
|
108 conn->txqueue = NULL;
|
|
109 }
|
|
110
|
|
111 if (yahoo_socket_notify)
|
|
112 (*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_READ, TRUE);
|
|
113 else
|
|
114 YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "yahoo_socket_notify not set up");
|
|
115
|
|
116 return 1;
|
|
117 }
|
|
118
|
|
119 struct yahoo_conn *yahoo_new_conn(struct yahoo_session *session, int type, const char *host, int port)
|
|
120 {
|
|
121 struct yahoo_conn *conn;
|
|
122 int status;
|
|
123
|
|
124 if (!session)
|
|
125 return NULL;
|
|
126
|
|
127 conn = g_new0(struct yahoo_conn, 1);
|
|
128 conn->type = type;
|
|
129
|
|
130 if (yahoo_connector) {
|
|
131 YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "Connecting using user-specified connect routine");
|
|
132 if ((*yahoo_connector)(session, host, port, conn) < 0) {
|
|
133 YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "connect failed");
|
|
134 g_free(conn);
|
|
135 return NULL;
|
|
136 }
|
|
137 session->connlist = g_list_append(session->connlist, conn);
|
|
138 return conn;
|
|
139 }
|
|
140
|
|
141 if (session->proxy_type) {
|
|
142 YAHOO_PRINT(session, YAHOO_LOG_DEBUG, "connecting to proxy");
|
|
143 conn->socket = yahoo_connect_host(session, session->proxy_host,
|
|
144 session->proxy_port, &status);
|
|
145 if (type == YAHOO_CONN_TYPE_MAIN)
|
|
146 conn->type = YAHOO_CONN_TYPE_PROXY;
|
|
147 } else
|
|
148 conn->socket = yahoo_connect_host(session, host, port, &status);
|
|
149
|
|
150 if (conn->socket < 0) {
|
|
151 g_free(conn);
|
|
152 return NULL;
|
|
153 }
|
|
154
|
|
155 if (yahoo_socket_notify)
|
|
156 (*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_WRITE, TRUE);
|
|
157 else
|
|
158 YAHOO_PRINT(session, YAHOO_LOG_CRITICAL, "yahoo_socket_notify not set up");
|
|
159
|
|
160 session->connlist = g_list_append(session->connlist, conn);
|
|
161
|
|
162 return conn;
|
|
163 }
|
|
164
|
|
165 struct yahoo_conn *yahoo_getconn_type(struct yahoo_session *sess, int type)
|
|
166 {
|
|
167 GList *c;
|
|
168 struct yahoo_conn *conn;
|
|
169
|
|
170 if (!sess)
|
|
171 return NULL;
|
|
172
|
|
173 c = sess->connlist;
|
|
174 while (c) {
|
|
175 conn = c->data;
|
|
176 if (conn->type == type)
|
|
177 return conn;
|
|
178 c = g_list_next(c);
|
|
179 }
|
|
180
|
|
181 return NULL;
|
|
182 }
|
|
183
|
|
184 struct yahoo_conn *yahoo_find_conn(struct yahoo_session *sess, int socket)
|
|
185 {
|
|
186 GList *c;
|
|
187 struct yahoo_conn *conn;
|
|
188
|
|
189 c = sess->connlist;
|
|
190 while (c) {
|
|
191 conn = c->data;
|
|
192 if (conn->socket == socket)
|
|
193 return conn;
|
|
194 c = g_list_next(c);
|
|
195 }
|
|
196
|
|
197 return NULL;
|
|
198 }
|
|
199
|
|
200 int yahoo_connect(struct yahoo_session *session, const char *host, int port)
|
|
201 {
|
|
202 if (!session)
|
|
203 return 0;
|
|
204
|
|
205 if (session->auth_host)
|
|
206 g_free(session->auth_host);
|
|
207 if (host && *host)
|
|
208 session->auth_host = g_strdup(host);
|
|
209 else
|
|
210 session->auth_host = g_strdup(YAHOO_AUTH_HOST);
|
|
211
|
|
212 if (port)
|
|
213 session->auth_port = port;
|
|
214 else
|
|
215 session->auth_port = YAHOO_AUTH_PORT;
|
|
216
|
|
217 if (!yahoo_new_conn(session, YAHOO_CONN_TYPE_AUTH, session->auth_host, session->auth_port))
|
|
218 return 0;
|
|
219
|
|
220 return 1;
|
|
221 }
|
|
222
|
|
223 int yahoo_major_connect(struct yahoo_session *session, const char *host, int port)
|
|
224 {
|
|
225 if (!session)
|
|
226 return 0;
|
|
227
|
|
228 if (session->pager_host)
|
|
229 g_free(session->pager_host);
|
|
230 if (host && *host)
|
|
231 session->pager_host = g_strdup(host);
|
|
232 else
|
|
233 session->pager_host = g_strdup(YAHOO_PAGER_HOST);
|
|
234
|
|
235 if (port)
|
|
236 session->pager_port = port;
|
|
237 else
|
|
238 session->pager_port = YAHOO_AUTH_PORT;
|
|
239
|
|
240 if (!yahoo_new_conn(session, YAHOO_CONN_TYPE_MAIN, session->pager_host, session->pager_port))
|
|
241 return 0;
|
|
242
|
|
243 return 1;
|
|
244 }
|
|
245
|
|
246 void yahoo_close(struct yahoo_session *session, struct yahoo_conn *conn)
|
|
247 {
|
|
248 if (!session || !conn)
|
|
249 return;
|
|
250
|
|
251 if (!g_list_find(session->connlist, conn))
|
|
252 return;
|
|
253
|
|
254 if (yahoo_socket_notify) {
|
|
255 if (conn->connected)
|
|
256 (*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_READ, FALSE);
|
|
257 else
|
|
258 (*yahoo_socket_notify)(session, conn->socket, YAHOO_SOCKET_WRITE, FALSE);
|
|
259 }
|
|
260 close(conn->socket);
|
|
261
|
|
262 session->connlist = g_list_remove(session->connlist, conn);
|
|
263 if (conn->txqueue)
|
|
264 g_free(conn->txqueue);
|
|
265 g_free(conn);
|
|
266 }
|
|
267
|
|
268 int yahoo_disconnect(struct yahoo_session *session)
|
|
269 {
|
|
270 if (!session)
|
|
271 return 0;
|
|
272 if (session->name)
|
|
273 g_free(session->name);
|
|
274 yahoo_logoff(session);
|
|
275 session->name = NULL;
|
|
276 while (session->connlist)
|
|
277 yahoo_close(session, session->connlist->data);
|
|
278 if (session->cookie)
|
|
279 g_free(session->cookie);
|
|
280 session->cookie = NULL;
|
|
281 if (session->login_cookie)
|
|
282 g_free(session->login_cookie);
|
|
283 session->login_cookie = NULL;
|
|
284 while (session->ignored) {
|
|
285 g_free(session->ignored->data);
|
|
286 session->ignored = g_list_remove(session->ignored, session->ignored->data);
|
|
287 }
|
|
288 if (session->identities)
|
|
289 g_strfreev(session->identities);
|
|
290 session->identities = NULL;
|
|
291 if (session->login)
|
|
292 g_free(session->login);
|
|
293 session->login = NULL;
|
|
294 while (session->groups) {
|
|
295 struct yahoo_group *grp = session->groups->data;
|
|
296 g_strfreev(grp->buddies);
|
|
297 g_free(grp->name);
|
|
298 g_free(grp);
|
|
299 session->groups = g_list_remove(session->groups, grp);
|
|
300 }
|
|
301 if (session->auth_host)
|
|
302 g_free(session->auth_host);
|
|
303 session->auth_host = NULL;
|
|
304 if (session->pager_host)
|
|
305 g_free(session->pager_host);
|
|
306 session->pager_host = NULL;
|
|
307 return 0;
|
|
308 }
|
|
309
|
|
310 int yahoo_delete(struct yahoo_session *session)
|
|
311 {
|
|
312 if (!session)
|
|
313 return 0;
|
|
314 if (session->proxy_host)
|
|
315 g_free(session->proxy_host);
|
|
316 g_free(session);
|
|
317 return 0;
|
|
318 }
|