From b377e69685c99150cf7661e1aa77d60934e00521 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 11 Nov 2010 09:57:25 -0500 Subject: [PATCH] Add gnetworking.h Install a public "gnetworking.h" header that can be used to include the relevant OS-dependent networking headers. This does not really abstract away unix-vs-windows however; error codes, in particular, are incompatible. gnetworkingprivate.h now contains just a few internal URI-related functions Also add a g_networking_init() function to gnetworking.h, which can be used to explicitly initialize OS-level networking, rather than having that happen as a side-effect of registering GInetAddress. https://bugzilla.gnome.org/show_bug.cgi?id=623187 --- configure.ac | 20 ++++++- docs/reference/gio/gio-docs.xml | 1 + docs/reference/gio/gio-sections.txt | 6 +++ gio/.gitignore | 1 + gio/Makefile.am | 3 ++ gio/gcredentials.c | 13 +---- gio/gdbusauth.c | 3 +- gio/ginetaddress.c | 22 +++----- gio/gio.symbols | 1 + gio/gnetworking.c | 79 +++++++++++++++++++++++++++ gio/gnetworking.h.in | 83 +++++++++++++++++++++++++++++ gio/gnetworkingprivate.h | 55 +------------------ gio/gresolver.c | 6 +-- gio/gsocket.c | 8 ++- gio/gunixconnection.c | 8 +-- gio/gunixcredentialsmessage.c | 16 ++---- gio/gunixfdlist.c | 3 +- gio/gunixfdmessage.c | 3 +- gio/gunixsocketaddress.c | 2 +- gio/tests/gdbus-peer.c | 2 +- gio/tests/socket.c | 3 +- gio/tests/unix-fd.c | 2 +- 22 files changed, 220 insertions(+), 120 deletions(-) create mode 100644 gio/gnetworking.c create mode 100644 gio/gnetworking.h.in diff --git a/configure.ac b/configure.ac index 780426269..e08b2556c 100644 --- a/configure.ac +++ b/configure.ac @@ -1064,7 +1064,24 @@ if $glib_failed ; then fi AC_CHECK_FUNCS(getprotobyname_r endservent if_nametoindex) -AC_CHECK_HEADERS([netdb.h wspiapi.h arpa/nameser_compat.h]) + +# in the Windows SDK and in mingw-w64 has wrappers for +# inline workarounds for getaddrinfo, getnameinfo and freeaddrinfo if +# they aren't present at run-time (on Windows 2000). +AC_CHECK_HEADER([wspiapi.h], [WSPIAPI_INCLUDE="\#include "]) +AC_SUBST(WSPIAPI_INCLUDE) + +AC_MSG_CHECKING([if arpa/nameser_compat.h is needed]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [int qclass = C_IN;])], + [AC_MSG_RESULT([no])], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include + #include ], + [int qclass = C_IN;])], + [AC_MSG_RESULT([yes]) + NAMESER_COMPAT_INCLUDE="\#include "], + [AC_MSG_ERROR([could not compile test program either way])])]) +AC_SUBST(NAMESER_COMPAT_INCLUDE) AS_IF([test $glib_native_win32 = no], [ # We can't just use AC_CHECK_FUNC/AC_CHECK_LIB here. Bug 586150 @@ -3618,6 +3635,7 @@ gthread/Makefile gio/Makefile gio/gdbus-2.0/codegen/Makefile gio/gdbus-2.0/codegen/config.py +gio/gnetworking.h gio/xdgmime/Makefile gio/inotify/Makefile gio/kqueue/Makefile diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 03dd28deb..5de3930ac 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -122,6 +122,7 @@ + High-level network functionallity diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 484f34be4..c9efdc566 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -3981,3 +3981,9 @@ G_IS_TASK_CLASS G_TASK_GET_CLASS g_task_get_type + +
+gnetworking +gnetworking.h +g_networking_init +
diff --git a/gio/.gitignore b/gio/.gitignore index 4a7c5109f..be25b26e7 100644 --- a/gio/.gitignore +++ b/gio/.gitignore @@ -10,6 +10,7 @@ gio-querymodules gioenumtypes.[ch] glib-compile-resources glib-compile-schemas +gnetworking.h gresource gschema-compile gsettings diff --git a/gio/Makefile.am b/gio/Makefile.am index 683ff071b..3ca53e4d8 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -400,6 +400,7 @@ libgio_2_0_la_SOURCES = \ gnativevolumemonitor.c \ gnativevolumemonitor.h \ gnetworkaddress.c \ + gnetworking.c \ gnetworkingprivate.h \ gnetworkmonitor.c \ gnetworkmonitorbase.c \ @@ -581,6 +582,7 @@ gio_headers = \ gmountoperation.h \ gnativevolumemonitor.h \ gnetworkaddress.h \ + gnetworking.h \ gnetworkmonitor.h \ gnetworkservice.h \ goutputstream.h \ @@ -643,6 +645,7 @@ BUILT_SOURCES = \ gioenumtypes.c \ gdbus-daemon-generated.c \ gdbus-daemon-generated.h \ + gnetworking.h \ $(NULL) EXTRA_DIST += \ diff --git a/gio/gcredentials.c b/gio/gcredentials.c index 2827c4524..42fd53e8d 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -22,22 +22,13 @@ #include "config.h" -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#include -#include -#endif -#ifdef __OpenBSD__ -#include -#include -#include -#endif #include +#include #include #include "gcredentials.h" -#include "gnetworkingprivate.h" +#include "gnetworking.h" #include "gioerror.h" #include "glibintl.h" diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index 355c60b40..962a218c0 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -39,8 +39,7 @@ #include "gdataoutputstream.h" #ifdef G_OS_UNIX -#include -#include +#include "gnetworking.h" #include "gunixconnection.h" #include "gunixcredentialsmessage.h" #endif diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c index 0b1a1ad50..de67272d3 100644 --- a/gio/ginetaddress.c +++ b/gio/ginetaddress.c @@ -56,21 +56,8 @@ * An IPv4 or IPv6 internet address. */ -/* Networking initialization function, called from inside the g_once of - * g_inet_address_get_type() - */ -static void -_g_networking_init (void) -{ -#ifdef G_OS_WIN32 - WSADATA wsadata; - if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0) - g_error ("Windows Sockets could not be initialized"); -#endif -} - G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT, - _g_networking_init ();) + g_networking_init ();) struct _GInetAddressPrivate { @@ -411,8 +398,11 @@ g_inet_address_new_from_string (const gchar *string) struct in6_addr in6_addr; #endif - /* Make sure _g_networking_init() has been called */ - g_type_ensure (G_TYPE_INET_ADDRESS); + /* If this GInetAddress is the first networking-related object to be + * created, then we won't have called g_networking_init() yet at + * this point. + */ + g_networking_init (); #ifdef G_OS_WIN32 memset (&sa, 0, sizeof (sa)); diff --git a/gio/gio.symbols b/gio/gio.symbols index 6788fc18d..c97e2bd8d 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -1801,3 +1801,4 @@ g_task_return_error_if_cancelled g_task_return_int g_task_return_new_error g_task_return_pointer +g_networking_init diff --git a/gio/gnetworking.c b/gio/gnetworking.c new file mode 100644 index 000000000..24c401375 --- /dev/null +++ b/gio/gnetworking.c @@ -0,0 +1,79 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gnetworking.h" + +/** + * SECTION:gnetworking + * @title: gnetworking.h + * @short_description: System networking includes + * @include: gio/gnetworking.h + * + * The gnetworking.h header can be included to get + * various low-level networking-related system headers, automatically + * taking care of certain portability issues for you. + * + * This can be used, for example, if you want to call setsockopt() + * on a #GSocket. + * + * Note that while WinSock has many of the same APIs as the + * traditional UNIX socket API, most of them behave at least slightly + * differently (particularly with respect to error handling). If you + * want your code to work under both UNIX and Windows, you will need + * to take these differences into account. + * + * Also, under glibc, certain non-portable functions are only visible + * in the headers if you define _GNU_SOURCE before + * including them. Note that this symbol must be defined before + * including any headers, or it may not take + * effect. + */ + +/** + * g_networking_init: + * + * Initializes the platform networking libraries (eg, on Windows, this + * calls WSAStartup()). GLib will call this itself if it is needed, so + * you only need to call it if you directly call system networking + * functions (without calling any GLib networking functions first). + * + * Since: 2.36 + */ +void +g_networking_init (void) +{ +#ifdef G_OS_WIN32 + static volatile gsize inited = 0; + + if (g_once_init_enter (&inited)) + { + WSADATA wsadata; + + if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0) + g_error ("Windows Sockets could not be initialized"); + + g_once_init_leave (&inited, 1); + } +#endif +} diff --git a/gio/gnetworking.h.in b/gio/gnetworking.h.in new file mode 100644 index 000000000..99bdadd53 --- /dev/null +++ b/gio/gnetworking.h.in @@ -0,0 +1,83 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2008-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __G_NETWORKING_H__ +#define __G_NETWORKING_H__ + +#include + +#ifdef G_OS_WIN32 + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include +#undef interface +#include +#include +#include +@WSPIAPI_INCLUDE@ + +#else /* !G_OS_WIN32 */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +@NAMESER_COMPAT_INCLUDE@ + +#ifndef T_SRV +#define T_SRV 33 +#endif + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +#ifndef CMSG_LEN +/* CMSG_LEN and CMSG_SPACE are defined by RFC 2292, but missing on + * some older platforms. + */ +#define CMSG_LEN(len) ((size_t)CMSG_DATA((struct cmsghdr *)NULL) + (len)) + +/* CMSG_SPACE must add at least as much padding as CMSG_NXTHDR() + * adds. We overestimate here. + */ +#define GLIB_ALIGN_TO_SIZEOF(len, obj) (((len) + sizeof (obj) - 1) & ~(sizeof (obj) - 1)) +#define CMSG_SPACE(len) GLIB_ALIGN_TO_SIZEOF (CMSG_LEN (len), struct cmsghdr) +#endif +#endif + +G_BEGIN_DECLS + +GLIB_AVAILABLE_IN_2_36 +void g_networking_init (void); + +G_END_DECLS + +#endif /* __G_NETWORKING_H__ */ diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h index 6259109ce..5c286f391 100644 --- a/gio/gnetworkingprivate.h +++ b/gio/gnetworkingprivate.h @@ -21,60 +21,7 @@ #ifndef __G_NETWORKINGPRIVATE_H__ #define __G_NETWORKINGPRIVATE_H__ -#ifdef G_OS_WIN32 - -#include -#undef interface -#include -#include -#include - -#ifdef HAVE_WSPIAPI_H -/* in the Windows SDK and in mingw-w64 has wrappers for - * inline workarounds for getaddrinfo, getnameinfo and freeaddrinfo if - * they aren't present at run-time (on Windows 2000). - */ -#include -#endif - -#else /* !G_OS_WIN32 */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(HAVE_ARPA_NAMESER_COMPAT_H) && !defined(GETSHORT) -#include -#endif -#include - -#ifndef T_SRV -#define T_SRV 33 -#endif - -#ifndef _PATH_RESCONF -#define _PATH_RESCONF "/etc/resolv.conf" -#endif - -#ifndef CMSG_LEN -/* CMSG_LEN and CMSG_SPACE are defined by RFC 2292, but missing on - * some older platforms. - */ -#define CMSG_LEN(len) ((size_t)CMSG_DATA((struct cmsghdr *)NULL) + (len)) - -/* CMSG_SPACE must add at least as much padding as CMSG_NXTHDR() - * adds. We overestimate here. - */ -#define ALIGN_TO_SIZEOF(len, obj) (((len) + sizeof (obj) - 1) & ~(sizeof (obj) - 1)) -#define CMSG_SPACE(len) ALIGN_TO_SIZEOF (CMSG_LEN (len), struct cmsghdr) -#endif -#endif +#include "gnetworking.h" G_BEGIN_DECLS diff --git a/gio/gresolver.c b/gio/gresolver.c index 3708ee2c3..589e3242b 100644 --- a/gio/gresolver.c +++ b/gio/gresolver.c @@ -76,7 +76,8 @@ struct _GResolverPrivate { * The object that handles DNS resolution. Use g_resolver_get_default() * to get the default resolver. */ -G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT) +G_DEFINE_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT, + g_networking_init ();) static GList * srv_records_to_targets (GList *records) @@ -153,9 +154,6 @@ g_resolver_class_init (GResolverClass *resolver_class) g_type_class_add_private (resolver_class, sizeof (GResolverPrivate)); - /* Make sure _g_networking_init() has been called */ - g_type_ensure (G_TYPE_INET_ADDRESS); - /** * GResolver::reload: * @resolver: a #GResolver diff --git a/gio/gsocket.c b/gio/gsocket.c index 9074285ed..548b348e5 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -59,7 +59,7 @@ #include "gioerror.h" #include "gioenums.h" #include "gioerror.h" -#include "gnetworkingprivate.h" +#include "gnetworking.h" #include "gsocketaddress.h" #include "gsocketcontrolmessage.h" #include "gcredentials.h" @@ -69,7 +69,7 @@ * SECTION:gsocket * @short_description: Low-level socket object * @include: gio/gio.h - * @see_also: #GInitable + * @see_also: #GInitable, gnetworking.h * * A #GSocket is a low-level networking primitive. It is a more or less * direct mapping of the BSD socket API in a portable GObject based API. @@ -127,6 +127,7 @@ static gboolean g_socket_initable_init (GInitable *initable, GError **error); G_DEFINE_TYPE_WITH_CODE (GSocket, g_socket, G_TYPE_OBJECT, + g_networking_init (); G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, g_socket_initable_iface_init)); @@ -781,9 +782,6 @@ g_socket_class_init (GSocketClass *klass) { GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass); - /* Make sure winsock has been initialized */ - g_type_ensure (G_TYPE_INET_ADDRESS); - #ifdef SIGPIPE /* There is no portable, thread-safe way to avoid having the process * be killed by SIGPIPE when calling send() or sendmsg(), so we are diff --git a/gio/gunixconnection.c b/gio/gunixconnection.c index d5d8ec0d7..8a0968e44 100644 --- a/gio/gunixconnection.c +++ b/gio/gunixconnection.c @@ -39,16 +39,12 @@ #include #include +#include #include -#include -#ifdef __linux__ -/* for getsockopt() and setsockopt() */ -#include /* See NOTES */ -#include #include #include -#endif +#include G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection, diff --git a/gio/gunixcredentialsmessage.c b/gio/gunixcredentialsmessage.c index 13bf3de03..541b58cd8 100644 --- a/gio/gunixcredentialsmessage.c +++ b/gio/gunixcredentialsmessage.c @@ -37,19 +37,8 @@ /* ---------------------------------------------------------------------------------------------------- */ #ifdef __linux__ -#include -#include -#include -#include -#include #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 - #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#include -#include -#include -#include #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 #else /* TODO: please add support for your UNIX flavor */ @@ -58,11 +47,14 @@ /* ---------------------------------------------------------------------------------------------------- */ -#include +#include #include +#include +#include #include "gunixcredentialsmessage.h" #include "gcredentials.h" +#include "gnetworking.h" #include "glibintl.h" diff --git a/gio/gunixfdlist.c b/gio/gunixfdlist.c index 9a888b2f6..628d95c69 100644 --- a/gio/gunixfdlist.c +++ b/gio/gunixfdlist.c @@ -33,14 +33,13 @@ #include "config.h" -#include -#include #include #include #include #include #include "gunixfdlist.h" +#include "gnetworking.h" #include "gioerror.h" diff --git a/gio/gunixfdmessage.c b/gio/gunixfdmessage.c index a9c5fe1df..4e7f49467 100644 --- a/gio/gunixfdmessage.c +++ b/gio/gunixfdmessage.c @@ -36,8 +36,6 @@ #include "config.h" -#include -#include #include #include #include @@ -45,6 +43,7 @@ #include "gunixfdmessage.h" #include "gunixfdlist.h" +#include "gnetworking.h" #include "gioerror.h" diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c index 1e760d009..31615cf17 100644 --- a/gio/gunixsocketaddress.c +++ b/gio/gunixsocketaddress.c @@ -27,7 +27,7 @@ #include "gunixsocketaddress.h" #include "glibintl.h" -#include "gnetworkingprivate.h" +#include "gnetworking.h" /** diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 917c88854..cc3226122 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -35,7 +35,7 @@ /* for g_unlink() */ #include -#include +#include #include #include diff --git a/gio/tests/socket.c b/gio/tests/socket.c index e96e79203..9c212c8cf 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -22,11 +22,10 @@ #ifdef G_OS_UNIX #include -#include -#include #include #include #include +#include #include #endif diff --git a/gio/tests/unix-fd.c b/gio/tests/unix-fd.c index fd922c5a4..4d984dfb3 100644 --- a/gio/tests/unix-fd.c +++ b/gio/tests/unix-fd.c @@ -1,7 +1,7 @@ #include +#include #include #include -#include #include #include