1 /*
2 * GNetwork Library: libgnetwork/gnetwork-connection.c
3 *
4 * Copyright (c) 2003 James M. Cape.
5 * All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; version 2.1 of the
10 * License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif /* HAVE_CONFIG_H */
26
27
28 #include "gnetwork-connection.h"
29
30 #include "gnetwork-type-builtins.h"
31 #include "gnetwork-errors.h"
32
33 #include "marshal.h"
34
35 #include <glib/gi18n.h>
36
37 #define G_UCHAR(ptr) ((guchar *) (ptr))
38
39
40 enum
41 {
42 RECEIVED,
43 SENT,
44 ERROR,
45 LAST_SIGNAL
46 };
47
48
49 typedef struct _EnumString
50 {
51 const guint value;
52 const gchar *const str;
53 }
54 EnumString;
55
56
57 static gint signals[LAST_SIGNAL] = { 0 };
58
59
60 /* ***************** *
61 * GType Functions *
62 * ***************** */
63
64 static void
gnetwork_connection_base_init(gpointer g_iface)65 gnetwork_connection_base_init (gpointer g_iface)
66 {
67 static gboolean initialized = FALSE;
68
69 if (!initialized)
70 {
71 signals[RECEIVED] =
72 g_signal_new ("received",
73 GNETWORK_TYPE_CONNECTION,
74 G_SIGNAL_RUN_FIRST,
75 G_STRUCT_OFFSET (GNetworkConnectionIface, received),
76 NULL, NULL, _gnetwork_marshal_VOID__POINTER_ULONG,
77 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_ULONG);
78 signals[SENT] =
79 g_signal_new ("sent",
80 GNETWORK_TYPE_CONNECTION,
81 G_SIGNAL_RUN_FIRST,
82 G_STRUCT_OFFSET (GNetworkConnectionIface, sent),
83 NULL, NULL, _gnetwork_marshal_VOID__POINTER_ULONG,
84 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_ULONG);
85 signals[ERROR] =
86 g_signal_new ("error",
87 GNETWORK_TYPE_CONNECTION,
88 (G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED),
89 G_STRUCT_OFFSET (GNetworkConnectionIface, error),
90 NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR);
91
92 g_object_interface_install_property (g_iface,
93 g_param_spec_enum ("connection-type",
94 _("Connection Type"),
95 _("The type of connection "
96 "represented by the implementing "
97 "object."),
98 GNETWORK_TYPE_CONNECTION_TYPE,
99 GNETWORK_CONNECTION_CLIENT,
100 (G_PARAM_READWRITE
101 | G_PARAM_CONSTRUCT)));
102
103 g_object_interface_install_property (g_iface,
104 g_param_spec_enum ("status", _("Connection Status"),
105 _("The status of this connection."),
106 GNETWORK_TYPE_CONNECTION_STATUS,
107 GNETWORK_CONNECTION_CLOSED,
108 G_PARAM_READABLE));
109 g_object_interface_install_property (g_iface,
110 g_param_spec_ulong ("bytes-received",
111 _("Bytes Received"),
112 _("The number of bytes received "
113 "through this connection."),
114 0, G_MAXULONG, 0, G_PARAM_READABLE));
115 g_object_interface_install_property (g_iface,
116 g_param_spec_ulong ("bytes-sent", _("Bytes Sent"),
117 _("The number of bytes sent through "
118 "this connection."),
119 0, G_MAXULONG, 0, G_PARAM_READABLE));
120 g_object_interface_install_property (g_iface,
121 g_param_spec_uint ("buffer-size", _("Buffer Size"),
122 _("The maximum size in bytes of "
123 "outgoing and incoming data "
124 "packets."), 0, G_MAXUINT, 2048,
125 (G_PARAM_READWRITE |
126 G_PARAM_CONSTRUCT)));
127
128 initialized = TRUE;
129 }
130 }
131
132
133 /* ************************************************************************** *
134 * Public API *
135 * ************************************************************************** */
136
137 GType
gnetwork_connection_get_type(void)138 gnetwork_connection_get_type (void)
139 {
140 static GType type = G_TYPE_INVALID;
141
142 if (type == G_TYPE_INVALID)
143 {
144 static const GTypeInfo info = {
145 sizeof (GNetworkConnectionIface), /* class_size */
146 gnetwork_connection_base_init, /* base_init */
147 NULL, /* base_finalize */
148 NULL,
149 NULL, /* class_finalize */
150 NULL, /* class_data */
151 0,
152 0, /* n_preallocs */
153 NULL
154 };
155
156 type = g_type_register_static (G_TYPE_INTERFACE, "GNetworkConnection", &info, 0);
157
158 g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
159 }
160
161 return type;
162 }
163
164
165 /**
166 * gnetwork_connection_open:
167 * @connection: the connection to open.
168 *
169 * Starts the connection process for @connection.
170 *
171 * Since: 1.0
172 **/
173 void
gnetwork_connection_open(GNetworkConnection * connection)174 gnetwork_connection_open (GNetworkConnection * connection)
175 {
176 GNetworkConnectionIface *iface;
177
178 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
179
180 iface = GNETWORK_CONNECTION_GET_IFACE (connection);
181
182 g_return_if_fail (iface->open != NULL);
183
184 g_object_ref (connection);
185 (*iface->open) (connection);
186 g_object_unref (connection);
187 }
188
189
190 /**
191 * gnetwork_connection_close:
192 * @connection: the connection to close.
193 *
194 * Closes the @connection in question.
195 *
196 * Since: 1.0
197 **/
198 void
gnetwork_connection_close(GNetworkConnection * connection)199 gnetwork_connection_close (GNetworkConnection * connection)
200 {
201 GNetworkConnectionIface *iface;
202
203 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
204
205 iface = GNETWORK_CONNECTION_GET_IFACE (connection);
206
207 g_return_if_fail (iface->close != NULL);
208
209 g_object_ref (connection);
210 (*iface->close) (connection);
211 g_object_unref (connection);
212 }
213
214
215 /**
216 * gnetwork_connection_send:
217 * @connection: the connection to send through.
218 * @data: the data to send.
219 * @length: the length in bytes of @data.
220 *
221 * Sends the data in @data through @connection. If @length is less than one,
222 * @data is assumed to be terminated by %0. This function will perform the
223 * necessary calculations for @length. After calling the implementation's
224 * send function, the "send" signal will be emitted.
225 *
226 * Since: 1.0
227 **/
228 void
gnetwork_connection_send(GNetworkConnection * connection,gconstpointer data,glong length)229 gnetwork_connection_send (GNetworkConnection * connection, gconstpointer data, glong length)
230 {
231 GNetworkConnectionIface *iface;
232
233 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
234 g_return_if_fail (data != NULL);
235 g_return_if_fail (data != 0);
236
237 iface = GNETWORK_CONNECTION_GET_IFACE (connection);
238
239 g_return_if_fail (iface->send != NULL);
240
241 if (length < 0)
242 {
243 for (length = 0; *(G_UCHAR (data) + length) != 0; length++);
244 }
245
246 g_object_ref (connection);
247 (*iface->send) (connection, data, (gulong) length);
248 g_object_unref (connection);
249 }
250
251
252 /**
253 * gnetwork_connection_received:
254 * @connection: the connection to use.
255 * @data: the data being recieved.
256 * @length: the length of @data in bytes.
257 *
258 * Emits the "received" signal for @connection, using the values in @data and @length.
259 * Implementations of the #GNetworkConnectionIface interface should use this function
260 * when data has been received.
261 *
262 * Since: 1.0
263 **/
264 void
gnetwork_connection_received(GNetworkConnection * connection,gconstpointer data,gulong length)265 gnetwork_connection_received (GNetworkConnection * connection, gconstpointer data, gulong length)
266 {
267 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
268 g_return_if_fail (data != NULL);
269 g_return_if_fail (length > 0);
270
271 g_object_ref (connection);
272 g_signal_emit (connection, signals[RECEIVED], 0, data, length);
273 g_object_unref (connection);
274 }
275
276
277 /**
278 * gnetwork_connection_sent:
279 * @connection: the connection to use.
280 * @data: the data which was sent.
281 * @length: the length of @data in bytes.
282 *
283 * Emits the "sent" signal for @connection, using the values in @data and
284 * @length. Implementations of the #GNetworkConnectionIface interface should
285 * call this function when data has been sent.
286 *
287 * Since: 1.0
288 **/
289 void
gnetwork_connection_sent(GNetworkConnection * connection,gconstpointer data,gulong length)290 gnetwork_connection_sent (GNetworkConnection * connection, gconstpointer data, gulong length)
291 {
292 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
293 g_return_if_fail (data != NULL);
294 g_return_if_fail (length > 0);
295
296 g_object_ref (connection);
297 g_signal_emit (connection, signals[SENT], 0, data, length);
298 g_object_unref (connection);
299 }
300
301
302 /**
303 * gnetwork_connection_error:
304 * @connection: the connection to use.
305 * @error: the error structure.
306 *
307 * Emits the "error" signal for @connection, using @error. Callers to this function
308 * should use their own error domains.
309 *
310 * Since: 1.0
311 **/
312 void
gnetwork_connection_error(GNetworkConnection * connection,const GError * error)313 gnetwork_connection_error (GNetworkConnection * connection, const GError * error)
314 {
315 g_return_if_fail (GNETWORK_IS_CONNECTION (connection));
316 g_return_if_fail (error != NULL);
317
318 g_object_ref (connection);
319 g_signal_emit (connection, signals[ERROR], error->domain, error);
320 g_object_unref (connection);
321 }
322
323
324 /**
325 * gnetwork_connection_strerror:
326 * @error: the connection error code to use.
327 *
328 * Retrieves a string message describing @error. The returned data should not
329 * be modified or freed.
330 *
331 * Returns: the string message describing @error.
332 *
333 * Since: 1.0
334 **/
335 G_CONST_RETURN gchar *
gnetwork_connection_strerror(GNetworkConnectionError error)336 gnetwork_connection_strerror (GNetworkConnectionError error)
337 {
338 const gchar *str;
339
340 g_return_val_if_fail (error >= GNETWORK_CONNECTION_ERROR_INTERNAL &&
341 error <= GNETWORK_CONNECTION_ERROR_PERMISSIONS, NULL);
342
343 switch (error)
344 {
345 case GNETWORK_CONNECTION_ERROR_INTERNAL:
346 str = _("There was an error inside of the networking library.");
347 break;
348 case GNETWORK_CONNECTION_ERROR_REFUSED:
349 str = _("The service will not let you connect.");
350 break;
351 case GNETWORK_CONNECTION_ERROR_TIMEOUT:
352 str = _("The service may be down, or you may have been disconnected from the network.");
353 break;
354 case GNETWORK_CONNECTION_ERROR_UNREACHABLE:
355 str = _("The service could not be contacted.");
356 break;
357 case GNETWORK_CONNECTION_ERROR_PERMISSIONS:
358 str = _("Your computer or firewall is configured to prevent access to the service.");
359 break;
360 default:
361 g_assert_not_reached ();
362 str = NULL;
363 };
364
365 return str;
366 }
367
368
369 G_LOCK_DEFINE_STATIC (quark);
370
371 GQuark
gnetwork_connection_error_get_quark(void)372 gnetwork_connection_error_get_quark (void)
373 {
374 static volatile GQuark quark = 0;
375
376 G_LOCK (quark);
377
378 if (quark == 0)
379 {
380 quark = g_quark_from_static_string ("gnetwork-connection-error");
381 }
382
383 G_UNLOCK (quark);
384
385 return quark;
386 }
387