send-data.c 5.16 KB
Newer Older
1 2 3 4
#include <gio/gio.h>
#include <string.h>
#include <stdio.h>

5 6
GMainLoop *loop;

7
int cancel_timeout = 0;
8
int io_timeout = 0;
9 10
gboolean async = FALSE;
gboolean graceful = FALSE;
11
gboolean verbose = FALSE;
12 13 14
static GOptionEntry cmd_entries[] = {
  {"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
   "Cancel any op after the specified amount of seconds", NULL},
15 16 17 18
  {"async", 'a', 0, G_OPTION_ARG_NONE, &async,
   "Use async ops", NULL},
  {"graceful-disconnect", 'g', 0, G_OPTION_ARG_NONE, &graceful,
   "Use graceful disconnect", NULL},
19 20
  {"timeout", 't', 0, G_OPTION_ARG_INT, &io_timeout,
   "Time out socket I/O after the specified number of seconds", NULL},
21 22
  {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
   "Verbose debugging output", NULL},
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  {NULL}
};

static gpointer
cancel_thread (gpointer data)
{
  GCancellable *cancellable = data;

  g_usleep (1000*1000*cancel_timeout);
  g_print ("Cancelling\n");
  g_cancellable_cancel (cancellable);
  return NULL;
}

static char *
socket_address_to_string (GSocketAddress *address)
{
  GInetAddress *inet_address;
  char *str, *res;
  int port;

  inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
  str = g_inet_address_to_string (inet_address);
  port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
  res = g_strdup_printf ("%s:%d", str, port);
  g_free (str);
  return res;
}

52 53 54 55 56 57 58 59 60 61
static void
async_cb (GObject *source_object,
	  GAsyncResult *res,
	  gpointer user_data)
{
  GAsyncResult **resp = user_data;
  *resp = g_object_ref (res);
  g_main_loop_quit (loop);
}

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
static void
socket_client_event (GSocketClient *client,
		     GSocketClientEvent event,
		     GSocketConnectable *connectable,
		     GSocketConnection *connection)
{
  static GEnumClass *event_class;
  GTimeVal tv;

  if (!event_class)
    event_class = g_type_class_ref (G_TYPE_SOCKET_CLIENT_EVENT);

  g_get_current_time (&tv);
  printf ("% 12ld.%06ld GSocketClient => %s [%s]\n",
	  tv.tv_sec, tv.tv_usec,
	  g_enum_get_value (event_class, event)->value_nick,
	  connection ? G_OBJECT_TYPE_NAME (connection) : "");
}
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
int
main (int argc, char *argv[])
{
  GOptionContext *context;
  GSocketClient *client;
  GSocketConnection *connection;
  GSocketAddress *address;
  GCancellable *cancellable;
  GOutputStream *out;
  GError *error = NULL;
  char buffer[1000];

  g_type_init ();

  context = g_option_context_new (" <hostname>[:port] - send data to tcp host");
  g_option_context_add_main_entries (context, cmd_entries, NULL);
  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      g_printerr ("%s: %s\n", argv[0], error->message);
      return 1;
    }

  if (argc != 2)
    {
      g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
      return 1;
    }

109 110 111
  if (async)
    loop = g_main_loop_new (NULL, FALSE);

112 113
  if (cancel_timeout)
    {
114
      GThread *thread;
115
      cancellable = g_cancellable_new ();
116
      thread = g_thread_new ("cancel", cancel_thread, cancellable);
117
      g_thread_unref (thread);
118 119 120 121 122 123 124
    }
  else
    {
      cancellable = NULL;
    }

  client = g_socket_client_new ();
125 126
  if (io_timeout)
    g_socket_client_set_timeout (client, io_timeout);
127 128
  if (verbose)
    g_signal_connect (client, "event", G_CALLBACK (socket_client_event), NULL);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

  if (async)
    {
      GAsyncResult *res;
      g_socket_client_connect_to_host_async (client, argv[1], 7777,
					     cancellable, async_cb, &res);
      g_main_loop_run (loop);
      connection = g_socket_client_connect_to_host_finish (client, res, &error);
      g_object_unref (res);
    }
  else
    {
      connection = g_socket_client_connect_to_host (client,
						    argv[1],
						    7777,
						    cancellable, &error);
    }
146 147 148 149 150
  if (connection == NULL)
    {
      g_printerr ("%s can't connect: %s\n", argv[0], error->message);
      return 1;
    }
151
  g_object_unref (client);
152 153 154 155 156 157 158 159 160 161 162 163

  address = g_socket_connection_get_remote_address (connection, &error);
  if (!address)
    {
      g_printerr ("Error getting remote address: %s\n",
		  error->message);
      return 1;
    }
  g_print ("Connected to address: %s\n",
	   socket_address_to_string (address));
  g_object_unref (address);

164 165 166
  if (graceful)
    g_tcp_connection_set_graceful_disconnect (G_TCP_CONNECTION (connection), TRUE);

167 168 169 170
  out = g_io_stream_get_output_stream (G_IO_STREAM (connection));

  while (fgets(buffer, sizeof (buffer), stdin) != NULL)
    {
171
      /* FIXME if (async) */
172 173 174 175 176 177 178 179 180 181
      if (!g_output_stream_write_all (out, buffer, strlen (buffer),
				      NULL, cancellable, &error))
	{
	  g_warning ("send error: %s\n",  error->message);
	  g_error_free (error);
	  error = NULL;
	}
    }

  g_print ("closing stream\n");
182
  if (async)
183
    {
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
      GAsyncResult *res;
      g_io_stream_close_async (G_IO_STREAM (connection),
			       0, cancellable, async_cb, &res);
      g_main_loop_run (loop);
      if (!g_io_stream_close_finish (G_IO_STREAM (connection),
				     res, &error))
	{
	  g_object_unref (res);
	  g_warning ("close error: %s\n",  error->message);
	  return 1;
	}
      g_object_unref (res);
    }
  else
    {
      if (!g_io_stream_close (G_IO_STREAM (connection), cancellable, &error))
	{
	  g_warning ("close error: %s\n",  error->message);
	  return 1;
	}
204 205
    }

206 207
  g_object_unref (connection);

208 209
  return 0;
}