Branch data Line data Source code
1 : : #include <gio/gio.h>
2 : : #include <string.h>
3 : : #include <stdio.h>
4 : :
5 : : GMainLoop *loop;
6 : :
7 : : int cancel_timeout = 0;
8 : : int io_timeout = 0;
9 : : gboolean async = FALSE;
10 : : gboolean graceful = FALSE;
11 : : gboolean verbose = FALSE;
12 : : static GOptionEntry cmd_entries[] = {
13 : : {"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
14 : : "Cancel any op after the specified amount of seconds", NULL},
15 : : {"async", 'a', 0, G_OPTION_ARG_NONE, &async,
16 : : "Use async ops", NULL},
17 : : {"graceful-disconnect", 'g', 0, G_OPTION_ARG_NONE, &graceful,
18 : : "Use graceful disconnect", NULL},
19 : : {"timeout", 't', 0, G_OPTION_ARG_INT, &io_timeout,
20 : : "Time out socket I/O after the specified number of seconds", NULL},
21 : : {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
22 : : "Verbose debugging output", NULL},
23 : : G_OPTION_ENTRY_NULL
24 : : };
25 : :
26 : : static gpointer
27 : 0 : cancel_thread (gpointer data)
28 : : {
29 : 0 : GCancellable *cancellable = data;
30 : :
31 : 0 : g_usleep (1000*1000*cancel_timeout);
32 : 0 : g_print ("Cancelling\n");
33 : 0 : g_cancellable_cancel (cancellable);
34 : 0 : return NULL;
35 : : }
36 : :
37 : : static char *
38 : 0 : socket_address_to_string (GSocketAddress *address)
39 : : {
40 : : GInetAddress *inet_address;
41 : : char *str, *res;
42 : : int port;
43 : :
44 : 0 : inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
45 : 0 : str = g_inet_address_to_string (inet_address);
46 : 0 : port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
47 : 0 : res = g_strdup_printf ("%s:%d", str, port);
48 : 0 : g_free (str);
49 : 0 : return res;
50 : : }
51 : :
52 : : static void
53 : 0 : async_cb (GObject *source_object,
54 : : GAsyncResult *res,
55 : : gpointer user_data)
56 : : {
57 : 0 : GAsyncResult **resp = user_data;
58 : 0 : *resp = g_object_ref (res);
59 : 0 : g_main_loop_quit (loop);
60 : 0 : }
61 : :
62 : : static void
63 : 0 : socket_client_event (GSocketClient *client,
64 : : GSocketClientEvent event,
65 : : GSocketConnectable *connectable,
66 : : GSocketConnection *connection)
67 : : {
68 : : static GEnumClass *event_class;
69 : : gint64 now_us;
70 : :
71 : 0 : if (!event_class)
72 : 0 : event_class = g_type_class_ref (G_TYPE_SOCKET_CLIENT_EVENT);
73 : :
74 : 0 : now_us = g_get_real_time ();
75 : 0 : g_print ("%" G_GINT64_FORMAT " GSocketClient => %s [%s]\n",
76 : : now_us,
77 : 0 : g_enum_get_value (event_class, event)->value_nick,
78 : 0 : connection ? G_OBJECT_TYPE_NAME (connection) : "");
79 : 0 : }
80 : :
81 : : int
82 : 0 : main (int argc, char *argv[])
83 : : {
84 : : GOptionContext *context;
85 : : GSocketClient *client;
86 : : GSocketConnection *connection;
87 : : GSocketAddress *address;
88 : : GCancellable *cancellable;
89 : : GOutputStream *out;
90 : 0 : GError *error = NULL;
91 : : char buffer[1000];
92 : :
93 : 0 : context = g_option_context_new (" <hostname>[:port] - send data to tcp host");
94 : 0 : g_option_context_add_main_entries (context, cmd_entries, NULL);
95 : 0 : if (!g_option_context_parse (context, &argc, &argv, &error))
96 : : {
97 : 0 : g_printerr ("%s: %s\n", argv[0], error->message);
98 : 0 : return 1;
99 : : }
100 : :
101 : 0 : if (argc != 2)
102 : : {
103 : 0 : g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
104 : 0 : return 1;
105 : : }
106 : :
107 : 0 : if (async)
108 : 0 : loop = g_main_loop_new (NULL, FALSE);
109 : :
110 : 0 : if (cancel_timeout)
111 : : {
112 : : GThread *thread;
113 : 0 : cancellable = g_cancellable_new ();
114 : 0 : thread = g_thread_new ("cancel", cancel_thread, cancellable);
115 : 0 : g_thread_unref (thread);
116 : : }
117 : : else
118 : : {
119 : 0 : cancellable = NULL;
120 : : }
121 : :
122 : 0 : client = g_socket_client_new ();
123 : 0 : if (io_timeout)
124 : 0 : g_socket_client_set_timeout (client, io_timeout);
125 : 0 : if (verbose)
126 : 0 : g_signal_connect (client, "event", G_CALLBACK (socket_client_event), NULL);
127 : :
128 : 0 : if (async)
129 : : {
130 : : GAsyncResult *res;
131 : 0 : g_socket_client_connect_to_host_async (client, argv[1], 7777,
132 : : cancellable, async_cb, &res);
133 : 0 : g_main_loop_run (loop);
134 : 0 : connection = g_socket_client_connect_to_host_finish (client, res, &error);
135 : 0 : g_object_unref (res);
136 : : }
137 : : else
138 : : {
139 : 0 : connection = g_socket_client_connect_to_host (client,
140 : 0 : argv[1],
141 : : 7777,
142 : : cancellable, &error);
143 : : }
144 : 0 : if (connection == NULL)
145 : : {
146 : 0 : g_printerr ("%s can't connect: %s\n", argv[0], error->message);
147 : 0 : return 1;
148 : : }
149 : 0 : g_object_unref (client);
150 : :
151 : 0 : address = g_socket_connection_get_remote_address (connection, &error);
152 : 0 : if (!address)
153 : : {
154 : 0 : g_printerr ("Error getting remote address: %s\n",
155 : 0 : error->message);
156 : 0 : return 1;
157 : : }
158 : 0 : g_print ("Connected to address: %s\n",
159 : : socket_address_to_string (address));
160 : 0 : g_object_unref (address);
161 : :
162 : 0 : if (graceful)
163 : 0 : g_tcp_connection_set_graceful_disconnect (G_TCP_CONNECTION (connection), TRUE);
164 : :
165 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
166 : :
167 : 0 : while (fgets(buffer, sizeof (buffer), stdin) != NULL)
168 : : {
169 : : /* FIXME if (async) */
170 : 0 : if (!g_output_stream_write_all (out, buffer, strlen (buffer),
171 : : NULL, cancellable, &error))
172 : : {
173 : 0 : g_warning ("send error: %s", error->message);
174 : 0 : g_error_free (error);
175 : 0 : error = NULL;
176 : : }
177 : : }
178 : :
179 : 0 : g_print ("closing stream\n");
180 : 0 : if (async)
181 : : {
182 : : GAsyncResult *res;
183 : 0 : g_io_stream_close_async (G_IO_STREAM (connection),
184 : : 0, cancellable, async_cb, &res);
185 : 0 : g_main_loop_run (loop);
186 : 0 : if (!g_io_stream_close_finish (G_IO_STREAM (connection),
187 : : res, &error))
188 : : {
189 : 0 : g_object_unref (res);
190 : 0 : g_warning ("close error: %s", error->message);
191 : 0 : return 1;
192 : : }
193 : 0 : g_object_unref (res);
194 : : }
195 : : else
196 : : {
197 : 0 : if (!g_io_stream_close (G_IO_STREAM (connection), cancellable, &error))
198 : : {
199 : 0 : g_warning ("close error: %s", error->message);
200 : 0 : return 1;
201 : : }
202 : : }
203 : :
204 : 0 : g_object_unref (connection);
205 : :
206 : 0 : return 0;
207 : : }
|