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

source code of gtk/subprojects/glib/gio/tests/send-data.c