* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Youness Alaoui <youness.alaoui@collabora.co.uk
*
#include "goutputstream.h"
#include "gproxy.h"
#include "gproxyaddress.h"
-#include "gsimpleasyncresult.h"
+#include "gtask.h"
#define SOCKS5_VERSION 0x05
case SOCKS5_AUTH_NO_ACCEPT:
default:
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED,
- _("The SOCKSv5 proxy requires an authentication method that is not "
- "supported by GLib."));
+ _("The SOCKSv5 proxy requires an authentication "
+ "method that is not supported by GLib."));
return FALSE;
break;
}
if (ulen > SOCKS5_MAX_LEN || plen > SOCKS5_MAX_LEN)
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
- _("Username or password is too long for SOCKSv5 "
- "protocol (max. is %i)."),
- SOCKS5_MAX_LEN);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
+ _("Username or password is too long for SOCKSv5 "
+ "protocol."));
return FALSE;
}
if (host_len > SOCKS5_MAX_LEN)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
- _("Hostname '%s' too long for SOCKSv5 protocol "
- "(maximum is %i bytes)"),
- hostname, SOCKS5_MAX_LEN);
+ _("Hostname '%s' is too long for SOCKSv5 protocol"),
+ hostname);
return -1;
}
default:
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
- _("The SOCKSv5 proxy server uses unkown address type."));
+ _("The SOCKSv5 proxy server uses unknown address type."));
return FALSE;
}
break;
default: /* Unknown error */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
- _("Unkown SOCKSv5 proxy error."));
+ _("Unknown SOCKSv5 proxy error."));
return FALSE;
break;
}
goto error;
}
- /* Recieve SOCKS5 response and reply with authentication if required */
+ /* Receive SOCKS5 response and reply with authentication if required */
{
guint8 data[SOCKS5_NEGO_REP_LEN];
gboolean must_auth = FALSE;
typedef struct
{
- GSimpleAsyncResult *simple;
GIOStream *io_stream;
gchar *hostname;
guint16 port;
guint8 *buffer;
gssize length;
gssize offset;
- GCancellable *cancellable;
} ConnectAsyncData;
static void nego_msg_write_cb (GObject *source,
static void auth_reply_read_cb (GObject *source,
GAsyncResult *result,
gpointer user_data);
-static void send_connect_msg (ConnectAsyncData *data);
+static void send_connect_msg (GTask *task);
static void connect_msg_write_cb (GObject *source,
GAsyncResult *result,
gpointer user_data);
static void
free_connect_data (ConnectAsyncData *data)
{
- if (data->io_stream)
- g_object_unref (data->io_stream);
+ g_object_unref (data->io_stream);
g_free (data->hostname);
g_free (data->username);
g_free (data->password);
g_free (data->buffer);
-
- if (data->cancellable)
- g_object_unref (data->cancellable);
g_slice_free (ConnectAsyncData, data);
}
static void
-complete_async_from_error (ConnectAsyncData *data, GError *error)
-{
- GSimpleAsyncResult *simple = data->simple;
- g_simple_async_result_take_error (data->simple, error);
- g_simple_async_result_set_op_res_gpointer (simple, NULL, NULL);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-}
-
-static void
-do_read (GAsyncReadyCallback callback, ConnectAsyncData *data)
+do_read (GAsyncReadyCallback callback, GTask *task, ConnectAsyncData *data)
{
GInputStream *in;
in = g_io_stream_get_input_stream (data->io_stream);
g_input_stream_read_async (in,
data->buffer + data->offset,
data->length - data->offset,
- G_PRIORITY_DEFAULT, data->cancellable,
- callback, data);
+ g_task_get_priority (task),
+ g_task_get_cancellable (task),
+ callback, task);
}
static void
-do_write (GAsyncReadyCallback callback, ConnectAsyncData *data)
+do_write (GAsyncReadyCallback callback, GTask *task, ConnectAsyncData *data)
{
GOutputStream *out;
out = g_io_stream_get_output_stream (data->io_stream);
g_output_stream_write_async (out,
data->buffer + data->offset,
data->length - data->offset,
- G_PRIORITY_DEFAULT, data->cancellable,
- callback, data);
+ g_task_get_priority (task),
+ g_task_get_cancellable (task),
+ callback, task);
}
static void
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *simple;
+ GTask *task;
ConnectAsyncData *data;
- simple = g_simple_async_result_new (G_OBJECT (proxy),
- callback, user_data,
- g_socks5_proxy_connect_async);
-
data = g_slice_new0 (ConnectAsyncData);
-
- data->simple = simple;
data->io_stream = g_object_ref (io_stream);
- if (cancellable)
- data->cancellable = g_object_ref (cancellable);
+ task = g_task_new (proxy, cancellable, callback, user_data);
+ g_task_set_task_data (task, data, (GDestroyNotify) free_connect_data);
g_object_get (G_OBJECT (proxy_address),
"destination-hostname", &data->hostname,
"password", &data->password,
NULL);
- g_simple_async_result_set_op_res_gpointer (simple, data,
- (GDestroyNotify) free_connect_data);
-
data->buffer = g_malloc0 (SOCKS5_NEGO_MSG_LEN);
data->length = set_nego_msg (data->buffer,
data->username || data->password);
data->offset = 0;
- do_write (nego_msg_write_cb, data);
+ do_write (nego_msg_write_cb, task, data);
}
GAsyncResult *res,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize written;
written = g_output_stream_write_finish (G_OUTPUT_STREAM (source),
if (written < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
data->length = SOCKS5_NEGO_REP_LEN;
data->offset = 0;
- do_read (nego_reply_read_cb, data);
+ do_read (nego_reply_read_cb, task, data);
}
else
{
- do_write (nego_msg_write_cb, data);
+ do_write (nego_msg_write_cb, task, data);
}
}
GAsyncResult *res,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize read;
read = g_input_stream_read_finish (G_INPUT_STREAM (source),
if (read < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
if (data->offset == data->length)
{
- GError *error;
+ GError *error = NULL;
gboolean must_auth = FALSE;
gboolean has_auth = data->username || data->password;
if (!parse_nego_reply (data->buffer, has_auth, &must_auth, &error))
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
if (data->length < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- do_write (auth_msg_write_cb, data);
+ do_write (auth_msg_write_cb, task, data);
}
else
{
- send_connect_msg (data);
+ send_connect_msg (task);
}
}
else
{
- do_read (nego_reply_read_cb, data);
+ do_read (nego_reply_read_cb, task, data);
}
}
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize written;
written = g_output_stream_write_finish (G_OUTPUT_STREAM (source),
if (written < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
data->length = SOCKS5_NEGO_REP_LEN;
data->offset = 0;
- do_read (auth_reply_read_cb, data);
+ do_read (auth_reply_read_cb, task, data);
}
else
{
- do_write (auth_msg_write_cb, data);
+ do_write (auth_msg_write_cb, task, data);
}
}
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize read;
read = g_input_stream_read_finish (G_INPUT_STREAM (source),
if (read < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
{
if (!check_auth_status (data->buffer, &error))
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- send_connect_msg (data);
+ send_connect_msg (task);
}
else
{
- do_read (auth_reply_read_cb, data);
+ do_read (auth_reply_read_cb, task, data);
}
}
static void
-send_connect_msg (ConnectAsyncData *data)
+send_connect_msg (GTask *task)
{
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
g_free (data->buffer);
if (data->length < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- do_write (connect_msg_write_cb, data);
+ do_write (connect_msg_write_cb, task, data);
}
static void
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize written;
written = g_output_stream_write_finish (G_OUTPUT_STREAM (source),
if (written < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
data->length = 4;
data->offset = 0;
- do_read (connect_reply_read_cb, data);
+ do_read (connect_reply_read_cb, task, data);
}
else
{
- do_write (connect_msg_write_cb, data);
+ do_write (connect_msg_write_cb, task, data);
}
}
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize read;
read = g_input_stream_read_finish (G_INPUT_STREAM (source),
if (read < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
if (!parse_connect_reply (data->buffer, &atype, &error))
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
case SOCKS5_ATYP_IPV4:
data->length = 6;
data->offset = 0;
- do_read (connect_addr_read_cb, data);
+ do_read (connect_addr_read_cb, task, data);
break;
case SOCKS5_ATYP_IPV6:
data->length = 18;
data->offset = 0;
- do_read (connect_addr_read_cb, data);
+ do_read (connect_addr_read_cb, task, data);
break;
case SOCKS5_ATYP_DOMAINNAME:
data->length = 1;
data->offset = 0;
- do_read (connect_addr_len_read_cb, data);
+ do_read (connect_addr_len_read_cb, task, data);
break;
}
}
else
{
- do_read (connect_reply_read_cb, data);
+ do_read (connect_reply_read_cb, task, data);
}
}
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize read;
read = g_input_stream_read_finish (G_INPUT_STREAM (source),
if (read < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
data->length = data->buffer[0] + 2;
data->offset = 0;
- do_read (connect_addr_read_cb, data);
+ do_read (connect_addr_read_cb, task, data);
}
static void
GAsyncResult *result,
gpointer user_data)
{
+ GTask *task = user_data;
+ ConnectAsyncData *data = g_task_get_task_data (task);
GError *error = NULL;
- ConnectAsyncData *data = user_data;
gssize read;
read = g_input_stream_read_finish (G_INPUT_STREAM (source),
if (read < 0)
{
- complete_async_from_error (data, error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
if (data->offset == data->length)
{
- GSimpleAsyncResult *simple = data->simple;
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ g_task_return_pointer (task, g_object_ref (data->io_stream), g_object_unref);
+ g_object_unref (task);
+ return;
}
else
{
- do_read (connect_reply_read_cb, data);
+ do_read (connect_reply_read_cb, task, data);
}
}
GAsyncResult *result,
GError **error)
{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
- ConnectAsyncData *data = g_simple_async_result_get_op_res_gpointer (simple);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
-
- return g_object_ref (data->io_stream);
+ return g_task_propagate_pointer (G_TASK (result), error);
}
static gboolean