|
Packit |
ae235b |
#include <gio/gio.h>
|
|
Packit |
ae235b |
#include <string.h>
|
|
Packit |
ae235b |
#include <stdio.h>
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
GMainLoop *loop;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
int cancel_timeout = 0;
|
|
Packit |
ae235b |
int io_timeout = 0;
|
|
Packit |
ae235b |
gboolean async = FALSE;
|
|
Packit |
ae235b |
gboolean graceful = FALSE;
|
|
Packit |
ae235b |
gboolean verbose = FALSE;
|
|
Packit |
ae235b |
static GOptionEntry cmd_entries[] = {
|
|
Packit |
ae235b |
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
|
Packit |
ae235b |
"Cancel any op after the specified amount of seconds", NULL},
|
|
Packit |
ae235b |
{"async", 'a', 0, G_OPTION_ARG_NONE, &async,
|
|
Packit |
ae235b |
"Use async ops", NULL},
|
|
Packit |
ae235b |
{"graceful-disconnect", 'g', 0, G_OPTION_ARG_NONE, &graceful,
|
|
Packit |
ae235b |
"Use graceful disconnect", NULL},
|
|
Packit |
ae235b |
{"timeout", 't', 0, G_OPTION_ARG_INT, &io_timeout,
|
|
Packit |
ae235b |
"Time out socket I/O after the specified number of seconds", NULL},
|
|
Packit |
ae235b |
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
|
|
Packit |
ae235b |
"Verbose debugging output", NULL},
|
|
Packit |
ae235b |
{NULL}
|
|
Packit |
ae235b |
};
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static gpointer
|
|
Packit |
ae235b |
cancel_thread (gpointer data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GCancellable *cancellable = data;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_usleep (1000*1000*cancel_timeout);
|
|
Packit |
ae235b |
g_print ("Cancelling\n");
|
|
Packit |
ae235b |
g_cancellable_cancel (cancellable);
|
|
Packit |
ae235b |
return NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static char *
|
|
Packit |
ae235b |
socket_address_to_string (GSocketAddress *address)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GInetAddress *inet_address;
|
|
Packit |
ae235b |
char *str, *res;
|
|
Packit |
ae235b |
int port;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
|
|
Packit |
ae235b |
str = g_inet_address_to_string (inet_address);
|
|
Packit |
ae235b |
port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
|
|
Packit |
ae235b |
res = g_strdup_printf ("%s:%d", str, port);
|
|
Packit |
ae235b |
g_free (str);
|
|
Packit |
ae235b |
return res;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
async_cb (GObject *source_object,
|
|
Packit |
ae235b |
GAsyncResult *res,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GAsyncResult **resp = user_data;
|
|
Packit |
ae235b |
*resp = g_object_ref (res);
|
|
Packit |
ae235b |
g_main_loop_quit (loop);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
socket_client_event (GSocketClient *client,
|
|
Packit |
ae235b |
GSocketClientEvent event,
|
|
Packit |
ae235b |
GSocketConnectable *connectable,
|
|
Packit |
ae235b |
GSocketConnection *connection)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
static GEnumClass *event_class;
|
|
Packit |
ae235b |
GTimeVal tv;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!event_class)
|
|
Packit |
ae235b |
event_class = g_type_class_ref (G_TYPE_SOCKET_CLIENT_EVENT);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_get_current_time (&tv;;
|
|
Packit |
ae235b |
printf ("% 12ld.%06ld GSocketClient => %s [%s]\n",
|
|
Packit |
ae235b |
tv.tv_sec, tv.tv_usec,
|
|
Packit |
ae235b |
g_enum_get_value (event_class, event)->value_nick,
|
|
Packit |
ae235b |
connection ? G_OBJECT_TYPE_NAME (connection) : "");
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
int
|
|
Packit |
ae235b |
main (int argc, char *argv[])
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GOptionContext *context;
|
|
Packit |
ae235b |
GSocketClient *client;
|
|
Packit |
ae235b |
GSocketConnection *connection;
|
|
Packit |
ae235b |
GSocketAddress *address;
|
|
Packit |
ae235b |
GCancellable *cancellable;
|
|
Packit |
ae235b |
GOutputStream *out;
|
|
Packit |
ae235b |
GError *error = NULL;
|
|
Packit |
ae235b |
char buffer[1000];
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
context = g_option_context_new (" <hostname>[:port] - send data to tcp host");
|
|
Packit |
ae235b |
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
|
Packit |
ae235b |
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_printerr ("%s: %s\n", argv[0], error->message);
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (argc != 2)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (async)
|
|
Packit |
ae235b |
loop = g_main_loop_new (NULL, FALSE);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (cancel_timeout)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GThread *thread;
|
|
Packit |
ae235b |
cancellable = g_cancellable_new ();
|
|
Packit |
ae235b |
thread = g_thread_new ("cancel", cancel_thread, cancellable);
|
|
Packit |
ae235b |
g_thread_unref (thread);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
cancellable = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
client = g_socket_client_new ();
|
|
Packit |
ae235b |
if (io_timeout)
|
|
Packit |
ae235b |
g_socket_client_set_timeout (client, io_timeout);
|
|
Packit |
ae235b |
if (verbose)
|
|
Packit |
ae235b |
g_signal_connect (client, "event", G_CALLBACK (socket_client_event), NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (async)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GAsyncResult *res;
|
|
Packit |
ae235b |
g_socket_client_connect_to_host_async (client, argv[1], 7777,
|
|
Packit |
ae235b |
cancellable, async_cb, &res;;
|
|
Packit |
ae235b |
g_main_loop_run (loop);
|
|
Packit |
ae235b |
connection = g_socket_client_connect_to_host_finish (client, res, &error);
|
|
Packit |
ae235b |
g_object_unref (res);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
connection = g_socket_client_connect_to_host (client,
|
|
Packit |
ae235b |
argv[1],
|
|
Packit |
ae235b |
7777,
|
|
Packit |
ae235b |
cancellable, &error);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
if (connection == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_printerr ("%s can't connect: %s\n", argv[0], error->message);
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
g_object_unref (client);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
address = g_socket_connection_get_remote_address (connection, &error);
|
|
Packit |
ae235b |
if (!address)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_printerr ("Error getting remote address: %s\n",
|
|
Packit |
ae235b |
error->message);
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
g_print ("Connected to address: %s\n",
|
|
Packit |
ae235b |
socket_address_to_string (address));
|
|
Packit |
ae235b |
g_object_unref (address);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (graceful)
|
|
Packit |
ae235b |
g_tcp_connection_set_graceful_disconnect (G_TCP_CONNECTION (connection), TRUE);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
while (fgets(buffer, sizeof (buffer), stdin) != NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
/* FIXME if (async) */
|
|
Packit |
ae235b |
if (!g_output_stream_write_all (out, buffer, strlen (buffer),
|
|
Packit |
ae235b |
NULL, cancellable, &error))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_warning ("send error: %s\n", error->message);
|
|
Packit |
ae235b |
g_error_free (error);
|
|
Packit |
ae235b |
error = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_print ("closing stream\n");
|
|
Packit |
ae235b |
if (async)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GAsyncResult *res;
|
|
Packit |
ae235b |
g_io_stream_close_async (G_IO_STREAM (connection),
|
|
Packit |
ae235b |
0, cancellable, async_cb, &res;;
|
|
Packit |
ae235b |
g_main_loop_run (loop);
|
|
Packit |
ae235b |
if (!g_io_stream_close_finish (G_IO_STREAM (connection),
|
|
Packit |
ae235b |
res, &error))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (res);
|
|
Packit |
ae235b |
g_warning ("close error: %s\n", error->message);
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
g_object_unref (res);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (!g_io_stream_close (G_IO_STREAM (connection), cancellable, &error))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_warning ("close error: %s\n", error->message);
|
|
Packit |
ae235b |
return 1;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (connection);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
return 0;
|
|
Packit |
ae235b |
}
|