diff options
author | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2010-12-07 04:48:14 +0000 |
---|---|---|
committer | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2010-12-07 04:48:14 +0000 |
commit | 14c652150c9a6339c792eb1911da809327237123 (patch) | |
tree | ad1bfa3e8818651ae8e4026f7571ec6392fb45b0 /libsylph/session.c | |
parent | 3a54dc9a9d8e28b9415552512d45d172528d1a78 (diff) |
added SOCKS4/5 proxy support.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2733 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph/session.c')
-rw-r--r-- | libsylph/session.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/libsylph/session.c b/libsylph/session.c index 0b561eda..f45138f0 100644 --- a/libsylph/session.c +++ b/libsylph/session.c @@ -1,6 +1,6 @@ /* * LibSylph -- E-Mail client library - * Copyright (C) 1999-2009 Hiroyuki Yamamoto + * Copyright (C) 1999-2010 Hiroyuki Yamamoto * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,6 +35,18 @@ #include "session.h" #include "utils.h" +typedef struct _SessionPrivData SessionPrivData; + +struct _SessionPrivData { + Session *session; + SocksInfo *socks_info; + gpointer data; +}; + +static GList *priv_list = NULL; + +static SessionPrivData *session_get_priv(Session *session); + static gint session_connect_cb (SockInfo *sock, gpointer data); static gint session_close (Session *session); @@ -117,8 +129,30 @@ void session_init(Session *session) session->data = NULL; } +static SessionPrivData *session_get_priv(Session *session) +{ + SessionPrivData *priv; + GList *cur; + + g_return_val_if_fail(session != NULL, NULL); + + for (cur = priv_list; cur != NULL; cur = cur->next) { + priv = (SessionPrivData *)cur->data; + if (priv->session == session) + return priv; + } + + return NULL; +} + gint session_connect(Session *session, const gchar *server, gushort port) { + return session_connect_full(session, server, port, NULL); +} + +gint session_connect_full(Session *session, const gchar *server, gushort port, + SocksInfo *socks_info) +{ #ifndef G_OS_UNIX SockInfo *sock = NULL; #endif @@ -132,6 +166,11 @@ gint session_connect(Session *session, const gchar *server, gushort port) } session->port = port; + if (socks_info) { + server = socks_info->proxy_host; + port = socks_info->proxy_port; + } + #ifdef G_OS_UNIX session->conn_id = sock_connect_async(server, port, session_connect_cb, session); @@ -140,8 +179,6 @@ gint session_connect(Session *session, const gchar *server, gushort port) session->state = SESSION_ERROR; return -1; } - - return 0; #elif USE_THREADS session->conn_id = sock_connect_async_thread(server, port); if (session->conn_id < 0) { @@ -154,8 +191,6 @@ gint session_connect(Session *session, const gchar *server, gushort port) session->state = SESSION_ERROR; return -1; } - - return session_connect_cb(sock, session); #else /* !USE_THREADS */ sock = sock_connect(server, port); if (sock == NULL) { @@ -163,7 +198,20 @@ gint session_connect(Session *session, const gchar *server, gushort port) session->state = SESSION_ERROR; return -1; } +#endif + + if (socks_info) { + SessionPrivData *priv; + + priv = g_new0(SessionPrivData, 1); + priv->session = session; + priv->socks_info = socks_info; + priv_list = g_list_prepend(priv_list, priv); + } +#ifdef G_OS_UNIX + return 0; +#else return session_connect_cb(sock, session); #endif } @@ -171,6 +219,7 @@ gint session_connect(Session *session, const gchar *server, gushort port) static gint session_connect_cb(SockInfo *sock, gpointer data) { Session *session = SESSION(data); + SessionPrivData *priv; session->conn_id = 0; @@ -182,6 +231,17 @@ static gint session_connect_cb(SockInfo *sock, gpointer data) session->sock = sock; + priv = session_get_priv(session); + if (priv && priv->socks_info) { + sock_set_nonblocking_mode(sock, FALSE); + if (socks_connect(sock, session->server, session->port, + priv->socks_info) < 0) { + g_warning("can't establish SOCKS connection."); + session->state = SESSION_ERROR; + return -1; + } + } + #if USE_SSL if (session->ssl_type == SSL_TUNNEL) { sock_set_nonblocking_mode(sock, FALSE); @@ -217,6 +277,8 @@ gint session_disconnect(Session *session) void session_destroy(Session *session) { + SessionPrivData *priv; + g_return_if_fail(session != NULL); g_return_if_fail(session->destroy != NULL); @@ -230,6 +292,13 @@ void session_destroy(Session *session) fclose(session->read_data_fp); g_free(session->write_buf); + priv = session_get_priv(session); + if (priv) { + priv_list = g_list_remove(priv_list, priv); + socks_info_free(priv->socks_info); + g_free(priv); + } + debug_print("session (%p): destroyed\n", session); g_free(session); |