Merge branch 'master' into wip/gsettings-list

This commit is contained in:
Rodrigo Moya 2010-12-02 18:08:37 +01:00
commit 3ed846e753
130 changed files with 6355 additions and 961 deletions

40
NEWS
View File

@ -1,3 +1,43 @@
Overview of Changes from GLib 2.27.3 to 2.27.4
==============================================
* GIO
- Mounts are treated as hidden if they have a path element
that starts with a dot
- GAppInfo gained API to differentiate between recommended
and fallback mime handlers
- g_cancellable_create_source: creates a GSource that triggers
when the GCancellable is canceled
- GPollableInput/OutputStream: Interfaces for pollable streams
- TLS support has landed, with an extension point that is
implemented in glib-networking
* GLib
- Mainloop sources can now have 'child sources'
- g_get_runtime_dir: New function to return the XDG_RUNTIME_DIR
* Bugs fixed:
530786 GFileMonitor "changed" signal underdocumented
588189 TLS support for GSocket*
630357 g_object_new_valist uses uninitialized memory
630559 typo in public string in gsocks: 'The SOCKSv5 require...
632445 Documentation refers to removed GNOME 2.0 porting guide
634239 Child GSources
634241 Add pollable input/output streams
634504 allow passing a NULL emblem to g_emblemed_icon_new()
634613 unsufficient g_get_user_runtime_dir() documentation
635640 schema should inherit gettext-domain from schemalist
635768 Protect g_file_monitor_set_rate_limit() against negative...
635882 Fix the wrong-category schema test
635187 Wrong type of GVariant received in an action...
* Updated translations:
Galician
Italian
Norwegian bokmål
Uyghur
Overview of Changes from GLib 2.27.2 to 2.27.3
==============================================

View File

@ -22,7 +22,7 @@ m4_define(glib_configure_ac)
#
m4_define([glib_major_version], [2])
m4_define([glib_minor_version], [27])
m4_define([glib_micro_version], [4])
m4_define([glib_micro_version], [5])
m4_define([glib_interface_age], [0])
m4_define([glib_binary_age],
[m4_eval(100 * glib_minor_version + glib_micro_version)])

View File

@ -32,6 +32,10 @@
<title>File System Monitoring</title>
<xi:include href="xml/gfilemonitor.xml"/>
</chapter>
<chapter id="utils">
<title>File-related Utilities</title>
<xi:include href="xml/gfilenamecompleter.xml"/>
</chapter>
<chapter id="async">
<title>Asynchronous I/O</title>
<xi:include href="xml/gcancellable.xml"/>
@ -68,6 +72,8 @@
<xi:include href="xml/gunixoutputstream.xml"/>
<xi:include href="xml/gconverterinputstream.xml"/>
<xi:include href="xml/gconverteroutputstream.xml"/>
<xi:include href="xml/gpollableinputstream.xml"/>
<xi:include href="xml/gpollableoutputstream.xml"/>
</chapter>
<chapter id="types">
<title>File types and applications</title>
@ -118,10 +124,20 @@
<xi:include href="xml/gsocketconnection.xml"/>
<xi:include href="xml/gunixconnection.xml"/>
<xi:include href="xml/gtcpconnection.xml"/>
<xi:include href="xml/gtcpwrapperconnection.xml"/>
<xi:include href="xml/gsocketlistener.xml"/>
<xi:include href="xml/gsocketservice.xml"/>
<xi:include href="xml/gthreadedsocketservice.xml"/>
</chapter>
<chapter id="tls">
<title>TLS (SSL) support</title>
<xi:include href="xml/gtls.xml"/>
<xi:include href="xml/gtlscertificate.xml"/>
<xi:include href="xml/gtlsconnection.xml"/>
<xi:include href="xml/gtlsclientconnection.xml"/>
<xi:include href="xml/gtlsserverconnection.xml"/>
<xi:include href="xml/gtlsbackend.xml"/>
</chapter>
<chapter id="resolver">
<title>DNS resolution</title>
<xi:include href="xml/gresolver.xml"/>
@ -149,10 +165,6 @@
<xi:include href="xml/gdbusnamewatching.xml"/>
<xi:include href="xml/gdbusproxy.xml"/>
</chapter>
<chapter id="utils">
<title>Utilities</title>
<xi:include href="xml/gfilenamecompleter.xml"/>
</chapter>
<chapter id="settings">
<title>Settings</title>
<xi:include href="xml/gsettings.xml"/>
@ -232,6 +244,10 @@
<title>Index of new symbols in 2.26</title>
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-28" role="2.28">
<title>Index of new symbols in 2.28</title>
<xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>

View File

@ -1107,6 +1107,8 @@ g_cancellable_set_error_if_cancelled
g_cancellable_get_fd
g_cancellable_make_pollfd
g_cancellable_release_fd
g_cancellable_source_new
GCancellableSourceFunc
g_cancellable_get_current
g_cancellable_pop_current
g_cancellable_push_current
@ -1257,6 +1259,8 @@ g_app_info_get_all
g_app_info_get_all_for_type
g_app_info_get_default_for_type
g_app_info_get_default_for_uri_scheme
g_app_info_get_fallback_for_type
g_app_info_get_recommended_for_type
g_app_info_launch_default_for_uri
g_app_launch_context_get_display
g_app_launch_context_get_startup_notify_id
@ -1794,13 +1798,17 @@ g_socket_client_set_local_address
g_socket_client_set_protocol
g_socket_client_set_socket_type
g_socket_client_set_timeout
g_socket_client_set_enable_proxy
g_socket_client_set_tls
g_socket_client_set_tls_validation_flags
g_socket_client_get_family
g_socket_client_get_local_address
g_socket_client_get_protocol
g_socket_client_get_socket_type
g_socket_client_get_timeout
g_socket_client_get_enable_proxy
g_socket_client_set_enable_proxy
g_socket_client_get_tls
g_socket_client_get_tls_validation_flags
<SUBSECTION Standard>
GSocketClientClass
G_IS_SOCKET_CLIENT
@ -1878,6 +1886,25 @@ GTcpConnectionPrivate
g_tcp_connection_get_type
</SECTION>
<SECTION>
<FILE>gtcpwrapperconnection</FILE>
<TITLE>GTcpWrapperConnection</TITLE>
GTcpWrapperConnection
g_tcp_wrapper_connection_new
g_tcp_wrapper_connection_get_base_io_stream
<SUBSECTION Standard>
GTcpWrapperConnectionClass
G_IS_TCP_WRAPPER_CONNECTION
G_IS_TCP_WRAPPER_CONNECTION_CLASS
G_TYPE_TCP_WRAPPER_CONNECTION
G_TCP_WRAPPER_CONNECTION
G_TCP_WRAPPER_CONNECTION_CLASS
G_TCP_WRAPPER_CONNECTION_GET_CLASS
<SUBSECTION Private>
GTcpWrapperConnectionPrivate
g_tcp_wrapper_connection_get_type
</SECTION>
<SECTION>
<FILE>gsocketcontrolmessage</FILE>
<TITLE>GSocketControlMessage</TITLE>
@ -2930,3 +2957,166 @@ G_IS_PERIODIC
<SUBSECTION Private>
g_periodic_get_type
</SECTION>
<SECTION>
<FILE>gpollableinputstream</FILE>
<TITLE>GPollableInputStream</TITLE>
GPollableInputStream
GPollableInputStreamInterface
<SUBSECTION>
g_pollable_input_stream_can_poll
g_pollable_input_stream_is_readable
g_pollable_input_stream_create_source
g_pollable_input_stream_read_nonblocking
<SUBSECTION>
GPollableSourceFunc
g_pollable_source_new
<SUBSECTION Standard>
G_POLLABLE_INPUT_STREAM
G_POLLABLE_INPUT_STREAM_GET_INTERFACE
G_IS_POLLABLE_INPUT_STREAM
G_TYPE_POLLABLE_INPUT_STREAM
<SUBSECTION Private>
g_pollable_input_stream_get_type
</SECTION>
<SECTION>
<FILE>gpollableoutputstream</FILE>
<TITLE>GPollableOutputStream</TITLE>
GPollableOutputStream
GPollableOutputStreamInterface
<SUBSECTION>
g_pollable_output_stream_can_poll
g_pollable_output_stream_is_writable
g_pollable_output_stream_create_source
g_pollable_output_stream_write_nonblocking
<SUBSECTION Standard>
G_POLLABLE_OUTPUT_STREAM
G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE
G_IS_POLLABLE_OUTPUT_STREAM
G_TYPE_POLLABLE_OUTPUT_STREAM
<SUBSECTION Private>
g_pollable_output_stream_get_type
</SECTION>
<SECTION>
<FILE>gtls</FILE>
G_TLS_ERROR
GTlsError
<SUBSECTION>
GTlsAuthenticationMode
GTlsCertificateFlags
</SECTION>
<SECTION>
<FILE>gtlsbackend</FILE>
<TITLE>GTlsBackend</TITLE>
G_TLS_BACKEND_EXTENSION_POINT_NAME
GTlsBackend
GTlsBackendInterface
g_tls_backend_get_default
g_tls_backend_supports_tls
g_tls_backend_get_certificate_type
g_tls_backend_get_client_connection_type
g_tls_backend_get_server_connection_type
<SUBSECTION Standard>
G_IS_TLS_BACKEND
G_TLS_BACKEND
G_TLS_BACKEND_GET_INTERFACE
G_TYPE_TLS_BACKEND
g_tls_error_quark
<SUBSECTION Private>
g_tls_backend_get_type
</SECTION>
<SECTION>
<FILE>gtlscertificate</FILE>
<TITLE>GTlsCertificate</TITLE>
GTlsCertificate
g_tls_certificate_new_from_pem
g_tls_certificate_new_from_file
g_tls_certificate_new_from_files
g_tls_certificate_list_new_from_file
g_tls_certificate_get_issuer
<SUBSECTION Standard>
GTlsCertificateClass
GTlsCertificatePrivate
G_IS_TLS_CERTIFICATE
G_IS_TLS_CERTIFICATE_CLASS
G_TLS_CERTIFICATE
G_TLS_CERTIFICATE_CLASS
G_TLS_CERTIFICATE_GET_CLASS
G_TYPE_TLS_CERTIFICATE
<SUBSECTION Private>
g_tls_certificate_get_type
</SECTION>
<SECTION>
<FILE>gtlsconnection</FILE>
<TITLE>GTlsConnection</TITLE>
GTlsConnection
g_tls_connection_set_certificate
g_tls_connection_get_certificate
g_tls_connection_get_peer_certificate
g_tls_connection_set_require_close_notify
g_tls_connection_get_require_close_notify
GTlsRehandshakeMode
g_tls_connection_set_rehandshake_mode
g_tls_connection_get_rehandshake_mode
<SUBSECTION>
g_tls_connection_handshake
g_tls_connection_handshake_async
g_tls_connection_handshake_finish
<SUBSECTION>
g_tls_connection_set_peer_certificate
g_tls_connection_emit_accept_certificate
g_tls_connection_emit_need_certificate
<SUBSECTION Standard>
GTlsConnectionClass
GTlsConnectionPrivate
G_IS_TLS_CONNECTION
G_IS_TLS_CONNECTION_CLASS
G_TLS_CONNECTION
G_TLS_CONNECTION_CLASS
G_TLS_CONNECTION_GET_CLASS
G_TYPE_TLS_CONNECTION
<SUBSECTION Private>
g_tls_connection_get_type
</SECTION>
<SECTION>
<FILE>gtlsclientconnection</FILE>
<TITLE>GTlsClientConnection</TITLE>
GTlsClientConnection
GTlsClientConnectionInterface
g_tls_client_connection_new
g_tls_client_connection_set_server_identity
g_tls_client_connection_get_server_identity
g_tls_client_connection_set_validation_flags
g_tls_client_connection_get_validation_flags
g_tls_client_connection_set_use_ssl3
g_tls_client_connection_get_use_ssl3
g_tls_client_connection_get_accepted_cas
<SUBSECTION Standard>
G_IS_TLS_CLIENT_CONNECTION
G_TLS_CLIENT_CONNECTION
G_TLS_CLIENT_CONNECTION_GET_INTERFACE
G_TYPE_TLS_CLIENT_CONNECTION
<SUBSECTION Private>
g_tls_client_connection_get_type
</SECTION>
<SECTION>
<FILE>gtlsserverconnection</FILE>
<TITLE>GTlsServerConnection</TITLE>
GTlsServerConnection
GTlsServerConnectionInterface
g_tls_server_connection_new
<SUBSECTION Standard>
G_IS_TLS_SERVER_CONNECTION
G_TLS_SERVER_CONNECTION
G_TLS_SERVER_CONNECTION_GET_INTERFACE
G_TYPE_TLS_SERVER_CONNECTION
<SUBSECTION Private>
g_tls_server_connection_get_type
</SECTION>

View File

@ -76,6 +76,8 @@ g_output_stream_splice_flags_get_type
g_password_save_get_type
g_periodic_get_type
g_permission_get_type
g_pollable_input_stream_get_type
g_pollable_output_stream_get_type
g_proxy_address_enumerator_get_type
g_proxy_address_get_type
g_proxy_get_type
@ -102,8 +104,14 @@ g_socket_service_get_type
g_socket_type_get_type
g_srv_target_get_type
g_tcp_connection_get_type
g_tcp_wrapper_connection_get_type
g_themed_icon_get_type
g_threaded_socket_service_get_type
g_tls_backend_get_type
g_tls_certificate_get_type
g_tls_client_connection_get_type
g_tls_connection_get_type
g_tls_server_connection_get_type
g_unix_connection_get_type
g_unix_fd_list_get_type
g_unix_fd_message_get_type

View File

@ -518,8 +518,10 @@
implementation with the highest priority.
</para>
<para>
gvfs contains a GConf-based implementation that uses the
same GConf keys as gnome-vfs.
This extension point has been discontinued in GLib 2.28. It is
still available to keep API and ABI stability, but GIO is no
longer using to for default handlers. Instead, the mime handler
mechanism is used, together with x-scheme-handler pseudo-mimetypes.
</para>
</formalpara>
@ -544,6 +546,24 @@
#GProxy interface, and must be named after the network
protocol they are proxying.
</para>
<para>
glib-networking contains an implementation of this extension
point based on libproxy.
</para>
</formalpara>
<formalpara>
<title>G_TLS_BACKEND_EXTENSION_POINT_NAME</title>
<para>
Allows to provide implementations for TLS support.
Implementations of this extension point must implement
the #GTlsBackend interface.
</para>
<para>
glib-networking contains an implementation of this extension
point.
</para>
</formalpara>
</chapter>

View File

@ -56,14 +56,6 @@ with Glib-2.0 that you need to reproduce exactly.
<refsect1>
<title>Incompatible changes from 1.2 to 2.0</title>
<para>
The <ulink url="http://developer.gnome.org/dotplan/porting/">GNOME 2.0
porting guide</ulink> on <ulink
url="http://developer.gnome.org">http://developer.gnome.org</ulink>
has some more detailed discussion of porting from 1.2 to 2.0.
See the section on GLib.
</para>
<itemizedlist>
<listitem>

View File

@ -194,6 +194,10 @@ synchronize their operation.
<title>Index of new symbols in 2.26</title>
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-28" role="2.28">
<title>Index of new symbols in 2.28</title>
<xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>

View File

@ -535,6 +535,8 @@ GSourceFunc
g_source_set_callback_indirect
g_source_add_poll
g_source_remove_poll
g_source_add_child_source
g_source_remove_child_source
g_source_get_time
g_source_get_current_time
g_source_remove

View File

@ -148,6 +148,10 @@
<title>Index of new symbols in 2.26</title>
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-2-28" role="2.28">
<title>Index of new symbols in 2.28</title>
<xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>

View File

@ -376,6 +376,7 @@ g_array_get_type
g_byte_array_get_type
g_ptr_array_get_type
g_error_get_type
g_date_time_get_type
g_variant_get_gtype
g_variant_type_get_gtype
</SECTION>
@ -828,6 +829,7 @@ g_closure_set_marshal
g_closure_add_marshal_guards
g_closure_set_meta_marshal
g_source_set_closure
g_source_set_dummy_callback
G_TYPE_IO_CHANNEL
G_TYPE_IO_CONDITION

View File

@ -202,7 +202,6 @@ platform_libadd += win32/libgiowin32.la
platform_deps += win32/libgiowin32.la
endif
SUBDIRS += .
if HAVE_FAM
@ -307,6 +306,8 @@ libgio_2_0_la_SOURCES = \
gdummyfile.c \
gdummyproxyresolver.c \
gdummyproxyresolver.h \
gdummytlsbackend.c \
gdummytlsbackend.h \
gemblem.h \
gemblem.c \
gemblemedicon.h \
@ -349,6 +350,8 @@ libgio_2_0_la_SOURCES = \
goutputstream.c \
gperiodic.c \
gpermission.c \
gpollableinputstream.c \
gpollableoutputstream.c \
gpollfilemonitor.c \
gpollfilemonitor.h \
gproxyresolver.c \
@ -371,15 +374,19 @@ libgio_2_0_la_SOURCES = \
gproxy.c \
gproxyaddress.c \
gproxyaddressenumerator.c \
gproxyconnection.c \
gproxyconnection.h \
gsocketservice.c \
gsrvtarget.c \
gtcpconnection.c \
gtcpwrapperconnection.c \
gthreadedsocketservice.c\
gthemedicon.c \
gthreadedresolver.c \
gthreadedresolver.h \
gtlsbackend.c \
gtlscertificate.c \
gtlsclientconnection.c \
gtlsconnection.c \
gtlsserverconnection.c \
gunionvolumemonitor.c \
gunionvolumemonitor.h \
gvfs.c \
@ -505,6 +512,8 @@ gio_headers = \
goutputstream.h \
gperiodic.h \
gpermission.h \
gpollableinputstream.h \
gpollableoutputstream.h \
gproxyaddress.h \
gproxy.h \
gproxyaddressenumerator.h \
@ -524,8 +533,14 @@ gio_headers = \
gsocketservice.h \
gsrvtarget.h \
gtcpconnection.h \
gtcpwrapperconnection.h \
gthreadedsocketservice.h\
gthemedicon.h \
gtlsbackend.h \
gtlscertificate.h \
gtlsclientconnection.h \
gtlsconnection.h \
gtlsserverconnection.h \
gvfs.h \
gvolume.h \
gvolumemonitor.h \

View File

@ -28,7 +28,7 @@ G_DEFINE_INTERFACE (GAction, g_action, G_TYPE_OBJECT)
/**
* SECTION:gaction
* @title: GAction
* @short_description: an action
* @short_description: An action
*
* #GAction represents a single named action.
*

View File

@ -28,7 +28,7 @@
/**
* SECTION:gactiongroup
* @title: GActionGroup
* @short_description: a group of actions
* @short_description: A group of actions
*
* #GActionGroup represents a group of actions.
*

View File

@ -737,7 +737,7 @@ g_app_launch_context_init (GAppLaunchContext *launch_context)
*
* Gets the display string for the @context. This is used to ensure new
* applications are started on the same display as the launching
* application, by setting the <envvar>DISPLAY</envvar> environment variable.
* application, by setting the <envar>DISPLAY</envar> environment variable.
*
* Returns: a display string for the display.
**/
@ -766,7 +766,7 @@ g_app_launch_context_get_display (GAppLaunchContext *context,
* @files: (element-type GFile): a #GList of of #GFile objects
*
* Initiates startup notification for the application and returns the
* <envvar>DESKTOP_STARTUP_ID</envvar> for the launched operation,
* <envar>DESKTOP_STARTUP_ID</envar> for the launched operation,
* if supported.
*
* Startup notification IDs are defined in the <ulink

View File

@ -175,6 +175,9 @@ gboolean g_app_info_delete (GAppInfo *appinfo);
GList * g_app_info_get_all (void);
GList * g_app_info_get_all_for_type (const char *content_type);
GList * g_app_info_get_recommended_for_type (const gchar *content_type);
GList * g_app_info_get_fallback_for_type (const gchar *content_type);
void g_app_info_reset_type_associations (const char *content_type);
GAppInfo *g_app_info_get_default_for_type (const char *content_type,
gboolean must_support_uris);

View File

@ -33,8 +33,7 @@ G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJEC
/**
* SECTION:gapplicationcommandline
* @title: GApplicationCommandLine
* @short_description: A class representing a command-line invocation of
* an application
* @short_description: A command-line invocation of an application
* @see_also: #GApplication
*
* #GApplicationCommandLine represents a command-line invocation of

View File

@ -354,17 +354,21 @@ g_application_impl_actions_method_call (GDBusConnection *connection,
GVariant *platform_data;
GVariantIter *param;
GVariant *parameter;
GVariant *unboxed_parameter;
g_variant_get (parameters, "(&sav@a{sv})",
&action_name, &param, &platform_data);
parameter = g_variant_iter_next_value (param);
unboxed_parameter = parameter ? g_variant_get_variant (parameter) : NULL;
g_variant_iter_free (param);
class->before_emit (impl->app, platform_data);
g_action_group_activate_action (action_group, action_name, parameter);
g_action_group_activate_action (action_group, action_name, unboxed_parameter);
class->after_emit (impl->app, platform_data);
g_variant_unref (platform_data);
if (unboxed_parameter)
g_variant_unref (unboxed_parameter);
if (parameter)
g_variant_unref (parameter);

View File

@ -43,18 +43,14 @@ typedef struct
{
GSource source;
GPollFD pollfd;
GCancellable *cancellable;
gulong cancelled_tag;
} FDSource;
static gboolean
fd_source_prepare (GSource *source,
gint *timeout)
{
FDSource *fd_source = (FDSource *)source;
*timeout = -1;
return g_cancellable_is_cancelled (fd_source->cancellable);
return FALSE;
}
static gboolean
@ -62,9 +58,7 @@ fd_source_check (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
return
g_cancellable_is_cancelled (fd_source->cancellable) ||
fd_source->pollfd.revents != 0;
return fd_source->pollfd.revents != 0;
}
static gboolean
@ -78,42 +72,76 @@ fd_source_dispatch (GSource *source,
g_warn_if_fail (func != NULL);
return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
return (*func) (fd_source->pollfd.fd, fd_source->pollfd.revents, user_data);
}
static void
fd_source_finalize (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
}
/* we don't use g_cancellable_disconnect() here, since we are holding
* the main context lock here, and the ::disconnect signal handler
* will try to grab that, and deadlock looms.
*/
if (fd_source->cancelled_tag)
g_signal_handler_disconnect (fd_source->cancellable,
fd_source->cancelled_tag);
static gboolean
fd_source_closure_callback (int fd,
GIOCondition condition,
gpointer data)
{
GClosure *closure = data;
if (fd_source->cancellable)
g_object_unref (fd_source->cancellable);
GValue params[2] = { { 0, }, { 0, } };
GValue result_value = { 0, };
gboolean result;
g_value_init (&result_value, G_TYPE_BOOLEAN);
g_value_init (&params[0], G_TYPE_INT);
g_value_set_int (&params[0], fd);
g_value_init (&params[1], G_TYPE_IO_CONDITION);
g_value_set_flags (&params[1], condition);
g_closure_invoke (closure, &result_value, 2, params, NULL);
result = g_value_get_boolean (&result_value);
g_value_unset (&result_value);
g_value_unset (&params[0]);
g_value_unset (&params[1]);
return result;
}
static void
fd_source_closure_marshal (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
GFDSourceFunc callback;
GCClosure *cc = (GCClosure*) closure;
gboolean v_return;
g_return_if_fail (return_value != NULL);
g_return_if_fail (n_param_values == 0);
callback = (GFDSourceFunc) (marshal_data ? marshal_data : cc->callback);
v_return = callback (g_value_get_int (param_values),
g_value_get_flags (param_values + 1),
closure->data);
g_value_set_boolean (return_value, v_return);
}
static GSourceFuncs fd_source_funcs = {
fd_source_prepare,
fd_source_check,
fd_source_dispatch,
fd_source_finalize
fd_source_finalize,
(GSourceFunc)fd_source_closure_callback,
(GSourceDummyMarshal)fd_source_closure_marshal,
};
/* Might be called on another thread */
static void
fd_source_cancelled_cb (GCancellable *cancellable,
gpointer data)
{
/* Wake up the mainloop in case we're waiting on async calls with FDSource */
g_main_context_wakeup (NULL);
}
GSource *
_g_fd_source_new (int fd,
gushort events,
@ -125,18 +153,18 @@ _g_fd_source_new (int fd,
source = g_source_new (&fd_source_funcs, sizeof (FDSource));
fd_source = (FDSource *)source;
if (cancellable)
fd_source->cancellable = g_object_ref (cancellable);
fd_source->pollfd.fd = fd;
fd_source->pollfd.events = events;
g_source_add_poll (source, &fd_source->pollfd);
if (cancellable)
fd_source->cancelled_tag =
g_cancellable_connect (cancellable,
(GCallback)fd_source_cancelled_cb,
NULL, NULL);
{
GSource *cancellable_source = g_cancellable_source_new (cancellable);
g_source_set_dummy_callback (cancellable_source);
g_source_add_child_source (source, cancellable_source);
g_source_unref (cancellable_source);
}
return source;
}

View File

@ -27,9 +27,9 @@
G_BEGIN_DECLS
typedef gboolean (*GFDSourceFunc) (gpointer user_data,
typedef gboolean (*GFDSourceFunc) (int fd,
GIOCondition condition,
int fd);
gpointer user_data);
GSource *_g_fd_source_new (int fd,
gushort events,

View File

@ -32,6 +32,7 @@
#include <io.h>
#endif
#include "gcancellable.h"
#include "gio-marshal.h"
#include "glibintl.h"
@ -770,3 +771,118 @@ g_cancellable_disconnect (GCancellable *cancellable,
g_signal_handler_disconnect (cancellable, handler_id);
G_UNLOCK (cancellable);
}
typedef struct {
GSource source;
GCancellable *cancellable;
GPollFD pollfd;
} GCancellableSource;
static gboolean
cancellable_source_prepare (GSource *source,
gint *timeout)
{
GCancellableSource *cancellable_source = (GCancellableSource *)source;
*timeout = -1;
return g_cancellable_is_cancelled (cancellable_source->cancellable);
}
static gboolean
cancellable_source_check (GSource *source)
{
GCancellableSource *cancellable_source = (GCancellableSource *)source;
return g_cancellable_is_cancelled (cancellable_source->cancellable);
}
static gboolean
cancellable_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GCancellableSourceFunc func = (GCancellableSourceFunc)callback;
GCancellableSource *cancellable_source = (GCancellableSource *)source;
return (*func) (cancellable_source->cancellable, user_data);
}
static void
cancellable_source_finalize (GSource *source)
{
GCancellableSource *cancellable_source = (GCancellableSource *)source;
if (cancellable_source->cancellable)
g_object_unref (cancellable_source->cancellable);
}
static gboolean
cancellable_source_closure_callback (GCancellable *cancellable,
gpointer data)
{
GClosure *closure = data;
GValue params = { 0, };
GValue result_value = { 0, };
gboolean result;
g_value_init (&result_value, G_TYPE_BOOLEAN);
g_value_init (&params, G_TYPE_CANCELLABLE);
g_value_set_object (&params, cancellable);
g_closure_invoke (closure, &result_value, 1, &params, NULL);
result = g_value_get_boolean (&result_value);
g_value_unset (&result_value);
g_value_unset (&params);
return result;
}
static GSourceFuncs cancellable_source_funcs =
{
cancellable_source_prepare,
cancellable_source_check,
cancellable_source_dispatch,
cancellable_source_finalize,
(GSourceFunc)cancellable_source_closure_callback,
(GSourceDummyMarshal)_gio_marshal_BOOLEAN__VOID,
};
/**
* g_cancellable_source_new:
* @cancellable: a #GCancellable, or %NULL
*
* Creates a source that triggers if @cancellable is cancelled and
* calls its callback of type #GCancellableSourceFunc. This is
* primarily useful for attaching to another (non-cancellable) source
* with g_source_add_child_source() to add cancellability to it.
*
* For convenience, you can call this with a %NULL #GCancellable,
* in which case the source will never trigger.
*
* Return value: the new #GSource.
*
* Since: 2.28
*/
GSource *
g_cancellable_source_new (GCancellable *cancellable)
{
GSource *source;
GCancellableSource *cancellable_source;
source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource));
g_source_set_name (source, "GCancellable");
cancellable_source = (GCancellableSource *)source;
if (g_cancellable_make_pollfd (cancellable,
&cancellable_source->pollfd))
{
cancellable_source->cancellable = g_object_ref (cancellable);
g_source_add_poll (source, &cancellable_source->pollfd);
}
return source;
}

View File

@ -83,6 +83,8 @@ gboolean g_cancellable_make_pollfd (GCancellable *cancellable,
GPollFD *pollfd);
void g_cancellable_release_fd (GCancellable *cancellable);
GSource * g_cancellable_source_new (GCancellable *cancellable);
GCancellable *g_cancellable_get_current (void);
void g_cancellable_push_current (GCancellable *cancellable);
void g_cancellable_pop_current (GCancellable *cancellable);

View File

@ -48,6 +48,7 @@
/**
* SECTION:gdesktopappinfo
* @title: GDesktopAppInfo
* @short_description: Application information from desktop files
* @include: gio/gdesktopappinfo.h
*
@ -67,7 +68,8 @@
static void g_desktop_app_info_iface_init (GAppInfoIface *iface);
static GList * get_all_desktop_entries_for_mime_type (const char *base_mime_type,
const char **except);
const char **except,
gboolean include_fallback);
static void mime_info_cache_reload (const char *dir);
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
GError **error);
@ -1249,10 +1251,10 @@ update_mimeapps_list (const char *desktop_id,
add the current list of (not yet listed) apps before it. */
list[i] = NULL; /* Terminate current list so we can use it */
system_list = get_all_desktop_entries_for_mime_type (content_type, (const char **)list);
system_list = get_all_desktop_entries_for_mime_type (content_type, (const char **)list, FALSE);
list = g_renew (char *, list, 1 + length + g_list_length (system_list) + 1);
for (l = system_list; l != NULL; l = l->next)
{
list[i++] = l->data; /* no strdup, taking ownership */
@ -1722,15 +1724,107 @@ app_info_in_list (GAppInfo *info,
return FALSE;
}
/**
* g_app_info_get_recommended_for_type:
* @content_type: the content type to find a #GAppInfo for
*
* Gets a list of recommended #GAppInfos for a given content type, i.e.
* those applications which claim to support the given content type exactly,
* and not by MIME type subclassing.
*
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
* for given @content_type or %NULL on error.
*
* Since: 2.28
**/
GList *
g_app_info_get_recommended_for_type (const gchar *content_type)
{
GList *desktop_entries, *l;
GList *infos;
GDesktopAppInfo *info;
g_return_val_if_fail (content_type != NULL, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, FALSE);
infos = NULL;
for (l = desktop_entries; l != NULL; l = l->next)
{
char *desktop_entry = l->data;
info = g_desktop_app_info_new (desktop_entry);
if (info)
{
if (app_info_in_list (G_APP_INFO (info), infos))
g_object_unref (info);
else
infos = g_list_prepend (infos, info);
}
g_free (desktop_entry);
}
g_list_free (desktop_entries);
return g_list_reverse (infos);
}
/**
* g_app_info_get_fallback_for_type:
* @content_type: the content type to find a #GAppInfo for
*
* Gets a list of fallback #GAppInfos for a given content type, i.e.
* those applications which claim to support the given content type
* by MIME type subclassing and not directly.
*
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
* for given @content_type or %NULL on error.
*
* Since: 2.28
**/
GList *
g_app_info_get_fallback_for_type (const gchar *content_type)
{
GList *desktop_entries, *l;
GList *infos, *recommended_infos;
GDesktopAppInfo *info;
g_return_val_if_fail (content_type != NULL, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
recommended_infos = g_app_info_get_recommended_for_type (content_type);
infos = NULL;
for (l = desktop_entries; l != NULL; l = l->next)
{
char *desktop_entry = l->data;
info = g_desktop_app_info_new (desktop_entry);
if (info)
{
if (app_info_in_list (G_APP_INFO (info), infos) ||
app_info_in_list (G_APP_INFO (info), recommended_infos))
g_object_unref (info);
else
infos = g_list_prepend (infos, info);
}
g_free (desktop_entry);
}
g_list_free (desktop_entries);
g_list_free_full (recommended_infos, g_object_unref);
return g_list_reverse (infos);
}
/**
* g_app_info_get_all_for_type:
* @content_type: the content type to find a #GAppInfo for
*
* Gets a list of all #GAppInfo<!-- -->s for a given content type.
* Gets a list of all #GAppInfos for a given content type.
*
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfo<!-- -->s for given @content_type
* or %NULL on error.
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
* for given @content_type or %NULL on error.
**/
GList *
g_app_info_get_all_for_type (const char *content_type)
@ -1741,7 +1835,7 @@ g_app_info_get_all_for_type (const char *content_type)
g_return_val_if_fail (content_type != NULL, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
infos = NULL;
for (l = desktop_entries; l != NULL; l = l->next)
@ -1800,7 +1894,7 @@ g_app_info_get_default_for_type (const char *content_type,
g_return_val_if_fail (content_type != NULL, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL);
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
info = NULL;
for (l = desktop_entries; l != NULL; l = l->next)
@ -2542,7 +2636,8 @@ append_desktop_entry (GList *list,
*/
static GList *
get_all_desktop_entries_for_mime_type (const char *base_mime_type,
const char **except)
const char **except,
gboolean include_fallback)
{
GList *desktop_entries, *removed_entries, *list, *dir_list, *tmp;
MimeInfoCacheDir *dir;
@ -2556,29 +2651,38 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
mime_info_cache_init ();
/* collect all ancestors */
mime_types = _g_unix_content_type_get_parents (base_mime_type);
array = g_ptr_array_new ();
for (i = 0; mime_types[i]; i++)
g_ptr_array_add (array, mime_types[i]);
g_free (mime_types);
for (i = 0; i < array->len; i++)
if (include_fallback)
{
anc = _g_unix_content_type_get_parents (g_ptr_array_index (array, i));
for (j = 0; anc[j]; j++)
{
for (k = 0; k < array->len; k++)
{
if (strcmp (anc[j], g_ptr_array_index (array, k)) == 0)
break;
}
if (k == array->len) /* not found */
g_ptr_array_add (array, g_strdup (anc[j]));
}
g_strfreev (anc);
/* collect all ancestors */
mime_types = _g_unix_content_type_get_parents (base_mime_type);
array = g_ptr_array_new ();
for (i = 0; mime_types[i]; i++)
g_ptr_array_add (array, mime_types[i]);
g_free (mime_types);
for (i = 0; i < array->len; i++)
{
anc = _g_unix_content_type_get_parents (g_ptr_array_index (array, i));
for (j = 0; anc[j]; j++)
{
for (k = 0; k < array->len; k++)
{
if (strcmp (anc[j], g_ptr_array_index (array, k)) == 0)
break;
}
if (k == array->len) /* not found */
g_ptr_array_add (array, g_strdup (anc[j]));
}
g_strfreev (anc);
}
g_ptr_array_add (array, NULL);
mime_types = (char **)g_ptr_array_free (array, FALSE);
}
else
{
mime_types = g_malloc0 (2 * sizeof (gchar *));
mime_types[0] = g_strdup (base_mime_type);
mime_types[1] = NULL;
}
g_ptr_array_add (array, NULL);
mime_types = (char **)g_ptr_array_free (array, FALSE);
G_LOCK (mime_info_cache);

274
gio/gdummytlsbackend.c Normal file
View File

@ -0,0 +1,274 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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 "gdummytlsbackend.h"
#include <glib.h>
#include "gasyncresult.h"
#include "gcancellable.h"
#include "ginitable.h"
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "gtlsclientconnection.h"
#include "gtlsserverconnection.h"
#include "gsimpleasyncresult.h"
#include "giomodule.h"
#include "giomodule-priv.h"
#include "glibintl.h"
static GType _g_dummy_tls_certificate_get_type (void);
static GType _g_dummy_tls_connection_get_type (void);
struct _GDummyTlsBackend {
GObject parent_instance;
};
static void g_dummy_tls_backend_iface_init (GTlsBackendInterface *iface);
#define g_dummy_tls_backend_get_type _g_dummy_tls_backend_get_type
G_DEFINE_TYPE_WITH_CODE (GDummyTlsBackend, g_dummy_tls_backend, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_TLS_BACKEND,
g_dummy_tls_backend_iface_init)
_g_io_modules_ensure_extension_points_registered ();
g_io_extension_point_implement (G_TLS_BACKEND_EXTENSION_POINT_NAME,
g_define_type_id,
"dummy",
-100))
static void
g_dummy_tls_backend_init (GDummyTlsBackend *backend)
{
}
static void
g_dummy_tls_backend_class_init (GDummyTlsBackendClass *backend_class)
{
}
static void
g_dummy_tls_backend_iface_init (GTlsBackendInterface *iface)
{
iface->get_certificate_type = _g_dummy_tls_certificate_get_type;
iface->get_client_connection_type = _g_dummy_tls_connection_get_type;
iface->get_server_connection_type = _g_dummy_tls_connection_get_type;
}
/* Dummy certificate type */
typedef struct _GDummyTlsCertificate GDummyTlsCertificate;
typedef struct _GDummyTlsCertificateClass GDummyTlsCertificateClass;
struct _GDummyTlsCertificate {
GTlsCertificate parent_instance;
};
struct _GDummyTlsCertificateClass {
GTlsCertificateClass parent_class;
};
enum
{
PROP_CERTIFICATE_0,
PROP_CERTIFICATE,
PROP_CERTIFICATE_PEM,
PROP_PRIVATE_KEY,
PROP_PRIVATE_KEY_PEM
};
static void g_dummy_tls_certificate_initable_iface_init (GInitableIface *iface);
#define g_dummy_tls_certificate_get_type _g_dummy_tls_certificate_get_type
G_DEFINE_TYPE_WITH_CODE (GDummyTlsCertificate, g_dummy_tls_certificate, G_TYPE_TLS_CERTIFICATE,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
g_dummy_tls_certificate_initable_iface_init);)
static void
g_dummy_tls_certificate_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
/* We need to define this method to make GObject happy, but it will
* never be possible to construct a working GDummyTlsCertificate, so
* it doesn't have to do anything useful.
*/
}
static void
g_dummy_tls_certificate_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
/* Just ignore all attempts to set properties. */
}
static void
g_dummy_tls_certificate_class_init (GDummyTlsCertificateClass *certificate_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (certificate_class);
gobject_class->get_property = g_dummy_tls_certificate_get_property;
gobject_class->set_property = g_dummy_tls_certificate_set_property;
g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
g_object_class_override_property (gobject_class, PROP_CERTIFICATE_PEM, "certificate-pem");
g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY, "private-key");
g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PEM, "private-key-pem");
}
static void
g_dummy_tls_certificate_init (GDummyTlsCertificate *certificate)
{
}
static gboolean
g_dummy_tls_certificate_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
_("TLS support is not available"));
return FALSE;
}
static void
g_dummy_tls_certificate_initable_iface_init (GInitableIface *iface)
{
iface->init = g_dummy_tls_certificate_initable_init;
}
/* Dummy connection type; since GTlsClientConnection and
* GTlsServerConnection are just interfaces, we can implement them
* both on a single object.
*/
typedef struct _GDummyTlsConnection GDummyTlsConnection;
typedef struct _GDummyTlsConnectionClass GDummyTlsConnectionClass;
struct _GDummyTlsConnection {
GTlsConnection parent_instance;
};
struct _GDummyTlsConnectionClass {
GTlsConnectionClass parent_class;
};
enum
{
PROP_CONNECTION_0,
PROP_BASE_IO_STREAM,
PROP_REQUIRE_CLOSE_NOTIFY,
PROP_REHANDSHAKE_MODE,
PROP_VALIDATION_FLAGS,
PROP_SERVER_IDENTITY,
PROP_USE_SSL3,
PROP_ACCEPTED_CAS,
PROP_AUTHENTICATION_MODE
};
static void g_dummy_tls_connection_initable_iface_init (GInitableIface *iface);
#define g_dummy_tls_connection_get_type _g_dummy_tls_connection_get_type
G_DEFINE_TYPE_WITH_CODE (GDummyTlsConnection, g_dummy_tls_connection, G_TYPE_TLS_CONNECTION,
G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION, NULL);
G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION, NULL);
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
g_dummy_tls_connection_initable_iface_init);)
static void
g_dummy_tls_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
}
static void
g_dummy_tls_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
}
static gboolean
g_dummy_tls_connection_close (GIOStream *stream,
GCancellable *cancellable,
GError **error)
{
return TRUE;
}
static void
g_dummy_tls_connection_class_init (GDummyTlsConnectionClass *connection_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (connection_class);
GIOStreamClass *io_stream_class = G_IO_STREAM_CLASS (connection_class);
gobject_class->get_property = g_dummy_tls_connection_get_property;
gobject_class->set_property = g_dummy_tls_connection_set_property;
/* Need to override this because when initable_init fails it will
* dispose the connection, which will close it, which would
* otherwise try to close its input/output streams, which don't
* exist.
*/
io_stream_class->close_fn = g_dummy_tls_connection_close;
g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
g_object_class_override_property (gobject_class, PROP_ACCEPTED_CAS, "accepted-cas");
g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
}
static void
g_dummy_tls_connection_init (GDummyTlsConnection *connection)
{
}
static gboolean
g_dummy_tls_connection_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
_("TLS support is not available"));
return FALSE;
}
static void
g_dummy_tls_connection_initable_iface_init (GInitableIface *iface)
{
iface->init = g_dummy_tls_connection_initable_init;
}

46
gio/gdummytlsbackend.h Normal file
View File

@ -0,0 +1,46 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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_DUMMY_TLS_BACKEND_H__
#define __G_DUMMY_TLS_BACKEND_H__
#include <gio/giotypes.h>
G_BEGIN_DECLS
#define G_TYPE_DUMMY_TLS_BACKEND (_g_dummy_tls_backend_get_type ())
#define G_DUMMY_TLS_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DUMMY_TLS_BACKEND, GDummyTlsBackend))
#define G_DUMMY_TLS_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DUMMY_TLS_BACKEND, GDummyTlsBackendClass))
#define G_IS_DUMMY_TLS_BACKEND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DUMMY_TLS_BACKEND))
#define G_IS_DUMMY_TLS_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DUMMY_TLS_BACKEND))
#define G_DUMMY_TLS_BACKEND_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DUMMY_TLS_BACKEND, GDummyTlsBackendClass))
typedef struct _GDummyTlsBackend GDummyTlsBackend;
typedef struct _GDummyTlsBackendClass GDummyTlsBackendClass;
struct _GDummyTlsBackendClass {
GObjectClass parent_class;
};
GType _g_dummy_tls_backend_get_type (void);
G_END_DECLS
#endif /* __G_DUMMY_TLS_BACKEND_H__ */

View File

@ -224,10 +224,16 @@ g_file_monitor_class_init (GFileMonitorClass *klass)
* GFileMonitor::changed:
* @monitor: a #GFileMonitor.
* @file: a #GFile.
* @other_file: a #GFile.
* @other_file: a #GFile or #NULL.
* @event_type: a #GFileMonitorEvent.
*
* Emitted when a file has been changed.
*
* Emitted when @file has been changed.
*
* If using #G_FILE_MONITOR_SEND_MOVED flag and @event_type is
* #G_FILE_MONITOR_SEND_MOVED, @file will be set to a #GFile containing the
* old path, and @other_file will be set to a #GFile containing the new path.
*
* In all the other cases, @other_file will be set to #NULL.
**/
signals[CHANGED] =
g_signal_new (I_("changed"),
@ -327,21 +333,21 @@ g_file_monitor_cancel (GFileMonitor* monitor)
/**
* g_file_monitor_set_rate_limit:
* @monitor: a #GFileMonitor.
* @limit_msecs: a integer with the limit in milliseconds to
* poll for changes.
* @limit_msecs: a non-negative integer with the limit in milliseconds
* to poll for changes
*
* Sets the rate limit to which the @monitor will report
* consecutive change events to the same file.
*
**/
* consecutive change events to the same file.
*/
void
g_file_monitor_set_rate_limit (GFileMonitor *monitor,
int limit_msecs)
gint limit_msecs)
{
GFileMonitorPrivate *priv;
g_return_if_fail (G_IS_FILE_MONITOR (monitor));
g_return_if_fail (limit_msecs >= 0);
priv = monitor->priv;
if (priv->rate_limit_msec != limit_msecs)
{

View File

@ -81,7 +81,7 @@ GType g_file_monitor_get_type (void) G_GNUC_CONST;
gboolean g_file_monitor_cancel (GFileMonitor *monitor);
gboolean g_file_monitor_is_cancelled (GFileMonitor *monitor);
void g_file_monitor_set_rate_limit (GFileMonitor *monitor,
int limit_msecs);
gint limit_msecs);
/* For implementations */

View File

@ -25,3 +25,7 @@ VOID:POINTER,INT,STRING
BOOLEAN:OBJECT
INT:OBJECT
VOID:INT64
VOID:UINT64
BOOLEAN:FLAGS
BOOLEAN:OBJECT,FLAGS
OBJECT:VOID

View File

@ -95,6 +95,8 @@
#include <gio/goutputstream.h>
#include <gio/gperiodic.h>
#include <gio/gpermission.h>
#include <gio/gpollableinputstream.h>
#include <gio/gpollableoutputstream.h>
#include <gio/gproxy.h>
#include <gio/gproxyaddress.h>
#include <gio/gproxyaddressenumerator.h>
@ -115,8 +117,14 @@
#include <gio/gsocketservice.h>
#include <gio/gsrvtarget.h>
#include <gio/gtcpconnection.h>
#include <gio/gtcpwrapperconnection.h>
#include <gio/gthemedicon.h>
#include <gio/gthreadedsocketservice.h>
#include <gio/gtlsbackend.h>
#include <gio/gtlscertificate.h>
#include <gio/gtlsclientconnection.h>
#include <gio/gtlsconnection.h>
#include <gio/gtlsserverconnection.h>
#include <gio/gvfs.h>
#include <gio/gvolume.h>
#include <gio/gvolumemonitor.h>

View File

@ -103,6 +103,8 @@ g_app_info_get_all
g_app_info_get_all_for_type
g_app_info_get_default_for_type
g_app_info_get_default_for_uri_scheme
g_app_info_get_fallback_for_type
g_app_info_get_recommended_for_type
g_app_info_reset_type_associations
#endif
#endif
@ -191,6 +193,7 @@ g_cancellable_reset
g_cancellable_cancel
g_cancellable_connect
g_cancellable_disconnect
g_cancellable_source_new
#endif
#endif
@ -1064,6 +1067,9 @@ g_dbus_signal_flags_get_type G_GNUC_CONST
g_dbus_send_message_flags_get_type G_GNUC_CONST
g_credentials_type_get_type G_GNUC_CONST
g_dbus_message_byte_order_get_type G_GNUC_CONST
g_tls_authentication_mode_get_type G_GNUC_CONST
g_tls_certificate_flags_get_type G_GNUC_CONST
g_tls_rehandshake_mode_get_type G_GNUC_CONST
#endif
#endif
@ -1368,6 +1374,7 @@ g_socket_control_message_serialize
#if IN_HEADER(__G_SOCKET_CLIENT_H__)
#if IN_FILE(__G_SOCKET_CLIENT_C__)
g_socket_client_get_type G_GNUC_CONST
g_socket_client_add_application_proxy
g_socket_client_connect
g_socket_client_connect_async
g_socket_client_connect_finish
@ -1380,20 +1387,23 @@ g_socket_client_connect_to_service_finish
g_socket_client_connect_to_uri
g_socket_client_connect_to_uri_async
g_socket_client_connect_to_uri_finish
g_socket_client_get_enable_proxy
g_socket_client_get_family
g_socket_client_get_local_address
g_socket_client_get_protocol
g_socket_client_get_socket_type
g_socket_client_get_timeout
g_socket_client_get_enable_proxy
g_socket_client_get_tls
g_socket_client_get_tls_validation_flags
g_socket_client_new
g_socket_client_set_enable_proxy
g_socket_client_set_family
g_socket_client_set_local_address
g_socket_client_set_protocol
g_socket_client_set_socket_type
g_socket_client_set_timeout
g_socket_client_set_enable_proxy
g_socket_client_add_application_proxy
g_socket_client_set_tls
g_socket_client_set_tls_validation_flags
#endif
#endif
@ -1975,3 +1985,96 @@ g_periodic_remove
g_periodic_unblock
#endif
#endif
#if IN_HEADER(__G_POLLABLE_INPUT_STREAM_H__)
#if IN_FILE(__G_POLLABLE_INPUT_STREAM_C__)
g_pollable_input_stream_get_type G_GNUC_CONST
g_pollable_input_stream_can_poll
g_pollable_input_stream_create_source
g_pollable_input_stream_is_readable
g_pollable_input_stream_read_nonblocking
g_pollable_source_new
#endif
#endif
#if IN_HEADER(__G_POLLABLE_OUTPUT_STREAM_H__)
#if IN_FILE(__G_POLLABLE_OUTPUT_STREAM_C__)
g_pollable_output_stream_get_type G_GNUC_CONST
g_pollable_output_stream_can_poll
g_pollable_output_stream_create_source
g_pollable_output_stream_is_writable
g_pollable_output_stream_write_nonblocking
#endif
#endif
#if IN_HEADER(__G_TCP_WRAPPER_CONNECTION_H__)
#if IN_FILE(__G_TCP_WRAPPER_CONNECTION_C__)
g_tcp_wrapper_connection_get_type G_GNUC_CONST
g_tcp_wrapper_connection_get_base_io_stream
g_tcp_wrapper_connection_new
#endif
#endif
#if IN_HEADER(__G_TLS_BACKEND_H__)
#if IN_FILE(__G_TLS_BACKEND_C__)
g_tls_backend_get_certificate_type
g_tls_backend_get_client_connection_type
g_tls_backend_get_default
g_tls_backend_get_server_connection_type
g_tls_backend_get_type G_GNUC_CONST
g_tls_backend_supports_tls
g_tls_error_get_type G_GNUC_CONST
g_tls_error_quark
#endif
#endif
#if IN_HEADER(__G_TLS_CERTIFICATE_H__)
#if IN_FILE(__G_TLS_CERTIFICATE_C__)
g_tls_certificate_get_issuer
g_tls_certificate_get_type G_GNUC_CONST
g_tls_certificate_list_new_from_file
g_tls_certificate_new_from_file
g_tls_certificate_new_from_files
g_tls_certificate_new_from_pem
#endif
#endif
#if IN_HEADER(__G_TLS_CONNECTION_H__)
#if IN_FILE(__G_TLS_CONNECTION_C__)
g_tls_connection_emit_accept_certificate
g_tls_connection_emit_need_certificate
g_tls_connection_get_certificate
g_tls_connection_get_peer_certificate
g_tls_connection_get_rehandshake_mode
g_tls_connection_get_require_close_notify
g_tls_connection_get_type G_GNUC_CONST
g_tls_connection_handshake
g_tls_connection_handshake_async
g_tls_connection_handshake_finish
g_tls_connection_set_certificate
g_tls_connection_set_peer_certificate
g_tls_connection_set_rehandshake_mode
g_tls_connection_set_require_close_notify
#endif
#endif
#if IN_HEADER(__G_TLS_CLIENT_CONNECTION_H__)
#if IN_FILE(__G_TLS_CLIENT_CONNECTION_C__)
g_tls_client_connection_get_accepted_cas
g_tls_client_connection_get_server_identity
g_tls_client_connection_get_type G_GNUC_CONST
g_tls_client_connection_get_use_ssl3
g_tls_client_connection_get_validation_flags
g_tls_client_connection_new
g_tls_client_connection_set_server_identity
g_tls_client_connection_set_use_ssl3
g_tls_client_connection_set_validation_flags
#endif
#endif
#if IN_HEADER(__G_TLS_SERVER_CONNECTION_H__)
#if IN_FILE(__G_TLS_SERVER_CONNECTION_C__)
g_tls_server_connection_get_type G_GNUC_CONST
g_tls_server_connection_new
#endif
#endif

View File

@ -1249,6 +1249,106 @@ typedef enum
G_APPLICATION_SEND_ENVIRONMENT = (1 << 4)
} GApplicationFlags;
/**
* GTlsError:
* @G_TLS_ERROR_MISC: Miscellaneous TLS error
* @G_TLS_ERROR_BAD_CERTIFICATE: A certificate could not be parsed
* @G_TLS_ERROR_NOT_TLS: The TLS handshake failed because the
* peer does not seem to be a TLS server.
* @G_TLS_ERROR_HANDSHAKE: The TLS handshake failed because the
* peer's certificate was not acceptable.
* @G_TLS_ERROR_CERTIFICATE_REQUIRED: The TLS handshake failed because
* the server requested a client-side certificate, but none was
* provided. See #GTlsConnection::need-certificate.
* @G_TLS_ERROR_EOF: The TLS connection was closed without proper
* notice, which may indicate an attack. See
* g_tls_connection_set_require_close_notify().
*
* An error code used with %G_TLS_ERROR in a #GError returned from a
* TLS-related routine.
*
* Since: 2.28
*/
typedef enum {
G_TLS_ERROR_MISC,
G_TLS_ERROR_BAD_CERTIFICATE,
G_TLS_ERROR_NOT_TLS,
G_TLS_ERROR_HANDSHAKE,
G_TLS_ERROR_CERTIFICATE_REQUIRED,
G_TLS_ERROR_EOF
} GTlsError;
/**
* GTlsCertificateFlags:
* @G_TLS_CERTIFICATE_UNKNOWN_CA: The signing certificate authority is
* not known.
* @G_TLS_CERTIFICATE_BAD_IDENTITY: The certificate does not match the
* expected identity of the site that it was retrieved from.
* @G_TLS_CERTIFICATE_NOT_ACTIVATED: The certificate's activation time
* is still in the future
* @G_TLS_CERTIFICATE_EXPIRED: The certificate has expired
* @G_TLS_CERTIFICATE_REVOKED: The certificate has been revoked
* according to the #GTlsContext's certificate revocation list.
* @G_TLS_CERTIFICATE_INSECURE: The certificate's algorithm is
* considered insecure.
* @G_TLS_CERTIFICATE_GENERIC_ERROR: Some other error occurred validating
* the certificate
* @G_TLS_CERTIFICATE_VALIDATE_ALL: the combination of all of the above
* flags
*
* A set of flags describing TLS certification validation. This can be
* used to set which validation steps to perform (eg, with
* g_tls_client_connection_set_validation_flags()), or to describe why
* a particular certificate was rejected (eg, in
* #GTlsConnection::accept-certificate).
*
* Since: 2.28
*/
typedef enum {
G_TLS_CERTIFICATE_UNKNOWN_CA = (1 << 0),
G_TLS_CERTIFICATE_BAD_IDENTITY = (1 << 1),
G_TLS_CERTIFICATE_NOT_ACTIVATED = (1 << 2),
G_TLS_CERTIFICATE_EXPIRED = (1 << 3),
G_TLS_CERTIFICATE_REVOKED = (1 << 4),
G_TLS_CERTIFICATE_INSECURE = (1 << 5),
G_TLS_CERTIFICATE_GENERIC_ERROR = (1 << 6),
G_TLS_CERTIFICATE_VALIDATE_ALL = 0x007f
} GTlsCertificateFlags;
/**
* GTlsAuthenticationMode:
* @G_TLS_AUTHENTICATION_NONE: client authentication not required
* @G_TLS_AUTHENTICATION_REQUESTED: client authentication is requested
* @G_TLS_AUTHENTICATION_REQUIRED: client authentication is required
*
* The client authentication mode for a #GTlsServerConnection.
*
* Since: 2.28
*/
typedef enum {
G_TLS_AUTHENTICATION_NONE,
G_TLS_AUTHENTICATION_REQUESTED,
G_TLS_AUTHENTICATION_REQUIRED
} GTlsAuthenticationMode;
/**
* GTlsRehandshakeMode:
* @G_TLS_REHANDSHAKE_NEVER: Never allow rehandshaking
* @G_TLS_REHANDSHAKE_SAFELY: Allow safe rehandshaking only
* @G_TLS_REHANDSHAKE_UNSAFELY: Allow unsafe rehandshaking
*
* When to allow rehandshaking. See
* g_tls_connection_set_rehandshake_mode().
*
* Since: 2.28
*/
typedef enum {
G_TLS_REHANDSHAKE_NEVER,
G_TLS_REHANDSHAKE_SAFELY,
G_TLS_REHANDSHAKE_UNSAFELY
} GTlsRehandshakeMode;
G_END_DECLS
#endif /* __GIO_ENUMS_H__ */

View File

@ -35,6 +35,7 @@
#include "gsocks4proxy.h"
#include "gsocks4aproxy.h"
#include "gsocks5proxy.h"
#include "gtlsbackend.h"
#include "gvfs.h"
#ifdef G_OS_WIN32
#include "gregistrysettingsbackend.h"
@ -277,7 +278,7 @@ is_valid_module_name (const gchar *basename)
* g_io_extension_point_get_extension_by_name().
*
* If you need to guarantee that all types are loaded in all the modules,
* use g_io_modules_scan_all_in_directory().
* use g_io_modules_load_all_in_directory().
*
* Since: 2.24
**/
@ -480,6 +481,7 @@ extern GType g_win32_directory_monitor_get_type (void);
extern GType _g_winhttp_vfs_get_type (void);
extern GType _g_dummy_proxy_resolver_get_type (void);
extern GType _g_dummy_tls_backend_get_type (void);
#ifdef G_PLATFORM_WIN32
@ -556,6 +558,9 @@ _g_io_modules_ensure_extension_points_registered (void)
ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
}
G_UNLOCK (registered_extensions);
@ -618,6 +623,7 @@ _g_io_modules_ensure_loaded (void)
_g_socks4a_proxy_get_type ();
_g_socks4_proxy_get_type ();
_g_socks5_proxy_get_type ();
_g_dummy_tls_backend_get_type ();
}
G_UNLOCK (loaded_dirs);

View File

@ -109,6 +109,7 @@ typedef struct _GIOExtension GIOExtension;
* Opaque class for definining and scheduling IO jobs.
**/
typedef struct _GIOSchedulerJob GIOSchedulerJob;
typedef struct _GIOStreamAdapter GIOStreamAdapter;
typedef struct _GLoadableIcon GLoadableIcon; /* Dummy typedef */
typedef struct _GMemoryInputStream GMemoryInputStream;
typedef struct _GMemoryOutputStream GMemoryOutputStream;
@ -124,6 +125,8 @@ typedef struct _GNetworkAddress GNetworkAddress;
typedef struct _GNetworkService GNetworkService;
typedef struct _GOutputStream GOutputStream;
typedef struct _GIOStream GIOStream;
typedef struct _GPollableInputStream GPollableInputStream; /* Dummy typedef */
typedef struct _GPollableOutputStream GPollableOutputStream; /* Dummy typedef */
typedef struct _GResolver GResolver;
typedef struct _GSeekable GSeekable;
typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
@ -189,6 +192,7 @@ typedef struct _GSrvTarget GSrvTarget;
* Since: 2.22
**/
typedef struct _GTcpConnection GTcpConnection;
typedef struct _GTcpWrapperConnection GTcpWrapperConnection;
/**
* GThreadedSocketService:
*
@ -199,6 +203,13 @@ typedef struct _GTcpConnection GTcpConnection;
**/
typedef struct _GThreadedSocketService GThreadedSocketService;
typedef struct _GThemedIcon GThemedIcon;
typedef struct _GTlsCertificate GTlsCertificate;
typedef struct _GTlsClientConnection GTlsClientConnection; /* Dummy typedef */
typedef struct _GTlsClientContext GTlsClientContext; /* Dummy typedef */
typedef struct _GTlsConnection GTlsConnection;
typedef struct _GTlsContext GTlsContext;
typedef struct _GTlsServerConnection GTlsServerConnection; /* Dummy typedef */
typedef struct _GTlsServerContext GTlsServerContext; /* Dummy typedef */
typedef struct _GVfs GVfs; /* Dummy typedef */
/**
@ -376,6 +387,37 @@ typedef struct _GDBusPropertyInfo GDBusPropertyInfo;
typedef struct _GDBusInterfaceInfo GDBusInterfaceInfo;
typedef struct _GDBusNodeInfo GDBusNodeInfo;
/**
* GCancellableSourceFunc:
* @cancellable: the #GCancellable
* @user_data: data passed in by the user.
*
* This is the function type of the callback used for the #GSource
* returned by g_cancellable_source_new().
*
* Returns: it should return %FALSE if the source should be removed.
*
* Since: 2.28
*/
typedef gboolean (*GCancellableSourceFunc) (GCancellable *cancellable,
gpointer user_data);
/**
* GPollableSourceFunc:
* @pollable_stream: the #GPollableInputStream or #GPollableOutputStream
* @user_data: data passed in by the user.
*
* This is the function type of the callback used for the #GSource
* returned by g_pollable_input_stream_create_source() and
* g_pollable_output_stream_create_source().
*
* Returns: it should return %FALSE if the source should be removed.
*
* Since: 2.28
*/
typedef gboolean (*GPollableSourceFunc) (GObject *pollable_stream,
gpointer user_data);
G_END_DECLS
#endif /* __GIO_TYPES_H__ */

View File

@ -1228,7 +1228,9 @@ start_element (GMarkupParseContext *context,
OPTIONAL | STRING, "gettext-domain", &gettext_domain,
OPTIONAL | STRING, "extends", &extends,
OPTIONAL | STRING, "list-of", &list_of))
parse_state_start_schema (state, id, path, gettext_domain,
parse_state_start_schema (state, id, path,
gettext_domain ? gettext_domain
: state->schemalist_domain,
extends, list_of, error);
return;
}

View File

@ -34,7 +34,7 @@
* of times per second and is capable of being put into synch with an
* external time source.
*
* A number of #GPeriodicTickFunc<!-- -->s are registered with
* A number of #GPeriodicTickFuncs are registered with
* g_periodic_add() and are called each time the clock "ticks".
*
* The tick functions can report "damage" (ie: updates that need to be
@ -262,7 +262,7 @@ g_periodic_prepare (GSource *source,
/* We need to run. */
{
gint64 remaining;
remaining = periodic->priv->last_run + 1000000 * (1 + periodic->priv->skip_frames) -
g_periodic_get_microticks (periodic);
@ -354,8 +354,10 @@ g_periodic_dispatch (GSource *source,
}
static void
g_periodic_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
g_periodic_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GPeriodic *periodic = G_PERIODIC (object);
@ -379,8 +381,10 @@ g_periodic_get_property (GObject *object, guint prop_id,
}
static void
g_periodic_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
g_periodic_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GPeriodic *periodic = G_PERIODIC (object);
@ -445,11 +449,25 @@ g_periodic_class_init (GPeriodicClass *class)
object_class->set_property = g_periodic_set_property;
object_class->finalize = g_periodic_finalize;
/**
* GPeriodic::tick
* @periodic: the #GPeriodic on which the signal was emitted
* @timestamp: the timestamp at the time of the tick
*
* The ::tick signal gets emitted whenever the clock "fires".
*/
g_periodic_tick = g_signal_new ("tick", G_TYPE_PERIODIC,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GPeriodicClass, tick),
NULL, NULL, _gio_marshal_VOID__INT64,
G_TYPE_NONE, 1, G_TYPE_INT64);
/**
* GPeriodic::repair:
* @periodic: the #GPeriodic on which the signal was emitted
*
* The ::repair signal gets emitted to start the "repair" phase.
*/
g_periodic_repair = g_signal_new ("repair", G_TYPE_PERIODIC,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GPeriodicClass, repair),
@ -484,13 +502,14 @@ g_periodic_class_init (GPeriodicClass *class)
* Temporarily blocks @periodic from running in order to bring it in
* synch with an external time source.
*
* This function must be called from a handler of the "repair" signal.
* This function must be called from a handler of the #GPeriodic::repair
* signal.
*
* If this function is called, emission of the tick signal will be
* suspended until g_periodic_unblock() is called an equal number of
* times. Once that happens, the "tick" signal will run immediately and
* future "tick" signals will be emitted relative to the time at which
* the last call to g_periodic_unblock() occured.
* If this function is called, emission of the #GPeriodic::tick signal
* will be suspended until g_periodic_unblock() is called an equal number
* of times. Once that happens, the ::tick signal will run immediately
* and future ::tick signals will be emitted relative to the time at
* which the last call to g_periodic_unblock() occured.
*
* Since: 2.28
**/
@ -510,9 +529,9 @@ g_periodic_block (GPeriodic *periodic)
*
* Reverses the effect of a previous call to g_periodic_block().
*
* If this call removes the last block, the tick signal is immediately
* run. The repair signal may also be run if the clock is marked as
* damaged.
* If this call removes the last block, the ::tick signal is
* immediately run. The ::repair signal may also be run if the clock
* is marked as damaged.
*
* @unblock_time is the monotonic time, as per g_get_monotonic_time(),
* at which the event causing the unblock occured.
@ -545,20 +564,21 @@ g_periodic_unblock (GPeriodic *periodic,
* @user_data: data for @callback
* @notify: for freeing @user_data when it is no longer needed
*
* Request periodic calls to @callback to start. The periodicity of the
* calls is determined by the 'hz' property.
* Request periodic calls to @callback to start. The periodicity of
* the calls is determined by the #GPeriodic:hz property.
*
* This function may not be called from a handler of the repair signal,
* but it is perfectly reasonable to call it from a handler of the tick
* signal.
* This function may not be called from a handler of the ::repair
* signal, but it is perfectly reasonable to call it from a handler
* of the ::tick signal.
*
* The callback may be cancelled later by using g_periodic_remove() on
* the return value of this function.
* The callback may be cancelled later by using g_periodic_remove()
* on the return value of this function.
*
* Returns: a non-zero tag identifying this callback
*
* Since: 2.28
**/
/**
* GPeriodicTickFunc:
* @periodic: the #GPeriodic clock that is ticking
@ -568,8 +588,8 @@ g_periodic_unblock (GPeriodic *periodic,
* The signature of the callback function that is called when the
* #GPeriodic clock ticks.
*
* The @timestamp parameter is equal for all callbacks called during a
* particular tick on a given clock.
* The @timestamp parameter is equal for all callbacks called during
* a particular tick on a given clock.
*
* Since: 2.28
**/
@ -605,9 +625,9 @@ g_periodic_add (GPeriodic *periodic,
*
* @tag is the ID returned by that function.
*
* This function may not be called from a handler of the repair signal,
* but it is perfectly reasonable to call it from a handler of the tick
* signal.
* This function may not be called from a handler of the ::repair
* signal, but it is perfectly reasonable to call it from a handler
* of the ::tick signal.
*
* Since: 2.28
**/
@ -626,7 +646,7 @@ g_periodic_remove (GPeriodic *periodic,
if (tick->id == tag)
{
/* do this first incase the destroy notify re-enters */
/* do this first, in case the destroy notify re-enters */
*iter = g_slist_remove (*iter, tick);
if (tick->notify)
@ -644,8 +664,8 @@ g_periodic_remove (GPeriodic *periodic,
* g_periodic_damaged:
* @periodic: a #GPeriodic clock
*
* Report damage and schedule the "repair" signal to be emitted during
* the next repair phase.
* Report damage and schedule the ::repair signal to be emitted
* during the next repair phase.
*
* You may not call this function during the repair phase.
*
@ -666,7 +686,7 @@ g_periodic_damaged (GPeriodic *periodic)
*
* Gets the frequency of the clock.
*
* Returns: the frquency of the clock, in Hz
* Returns: the frequency of the clock, in Hz
*
* Since: 2.28
**/
@ -713,13 +733,14 @@ g_periodic_get_low_priority (GPeriodic *periodic)
/**
* g_periodic_new:
* @hz: the frequency of the new clock in Hz (between 1 and 120)
* @priority: the #GSource priority to run at
* @high_priority: the #GSource priority to run at
* @low_priority: ignore tasks below this priority
*
* Creates a new #GPeriodic clock.
*
* The created clock is attached to the thread-default main context in
* effect at the time of the call to this function. See
* g_main_context_push_thread_default() for more information.
* The created clock is attached to the thread-default main context
* in effect at the time of the call to this function.
* See g_main_context_push_thread_default() for more information.
*
* Due to the fact that #GMainContext is only accurate to the nearest
* millisecond, the frequency can not meaningfully get too close to

View File

@ -28,7 +28,7 @@
/**
* SECTION:gpermission
* @title: GPermission
* @short_description: an object representing the permission to perform
* @short_description: An object representing the permission to perform
* a certain action
*
* A #GPermission represents the status of the caller's permission to

303
gio/gpollableinputstream.c Normal file
View File

@ -0,0 +1,303 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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 <errno.h>
#include "gpollableinputstream.h"
#include "gasynchelper.h"
#include "gio-marshal.h"
#include "glibintl.h"
/**
* SECTION:gpollableinputstream
* @short_description: Interface for pollable input streams
* @include: gio/gio.h
* @see_also: #GInputStream, #GPollableOutputStream, #GFileDescriptorBased
*
* #GPollableInputStream is implemented by #GInputStream<!-- -->s that
* can be polled for readiness to read. This can be used when
* interfacing with a non-GIO API that expects
* UNIX-file-descriptor-style asynchronous I/O rather than GIO-style.
*
* Since: 2.28
*/
G_DEFINE_INTERFACE (GPollableInputStream, g_pollable_input_stream, G_TYPE_INPUT_STREAM)
static gboolean g_pollable_input_stream_default_can_poll (GPollableInputStream *stream);
static gssize g_pollable_input_stream_default_read_nonblocking (GPollableInputStream *stream,
void *buffer,
gsize size,
GError **error);
static void
g_pollable_input_stream_default_init (GPollableInputStreamInterface *iface)
{
iface->can_poll = g_pollable_input_stream_default_can_poll;
iface->read_nonblocking = g_pollable_input_stream_default_read_nonblocking;
}
static gboolean
g_pollable_input_stream_default_can_poll (GPollableInputStream *stream)
{
return TRUE;
}
/**
* g_pollable_input_stream_can_poll:
* @stream: a #GPollableInputStream.
*
* Checks if @stream is actually pollable. Some classes may implement
* #GPollableInputStream but have only certain instances of that class
* be pollable. If this method returns %FALSE, then the behavior of
* other #GPollableInputStream methods is undefined.
*
* For any given stream, the value returned by this method is constant;
* a stream cannot switch from pollable to non-pollable or vice versa.
*
* Returns: %TRUE if @stream is pollable, %FALSE if not.
*
* Since: 2.28
*/
gboolean
g_pollable_input_stream_can_poll (GPollableInputStream *stream)
{
g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), FALSE);
return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->can_poll (stream);
}
/**
* g_pollable_input_stream_is_readable:
* @stream: a #GPollableInputStream.
*
* Checks if @stream can be read.
*
* Note that some stream types may not be able to implement this 100%
* reliably, and it is possible that a call to g_input_stream_read()
* after this returns %TRUE would still block. To guarantee
* non-blocking behavior, you should always use
* g_pollable_input_stream_read_nonblocking(), which will return a
* %G_IO_ERROR_WOULD_BLOCK error rather than blocking.
*
* Returns: %TRUE if @stream is readable, %FALSE if not. If an error
* has occurred on @stream, this will result in
* g_pollable_input_stream_is_readable() returning %TRUE, and the
* next attempt to read will return the error.
*
* Since: 2.28
*/
gboolean
g_pollable_input_stream_is_readable (GPollableInputStream *stream)
{
g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), FALSE);
return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->is_readable (stream);
}
/**
* g_pollable_input_stream_create_source:
* @stream: a #GPollableInputStream.
* @cancellable: a #GCancellable, or %NULL
*
* Creates a #GSource that triggers when @stream can be read, or
* @cancellable is triggered or an error occurs. The callback on the
* source is of the #GPollableSourceFunc type.
*
* As with g_pollable_input_stream_is_readable(), it is possible that
* the stream may not actually be readable even after the source
* triggers, so you should use g_pollable_input_stream_read_nonblocking()
* rather than g_input_stream_read() from the callback.
*
* Returns: a new #GSource
*
* Since: 2.28
*/
GSource *
g_pollable_input_stream_create_source (GPollableInputStream *stream,
GCancellable *cancellable)
{
g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), NULL);
return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
create_source (stream, cancellable);
}
static gssize
g_pollable_input_stream_default_read_nonblocking (GPollableInputStream *stream,
void *buffer,
gsize size,
GError **error)
{
if (!g_pollable_input_stream_is_readable (stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
g_strerror (EAGAIN));
return -1;
}
return g_input_stream_read (G_INPUT_STREAM (stream), buffer, size,
NULL, error);
}
/**
* g_pollable_input_stream_read_nonblocking:
* @stream: a #GPollableInputStream
* @buffer: a buffer to read data into (which should be at least @size
* bytes long).
* @size: the number of bytes you want to read
* @cancellable: a #GCancellable, or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Attempts to read up to @size bytes from @stream into @buffer, as
* with g_input_stream_read(). If @stream is not currently readable,
* this will immediately return %G_IO_ERROR_WOULD_BLOCK, and you can
* use g_pollable_input_stream_create_source() to create a #GSource
* that will be triggered when @stream is readable.
*
* Note that since this method never blocks, you cannot actually
* use @cancellable to cancel it. However, it will return an error
* if @cancellable has already been cancelled when you call, which
* may happen if you call this method after a source triggers due
* to having been cancelled.
*
* Return value: the number of bytes read, or -1 on error (including
* %G_IO_ERROR_WOULD_BLOCK).
*/
gssize
g_pollable_input_stream_read_nonblocking (GPollableInputStream *stream,
void *buffer,
gsize size,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), -1);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
read_nonblocking (stream, buffer, size, error);
}
/* GPollableSource */
typedef struct {
GSource source;
GObject *stream;
} GPollableSource;
static gboolean
pollable_source_prepare (GSource *source,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
static gboolean
pollable_source_check (GSource *source)
{
return FALSE;
}
static gboolean
pollable_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GPollableSourceFunc func = (GPollableSourceFunc)callback;
GPollableSource *pollable_source = (GPollableSource *)source;
return (*func) (pollable_source->stream, user_data);
}
static void
pollable_source_finalize (GSource *source)
{
GPollableSource *pollable_source = (GPollableSource *)source;
g_object_unref (pollable_source->stream);
}
static gboolean
pollable_source_closure_callback (GObject *stream,
gpointer data)
{
GClosure *closure = data;
GValue param = { 0, };
GValue result_value = { 0, };
gboolean result;
g_value_init (&result_value, G_TYPE_BOOLEAN);
g_value_init (&param, G_TYPE_OBJECT);
g_value_set_object (&param, stream);
g_closure_invoke (closure, &result_value, 1, &param, NULL);
result = g_value_get_boolean (&result_value);
g_value_unset (&result_value);
g_value_unset (&param);
return result;
}
static GSourceFuncs pollable_source_funcs =
{
pollable_source_prepare,
pollable_source_check,
pollable_source_dispatch,
pollable_source_finalize,
(GSourceFunc)pollable_source_closure_callback,
(GSourceDummyMarshal)_gio_marshal_BOOLEAN__VOID,
};
/**
* g_pollable_source_new:
* @pollable_stream: the stream associated with the new source
*
* Utility method for #GPollableInputStream and #GPollableOutputStream
* implementations. Creates a new #GSource that expects a callback of
* type #GPollableSourceFunc. The new source does not actually do
* anything on its own; use g_source_add_child_source() to add other
* sources to it to cause it to trigger.
*
* Return value: the new #GSource.
*
* Since: 2.28
*/
GSource *
g_pollable_source_new (GObject *pollable_stream)
{
GSource *source;
GPollableSource *pollable_source;
source = g_source_new (&pollable_source_funcs, sizeof (GPollableSource));
g_source_set_name (source, "GPollableSource");
pollable_source = (GPollableSource *)source;
pollable_source->stream = g_object_ref (pollable_stream);
return source;
}

101
gio/gpollableinputstream.h Normal file
View File

@ -0,0 +1,101 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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_POLLABLE_INPUT_STREAM_H__
#define __G_POLLABLE_INPUT_STREAM_H__
#include <gio/gio.h>
G_BEGIN_DECLS
#define G_TYPE_POLLABLE_INPUT_STREAM (g_pollable_input_stream_get_type ())
#define G_POLLABLE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_POLLABLE_INPUT_STREAM, GPollableInputStream))
#define G_IS_POLLABLE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_POLLABLE_INPUT_STREAM))
#define G_POLLABLE_INPUT_STREAM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_POLLABLE_INPUT_STREAM, GPollableInputStreamInterface))
/**
* GPollableInputStream:
*
* An interface for a #GInputStream that can be polled for readability.
*
* Since: 2.28
*/
typedef struct _GPollableInputStreamInterface GPollableInputStreamInterface;
/**
* GPollableInputStreamInterface:
* @g_iface: The parent interface.
* @can_poll: Checks if the #GPollableInputStream instance is actually pollable
* @is_readable: Checks if the stream is readable
* @create_source: Creates a #GSource to poll the stream
* @read_nonblocking: Does a non-blocking read or returns
* %G_IO_ERROR_WOULD_BLOCK
*
* The interface for pollable input streams.
*
* The default implementation of @can_poll always returns %TRUE.
*
* The default implementation of @read_nonblocking calls
* g_pollable_input_stream_is_readable(), and then calls
* g_input_stream_read() if it returns %TRUE. This means you only need
* to override it if it is possible that your @is_readable
* implementation may return %TRUE when the stream is not actually
* readable.
*
* Since: 2.28
*/
struct _GPollableInputStreamInterface
{
GTypeInterface g_iface;
/* Virtual Table */
gboolean (*can_poll) (GPollableInputStream *stream);
gboolean (*is_readable) (GPollableInputStream *stream);
GSource * (*create_source) (GPollableInputStream *stream,
GCancellable *cancellable);
gssize (*read_nonblocking) (GPollableInputStream *stream,
void *buffer,
gsize size,
GError **error);
};
GType g_pollable_input_stream_get_type (void) G_GNUC_CONST;
gboolean g_pollable_input_stream_can_poll (GPollableInputStream *stream);
gboolean g_pollable_input_stream_is_readable (GPollableInputStream *stream);
GSource *g_pollable_input_stream_create_source (GPollableInputStream *stream,
GCancellable *cancellable);
gssize g_pollable_input_stream_read_nonblocking (GPollableInputStream *stream,
void *buffer,
gsize size,
GCancellable *cancellable,
GError **error);
/* Helper method for stream implementations */
GSource *g_pollable_source_new (GObject *pollable_stream);
G_END_DECLS
#endif /* __G_POLLABLE_INPUT_STREAM_H__ */

200
gio/gpollableoutputstream.c Normal file
View File

@ -0,0 +1,200 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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 <errno.h>
#include "gpollableoutputstream.h"
#include "gasynchelper.h"
#include "gfiledescriptorbased.h"
#include "gio-marshal.h"
#include "glibintl.h"
/**
* SECTION:gpollableoutputstream
* @short_description: Interface for pollable output streams
* @include: gio/gio.h
* @see_also: #GOutputStream, #GFileDescriptorBased, #GPollableInputStream
*
* #GPollableOutputStream is implemented by #GOutputStream<!-- -->s that
* can be polled for readiness to write. This can be used when
* interfacing with a non-GIO API that expects
* UNIX-file-descriptor-style asynchronous I/O rather than GIO-style.
*
* Since: 2.28
*/
G_DEFINE_INTERFACE (GPollableOutputStream, g_pollable_output_stream, G_TYPE_OUTPUT_STREAM)
static gboolean g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream);
static gssize g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
const void *buffer,
gsize size,
GError **error);
static void
g_pollable_output_stream_default_init (GPollableOutputStreamInterface *iface)
{
iface->can_poll = g_pollable_output_stream_default_can_poll;
iface->write_nonblocking = g_pollable_output_stream_default_write_nonblocking;
}
static gboolean
g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream)
{
return TRUE;
}
/**
* g_pollable_output_stream_can_poll:
* @stream: a #GPollableOutputStream.
*
* Checks if @stream is actually pollable. Some classes may implement
* #GPollableOutputStream but have only certain instances of that
* class be pollable. If this method returns %FALSE, then the behavior
* of other #GPollableOutputStream methods is undefined.
*
* For any given stream, the value returned by this method is constant;
* a stream cannot switch from pollable to non-pollable or vice versa.
*
* Returns: %TRUE if @stream is pollable, %FALSE if not.
*
* Since: 2.28
*/
gboolean
g_pollable_output_stream_can_poll (GPollableOutputStream *stream)
{
g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), FALSE);
return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->can_poll (stream);
}
/**
* g_pollable_output_stream_is_writable:
* @stream: a #GPollableOutputStream.
*
* Checks if @stream can be written.
*
* Note that some stream types may not be able to implement this 100%
* reliably, and it is possible that a call to g_output_stream_write()
* after this returns %TRUE would still block. To guarantee
* non-blocking behavior, you should always use
* g_pollable_output_stream_write_nonblocking(), which will return a
* %G_IO_ERROR_WOULD_BLOCK error rather than blocking.
*
* Returns: %TRUE if @stream is writable, %FALSE if not. If an error
* has occurred on @stream, this will result in
* g_pollable_output_stream_is_writable() returning %TRUE, and the
* next attempt to write will return the error.
*
* Since: 2.28
*/
gboolean
g_pollable_output_stream_is_writable (GPollableOutputStream *stream)
{
g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), FALSE);
return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->is_writable (stream);
}
/**
* g_pollable_output_stream_create_source:
* @stream: a #GPollableOutputStream.
* @cancellable: a #GCancellable, or %NULL
*
* Creates a #GSource that triggers when @stream can be written, or
* @cancellable is triggered or an error occurs. The callback on the
* source is of the #GPollableSourceFunc type.
*
* As with g_pollable_output_stream_is_writable(), it is possible that
* the stream may not actually be writable even after the source
* triggers, so you should use g_pollable_output_stream_write_nonblocking()
* rather than g_output_stream_write() from the callback.
*
* Returns: a new #GSource
*
* Since: 2.28
*/
GSource *
g_pollable_output_stream_create_source (GPollableOutputStream *stream,
GCancellable *cancellable)
{
g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), NULL);
return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
create_source (stream, cancellable);
}
static gssize
g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
const void *buffer,
gsize size,
GError **error)
{
if (!g_pollable_output_stream_is_writable (stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
g_strerror (EAGAIN));
return -1;
}
return g_output_stream_write (G_OUTPUT_STREAM (stream), buffer, size,
NULL, error);
}
/**
* g_pollable_output_stream_write_nonblocking:
* @stream: a #GPollableOutputStream
* @buffer: a buffer to write data from
* @size: the number of bytes you want to write
* @cancellable: a #GCancellable, or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Attempts to write up to @size bytes from @buffer to @stream, as
* with g_output_stream_write(). If @stream is not currently writable,
* this will immediately return %G_IO_ERROR_WOULD_BLOCK, and you can
* use g_pollable_output_stream_create_source() to create a #GSource
* that will be triggered when @stream is writable.
*
* Note that since this method never blocks, you cannot actually
* use @cancellable to cancel it. However, it will return an error
* if @cancellable has already been cancelled when you call, which
* may happen if you call this method after a source triggers due
* to having been cancelled.
*
* Return value: the number of bytes written, or -1 on error (including
* %G_IO_ERROR_WOULD_BLOCK).
*/
gssize
g_pollable_output_stream_write_nonblocking (GPollableOutputStream *stream,
const void *buffer,
gsize size,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), -1);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
write_nonblocking (stream, buffer, size, error);
}

View File

@ -0,0 +1,98 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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_POLLABLE_OUTPUT_STREAM_H__
#define __G_POLLABLE_OUTPUT_STREAM_H__
#include <gio/gio.h>
G_BEGIN_DECLS
#define G_TYPE_POLLABLE_OUTPUT_STREAM (g_pollable_output_stream_get_type ())
#define G_POLLABLE_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_POLLABLE_OUTPUT_STREAM, GPollableOutputStream))
#define G_IS_POLLABLE_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_POLLABLE_OUTPUT_STREAM))
#define G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_POLLABLE_OUTPUT_STREAM, GPollableOutputStreamInterface))
/**
* GPollableOutputStream:
*
* An interface for a #GOutputStream that can be polled for readability.
*
* Since: 2.28
*/
typedef struct _GPollableOutputStreamInterface GPollableOutputStreamInterface;
/**
* GPollableOutputStreamInterface:
* @g_iface: The parent interface.
* @can_poll: Checks if the #GPollableOutputStream instance is actually pollable
* @is_writable: Checks if the stream is writable
* @create_source: Creates a #GSource to poll the stream
* @write_nonblocking: Does a non-blocking write or returns
* %G_IO_ERROR_WOULD_BLOCK
*
* The interface for pollable output streams.
*
* The default implementation of @can_poll always returns %TRUE.
*
* The default implementation of @write_nonblocking calls
* g_pollable_output_stream_is_writable(), and then calls
* g_output_stream_write() if it returns %TRUE. This means you only
* need to override it if it is possible that your @is_writable
* implementation may return %TRUE when the stream is not actually
* writable.
*
* Since: 2.28
*/
struct _GPollableOutputStreamInterface
{
GTypeInterface g_iface;
/* Virtual Table */
gboolean (*can_poll) (GPollableOutputStream *stream);
gboolean (*is_writable) (GPollableOutputStream *stream);
GSource * (*create_source) (GPollableOutputStream *stream,
GCancellable *cancellable);
gssize (*write_nonblocking) (GPollableOutputStream *stream,
const void *buffer,
gsize size,
GError **error);
};
GType g_pollable_output_stream_get_type (void) G_GNUC_CONST;
gboolean g_pollable_output_stream_can_poll (GPollableOutputStream *stream);
gboolean g_pollable_output_stream_is_writable (GPollableOutputStream *stream);
GSource *g_pollable_output_stream_create_source (GPollableOutputStream *stream,
GCancellable *cancellable);
gssize g_pollable_output_stream_write_nonblocking (GPollableOutputStream *stream,
const void *buffer,
gsize size,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_POLLABLE_OUTPUT_STREAM_H__ */

View File

@ -1,155 +0,0 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 Collabora Ltd.
*
* 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.
*
* Authors: Nicolas Dufresne <nicolas.dufresne@colllabora.co.uk>
*/
#include "config.h"
#include "gproxyconnection.h"
#include "gtcpconnection.h"
#include "glibintl.h"
#define g_proxy_connection_get_type _g_proxy_connection_get_type
G_DEFINE_TYPE (GProxyConnection,
g_proxy_connection, G_TYPE_TCP_CONNECTION);
enum
{
PROP_NONE,
PROP_IO_STREAM
};
struct _GProxyConnectionPrivate
{
GIOStream *io_stream;
};
static GInputStream *
g_proxy_connection_get_input_stream (GIOStream *io_stream)
{
GProxyConnection *connection;
connection = G_PROXY_PROXY_CONNECTION (io_stream);
return g_io_stream_get_input_stream (connection->priv->io_stream);
}
static GOutputStream *
g_proxy_connection_get_output_stream (GIOStream *io_stream)
{
GProxyConnection *connection;
connection = G_PROXY_PROXY_CONNECTION (io_stream);
return g_io_stream_get_output_stream (connection->priv->io_stream);
}
static void
g_proxy_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GProxyConnection *connection = G_PROXY_PROXY_CONNECTION (object);
switch (prop_id)
{
case PROP_IO_STREAM:
g_value_set_object (value, connection->priv->io_stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_proxy_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GProxyConnection *connection = G_PROXY_PROXY_CONNECTION (object);
switch (prop_id)
{
case PROP_IO_STREAM:
connection->priv->io_stream = G_IO_STREAM (g_value_dup_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_proxy_connection_finalize (GObject *object)
{
GProxyConnection *connection = G_PROXY_PROXY_CONNECTION (object);
g_object_unref (connection->priv->io_stream);
G_OBJECT_CLASS (g_proxy_connection_parent_class)->finalize (object);
}
static void
g_proxy_connection_class_init (GProxyConnectionClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (GProxyConnectionPrivate));
gobject_class->set_property = g_proxy_connection_set_property;
gobject_class->get_property = g_proxy_connection_get_property;
gobject_class->finalize = g_proxy_connection_finalize;
stream_class->get_input_stream = g_proxy_connection_get_input_stream;
stream_class->get_output_stream = g_proxy_connection_get_output_stream;
g_object_class_install_property (gobject_class,
PROP_IO_STREAM,
g_param_spec_object ("io-stream",
P_("IO Stream"),
P_("The altered streams"),
G_TYPE_SOCKET_CONNECTION,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
static void
g_proxy_connection_init (GProxyConnection *connection)
{
connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
G_TYPE_PROXY_CONNECTION,
GProxyConnectionPrivate);
}
GSocketConnection *
_g_proxy_connection_new (GTcpConnection *connection,
GIOStream *io_stream)
{
GSocket *socket;
socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection));
return G_SOCKET_CONNECTION (g_object_new (G_TYPE_PROXY_CONNECTION,
"io-stream", io_stream,
"socket", socket,
NULL));
}

View File

@ -1,69 +0,0 @@
/* GIO - GLib Input, Output and Streaming Library
* Copyright © 2010 Collabora Ltd.
*
* This program 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 licence 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.
*
* Authors: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
*
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_PROXY_PROXY_CONNECTION_H__
#define __G_PROXY_PROXY_CONNECTION_H__
#include <glib-object.h>
#include <gio/gtcpconnection.h>
G_BEGIN_DECLS
#define G_TYPE_PROXY_CONNECTION (_g_proxy_connection_get_type ())
#define G_PROXY_PROXY_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
G_TYPE_PROXY_CONNECTION, GProxyConnection))
#define G_PROXY_PROXY_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \
G_TYPE_PROXY_CONNECTION, GProxyConnectionClass))
#define G_IS_PROXY_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
G_TYPE_PROXY_CONNECTION))
#define G_IS_PROXY_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
G_TYPE_PROXY_CONNECTION))
#define G_PROXY_PROXY_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
G_TYPE_PROXY_CONNECTION, GProxyConnectionClass))
typedef struct _GProxyConnection GProxyConnection;
typedef struct _GProxyConnectionPrivate GProxyConnectionPrivate;
typedef struct _GProxyConnectionClass GProxyConnectionClass;
struct _GProxyConnectionClass
{
GTcpConnectionClass parent_class;
};
struct _GProxyConnection
{
GTcpConnection parent_instance;
GProxyConnectionPrivate *priv;
};
GType _g_proxy_connection_get_type (void) G_GNUC_CONST;
GSocketConnection *_g_proxy_connection_new (GTcpConnection *connection,
GIOStream *io_stream);
G_END_DECLS
#endif /* __G_PROXY_PROXY_CONNECTION_H__ */

View File

@ -42,7 +42,7 @@
/**
* SECTION:gsettings
* @short_description: a high-level API for application settings
* @short_description: High-level API for application settings
*
* The #GSettings class provides a convenient API for storing and retrieving
* application settings.
@ -436,6 +436,10 @@ g_settings_get_property (GObject *object,
g_value_set_string (value, settings->priv->schema_name);
break;
case PROP_BACKEND:
g_value_set_object (value, settings->priv->backend);
break;
case PROP_PATH:
g_value_set_string (value, settings->priv->path);
break;
@ -2202,7 +2206,7 @@ g_settings_list_keys (GSettings *settings)
* time and you should connect to the "children-changed" signal to watch
* for those changes. Note that there is a race condition here: you may
* request a child after listing it only for it to have been destroyed
* in the meantime. For this reason, g_settings_get_chuld() may return
* in the meantime. For this reason, g_settings_get_child() may return
* %NULL even for a child that was listed by this function.
*
* For GSettings objects that are not lists, you should probably not be

View File

@ -49,7 +49,7 @@ struct _GSettingsBackendPrivate
/**
* SECTION:gsettingsbackend
* @title: GSettingsBackend
* @short_description: an interface for settings backend implementations
* @short_description: Interface for settings backend implementations
* @include: gio/gsettingsbackend.h
* @see_also: #GSettings, #GIOExtensionPoint
*

View File

@ -138,6 +138,8 @@ ensure_schema_lists (void)
g_hash_table_insert (single, g_strdup (list[i]), NULL);
else
g_hash_table_insert (reloc, g_strdup (list[i]), NULL);
gvdb_table_unref (table);
}
}

View File

@ -33,7 +33,7 @@ G_DEFINE_TYPE_WITH_CODE (GSimpleAction, g_simple_action, G_TYPE_OBJECT,
/**
* SECTION:gsimpleaction
* @title: GSimpleAction
* @short_description: a simple GSimpleAction
* @short_description: A simple GSimpleAction
*
* A #GSimpleAction is the obvious simple implementation of the #GSimpleAction
* interface. This is the easiest way to create an action for purposes of

View File

@ -25,7 +25,7 @@
/**
* SECTION:gsimpleactiongroup
* @title: GSimpleActionGroup
* @short_description: a simple GActionGroup implementation
* @short_description: A simple GActionGroup implementation
*
* #GSimpleActionGroup is a hash table filled with #GAction objects,
* implementing the #GActionGroup interface.

View File

@ -28,7 +28,7 @@
/**
* SECTION:gsimplepermission
* @title: GSimplePermission
* @short_description: a GPermission that doesn't change value
* @short_description: A GPermission that doesn't change value
*
* #GSimplePermission is a trivial implementation of #GPermission that
* represents a permission that is either always or never allowed. The

View File

@ -50,6 +50,7 @@
#include "gioerror.h"
#include "gioenums.h"
#include "gioerror.h"
#include "gio-marshal.h"
#include "gnetworkingprivate.h"
#include "gsocketaddress.h"
#include "gsocketcontrolmessage.h"
@ -2493,12 +2494,42 @@ socket_source_finalize (GSource *source)
}
}
static gboolean
socket_source_closure_callback (GSocket *socket,
GIOCondition condition,
gpointer data)
{
GClosure *closure = data;
GValue params[2] = { { 0, }, { 0, } };
GValue result_value = { 0, };
gboolean result;
g_value_init (&result_value, G_TYPE_BOOLEAN);
g_value_init (&params[0], G_TYPE_SOCKET);
g_value_set_object (&params[0], socket);
g_value_init (&params[1], G_TYPE_IO_CONDITION);
g_value_set_flags (&params[1], condition);
g_closure_invoke (closure, &result_value, 2, params, NULL);
result = g_value_get_boolean (&result_value);
g_value_unset (&result_value);
g_value_unset (&params[0]);
g_value_unset (&params[1]);
return result;
}
static GSourceFuncs socket_source_funcs =
{
socket_source_prepare,
socket_source_check,
socket_source_dispatch,
socket_source_finalize
socket_source_finalize,
(GSourceFunc)socket_source_closure_callback,
(GSourceDummyMarshal)_gio_marshal_BOOLEAN__FLAGS,
};
static GSource *

View File

@ -34,7 +34,6 @@
#include <gio/gsocketconnection.h>
#include <gio/gproxyaddressenumerator.h>
#include <gio/gproxyaddress.h>
#include <gio/gproxyconnection.h>
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
#include <gio/gioerror.h>
@ -44,6 +43,9 @@
#include <gio/gproxy.h>
#include <gio/gsocketaddress.h>
#include <gio/gtcpconnection.h>
#include <gio/gtcpwrapperconnection.h>
#include <gio/gtlscertificate.h>
#include <gio/gtlsclientconnection.h>
#include "glibintl.h"
@ -79,6 +81,8 @@ enum
PROP_LOCAL_ADDRESS,
PROP_TIMEOUT,
PROP_ENABLE_PROXY,
PROP_TLS,
PROP_TLS_VALIDATION_FLAGS
};
struct _GSocketClientPrivate
@ -90,6 +94,8 @@ struct _GSocketClientPrivate
guint timeout;
gboolean enable_proxy;
GHashTable *app_proxies;
gboolean tls;
GTlsCertificateFlags tls_validation_flags;
};
static GSocket *
@ -218,6 +224,14 @@ g_socket_client_get_property (GObject *object,
g_value_set_boolean (value, client->priv->enable_proxy);
break;
case PROP_TLS:
g_value_set_boolean (value, g_socket_client_get_tls (client));
break;
case PROP_TLS_VALIDATION_FLAGS:
g_value_set_flags (value, g_socket_client_get_tls_validation_flags (client));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -257,6 +271,14 @@ g_socket_client_set_property (GObject *object,
g_socket_client_set_enable_proxy (client, g_value_get_boolean (value));
break;
case PROP_TLS:
g_socket_client_set_tls (client, g_value_get_boolean (value));
break;
case PROP_TLS_VALIDATION_FLAGS:
g_socket_client_set_tls_validation_flags (client, g_value_get_flags (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -525,6 +547,91 @@ g_socket_client_set_enable_proxy (GSocketClient *client,
g_object_notify (G_OBJECT (client), "enable-proxy");
}
/**
* g_socket_client_get_tls:
* @client: a #GSocketClient.
*
* Gets whether @client creates TLS connections. See
* g_socket_client_set_tls() for details.
*
* Returns: whether @client uses TLS
*
* Since: 2.28
*/
gboolean
g_socket_client_get_tls (GSocketClient *client)
{
return client->priv->tls;
}
/**
* g_socket_client_set_tls:
* @client: a #GSocketClient.
* @tls: whether to use TLS
*
* Sets whether @client creates TLS (aka SSL) connections. If @tls is
* %TRUE, @client will wrap its connections in a #GTlsClientConnection
* and perform a TLS handshake when connecting.
*
* Note that since #GSocketClient must return a #GSocketConnection,
* but #GTlsClientConnection is not a #GSocketConnection, this
* actually wraps the resulting #GTlsClientConnection in a
* #GTcpWrapperConnection when returning it. You can use
* g_tcp_wrapper_connection_get_base_io_stream() on the return value
* to extract the #GTlsClientConnection.
*
* Since: 2.28
*/
void
g_socket_client_set_tls (GSocketClient *client,
gboolean tls)
{
tls = !!tls;
if (tls == client->priv->tls)
return;
client->priv->tls = tls;
g_object_notify (G_OBJECT (client), "tls");
}
/**
* g_socket_client_get_tls_validation_flags:
* @client: a #GSocketClient.
*
* Gets the TLS validation flags used creating TLS connections via
* @client.
*
* Returns: the TLS validation flags
*
* Since: 2.28
*/
GTlsCertificateFlags
g_socket_client_get_tls_validation_flags (GSocketClient *client)
{
return client->priv->tls_validation_flags;
}
/**
* g_socket_client_set_tls_validation_flags:
* @client: a #GSocketClient.
* @flags: the validation flags
*
* Sets the TLS validation flags used when creating TLS connections
* via @client. The default value is %G_TLS_CERTIFICATE_VALIDATE_ALL.
*
* Since: 2.28
*/
void
g_socket_client_set_tls_validation_flags (GSocketClient *client,
GTlsCertificateFlags flags)
{
if (client->priv->tls_validation_flags != flags)
{
client->priv->tls_validation_flags = flags;
g_object_notify (G_OBJECT (client), "tls-validation-flags");
}
}
static void
g_socket_client_class_init (GSocketClientClass *class)
{
@ -593,6 +700,23 @@ g_socket_client_class_init (GSocketClientClass *class)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TLS,
g_param_spec_boolean ("tls",
P_("TLS"),
P_("Whether to create TLS connections"),
FALSE,
G_PARAM_CONSTRUCT |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TLS_VALIDATION_FLAGS,
g_param_spec_flags ("tls-validation-flags",
P_("TLS validation flags"),
P_("TLS validation flags to use"),
G_TYPE_TLS_CERTIFICATE_FLAGS,
G_TLS_CERTIFICATE_VALIDATE_ALL,
G_PARAM_CONSTRUCT |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
/**
@ -631,7 +755,7 @@ g_socket_client_connect (GSocketClient *client,
GCancellable *cancellable,
GError **error)
{
GSocketConnection *connection = NULL;
GIOStream *connection = NULL;
GSocketAddressEnumerator *enumerator = NULL;
GError *last_error, *tmp_error;
@ -679,14 +803,15 @@ g_socket_client_connect (GSocketClient *client,
g_clear_error (&last_error);
socket = create_socket (client, address, &last_error);
if (socket != NULL)
if (socket == NULL)
{
if (g_socket_connect (socket, address, cancellable, &last_error))
connection = g_socket_connection_factory_create_connection (socket);
g_object_unref (socket);
g_object_unref (address);
continue;
}
if (g_socket_connect (socket, address, cancellable, &last_error))
connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
if (connection &&
G_IS_PROXY_ADDRESS (address) &&
client->priv->enable_proxy)
@ -715,31 +840,15 @@ g_socket_client_connect (GSocketClient *client,
}
else if (proxy)
{
GIOStream *io_stream;
GTcpConnection *old_connection = G_TCP_CONNECTION (connection);
GIOStream *proxy_connection;
io_stream = g_proxy_connect (proxy,
G_IO_STREAM (old_connection),
proxy_addr,
cancellable,
&last_error);
if (io_stream)
{
if (G_IS_SOCKET_CONNECTION (io_stream))
connection = G_SOCKET_CONNECTION (g_object_ref (io_stream));
else
connection = _g_proxy_connection_new (old_connection,
io_stream);
g_object_unref (io_stream);
}
else
{
connection = NULL;
}
g_object_unref (old_connection);
proxy_connection = g_proxy_connect (proxy,
connection,
proxy_addr,
cancellable,
&last_error);
g_object_unref (connection);
connection = proxy_connection;
g_object_unref (proxy);
}
else if (!g_hash_table_lookup_extended (client->priv->app_proxies,
@ -753,11 +862,41 @@ g_socket_client_connect (GSocketClient *client,
}
}
if (connection && client->priv->tls)
{
GTlsClientConnection *tlsconn;
tlsconn = g_tls_client_connection_new (connection, connectable, &last_error);
g_object_unref (connection);
connection = (GIOStream *)tlsconn;
if (tlsconn)
{
g_tls_client_connection_set_validation_flags (tlsconn, client->priv->tls_validation_flags);
if (!g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn),
cancellable, &last_error))
{
g_object_unref (tlsconn);
connection = NULL;
}
}
}
if (connection && !G_IS_SOCKET_CONNECTION (connection))
{
GSocketConnection *wrapper_connection;
wrapper_connection = g_tcp_wrapper_connection_new (connection, socket);
g_object_unref (connection);
connection = (GIOStream *)wrapper_connection;
}
g_object_unref (socket);
g_object_unref (address);
}
g_object_unref (enumerator);
return connection;
return G_SOCKET_CONNECTION (connection);
}
/**
@ -925,10 +1064,11 @@ typedef struct
GCancellable *cancellable;
GSocketClient *client;
GSocketConnectable *connectable;
GSocketAddressEnumerator *enumerator;
GProxyAddress *proxy_addr;
GSocket *current_socket;
GSocketConnection *connection;
GIOStream *connection;
GError *last_error;
} GSocketClientAsyncConnectData;
@ -944,6 +1084,16 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
{
g_assert (data->connection);
if (!G_IS_SOCKET_CONNECTION (data->connection))
{
GSocketConnection *wrapper_connection;
wrapper_connection = g_tcp_wrapper_connection_new (data->connection,
data->current_socket);
g_object_unref (data->connection);
data->connection = (GIOStream *)wrapper_connection;
}
g_simple_async_result_set_op_res_gpointer (data->result,
data->connection,
g_object_unref);
@ -951,6 +1101,7 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
g_simple_async_result_complete (data->result);
g_object_unref (data->result);
g_object_unref (data->connectable);
g_object_unref (data->enumerator);
if (data->cancellable)
g_object_unref (data->cancellable);
@ -984,44 +1135,104 @@ enumerator_next_async (GSocketClientAsyncConnectData *data)
data);
}
static void
g_socket_client_tls_handshake_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSocketClientAsyncConnectData *data = user_data;
if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object),
result,
&data->last_error))
{
g_object_unref (data->connection);
data->connection = G_IO_STREAM (object);
}
else
{
g_object_unref (object);
g_object_unref (data->current_socket);
data->current_socket = NULL;
g_object_unref (data->connection);
data->connection = NULL;
enumerator_next_async (data);
}
g_socket_client_async_connect_complete (data);
}
static void
g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data)
{
GTlsClientConnection *tlsconn;
if (!data->client->priv->tls)
{
g_socket_client_async_connect_complete (data);
return;
}
tlsconn = g_tls_client_connection_new (data->connection,
data->connectable,
&data->last_error);
if (tlsconn)
{
g_tls_client_connection_set_validation_flags (tlsconn, data->client->priv->tls_validation_flags);
g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn),
G_PRIORITY_DEFAULT,
data->cancellable,
g_socket_client_tls_handshake_callback,
data);
}
else
{
g_object_unref (data->current_socket);
data->current_socket = NULL;
g_object_unref (data->connection);
data->connection = NULL;
enumerator_next_async (data);
}
}
static void
g_socket_client_proxy_connect_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSocketClientAsyncConnectData *data = user_data;
GIOStream *io_stream;
GTcpConnection *old_connection = G_TCP_CONNECTION (data->connection);
io_stream = g_proxy_connect_finish (G_PROXY (object),
result,
&data->last_error);
g_object_unref (data->connection);
data->connection = g_proxy_connect_finish (G_PROXY (object),
result,
&data->last_error);
if (!data->connection)
{
g_object_unref (data->current_socket);
data->current_socket = NULL;
if (io_stream)
{
if (G_IS_SOCKET_CONNECTION (io_stream))
data->connection = G_SOCKET_CONNECTION (g_object_ref (io_stream));
else
data->connection = _g_proxy_connection_new (old_connection,
io_stream);
g_object_unref (io_stream);
}
else
{
data->connection = NULL;
enumerator_next_async (data);
return;
}
g_object_unref (old_connection);
g_socket_client_async_connect_complete (data);
g_socket_client_tls_handshake (data);
}
static void
g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
{
GProxy *proxy;
const gchar *protocol = g_proxy_address_get_protocol (data->proxy_addr);
const gchar *protocol;
if (!data->proxy_addr)
{
g_socket_client_tls_handshake (data);
return;
}
protocol = g_proxy_address_get_protocol (data->proxy_addr);
proxy = g_proxy_get_default_for_protocol (protocol);
/* The connection should not be anything else then TCP Connection,
@ -1038,13 +1249,15 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
g_object_unref (data->connection);
data->connection = NULL;
g_object_unref (data->current_socket);
data->current_socket = NULL;
enumerator_next_async (data);
}
else if (proxy)
{
g_proxy_connect_async (proxy,
G_IO_STREAM (data->connection),
data->connection,
data->proxy_addr,
data->cancellable,
g_socket_client_proxy_connect_callback,
@ -1060,8 +1273,12 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
_("Proxy protocol '%s' is not supported."),
protocol);
g_object_unref (data->current_socket);
data->current_socket = NULL;
g_object_unref (data->connection);
data->connection = NULL;
g_object_unref (data->current_socket);
data->current_socket = NULL;
enumerator_next_async (data);
}
@ -1072,15 +1289,10 @@ g_socket_client_socket_connected (GSocketClientAsyncConnectData *data)
{
g_socket_set_blocking (data->current_socket, TRUE);
data->connection =
data->connection = (GIOStream *)
g_socket_connection_factory_create_connection (data->current_socket);
g_object_unref (data->current_socket);
data->current_socket = NULL;
if (data->proxy_addr)
g_socket_client_proxy_connect (data);
else
g_socket_client_async_connect_complete (data);
g_socket_client_proxy_connect (data);
}
static gboolean
@ -1237,6 +1449,10 @@ g_socket_client_connect_async (GSocketClient *client,
data->client = client;
if (cancellable)
data->cancellable = g_object_ref (cancellable);
else
data->cancellable = NULL;
data->last_error = NULL;
data->connectable = g_object_ref (connectable);
if (can_use_proxy (client))
data->enumerator = g_socket_connectable_proxy_enumerate (connectable);

View File

@ -89,6 +89,13 @@ gboolean g_socket_client_get_enable_proxy (GSocket
void g_socket_client_set_enable_proxy (GSocketClient *client,
gboolean enable);
gboolean g_socket_client_get_tls (GSocketClient *client);
void g_socket_client_set_tls (GSocketClient *client,
gboolean tls);
GTlsCertificateFlags g_socket_client_get_tls_validation_flags (GSocketClient *client);
void g_socket_client_set_tls_validation_flags (GSocketClient *client,
GTlsCertificateFlags flags);
GSocketConnection * g_socket_client_connect (GSocketClient *client,
GSocketConnectable *connectable,
GCancellable *cancellable,

View File

@ -60,8 +60,7 @@
* Since: 2.22
*/
G_DEFINE_TYPE (GSocketConnection,
g_socket_connection, G_TYPE_IO_STREAM);
G_DEFINE_TYPE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM);
enum
{

View File

@ -27,13 +27,18 @@
#include "gsocketinputstream.h"
#include "glibintl.h"
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
#include <gio/gioerror.h>
#include "gsimpleasyncresult.h"
#include "gcancellable.h"
#include "gpollableinputstream.h"
#include "gioerror.h"
static void g_socket_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
#define g_socket_input_stream_get_type _g_socket_input_stream_get_type
G_DEFINE_TYPE (GSocketInputStream, g_socket_input_stream, G_TYPE_INPUT_STREAM);
G_DEFINE_TYPE_WITH_CODE (GSocketInputStream, g_socket_input_stream, G_TYPE_INPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, g_socket_input_stream_pollable_iface_init)
)
enum
{
@ -205,6 +210,44 @@ g_socket_input_stream_read_finish (GInputStream *stream,
return count;
}
static gboolean
g_socket_input_stream_pollable_is_readable (GPollableInputStream *pollable)
{
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
return g_socket_condition_check (input_stream->priv->socket, G_IO_IN);
}
static GSource *
g_socket_input_stream_pollable_create_source (GPollableInputStream *pollable,
GCancellable *cancellable)
{
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
GSource *socket_source, *pollable_source;
pollable_source = g_pollable_source_new (G_OBJECT (input_stream));
socket_source = g_socket_create_source (input_stream->priv->socket,
G_IO_IN, cancellable);
g_source_set_dummy_callback (socket_source);
g_source_add_child_source (pollable_source, socket_source);
g_source_unref (socket_source);
return pollable_source;
}
static gssize
g_socket_input_stream_pollable_read_nonblocking (GPollableInputStream *pollable,
void *buffer,
gsize size,
GError **error)
{
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
return g_socket_receive_with_blocking (input_stream->priv->socket,
buffer, size, FALSE,
NULL, error);
}
static void
g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
{
@ -229,6 +272,14 @@ g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
g_socket_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
{
iface->is_readable = g_socket_input_stream_pollable_is_readable;
iface->create_source = g_socket_input_stream_pollable_create_source;
iface->read_nonblocking = g_socket_input_stream_pollable_read_nonblocking;
}
static void
g_socket_input_stream_init (GSocketInputStream *stream)
{

View File

@ -28,14 +28,20 @@
#include "gsocketoutputstream.h"
#include "gsocket.h"
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
#include <gio/gioerror.h>
#include "gsimpleasyncresult.h"
#include "gcancellable.h"
#include "gpollableinputstream.h"
#include "gpollableoutputstream.h"
#include "gioerror.h"
#include "glibintl.h"
static void g_socket_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface);
#define g_socket_output_stream_get_type _g_socket_output_stream_get_type
G_DEFINE_TYPE (GSocketOutputStream, g_socket_output_stream, G_TYPE_OUTPUT_STREAM);
G_DEFINE_TYPE_WITH_CODE (GSocketOutputStream, g_socket_output_stream, G_TYPE_OUTPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, g_socket_output_stream_pollable_iface_init)
)
enum
{
@ -207,6 +213,44 @@ g_socket_output_stream_write_finish (GOutputStream *stream,
return count;
}
static gboolean
g_socket_output_stream_pollable_is_writable (GPollableOutputStream *pollable)
{
GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
return g_socket_condition_check (output_stream->priv->socket, G_IO_OUT);
}
static GSource *
g_socket_output_stream_pollable_create_source (GPollableOutputStream *pollable,
GCancellable *cancellable)
{
GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
GSource *socket_source, *pollable_source;
pollable_source = g_pollable_source_new (G_OBJECT (output_stream));
socket_source = g_socket_create_source (output_stream->priv->socket,
G_IO_OUT, cancellable);
g_source_set_dummy_callback (socket_source);
g_source_add_child_source (pollable_source, socket_source);
g_source_unref (socket_source);
return pollable_source;
}
static gssize
g_socket_output_stream_pollable_write_nonblocking (GPollableOutputStream *pollable,
const void *buffer,
gsize size,
GError **error)
{
GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
return g_socket_send_with_blocking (output_stream->priv->socket,
buffer, size, FALSE,
NULL, error);
}
static void
g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
{
@ -231,6 +275,14 @@ g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
g_socket_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface)
{
iface->is_writable = g_socket_output_stream_pollable_is_writable;
iface->create_source = g_socket_output_stream_pollable_create_source;
iface->write_nonblocking = g_socket_output_stream_pollable_write_nonblocking;
}
static void
g_socket_output_stream_init (GSocketOutputStream *stream)
{

View File

@ -176,7 +176,7 @@ parse_nego_reply (const guint8 *data,
case SOCKS5_AUTH_NO_ACCEPT:
default:
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED,
_("The SOCKSv5 require an authentication method that is not "
_("The SOCKSv5 proxy requires an authentication method that is not "
"supported by GLib."));
return FALSE;
break;

View File

@ -13,7 +13,7 @@
/**
* SECTION: gtcpconnection
* @title: GTcpConnection
* @short_description: a TCP GSocketConnection
* @short_description: A TCP GSocketConnection
* @see_also: #GSocketConnection.
*
* This is the subclass of #GSocketConnection that is created

199
gio/gtcpwrapperconnection.c Normal file
View File

@ -0,0 +1,199 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 Collabora Ltd.
*
* 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.
*
* Authors: Nicolas Dufresne <nicolas.dufresne@colllabora.co.uk>
*/
/**
* SECTION: gtcpwrapperconnection
* @title: GTcpWrapperConnection
* @short_description: wrapper for non-GSocketConnection-based, GSocket-based GIOStreams
* @see_also: #GSocketConnection.
*
* A #GTcpWrapperConnection can be used to wrap a #GIOStream that is
* based on a #GSocket, but which is not actually a
* #GSocketConnection. This is used by #GSocketClient so that it can
* always return a #GSocketConnection, even when the connection it has
* actually created is not directly a #GSocketConnection.
*
* Since: 2.28
*/
#include "config.h"
#include "gtcpwrapperconnection.h"
#include "gtcpconnection.h"
#include "glibintl.h"
G_DEFINE_TYPE (GTcpWrapperConnection,
g_tcp_wrapper_connection, G_TYPE_TCP_CONNECTION);
enum
{
PROP_NONE,
PROP_BASE_IO_STREAM
};
struct _GTcpWrapperConnectionPrivate
{
GIOStream *base_io_stream;
};
static GInputStream *
g_tcp_wrapper_connection_get_input_stream (GIOStream *io_stream)
{
GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (io_stream);
return g_io_stream_get_input_stream (connection->priv->base_io_stream);
}
static GOutputStream *
g_tcp_wrapper_connection_get_output_stream (GIOStream *io_stream)
{
GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (io_stream);
return g_io_stream_get_output_stream (connection->priv->base_io_stream);
}
static void
g_tcp_wrapper_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
switch (prop_id)
{
case PROP_BASE_IO_STREAM:
g_value_set_object (value, connection->priv->base_io_stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tcp_wrapper_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
switch (prop_id)
{
case PROP_BASE_IO_STREAM:
connection->priv->base_io_stream = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tcp_wrapper_connection_finalize (GObject *object)
{
GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
if (connection->priv->base_io_stream)
g_object_unref (connection->priv->base_io_stream);
G_OBJECT_CLASS (g_tcp_wrapper_connection_parent_class)->finalize (object);
}
static void
g_tcp_wrapper_connection_class_init (GTcpWrapperConnectionClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (GTcpWrapperConnectionPrivate));
gobject_class->set_property = g_tcp_wrapper_connection_set_property;
gobject_class->get_property = g_tcp_wrapper_connection_get_property;
gobject_class->finalize = g_tcp_wrapper_connection_finalize;
stream_class->get_input_stream = g_tcp_wrapper_connection_get_input_stream;
stream_class->get_output_stream = g_tcp_wrapper_connection_get_output_stream;
g_object_class_install_property (gobject_class,
PROP_BASE_IO_STREAM,
g_param_spec_object ("base-io-stream",
P_("Base IO Stream"),
P_("The wrapped GIOStream"),
G_TYPE_IO_STREAM,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
static void
g_tcp_wrapper_connection_init (GTcpWrapperConnection *connection)
{
connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
G_TYPE_TCP_WRAPPER_CONNECTION,
GTcpWrapperConnectionPrivate);
}
/**
* g_tcp_wrapper_connection_new:
* @base_io_stream: the #GIOStream to wrap
* @socket: the #GSocket associated with @base_io_stream
*
* Wraps @base_io_stream and @socket together as a #GSocketConnection.
*
* Return value: the new #GSocketConnection.
*
* Since: 2.28
*/
GSocketConnection *
g_tcp_wrapper_connection_new (GIOStream *base_io_stream,
GSocket *socket)
{
g_return_val_if_fail (G_IS_IO_STREAM (base_io_stream), NULL);
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
g_return_val_if_fail (g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV4 ||
g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6, NULL);
g_return_val_if_fail (g_socket_get_socket_type (socket) == G_SOCKET_TYPE_STREAM, NULL);
return g_object_new (G_TYPE_TCP_WRAPPER_CONNECTION,
"base-io-stream", base_io_stream,
"socket", socket,
NULL);
}
/**
* g_tcp_wrapper_connection_get_base_io_stream:
* @conn: a #GTcpWrapperConnection
*
* Get's @conn's base #GIOStream
*
* Return value: (transfer none): @conn's base #GIOStream
*/
GIOStream *
g_tcp_wrapper_connection_get_base_io_stream (GTcpWrapperConnection *conn)
{
g_return_val_if_fail (G_IS_TCP_WRAPPER_CONNECTION (conn), NULL);
return conn->priv->base_io_stream;
}

View File

@ -0,0 +1,68 @@
/* GIO - GLib Input, Output and Streaming Library
* Copyright © 2010 Collabora Ltd.
*
* This program 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 licence 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.
*
* Authors: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
*
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TCP_WRAPPER_CONNECTION_H__
#define __G_TCP_WRAPPER_CONNECTION_H__
#include <gio/gtcpconnection.h>
G_BEGIN_DECLS
#define G_TYPE_TCP_WRAPPER_CONNECTION (g_tcp_wrapper_connection_get_type ())
#define G_TCP_WRAPPER_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnection))
#define G_TCP_WRAPPER_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \
G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnectionClass))
#define G_IS_TCP_WRAPPER_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
G_TYPE_TCP_WRAPPER_CONNECTION))
#define G_IS_TCP_WRAPPER_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
G_TYPE_TCP_WRAPPER_CONNECTION))
#define G_TCP_WRAPPER_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnectionClass))
typedef struct _GTcpWrapperConnectionPrivate GTcpWrapperConnectionPrivate;
typedef struct _GTcpWrapperConnectionClass GTcpWrapperConnectionClass;
struct _GTcpWrapperConnectionClass
{
GTcpConnectionClass parent_class;
};
struct _GTcpWrapperConnection
{
GTcpConnection parent_instance;
GTcpWrapperConnectionPrivate *priv;
};
GType g_tcp_wrapper_connection_get_type (void) G_GNUC_CONST;
GSocketConnection *g_tcp_wrapper_connection_new (GIOStream *base_io_stream,
GSocket *socket);
GIOStream *g_tcp_wrapper_connection_get_base_io_stream (GTcpWrapperConnection *conn);
G_END_DECLS
#endif /* __G_TCP_WRAPPER_CONNECTION_H__ */

201
gio/gtlsbackend.c Normal file
View File

@ -0,0 +1,201 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 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 "glib.h"
#include "gtlsbackend.h"
#include "gdummytlsbackend.h"
#include "gioenumtypes.h"
#include "giomodule-priv.h"
/**
* SECTION:gtls
* @title: TLS Overview
* @short_description: TLS (aka SSL) support for GSocketConnection
* @include: gio/gio.h
*
* #GTlsConnection and related classes provide TLS (Transport Layer
* Security, previously known as SSL, Secure Sockets Layer) support for
* gio-based network streams.
*
* In the simplest case, for a client connection, you can just set the
* #GSocketClient:tls flag on a #GSocketClient, and then any
* connections created by that client will have TLS negotiated
* automatically, using appropriate default settings, and rejecting
* any invalid or self-signed certificates (unless you change that
* default by setting the #GSocketClient:tls-validation-flags
* property). The returned object will be a #GTcpWrapperConnection,
* which wraps the underlying #GTlsClientConnection.
*
* For greater control, you can create your own #GTlsClientConnection,
* wrapping a #GSocketConnection (or an arbitrary #GIOStream with
* pollable input and output streams) and then connect to its signals,
* such as #GTlsConnection::accept-certificate, before starting the
* handshake.
*
* Server-side TLS is similar, using #GTlsServerConnection. At the
* moment, there is no support for automatically wrapping server-side
* connections in the way #GSocketClient does for client-side
* connections.
*/
/**
* SECTION:gtlsbackend
* @title: GTlsBackend
* @short_description: TLS backend implementation
* @include: gio/gio.h
*/
/**
* GTlsBackend:
*
* Type implemented by TLS #GIOModules to provide access to additional
* TLS-related types.
*
* Since: 2.28
*/
G_DEFINE_INTERFACE (GTlsBackend, g_tls_backend, G_TYPE_OBJECT);
static void
g_tls_backend_default_init (GTlsBackendInterface *iface)
{
}
static gpointer
get_default_tls_backend (gpointer arg)
{
const char *use_this;
GList *extensions;
GIOExtensionPoint *ep;
GIOExtension *extension;
_g_io_modules_ensure_loaded ();
ep = g_io_extension_point_lookup (G_TLS_BACKEND_EXTENSION_POINT_NAME);
use_this = g_getenv ("GIO_USE_TLS");
if (use_this)
{
extension = g_io_extension_point_get_extension_by_name (ep, use_this);
if (extension)
return g_object_new (g_io_extension_get_type (extension), NULL);
}
extensions = g_io_extension_point_get_extensions (ep);
if (extensions)
{
extension = extensions->data;
return g_object_new (g_io_extension_get_type (extension), NULL);
}
return NULL;
}
/**
* g_tls_backend_get_default:
*
* Gets the default #GTlsBackend for the system.
*
* Returns: a #GTlsBackend
*
* Since: 2.28
*/
GTlsBackend *
g_tls_backend_get_default (void)
{
static GOnce once_init = G_ONCE_INIT;
return g_once (&once_init, get_default_tls_backend, NULL);
}
/**
* g_tls_backend_supports_tls:
* @backend: the #GTlsBackend
*
* Checks if TLS is supported; if this returns %FALSE for the default
* #GTlsBackend, it means no "real" TLS backend is available.
*
* Return value: whether or not TLS is supported
*
* Since: 2.28
*/
gboolean
g_tls_backend_supports_tls (GTlsBackend *backend)
{
if (G_TLS_BACKEND_GET_INTERFACE (backend)->supports_tls)
return G_TLS_BACKEND_GET_INTERFACE (backend)->supports_tls (backend);
else if (G_IS_DUMMY_TLS_BACKEND (backend))
return FALSE;
else
return TRUE;
}
/**
* g_tls_backend_get_certificate_type:
* @backend: the #GTlsBackend
*
* Gets the #GType of @backend's #GTlsCertificate implementation.
*
* Return value: the #GType of @backend's #GTlsCertificate
* implementation.
*
* Since: 2.28
*/
GType
g_tls_backend_get_certificate_type (GTlsBackend *backend)
{
return G_TLS_BACKEND_GET_INTERFACE (backend)->get_certificate_type ();
}
/**
* g_tls_backend_get_client_connection_type:
* @backend: the #GTlsBackend
*
* Gets the #GType of @backend's #GTlsClientConnection implementation.
*
* Return value: the #GType of @backend's #GTlsClientConnection
* implementation.
*
* Since: 2.28
*/
GType
g_tls_backend_get_client_connection_type (GTlsBackend *backend)
{
return G_TLS_BACKEND_GET_INTERFACE (backend)->get_client_connection_type ();
}
/**
* g_tls_backend_get_server_connection_type:
* @backend: the #GTlsBackend
*
* Gets the #GType of @backend's #GTlsServerConnection implementation.
*
* Return value: the #GType of @backend's #GTlsServerConnection
* implementation.
*
* Since: 2.28
*/
GType
g_tls_backend_get_server_connection_type (GTlsBackend *backend)
{
return G_TLS_BACKEND_GET_INTERFACE (backend)->get_server_connection_type ();
}

92
gio/gtlsbackend.h Normal file
View File

@ -0,0 +1,92 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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.
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TLS_BACKEND_H__
#define __G_TLS_BACKEND_H__
#include <gio/giotypes.h>
G_BEGIN_DECLS
/**
* G_TLS_BACKEND_EXTENSION_POINT_NAME:
*
* Extension point for TLS functionality via #GTlsBackend.
* See <link linkend="extending-gio">Extending GIO</link>.
*/
#define G_TLS_BACKEND_EXTENSION_POINT_NAME "gio-tls-backend"
#define G_TYPE_TLS_BACKEND (g_tls_backend_get_type ())
#define G_TLS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_TLS_BACKEND, GTlsBackend))
#define G_IS_TLS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_TLS_BACKEND))
#define G_TLS_BACKEND_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_TLS_BACKEND, GTlsBackendInterface))
/**
* GTlsBackend:
*
* TLS (Transport Layer Security, aka SSL) backend. This is an
* internal type used to coordinate the different classes implemented
* by a TLS backend.
*
* Since: 2.28
*/
typedef struct _GTlsBackend GTlsBackend;
typedef struct _GTlsBackendInterface GTlsBackendInterface;
/**
* GTlsBackendInterface:
* @g_iface: The parent interface.
* @get_certificate_type: returns the #GTlsCertificate implementation type
* @get_client_connection_type: returns the #GTlsClientConnection implementation type
* @get_server_connection_type: returns the #GTlsServerConnection implementation type
*
* Provides an interface for describing TLS-related types.
*
* Since: 2.28
*/
struct _GTlsBackendInterface
{
GTypeInterface g_iface;
/* methods */
gboolean ( *supports_tls) (GTlsBackend *backend);
GType ( *get_certificate_type) (void);
GType ( *get_client_connection_type) (void);
GType ( *get_server_connection_type) (void);
};
GType g_tls_backend_get_type (void) G_GNUC_CONST;
GTlsBackend *g_tls_backend_get_default (void);
gboolean g_tls_backend_supports_tls (GTlsBackend *backend);
GType g_tls_backend_get_certificate_type (GTlsBackend *backend);
GType g_tls_backend_get_client_connection_type (GTlsBackend *backend);
GType g_tls_backend_get_server_connection_type (GTlsBackend *backend);
G_END_DECLS
#endif /* __G_TLS_BACKEND_H__ */

486
gio/gtlscertificate.c Normal file
View File

@ -0,0 +1,486 @@
/* GIO - GLib Input, Output and Certificateing Library
*
* Copyright (C) 2010 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 "gtlscertificate.h"
#include <string.h>
#include "ginitable.h"
#include "gtlsbackend.h"
#include "gtlsconnection.h"
#include "glibintl.h"
/**
* SECTION: gtlscertificate
* @title: GTlsCertificate
* @short_description: TLS certificate
* @see_also: #GTlsConnection
*
* A certificate used for TLS authentication and encryption.
* This can represent either a public key only (eg, the certificate
* received by a client from a server), or the combination of
* a public key and a private key (which is needed when acting as a
* #GTlsServerConnection).
*
* Since: 2.28
*/
/**
* GTlsCertificate:
*
* Abstract base class for TLS certificate types.
*
* Since: 2.28
*/
G_DEFINE_ABSTRACT_TYPE (GTlsCertificate, g_tls_certificate, G_TYPE_OBJECT);
struct _GTlsCertificatePrivate
{
GTlsCertificate *issuer;
};
enum
{
PROP_0,
PROP_CERTIFICATE,
PROP_CERTIFICATE_PEM,
PROP_PRIVATE_KEY,
PROP_PRIVATE_KEY_PEM,
PROP_ISSUER
};
static void
g_tls_certificate_init (GTlsCertificate *cert)
{
cert->priv = G_TYPE_INSTANCE_GET_PRIVATE (cert,
G_TYPE_TLS_CERTIFICATE,
GTlsCertificatePrivate);
}
static void
g_tls_certificate_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
switch (prop_id)
{
case PROP_ISSUER:
g_value_set_object (value, cert->priv->issuer);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tls_certificate_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
switch (prop_id)
{
case PROP_ISSUER:
cert->priv->issuer = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tls_certificate_finalize (GObject *object)
{
GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
if (cert->priv->issuer)
g_object_unref (cert->priv->issuer);
G_OBJECT_CLASS (g_tls_certificate_parent_class)->finalize (object);
}
static void
g_tls_certificate_class_init (GTlsCertificateClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (GTlsCertificatePrivate));
gobject_class->set_property = g_tls_certificate_set_property;
gobject_class->get_property = g_tls_certificate_get_property;
gobject_class->finalize = g_tls_certificate_finalize;
/**
* GTlsCertificate:certificate:
*
* The DER (binary) encoded representation of the certificate's
* public key. This property and the
* #GTlsCertificate:certificate-pem property represent the same
* data, just in different forms.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
g_param_spec_boxed ("certificate",
P_("Certificate"),
P_("The DER representation of the certificate"),
G_TYPE_BYTE_ARRAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GTlsCertificate:certificate-pem:
*
* The PEM (ASCII) encoded representation of the certificate's
* public key. This property and the #GTlsCertificate:certificate
* property represent the same data, just in different forms.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_CERTIFICATE_PEM,
g_param_spec_string ("certificate-pem",
P_("Certificate (PEM)"),
P_("The PEM representation of the certificate"),
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GTlsCertificate:private-key:
*
* The DER (binary) encoded representation of the certificate's
* private key. This property (or the
* #GTlsCertificate:private-key-pem property) can be set when
* constructing a key (eg, from a file), but cannot be read.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
g_param_spec_boxed ("private-key",
P_("Private key"),
P_("The DER representation of the certificate's private key"),
G_TYPE_BYTE_ARRAY,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GTlsCertificate:private-key-pem:
*
* The PEM (ASCII) encoded representation of the certificate's
* private key. This property (or the #GTlsCertificate:private-key
* property) can be set when constructing a key (eg, from a file),
* but cannot be read.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PEM,
g_param_spec_string ("private-key-pem",
P_("Private key (PEM)"),
P_("The PEM representation of the certificate's private key"),
NULL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GTlsCertificate:issuer:
*
* A #GTlsCertificate representing the entity that issued this
* certificate. If %NULL, this means that the certificate is either
* self-signed, or else the certificate of the issuer is not
* available.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_ISSUER,
g_param_spec_object ("issuer",
P_("Issuer"),
P_("The certificate for the issuing entity"),
G_TYPE_TLS_CERTIFICATE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
static GTlsCertificate *
g_tls_certificate_new_internal (const gchar *certificate_pem,
const gchar *private_key_pem,
GError **error)
{
GObject *cert;
GTlsBackend *backend;
backend = g_tls_backend_get_default ();
cert = g_initable_new (g_tls_backend_get_certificate_type (backend),
NULL, error,
"certificate-pem", certificate_pem,
"private-key-pem", private_key_pem,
NULL);
return G_TLS_CERTIFICATE (cert);
}
#define PEM_CERTIFICATE_HEADER "-----BEGIN CERTIFICATE-----"
#define PEM_CERTIFICATE_FOOTER "-----END CERTIFICATE-----"
#define PEM_PRIVKEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
#define PEM_PRIVKEY_FOOTER "-----END RSA PRIVATE KEY-----"
static GTlsCertificate *
parse_next_pem_certificate (const gchar **data,
const gchar *data_end,
gboolean required,
GError **error)
{
const gchar *start, *end, *next;
gchar *cert_pem, *privkey_pem = NULL;
GTlsCertificate *cert;
start = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
if (!start)
{
if (required)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
_("No PEM-encoded certificate found"));
}
return NULL;
}
end = g_strstr_len (start, data_end - start, PEM_CERTIFICATE_FOOTER);
if (!end)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
_("Could not parse PEM-encoded certificate"));
return NULL;
}
end += strlen (PEM_CERTIFICATE_FOOTER);
while (*end == '\r' || *end == '\n')
end++;
cert_pem = g_strndup (start, end - start);
*data = end;
next = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
start = g_strstr_len (*data, data_end - *data, PEM_PRIVKEY_HEADER);
if (start)
end = g_strstr_len (start, data_end - start, PEM_PRIVKEY_FOOTER);
if (start && (!next || start < next))
{
if (!end || (next && end > next))
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
_("Could not parse PEM-encoded private key"));
return NULL;
}
end += strlen (PEM_PRIVKEY_FOOTER);
while (*end == '\r' || *end == '\n')
end++;
privkey_pem = g_strndup (start, end - start);
*data = end + strlen (PEM_PRIVKEY_FOOTER);
}
cert = g_tls_certificate_new_internal (cert_pem, privkey_pem, error);
g_free (cert_pem);
g_free (privkey_pem);
return cert;
}
/**
* g_tls_certificate_new_from_pem:
* @data: PEM-encoded certificate data
* @length: the length of @data, or -1 if it's 0-terminated.
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates a new #GTlsCertificate from the PEM-encoded data in @data.
* If @data includes both a certificate and a private key, then the
* returned certificate will include the private key data as well.
*
* If @data includes multiple certificates, only the first one will be
* parsed.
*
* Return value: the new certificate, or %NULL if @data is invalid
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_certificate_new_from_pem (const gchar *data,
gssize length,
GError **error)
{
const gchar *data_end;
g_return_val_if_fail (data != NULL, NULL);
if (length == -1)
data_end = data + strlen (data);
else
data_end = data + length;
return parse_next_pem_certificate (&data, data_end, TRUE, error);
}
/**
* g_tls_certificate_new_from_file:
* @file: file containing a PEM-encoded certificate to import
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates a #GTlsCertificate from the PEM-encoded data in @file. If
* @file cannot be read or parsed, the function will return %NULL and
* set @error. Otherwise, this behaves like g_tls_certificate_new().
*
* Return value: the new certificate, or %NULL on error
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_certificate_new_from_file (const gchar *file,
GError **error)
{
GTlsCertificate *cert;
gchar *contents;
gsize length;
if (!g_file_get_contents (file, &contents, &length, error))
return NULL;
cert = g_tls_certificate_new_from_pem (contents, length, error);
g_free (contents);
return cert;
}
/**
* g_tls_certificate_new_from_files:
* @cert_file: file containing a PEM-encoded certificate to import
* @key_file: file containing a PEM-encoded private key to import
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates a #GTlsCertificate from the PEM-encoded data in @cert_file
* and @key_file. If either file cannot be read or parsed, the
* function will return %NULL and set @error. Otherwise, this behaves
* like g_tls_certificate_new().
*
* Return value: the new certificate, or %NULL on error
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_certificate_new_from_files (const gchar *cert_file,
const gchar *key_file,
GError **error)
{
GTlsCertificate *cert;
gchar *cert_data, *key_data;
if (!g_file_get_contents (cert_file, &cert_data, NULL, error))
return NULL;
if (!g_file_get_contents (key_file, &key_data, NULL, error))
{
g_free (cert_data);
return NULL;
}
cert = g_tls_certificate_new_internal (cert_data, key_data, error);
g_free (cert_data);
g_free (key_data);
return cert;
}
/**
* g_tls_certificate_list_new_from_file:
* @file: file containing PEM-encoded certificates to import
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates one or more #GTlsCertificate<!-- -->s from the PEM-encoded
* data in @file. If @file cannot be read or parsed, the function will
* return %NULL and set @error. If @file does not contain any
* PEM-encoded certificates, this will return an empty list and not
* set @error.
*
* Return value: (element-type Gio.TlsCertificate) (transfer full): a
* #GList containing #GTlsCertificate objects. You must free the list
* and its contents when you are done with it.
*
* Since: 2.28
*/
GList *
g_tls_certificate_list_new_from_file (const gchar *file,
GError **error)
{
GTlsCertificate *cert;
GList *list, *l;
gchar *contents, *end;
const gchar *p;
gsize length;
if (!g_file_get_contents (file, &contents, &length, error))
return NULL;
list = NULL;
end = contents + length;
p = contents;
while (p && *p)
{
cert = parse_next_pem_certificate (&p, end, FALSE, error);
if (!cert)
{
for (l = list; l; l = l->next)
g_object_unref (l->data);
g_list_free (list);
list = NULL;
break;
}
list = g_list_prepend (list, cert);
}
return g_list_reverse (list);
}
/**
* g_tls_certificate_get_issuer:
* @cert: a #GTlsCertificate
*
* Gets the #GTlsCertificate representing @cert's issuer, if known
*
* Return value: (transfer none): The certificate of @cert's issuer,
* or %NULL if @cert is self-signed or signed with an unknown
* certificate.
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_certificate_get_issuer (GTlsCertificate *cert)
{
return cert->priv->issuer;
}

75
gio/gtlscertificate.h Normal file
View File

@ -0,0 +1,75 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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.
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TLS_CERTIFICATE_H__
#define __G_TLS_CERTIFICATE_H__
#include <gio/giotypes.h>
G_BEGIN_DECLS
#define G_TYPE_TLS_CERTIFICATE (g_tls_certificate_get_type ())
#define G_TLS_CERTIFICATE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CERTIFICATE, GTlsCertificate))
#define G_TLS_CERTIFICATE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_CERTIFICATE, GTlsCertificateClass))
#define G_IS_TLS_CERTIFICATE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CERTIFICATE))
#define G_IS_TLS_CERTIFICATE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_CERTIFICATE))
#define G_TLS_CERTIFICATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_CERTIFICATE, GTlsCertificateClass))
typedef struct _GTlsCertificateClass GTlsCertificateClass;
typedef struct _GTlsCertificatePrivate GTlsCertificatePrivate;
struct _GTlsCertificate {
GObject parent_instance;
GTlsCertificatePrivate *priv;
};
struct _GTlsCertificateClass
{
GObjectClass parent_class;
/*< private >*/
/* Padding for future expansion */
gpointer padding[8];
};
GType g_tls_certificate_get_type (void) G_GNUC_CONST;
GTlsCertificate *g_tls_certificate_new_from_pem (const gchar *data,
gssize length,
GError **error);
GTlsCertificate *g_tls_certificate_new_from_file (const gchar *file,
GError **error);
GTlsCertificate *g_tls_certificate_new_from_files (const gchar *cert_file,
const gchar *key_file,
GError **error);
GList *g_tls_certificate_list_new_from_file (const gchar *file,
GError **error);
GTlsCertificate *g_tls_certificate_get_issuer (GTlsCertificate *cert);
G_END_DECLS
#endif /* __G_TLS_CERTIFICATE_H__ */

333
gio/gtlsclientconnection.c Normal file
View File

@ -0,0 +1,333 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 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 "glib.h"
#include "gtlsclientconnection.h"
#include "ginitable.h"
#include "gioenumtypes.h"
#include "gio-marshal.h"
#include "gsocket.h"
#include "gsocketconnectable.h"
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "glibintl.h"
/**
* SECTION:gtlsclientconnection
* @short_description: TLS client-side connection
* @include: gio/gio.h
*
* #GTlsClientConnection is the client-side subclass of
* #GTlsConnection, representing a client-side TLS connection.
*
* Since: 2.28
*/
/**
* GTlsClientConnection:
*
* Abstract base class for the backend-specific client connection
* type.
*
* Since: 2.28
*/
G_DEFINE_INTERFACE (GTlsClientConnection, g_tls_client_connection, G_TYPE_TLS_CONNECTION)
static void
g_tls_client_connection_default_init (GTlsClientConnectionInterface *iface)
{
/**
* GTlsClientConnection:validation-flags:
*
* What steps to perform when validating a certificate received from
* a server. Server certificates that fail to validate in all of the
* ways indicated here will be rejected unless the application
* overrides the default via #GTlsConnection::accept-certificate.
*
* Since: 2.28
*/
g_object_interface_install_property (iface,
g_param_spec_flags ("validation-flags",
P_("Validation flags"),
P_("What certificate validation to perform"),
G_TYPE_TLS_CERTIFICATE_FLAGS,
G_TLS_CERTIFICATE_VALIDATE_ALL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/**
* GTlsClientConnection:server-identity:
*
* A #GSocketConnectable describing the identity of the server that
* is expected on the other end of the connection.
*
* If the %G_TLS_CERTIFICATE_BAD_IDENTITY flag is set in
* #GTlsClientConnection:validation-flags, this object will be used
* to determine the expected identify of the remote end of the
* connection; if #GTlsClientConnection:server-identity is not set,
* or does not match the identity presented by the server, then the
* %G_TLS_CERTIFICATE_BAD_IDENTITY validation will fail.
*
* In addition to its use in verifying the server certificate,
* this is also used to give a hint to the server about what
* certificate we expect, which is useful for servers that serve
* virtual hosts.
*
* Since: 2.28
*/
g_object_interface_install_property (iface,
g_param_spec_object ("server-identity",
P_("Server identity"),
P_("GSocketConnectable identifying the server"),
G_TYPE_SOCKET_CONNECTABLE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/**
* GTlsClientConnection:use-ssl3:
*
* If %TRUE, tells the connection to use SSL 3.0 rather than trying
* to negotiate the best version of TLS or SSL to use. This can be
* used when talking to servers that don't implement version
* negotiation correctly and therefore refuse to handshake at all with
* a "modern" TLS handshake.
*
* Since: 2.28
*/
g_object_interface_install_property (iface,
g_param_spec_boolean ("use-ssl3",
P_("Use SSL3"),
P_("Use SSL 3.0 rather than trying to use TLS 1.x"),
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/**
* GTlsClientConnection:accepted-cas:
*
* A list of the distinguished names of the Certificate Authorities
* that the server will accept client certificates signed by. If the
* server requests a client certificate during the handshake, then
* this property will be set by the time the
* #GTlsConnection::need-certificate signal is emitted.
*
* Since: 2.28
*/
g_object_interface_install_property (iface,
g_param_spec_boxed ("accepted-cas",
P_("Accepted CAs"),
P_("Distinguished names of the CAs the server accepts certificates from"),
G_TYPE_STRV,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}
/**
* g_tls_client_connection_new:
* @base_io_stream: the #GIOStream to wrap
* @server_identity: (allow-none): the expected identity of the server
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates a new #GTlsClientConnection wrapping @base_io_stream (which
* must have pollable input and output streams) which is assumed to
* communicate with the server identified by @server_identity.
*
* Return value: the new #GTlsClientConnection, or %NULL on error
*
* Since: 2.28
*/
GTlsClientConnection *
g_tls_client_connection_new (GIOStream *base_io_stream,
GSocketConnectable *server_identity,
GError **error)
{
GObject *conn;
GTlsBackend *backend;
backend = g_tls_backend_get_default ();
conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
NULL, error,
"base-io-stream", base_io_stream,
"server-identity", server_identity,
NULL);
return G_TLS_CLIENT_CONNECTION (conn);
}
/**
* g_tls_client_connection_get_validation_flags:
* @conn: the #GTlsClientConnection
*
* Gets @conn's validation flags
*
* Return value: the validation flags
*
* Since: 2.28
*/
GTlsCertificateFlags
g_tls_client_connection_get_validation_flags (GTlsClientConnection *conn)
{
GTlsCertificateFlags flags = 0;
g_return_val_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn), 0);
g_object_get (G_OBJECT (conn), "validation-flags", &flags, NULL);
return flags;
}
/**
* g_tls_client_connection_set_validation_flags:
* @conn: the #GTlsClientConnection
* @flags: the #GTlsCertificatelags to use
*
* Sets @conn's validation flags, to override the default set of
* checks performed when validating a server certificate.
*
* Since: 2.28
*/
void
g_tls_client_connection_set_validation_flags (GTlsClientConnection *conn,
GTlsCertificateFlags flags)
{
g_return_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn));
g_object_set (G_OBJECT (conn), "validation-flags", flags, NULL);
}
/**
* g_tls_client_connection_get_server_identity:
* @conn: the #GTlsClientConnection
*
* Gets @conn's expected server identity
*
* Return value: a #GSocketConnectable describing the
* expected server identity, or %NULL if the expected identity is not
* known.
*
* Since: 2.28
*/
GSocketConnectable *
g_tls_client_connection_get_server_identity (GTlsClientConnection *conn)
{
GSocketConnectable *identity = NULL;
g_return_val_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn), 0);
g_object_get (G_OBJECT (conn), "server-identity", &identity, NULL);
if (identity)
g_object_unref (identity);
return identity;
}
/**
* g_tls_client_connection_set_server_identity:
* @conn: the #GTlsClientConnection
* @identity: a #GSocketConnectable describing the expected server identity
*
* Sets @conn's expected server identity, which is used both to tell
* servers on virtual hosts which certificate to present, and also
* to let @conn know what name to look for in the certificate when
* performing %G_TLS_CERTIFICATE_BAD_IDENTITY validation, if enabled.
*
* Since: 2.28
*/
void
g_tls_client_connection_set_server_identity (GTlsClientConnection *conn,
GSocketConnectable *identity)
{
g_return_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn));
g_object_set (G_OBJECT (conn), "server-identity", identity, NULL);
}
/**
* g_tls_client_connection_get_use_ssl3:
* @conn: the #GTlsClientConnection
*
* Gets whether @conn will use SSL 3.0 rather than the
* highest-supported version of TLS; see
* g_tls_client_connection_set_use_ssl3().
*
* Return value: whether @conn will use SSL 3.0
*
* Since: 2.28
*/
gboolean
g_tls_client_connection_get_use_ssl3 (GTlsClientConnection *conn)
{
gboolean use_ssl3 = FALSE;
g_return_val_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn), 0);
g_object_get (G_OBJECT (conn), "use-ssl3", &use_ssl3, NULL);
return use_ssl3;
}
/**
* g_tls_client_connection_set_use_ssl3:
* @conn: the #GTlsClientConnection
* @use_ssl3: whether to use SSL 3.0
*
* If @use_ssl3 is %TRUE, this forces @conn to use SSL 3.0 rather than
* trying to properly negotiate the right version of TLS or SSL to use.
* This can be used when talking to servers that do not implement the
* fallbacks correctly and which will therefore fail to handshake with
* a "modern" TLS handshake attempt.
*
* Since: 2.28
*/
void
g_tls_client_connection_set_use_ssl3 (GTlsClientConnection *conn,
gboolean use_ssl3)
{
g_return_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn));
g_object_set (G_OBJECT (conn), "use-ssl3", use_ssl3, NULL);
}
/**
* g_tls_client_connection_get_accepted_cas:
* @conn: the #GTlsClientConnection
*
* Gets the list of distinguished names of the Certificate Authorities
* that the server will accept certificates from. This will be set
* during the TLS handshake if the server requests a certificate.
* Otherwise, it will be %NULL.
*
* Return value: (transfer full) (array zero-terminated=1): the list
* of CA names, which you must free (eg, with g_strfreev()).
*
* Since: 2.28
*/
char **
g_tls_client_connection_get_accepted_cas (GTlsClientConnection *conn)
{
char **accepted_cas = NULL;
g_return_val_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn), NULL);
g_object_get (G_OBJECT (conn), "accepted-cas", &accepted_cas, NULL);
return accepted_cas;
}

View File

@ -0,0 +1,72 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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.
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TLS_CLIENT_CONNECTION_H__
#define __G_TLS_CLIENT_CONNECTION_H__
#include <gio/gtlsconnection.h>
G_BEGIN_DECLS
#define G_TYPE_TLS_CLIENT_CONNECTION (g_tls_client_connection_get_type ())
#define G_TLS_CLIENT_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CLIENT_CONNECTION, GTlsClientConnection))
#define G_IS_TLS_CLIENT_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CLIENT_CONNECTION))
#define G_TLS_CLIENT_CONNECTION_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), G_TYPE_TLS_CLIENT_CONNECTION, GTlsClientConnectionInterface))
/**
* GTlsClientConnection:
*
* TLS client-side connection; the client-side implementation of a
* #GTlsConnection
*
* Since: 2.28
*/
typedef struct _GTlsClientConnectionInterface GTlsClientConnectionInterface;
struct _GTlsClientConnectionInterface
{
GTypeInterface g_iface;
};
GType g_tls_client_connection_get_type (void) G_GNUC_CONST;
GTlsClientConnection *g_tls_client_connection_new (GIOStream *base_io_stream,
GSocketConnectable *server_identity,
GError **error);
GTlsCertificateFlags g_tls_client_connection_get_validation_flags (GTlsClientConnection *conn);
void g_tls_client_connection_set_validation_flags (GTlsClientConnection *conn,
GTlsCertificateFlags flags);
GSocketConnectable *g_tls_client_connection_get_server_identity (GTlsClientConnection *conn);
void g_tls_client_connection_set_server_identity (GTlsClientConnection *conn,
GSocketConnectable *identity);
gboolean g_tls_client_connection_get_use_ssl3 (GTlsClientConnection *conn);
void g_tls_client_connection_set_use_ssl3 (GTlsClientConnection *conn,
gboolean use_ssl3);
char ** g_tls_client_connection_get_accepted_cas (GTlsClientConnection *conn);
G_END_DECLS
#endif /* __G_TLS_CLIENT_CONNECTION_H__ */

727
gio/gtlsconnection.c Normal file
View File

@ -0,0 +1,727 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 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 "glib.h"
#include "gtlsconnection.h"
#include "gcancellable.h"
#include "gioenumtypes.h"
#include "gio-marshal.h"
#include "gsocket.h"
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "gtlsclientconnection.h"
#include "glibintl.h"
/**
* SECTION:gtlsconnection
* @short_description: TLS connection type
* @include: gio/gio.h
*
* #GTlsConnection is the base TLS connection class type, which wraps
* a #GIOStream and provides TLS encryption on top of it. Its
* subclasses, #GTlsClientConnection and #GTlsServerConnection,
* implement client-side and server-side TLS, respectively.
*
* Since: 2.28
*/
/**
* GTlsConnection:
*
* Abstract base class for the backend-specific #GTlsClientConnection
* and #GTlsServerConnection types.
*
* Since: 2.28
*/
G_DEFINE_ABSTRACT_TYPE (GTlsConnection, g_tls_connection, G_TYPE_IO_STREAM)
static void g_tls_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void g_tls_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_tls_connection_finalize (GObject *object);
static gboolean g_tls_connection_certificate_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer dummy);
enum {
NEED_CERTIFICATE,
ACCEPT_CERTIFICATE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
enum {
PROP_0,
PROP_BASE_IO_STREAM,
PROP_REQUIRE_CLOSE_NOTIFY,
PROP_REHANDSHAKE_MODE,
PROP_CERTIFICATE,
PROP_PEER_CERTIFICATE
};
struct _GTlsConnectionPrivate {
GTlsCertificate *certificate, *peer_certificate;
};
static void
g_tls_connection_class_init (GTlsConnectionClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (GTlsConnectionPrivate));
gobject_class->get_property = g_tls_connection_get_property;
gobject_class->set_property = g_tls_connection_set_property;
gobject_class->finalize = g_tls_connection_finalize;
/**
* GTlsConnection:base-io-stream:
*
* The #GIOStream that the connection wraps
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_BASE_IO_STREAM,
g_param_spec_object ("base-io-stream",
P_("Base IOStream"),
P_("The GIOStream that the connection wraps"),
G_TYPE_IO_STREAM,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:require-close-notify:
*
* Whether or not proper TLS close notification is required.
* See g_tls_connection_set_require_close_notify().
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY,
g_param_spec_boolean ("require-close-notify",
P_("Require close notify"),
P_("Whether to require proper TLS close notification"),
TRUE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:rehandshake-mode:
*
* The rehandshaking mode. See
* g_tls_connection_set_rehandshake_mode().
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_REHANDSHAKE_MODE,
g_param_spec_enum ("rehandshake-mode",
P_("Rehandshake mode"),
P_("When to allow rehandshaking"),
G_TYPE_TLS_REHANDSHAKE_MODE,
G_TLS_REHANDSHAKE_SAFELY,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:certificate:
*
* The connection's certificate; see
* g_tls_connection_set_certificate().
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
g_param_spec_object ("certificate",
P_("Certificate"),
P_("The connection's certificate"),
G_TYPE_TLS_CERTIFICATE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:peer-certificate:
*
* The connection's peer's certificate, after it has been set during
* the TLS handshake.
*
* Since: 2.28
*/
g_object_class_install_property (gobject_class, PROP_PEER_CERTIFICATE,
g_param_spec_object ("peer-certificate",
P_("Peer Certificate"),
P_("The connection's peer's certificate"),
G_TYPE_TLS_CERTIFICATE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection::need-certificate:
* @conn: a #GTlsConnection
*
* Emitted during the TLS handshake if a certificate is needed and
* one has not been set via g_tls_connection_set_certificate().
*
* For server-side connections, a certificate is always needed, and
* the connection will fail if none is provided.
*
* For client-side connections, the signal will be emitted only if
* the server has requested a certificate; you can call
* g_tls_client_connection_get_accepted_cas() to get a list of
* Certificate Authorities that the server will accept certificates
* from. If you do not return a certificate (and have not provided
* one via g_tls_connection_set_certificate()) then the server may
* reject the handshake, in which case the operation will eventually
* fail with %G_TLS_ERROR_CERTIFICATE_REQUIRED.
*
* Note that if this signal is emitted as part of asynchronous I/O
* in the main thread, then you should not attempt to interact with
* the user before returning from the signal handler. If you want to
* let the user choose a certificate to return, you would have to
* return %NULL from the signal handler on the first attempt, and
* then after the connection attempt returns a
* %G_TLS_ERROR_CERTIFICATE_REQUIRED, you can interact with the
* user, create a new connection, and call
* g_tls_connection_set_certificate() on it before handshaking (or
* just connect to the signal again and return the certificate the
* next time).
*
* If you are doing I/O in another thread, you do not
* need to worry about this, and can simply block in the signal
* handler until the UI thread returns an answer.
*
* Return value: the certificate to send to the peer, or %NULL to
* send no certificate. If you return a certificate, the signal
* emission will be stopped and further handlers will not be called.
*
* Since: 2.28
*/
signals[NEED_CERTIFICATE] =
g_signal_new (I_("need-certificate"),
G_TYPE_TLS_CONNECTION,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GTlsConnectionClass, need_certificate),
g_tls_connection_certificate_accumulator, NULL,
_gio_marshal_OBJECT__VOID,
G_TYPE_TLS_CERTIFICATE, 0);
/**
* GTlsConnection::accept-certificate:
* @conn: a #GTlsConnection
* @peer_cert: the peer's #GTlsCertificate
* @errors: the problems with @peer_cert.
*
* Emitted during the TLS handshake after the peer certificate has
* been received. You can examine @peer_cert's certification path by
* calling g_tls_certificate_get_issuer() on it.
*
* For a client-side connection, @peer_cert is the server's
* certificate, and the signal will only be emitted if the
* certificate was not acceptable according to @conn's
* #GTlsClientConnection:validation_flags. If you would like the
* certificate to be accepted despite @errors, return %TRUE from the
* signal handler. Otherwise, if no handler accepts the certificate,
* the handshake will fail with %G_TLS_ERROR_BAD_CERTIFICATE.
*
* For a server-side connection, @peer_cert is the certificate
* presented by the client, if this was requested via the server's
* #GTlsServerConnection:authentication_mode. On the server side,
* the signal is always emitted when the client presents a
* certificate, and the certificate will only be accepted if a
* handler returns %TRUE.
*
* As with #GTlsConnection::need_certificate, you should not
* interact with the user during the signal emission if the signal
* was emitted as part of an asynchronous operation in the main
* thread.
*
* Return value: %TRUE to accept @peer_cert (which will also
* immediately end the signal emission). %FALSE to allow the signal
* emission to continue, which will cause the handshake to fail if
* no one else overrides it.
*
* Since: 2.28
*/
signals[ACCEPT_CERTIFICATE] =
g_signal_new (I_("accept-certificate"),
G_TYPE_TLS_CONNECTION,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GTlsConnectionClass, accept_certificate),
g_signal_accumulator_true_handled, NULL,
_gio_marshal_BOOLEAN__OBJECT_FLAGS,
G_TYPE_BOOLEAN, 2,
G_TYPE_TLS_CERTIFICATE,
G_TYPE_TLS_CERTIFICATE_FLAGS);
}
static void
g_tls_connection_init (GTlsConnection *conn)
{
conn->priv = G_TYPE_INSTANCE_GET_PRIVATE (conn, G_TYPE_TLS_CONNECTION, GTlsConnectionPrivate);
}
static void
g_tls_connection_finalize (GObject *object)
{
GTlsConnection *conn = G_TLS_CONNECTION (object);
if (conn->priv->certificate)
g_object_unref (conn->priv->certificate);
if (conn->priv->peer_certificate)
g_object_unref (conn->priv->peer_certificate);
G_OBJECT_CLASS (g_tls_connection_parent_class)->finalize (object);
}
static void
g_tls_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GTlsConnection *conn = G_TLS_CONNECTION (object);
switch (prop_id)
{
case PROP_CERTIFICATE:
g_value_set_object (value, conn->priv->certificate);
break;
case PROP_PEER_CERTIFICATE:
g_value_set_object (value, conn->priv->peer_certificate);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_tls_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GTlsConnection *conn = G_TLS_CONNECTION (object);
switch (prop_id)
{
case PROP_CERTIFICATE:
g_tls_connection_set_certificate (conn, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* g_tls_connection_set_certificate:
* @conn: a #GTlsConnection
* @certificate: the certificate to use for @conn
*
* This sets the certificate that @conn will present to its peer
* during the TLS handshake. If this is not set,
* #GTlsConnection::need-certificate will be emitted during the
* handshake if needed.
*
* Since: 2.28
*/
void
g_tls_connection_set_certificate (GTlsConnection *conn,
GTlsCertificate *certificate)
{
g_return_if_fail (G_IS_TLS_CONNECTION (conn));
g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
if (conn->priv->certificate)
g_object_unref (conn->priv->certificate);
conn->priv->certificate = certificate ? g_object_ref (certificate) : NULL;
g_object_notify (G_OBJECT (conn), "certificate");
}
/**
* g_tls_connection_get_certificate:
* @conn: a #GTlsConnection
*
* Gets @conn's certificate, as set by
* g_tls_connection_set_certificate() or returned from one of the
* signals.
*
* Return value: @conn's certificate, or %NULL
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_connection_get_certificate (GTlsConnection *conn)
{
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
return conn->priv->certificate;
}
/**
* g_tls_connection_get_peer_certificate:
* @conn: a #GTlsConnection
*
* Gets @conn's peer's certificate after it has been set during the
* handshake.
*
* Return value: @conn's peer's certificate, or %NULL
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_connection_get_peer_certificate (GTlsConnection *conn)
{
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
return conn->priv->peer_certificate;
}
/**
* g_tls_connection_set_require_close_notify:
* @conn: a #GTlsConnection
* @require_close_notify: whether or not to require close notification
*
* Sets whether or not @conn requires a proper TLS close notification
* before closing the connection. If this is %TRUE (the default), then
* calling g_io_stream_close() on @conn will send a TLS close
* notification, and likewise it will expect to receive a close
* notification before the connection is closed when reading, and will
* return a %G_TLS_ERROR_EOF error if the connection is closed without
* proper notification (since this may indicate a network error, or
* man-in-the-middle attack).
*
* In some protocols, the application will know whether or not the
* connection was closed cleanly based on application-level data
* (because the application-level data includes a length field, or is
* somehow self-delimiting); in this case, the close notify is
* redundant and sometimes omitted. (TLS 1.1 explicitly allows this;
* in TLS 1.0 it is technically an error, but often done anyway.) You
* can use g_tls_connection_set_require_close_notify() to tell @conn to
* allow an "unannounced" connection close, in which case it is up to
* the application to check that the data has been fully received.
*
* Since: 2.28
*/
void
g_tls_connection_set_require_close_notify (GTlsConnection *conn,
gboolean require_close_notify)
{
g_return_if_fail (G_IS_TLS_CONNECTION (conn));
g_object_set (G_OBJECT (conn),
"require-close-notify", require_close_notify,
NULL);
}
/**
* g_tls_connection_get_require_close_notify:
* @conn: a #GTlsConnection
*
* Tests whether or not @conn requires a proper TLS close notification
* before closing the connection. See
* g_tls_connection_set_require_close_notify() for details.
*
* Return value: %TRUE if @conn requires a proper TLS close
* notification.
*
* Since: 2.28
*/
gboolean
g_tls_connection_get_require_close_notify (GTlsConnection *conn)
{
gboolean require_close_notify;
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), TRUE);
g_object_get (G_OBJECT (conn),
"require-close-notify", &require_close_notify,
NULL);
return require_close_notify;
}
/**
* g_tls_connection_set_rehandshake_mode:
* @conn: a #GTlsConnection
* @mode: the rehandshaking mode
*
* Sets how @conn behaves with respect to rehandshaking requests.
*
* %G_TLS_REHANDSHAKE_NEVER means that it will never agree to
* rehandshake after the initial handshake is complete. (For a client,
* this means it will refuse rehandshake requests from the server, and
* for a server, this means it will close the connection with an error
* if the client attempts to rehandshake.)
*
* %G_TLS_REHANDSHAKE_SAFELY means that the connection will allow a
* rehandshake only if the other end of the connection supports the
* TLS <literal>renegotiation_info</literal> extension. This is the
* default behavior, but means that rehandshaking will not work
* against older implementations that do not support that extension.
*
* %G_TLS_REHANDSHAKE_UNSAFELY means that the connection will allow
* rehandshaking even without the
* <literal>renegotiation_info</literal> extension. On the server side
* in particular, this is not recommended, since it leaves the server
* open to certain attacks. However, this mode is necessary if you
* need to allow renegotiation with older client software.
*
* Since: 2.28
*/
void
g_tls_connection_set_rehandshake_mode (GTlsConnection *conn,
GTlsRehandshakeMode mode)
{
g_return_if_fail (G_IS_TLS_CONNECTION (conn));
g_object_set (G_OBJECT (conn),
"rehandshake-mode", mode,
NULL);
}
/**
* g_tls_connection_get_rehandshake_mode:
* @conn: a #GTlsConnection
*
* Gets @conn rehandshaking mode. See
* g_tls_connection_set_rehandshake() for details.
*
* Return value: @conn's rehandshaking mode
*
* Since: 2.28
*/
GTlsRehandshakeMode
g_tls_connection_get_rehandshake_mode (GTlsConnection *conn)
{
GTlsRehandshakeMode mode;
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_REHANDSHAKE_NEVER);
g_object_get (G_OBJECT (conn),
"rehandshake-mode", &mode,
NULL);
return mode;
}
/**
* g_tls_connection_handshake:
* @conn: a #GTlsConnection
* @cancellable: a #GCancellable, or %NULL
* @error: a #GError, or %NULL
*
* Attempts a TLS handshake on @conn.
*
* On the client side, it is never necessary to call this method;
* although the connection needs to perform a handshake after
* connecting (or after sending a "STARTTLS"-type command) and may
* need to rehandshake later if the server requests it,
* #GTlsConnection will handle this for you automatically when you try
* to send or receive data on the connection. However, you can call
* g_tls_connection_handshake() manually if you want to know for sure
* whether the initial handshake succeeded or failed (as opposed to
* just immediately trying to write to @conn's output stream, in which
* case if it fails, it may not be possible to tell if it failed
* before or after completing the handshake).
*
* Likewise, on the server side, although a handshake is necessary at
* the beginning of the communication, you do not need to call this
* function explicitly unless you want clearer error reporting.
* However, you may call g_tls_connection_handshake() later on to
* renegotiate parameters (encryption methods, etc) with the client.
*
* #GTlsConnection::accept_certificate and
* #GTlsConnection::need_certificate may be emitted during the
* handshake.
*
* Return value: success or failure
*
* Since: 2.28
*/
gboolean
g_tls_connection_handshake (GTlsConnection *conn,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), FALSE);
return G_TLS_CONNECTION_GET_CLASS (conn)->handshake (conn, cancellable, error);
}
/**
* g_tls_connection_handshake_async:
* @conn: a #GTlsConnection
* @io_priority: the <link linkend="io-priority">I/O priority</link>
* of the request.
* @cancellable: a #GCancellable, or %NULL
* @callback: callback to call when the handshake is complete
* @user_data: the data to pass to the callback function
*
* Asynchronously performs a TLS handshake on @conn. See
* g_tls_connection_handshake() for more information.
*
* Since: 2.28
*/
void
g_tls_connection_handshake_async (GTlsConnection *conn,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (G_IS_TLS_CONNECTION (conn));
return G_TLS_CONNECTION_GET_CLASS (conn)->handshake_async (conn, io_priority,
cancellable,
callback, user_data);
}
/**
* g_tls_connection_handshake_finish:
* @conn: a #GTlsConnection
* @result: a #GAsyncResult.
* @error: a #GError pointer, or %NULL
*
* Finish an asynchronous TLS handshake operation. See
* g_tls_connection_handshake() for more information.
*
* Return value: %TRUE on success, %FALSE on failure, in which
* case @error will be set.
*
* Since: 2.28
*/
gboolean
g_tls_connection_handshake_finish (GTlsConnection *conn,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), FALSE);
return G_TLS_CONNECTION_GET_CLASS (conn)->handshake_finish (conn, result, error);
}
/**
* g_tls_error_quark:
*
* Gets the TLS error quark.
*
* Return value: a #GQuark.
*
* Since: 2.28
*/
GQuark
g_tls_error_quark (void)
{
return g_quark_from_static_string ("g-tls-error-quark");
}
static gboolean
g_tls_connection_certificate_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer dummy)
{
GTlsCertificate *cert;
cert = g_value_get_object (handler_return);
if (cert)
g_value_set_object (return_accu, cert);
return cert != NULL;
}
/**
* g_tls_connection_emit_need_certificate:
* @conn: a #GTlsConnection
*
* Used by #GTlsConnection implementations to emit the
* #GTlsConnection::need-certificate signal.
*
* Returns: a new #GTlsCertificate
*
* Since: 2.28
*/
GTlsCertificate *
g_tls_connection_emit_need_certificate (GTlsConnection *conn)
{
GTlsCertificate *cert = NULL;
g_signal_emit (conn, signals[NEED_CERTIFICATE], 0,
&cert);
return cert;
}
/**
* g_tls_connection_emit_accept_certificate:
* @conn: a #GTlsConnection
* @peer_cert: the peer's #GTlsCertificate
* @errors: the problems with @peer_cert
*
* Used by #GTlsConnection implementations to emit the
* #GTlsConnection::accept-certificate signal.
*
* Return value: %TRUE if one of the signal handlers has returned
* %TRUE to accept @peer_cert
*
* Since: 2.28
*/
gboolean
g_tls_connection_emit_accept_certificate (GTlsConnection *conn,
GTlsCertificate *peer_cert,
GTlsCertificateFlags errors)
{
gboolean accept = FALSE;
g_signal_emit (conn, signals[ACCEPT_CERTIFICATE], 0,
peer_cert, errors, &accept);
return accept;
}
/**
* g_tls_connection_set_peer_certificate:
* @conn: a #GTlsConnection
* @certificate: the peer certificate
*
* Used by #GTlsConnection implementations to set the connection's
* peer certificate.
*
* Since: 2.28
*/
void
g_tls_connection_set_peer_certificate (GTlsConnection *conn,
GTlsCertificate *certificate)
{
if (conn->priv->peer_certificate)
g_object_unref (conn->priv->peer_certificate);
conn->priv->peer_certificate = certificate ? g_object_ref (certificate) : NULL;
g_object_notify (G_OBJECT (conn), "peer-certificate");
}

137
gio/gtlsconnection.h Normal file
View File

@ -0,0 +1,137 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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.
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TLS_CONNECTION_H__
#define __G_TLS_CONNECTION_H__
#include <gio/giostream.h>
G_BEGIN_DECLS
#define G_TYPE_TLS_CONNECTION (g_tls_connection_get_type ())
#define G_TLS_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CONNECTION, GTlsConnection))
#define G_TLS_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_CONNECTION, GTlsConnectionClass))
#define G_IS_TLS_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CONNECTION))
#define G_IS_TLS_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_CONNECTION))
#define G_TLS_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_CONNECTION, GTlsConnectionClass))
/**
* GTlsConnection:
*
* TLS connection. This is an abstract type that will be subclassed by
* a TLS-library-specific subtype.
*
* Since: 2.28
*/
typedef struct _GTlsConnectionClass GTlsConnectionClass;
typedef struct _GTlsConnectionPrivate GTlsConnectionPrivate;
struct _GTlsConnection {
GIOStream parent_instance;
GTlsConnectionPrivate *priv;
};
struct _GTlsConnectionClass
{
GIOStreamClass parent_class;
/* signals */
GTlsCertificate * ( *need_certificate) (GTlsConnection *connection);
gboolean ( *accept_certificate) (GTlsConnection *connection,
GTlsCertificate *peer_cert,
GTlsCertificateFlags errors);
/* methods */
gboolean ( *handshake ) (GTlsConnection *conn,
GCancellable *cancellable,
GError **error);
void ( *handshake_async ) (GTlsConnection *conn,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ( *handshake_finish ) (GTlsConnection *conn,
GAsyncResult *result,
GError **error);
/*< private >*/
/* Padding for future expansion */
gpointer padding[8];
};
GType g_tls_connection_get_type (void) G_GNUC_CONST;
void g_tls_connection_set_certificate (GTlsConnection *conn,
GTlsCertificate *certificate);
GTlsCertificate *g_tls_connection_get_certificate (GTlsConnection *conn);
GTlsCertificate *g_tls_connection_get_peer_certificate (GTlsConnection *conn);
void g_tls_connection_set_require_close_notify (GTlsConnection *conn,
gboolean require_close_notify);
gboolean g_tls_connection_get_require_close_notify (GTlsConnection *conn);
void g_tls_connection_set_rehandshake_mode (GTlsConnection *conn,
GTlsRehandshakeMode mode);
GTlsRehandshakeMode g_tls_connection_get_rehandshake_mode (GTlsConnection *conn);
gboolean g_tls_connection_handshake (GTlsConnection *conn,
GCancellable *cancellable,
GError **error);
void g_tls_connection_handshake_async (GTlsConnection *conn,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_tls_connection_handshake_finish (GTlsConnection *conn,
GAsyncResult *result,
GError **error);
/**
* G_TLS_ERROR:
*
* Error domain for TLS. Errors in this domain will be from the
* #GTlsError enumeration. See #GError for more information on error
* domains.
*/
#define G_TLS_ERROR (g_tls_error_quark ())
GQuark g_tls_error_quark (void);
/*< protected >*/
GTlsCertificate *g_tls_connection_emit_need_certificate (GTlsConnection *conn);
gboolean g_tls_connection_emit_accept_certificate (GTlsConnection *conn,
GTlsCertificate *peer_cert,
GTlsCertificateFlags errors);
void g_tls_connection_set_peer_certificate (GTlsConnection *conn,
GTlsCertificate *certificate);
G_END_DECLS
#endif /* __G_TLS_CONNECTION_H__ */

View File

@ -0,0 +1,96 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2010 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 "glib.h"
#include "gtlsserverconnection.h"
#include "ginitable.h"
#include "gio-marshal.h"
#include "gioenumtypes.h"
#include "gsocket.h"
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "glibintl.h"
/**
* SECTION:gtlsserverconnection
* @short_description: TLS server-side connection
* @include: gio/gio.h
*
* #GTlsServerConnection is the server-side subclass of #GTlsConnection,
* representing a server-side TLS connection.
*
* Since: 2.28
*/
G_DEFINE_INTERFACE (GTlsServerConnection, g_tls_server_connection, G_TYPE_TLS_CONNECTION)
static void
g_tls_server_connection_default_init (GTlsServerConnectionInterface *iface)
{
/**
* GTlsServerConnection:authentication-mode:
*
* The #GTlsAuthenticationMode for the server. This can be changed
* before calling g_tls_connection_handshake() if you want to
* rehandshake with a different mode from the initial handshake.
*
* Since: 2.28
*/
g_object_interface_install_property (iface,
g_param_spec_enum ("authentication-mode",
P_("Authentication Mode"),
P_("The client authentication mode"),
G_TYPE_TLS_AUTHENTICATION_MODE,
G_TLS_AUTHENTICATION_NONE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
/**
* g_tls_server_connection_new:
* @base_io_stream: the #GIOStream to wrap
* @certificate: (allow-none): the default server certificate, or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Creates a new #GTlsServerConnection wrapping @base_io_stream (which
* must have pollable input and output streams).
*
* Return value: the new #GTlsServerConnection, or %NULL on error
*
* Since: 2.28
*/
GTlsServerConnection *
g_tls_server_connection_new (GIOStream *base_io_stream,
GTlsCertificate *certificate,
GError **error)
{
GObject *conn;
GTlsBackend *backend;
backend = g_tls_backend_get_default ();
conn = g_initable_new (g_tls_backend_get_server_connection_type (backend),
NULL, error,
"base-io-stream", base_io_stream,
"certificate", certificate,
NULL);
return G_TLS_SERVER_CONNECTION (conn);
}

View File

@ -0,0 +1,61 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2010 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.
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TLS_SERVER_CONNECTION_H__
#define __G_TLS_SERVER_CONNECTION_H__
#include <gio/gtlsconnection.h>
G_BEGIN_DECLS
#define G_TYPE_TLS_SERVER_CONNECTION (g_tls_server_connection_get_type ())
#define G_TLS_SERVER_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_SERVER_CONNECTION, GTlsServerConnection))
#define G_IS_TLS_SERVER_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_SERVER_CONNECTION))
#define G_TLS_SERVER_CONNECTION_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), G_TYPE_TLS_SERVER_CONNECTION, GTlsServerConnectionInterface))
/**
* GTlsServerConnection:
*
* TLS server-side connection. This is the server-side implementation
* of a #GTlsConnection.
*
* Since: 2.28
*/
typedef struct _GTlsServerConnectionInterface GTlsServerConnectionInterface;
struct _GTlsServerConnectionInterface
{
GTypeInterface g_iface;
};
GType g_tls_server_connection_get_type (void) G_GNUC_CONST;
GTlsServerConnection *g_tls_server_connection_new (GIOStream *base_io_stream,
GTlsCertificate *certificate,
GError **error);
G_END_DECLS
#endif /* __G_TLS_SERVER_CONNECTION_H__ */

View File

@ -60,7 +60,12 @@ enum {
PROP_CLOSE_FD
};
G_DEFINE_TYPE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM);
static void g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
g_unix_input_stream_pollable_iface_init)
);
struct _GUnixInputStreamPrivate {
int fd;
@ -111,6 +116,9 @@ static gboolean g_unix_input_stream_close_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
static gboolean g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream);
static GSource *g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
GCancellable *cancellable);
static void
g_unix_input_stream_finalize (GObject *object)
@ -174,6 +182,13 @@ g_unix_input_stream_class_init (GUnixInputStreamClass *klass)
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}
static void
g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
{
iface->is_readable = g_unix_input_stream_pollable_is_readable;
iface->create_source = g_unix_input_stream_pollable_create_source;
}
static void
g_unix_input_stream_set_property (GObject *object,
guint prop_id,
@ -422,9 +437,9 @@ typedef struct {
} ReadAsyncData;
static gboolean
read_async_cb (ReadAsyncData *data,
read_async_cb (int fd,
GIOCondition condition,
int fd)
ReadAsyncData *data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
@ -637,3 +652,37 @@ g_unix_input_stream_close_finish (GInputStream *stream,
/* Failures handled in generic close_finish code */
return TRUE;
}
static gboolean
g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream)
{
GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
GPollFD poll_fd;
gint result;
poll_fd.fd = unix_stream->priv->fd;
poll_fd.events = G_IO_IN;
do
result = g_poll (&poll_fd, 1, 0);
while (result == -1 && errno == EINTR);
return poll_fd.revents != 0;
}
static GSource *
g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
GCancellable *cancellable)
{
GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
GSource *inner_source, *pollable_source;
pollable_source = g_pollable_source_new (G_OBJECT (stream));
inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_IN, cancellable);
g_source_set_dummy_callback (inner_source);
g_source_add_child_source (pollable_source, inner_source);
g_source_unref (inner_source);
return pollable_source;
}

View File

@ -60,8 +60,12 @@ enum {
PROP_CLOSE_FD
};
G_DEFINE_TYPE (GUnixOutputStream, g_unix_output_stream, G_TYPE_OUTPUT_STREAM);
static void g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GUnixOutputStream, g_unix_output_stream, G_TYPE_OUTPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM,
g_unix_output_stream_pollable_iface_init)
);
struct _GUnixOutputStreamPrivate {
int fd;
@ -103,6 +107,9 @@ static gboolean g_unix_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static gboolean g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream);
static GSource *g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
GCancellable *cancellable);
static void
g_unix_output_stream_finalize (GObject *object)
@ -160,6 +167,13 @@ g_unix_output_stream_class_init (GUnixOutputStreamClass *klass)
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}
static void
g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface)
{
iface->is_writable = g_unix_output_stream_pollable_is_writable;
iface->create_source = g_unix_output_stream_pollable_create_source;
}
static void
g_unix_output_stream_set_property (GObject *object,
guint prop_id,
@ -409,9 +423,9 @@ typedef struct {
} WriteAsyncData;
static gboolean
write_async_cb (WriteAsyncData *data,
write_async_cb (int fd,
GIOCondition condition,
int fd)
WriteAsyncData *data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
@ -593,3 +607,37 @@ g_unix_output_stream_close_finish (GOutputStream *stream,
/* Failures handled in generic close_finish code */
return TRUE;
}
static gboolean
g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream)
{
GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
GPollFD poll_fd;
gint result;
poll_fd.fd = unix_stream->priv->fd;
poll_fd.events = G_IO_OUT;
do
result = g_poll (&poll_fd, 1, 0);
while (result == -1 && errno == EINTR);
return poll_fd.revents != 0;
}
static GSource *
g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
GCancellable *cancellable)
{
GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
GSource *inner_source, *pollable_source;
pollable_source = g_pollable_source_new (G_OBJECT (stream));
inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_OUT, cancellable);
g_source_set_dummy_callback (inner_source);
g_source_add_child_source (pollable_source, inner_source);
g_source_unref (inner_source);
return pollable_source;
}

View File

@ -587,6 +587,28 @@ g_app_info_get_all_for_type (const char *content_type)
return g_list_reverse (infos);
}
GList *
g_app_info_get_recommended_for_type (const char *content_type)
{
/* FIXME: this should generate a list of applications that are registered
* as direct handlers for the given content type, without using MIME subclassing.
* See g_app_info_get_recommended_for_type() in gdesktopappinfo.c for a reference
* UNIX implementation.
*/
return g_app_info_get_all_for_type (content_type);
}
GList *
g_app_info_get_fallback_for_type (const char *content_type)
{
/* FIXME: this should generate a list of applications that are registered
* as handlers for a superclass of the given content type, but are not
* direct handlers for the content type itself. See g_app_info_get_fallback_for_type()
* in gdesktopappinfo.c for a reference UNIX implementation.
*/
return g_app_info_get_all_for_type (content_type);
}
GAppInfo *
g_app_info_get_default_for_type (const char *content_type,
gboolean must_support_uris)

View File

@ -60,6 +60,7 @@ memory-input-stream
memory-output-stream
network-address
org.gtk.test.enums.xml
pollable
proxy
readwrite
resolver

View File

@ -43,6 +43,7 @@ TEST_PROGS += \
network-address \
gdbus-message \
socket \
pollable \
$(NULL)
if OS_UNIX
@ -204,6 +205,9 @@ network_address_LDADD = $(progs_ldadd)
socket_SOURCE = socket.c
socket_LDADD = $(progs_ldadd)
pollable_SOURCE = pollable.c
pollable_LDADD = $(progs_ldadd)
contexts_SOURCES = contexts.c
contexts_LDADD = $(progs_ldadd) \
$(top_builddir)/gthread/libgthread-2.0.la
@ -370,6 +374,7 @@ schema_tests = \
schema-tests/extending.gschema.xml \
schema-tests/from-docs.gschema.xml \
schema-tests/incomplete-list.gschema.xml \
schema-tests/inherit-gettext-domain.gschema.xml \
schema-tests/invalid-path.gschema.xml \
schema-tests/key-in-list-indirect.gschema.xml \
schema-tests/key-in-list.gschema.xml \

View File

@ -174,6 +174,77 @@ test_default (void)
g_object_unref (info2);
}
static void
test_fallback (void)
{
GAppInfo *info1, *info2, *app;
GList *apps, *recomm, *fallback, *list, *l, *m;
GError *error = NULL;
gint old_length;
info1 = create_app_info ("Test1");
info2 = create_app_info ("Test2");
g_assert (g_content_type_is_a ("text/x-python", "text/plain"));
apps = g_app_info_get_all_for_type ("text/x-python");
old_length = g_list_length (apps);
g_list_free_full (apps, g_object_unref);
g_app_info_set_as_default_for_type (info1, "text/x-python", &error);
g_assert (error == NULL);
g_app_info_set_as_default_for_type (info2, "text/plain", &error);
g_assert (error == NULL);
/* check that both apps are registered */
apps = g_app_info_get_all_for_type ("text/x-python");
g_assert (g_list_length (apps) == old_length + 2);
/* check the ordering */
app = g_list_nth_data (apps, 0);
g_assert (g_app_info_equal (info1, app));
app = g_list_nth_data (apps, 1);
g_assert (g_app_info_equal (info2, app));
/* check that Test1 is the first recommended app */
recomm = g_app_info_get_recommended_for_type ("text/x-python");
g_assert (recomm != NULL);
app = g_list_nth_data (recomm, 0);
g_assert (g_app_info_equal (info1, app));
/* and that Test2 is the first fallback */
fallback = g_app_info_get_fallback_for_type ("text/x-python");
g_assert (fallback != NULL);
app = g_list_nth_data (fallback, 0);
g_assert (g_app_info_equal (info2, app));
/* check that recomm + fallback = all applications */
list = g_list_concat (g_list_copy (recomm), g_list_copy (fallback));
g_assert (g_list_length (list) == g_list_length (apps));
for (l = list, m = apps; l != NULL && m != NULL; l = l->next, m = m->next)
{
g_assert (g_app_info_equal (l->data, m->data));
}
g_list_free (list);
g_list_free_full (apps, g_object_unref);
g_list_free_full (recomm, g_object_unref);
g_list_free_full (fallback, g_object_unref);
g_app_info_reset_type_associations ("text/x-python");
g_app_info_reset_type_associations ("text/plain");
g_app_info_delete (info1);
g_app_info_delete (info2);
g_object_unref (info1);
g_object_unref (info2);
}
static void
cleanup_dir_recurse (GFile *parent, GFile *root)
{
@ -250,6 +321,7 @@ main (int argc,
g_test_add_func ("/desktop-app-info/delete", test_delete);
g_test_add_func ("/desktop-app-info/default", test_default);
g_test_add_func ("/desktop-app-info/fallback", test_fallback);
result = g_test_run ();

View File

@ -258,7 +258,7 @@ test_themed_icon (void)
g_assert_cmpstr (names[0], ==, "first");
g_assert_cmpstr (names[1], ==, "testicon");
g_assert_cmpstr (names[2], ==, "last");
g_assert_cmpuint (g_icon_hash (icon1), ==, 3193088045U);
g_assert_cmpuint (g_icon_hash (icon1), ==, 2400773466U);
icon2 = g_themed_icon_new_from_names ((gchar**)names2, -1);
g_assert (g_icon_equal (icon1, icon2));
@ -299,11 +299,11 @@ test_emblemed_icon (void)
emblem = emblems->data;
g_assert (g_emblem_get_icon (emblem) == icon2);
g_assert (g_emblem_get_origin (emblem) == G_EMBLEM_ORIGIN_UNKNOWN);
g_assert (g_emblem_get_origin (emblem) == G_EMBLEM_ORIGIN_TAG);
emblem = emblems->next->data;
g_assert (g_emblem_get_icon (emblem) == icon2);
g_assert (g_emblem_get_origin (emblem) == G_EMBLEM_ORIGIN_TAG);
g_assert (g_emblem_get_origin (emblem) == G_EMBLEM_ORIGIN_UNKNOWN);
g_object_unref (icon1);
g_object_unref (icon2);

View File

@ -46,7 +46,7 @@ static const SchemaTest tests[] = {
{ "no-default", NULL, "*<default> is required in <key>*" },
{ "missing-quotes", NULL, "*unknown keyword*" },
{ "incomplete-list", NULL, "*to follow array element*" },
{ "wrong-category", NULL, "*attribute 'l10n' invalid*" },
{ "wrong-category", NULL, "*unsupported l10n category*" },
{ "bad-type", NULL, "*invalid GVariant type string*" },
{ "overflow", NULL, "*out of range*" },
{ "range-wrong-type", NULL, "*<range> not allowed for keys of type*" },
@ -117,9 +117,11 @@ static const SchemaTest tests[] = {
{ "flags-bad-default", NULL, "*<default> * not in the specified flags type*" },
{ "flags-more-than-one-bit", NULL, "*flags values must have at most 1 bit set*" },
{ "flags-with-enum-attr", NULL, "*<enum id='flags'> not (yet) defined*" },
{ "flags-with-enum-tag", NULL, "*<flags id='flags'> not (yet) defined*" }
{ "flags-with-enum-tag", NULL, "*<flags id='flags'> not (yet) defined*" },
{ "inherit-gettext-domain", NULL, NULL }
};
int
main (int argc, char *argv[])
{

240
gio/tests/pollable.c Normal file
View File

@ -0,0 +1,240 @@
/* GLib testing framework examples and tests
*
* Copyright (C) 2010 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 <gio/gio.h>
#ifdef G_OS_UNIX
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#endif
GMainLoop *loop;
GPollableInputStream *in;
GOutputStream *out;
static gboolean
poll_source_callback (GPollableInputStream *in,
gpointer user_data)
{
GError *error = NULL;
char buf[2];
gssize nread;
gboolean *success = user_data;
nread = g_pollable_input_stream_read_nonblocking (in, buf, 2, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (nread, ==, 2);
g_assert_cmpstr (buf, ==, "x");
*success = TRUE;
return FALSE;
}
static gboolean
check_source_readability_callback (gpointer user_data)
{
gboolean expected = GPOINTER_TO_INT (user_data);
gboolean readable;
readable = g_pollable_input_stream_is_readable (in);
g_assert_cmpint (readable, ==, expected);
return FALSE;
}
static gboolean
write_callback (gpointer user_data)
{
char *buf = "x";
gssize nwrote;
GError *error = NULL;
nwrote = g_output_stream_write (out, buf, 2, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (nwrote, ==, 2);
check_source_readability_callback (GINT_TO_POINTER (TRUE));
return FALSE;
}
static gboolean
check_source_and_quit_callback (gpointer user_data)
{
check_source_readability_callback (user_data);
g_main_loop_quit (loop);
return FALSE;
}
static void
test_streams (void)
{
gboolean readable;
GError *error = NULL;
char buf[1];
gssize nread;
GSource *poll_source;
gboolean success = FALSE;
readable = g_pollable_input_stream_is_readable (in);
g_assert (!readable);
nread = g_pollable_input_stream_read_nonblocking (in, buf, 1, NULL, &error);
g_assert_cmpint (nread, ==, -1);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
g_clear_error (&error);
/* Create 4 sources, in decreasing order of priority:
* 1. poll source on @in
* 2. idle source that checks if @in is readable once
* (it won't be) and then removes itself
* 3. idle source that writes a byte to @out, checks that
* @in is now readable, and removes itself
* 4. idle source that checks if @in is readable once
* (it won't be, since the poll source will fire before
* this one does) and then quits the loop.
*
* If the poll source triggers before it should, then it will get a
* %G_IO_ERROR_WOULD_BLOCK, and if check() fails in either
* direction, we will catch it at some point.
*/
poll_source = g_pollable_input_stream_create_source (in, NULL);
g_source_set_priority (poll_source, 1);
g_source_set_callback (poll_source, (GSourceFunc) poll_source_callback, &success, NULL);
g_source_attach (poll_source, NULL);
g_source_unref (poll_source);
g_idle_add_full (2, check_source_readability_callback, GINT_TO_POINTER (FALSE), NULL);
g_idle_add_full (3, write_callback, NULL, NULL);
g_idle_add_full (4, check_source_and_quit_callback, GINT_TO_POINTER (FALSE), NULL);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_assert_cmpint (success, ==, TRUE);
}
#ifdef G_OS_UNIX
static void
test_pollable_unix (void)
{
int pipefds[2], status;
status = pipe (pipefds);
g_assert_cmpint (status, ==, 0);
in = G_POLLABLE_INPUT_STREAM (g_unix_input_stream_new (pipefds[0], TRUE));
out = g_unix_output_stream_new (pipefds[1], TRUE);
test_streams ();
g_object_unref (in);
g_object_unref (out);
}
#endif
static void
client_connected (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSocketClient *client = G_SOCKET_CLIENT (source);
GSocketConnection **conn = user_data;
GError *error = NULL;
*conn = g_socket_client_connect_finish (client, result, &error);
g_assert_no_error (error);
}
static void
server_connected (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSocketListener *listener = G_SOCKET_LISTENER (source);
GSocketConnection **conn = user_data;
GError *error = NULL;
*conn = g_socket_listener_accept_finish (listener, result, NULL, &error);
g_assert_no_error (error);
}
static void
test_pollable_socket (void)
{
GInetAddress *iaddr;
GSocketAddress *saddr, *effective_address;
GSocketListener *listener;
GSocketClient *client;
GError *error = NULL;
GSocketConnection *client_conn = NULL, *server_conn = NULL;
iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
saddr = g_inet_socket_address_new (iaddr, 0);
g_object_unref (iaddr);
listener = g_socket_listener_new ();
g_socket_listener_add_address (listener, saddr,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP,
NULL,
&effective_address,
&error);
g_assert_no_error (error);
g_object_unref (saddr);
client = g_socket_client_new ();
g_socket_client_connect_async (client,
G_SOCKET_CONNECTABLE (effective_address),
NULL, client_connected, &client_conn);
g_socket_listener_accept_async (listener, NULL,
server_connected, &server_conn);
while (!client_conn || !server_conn)
g_main_context_iteration (NULL, TRUE);
in = G_POLLABLE_INPUT_STREAM (g_io_stream_get_input_stream (G_IO_STREAM (client_conn)));
out = g_io_stream_get_output_stream (G_IO_STREAM (server_conn));
test_streams ();
g_object_unref (client_conn);
g_object_unref (server_conn);
g_object_unref (client);
g_object_unref (listener);
}
int
main (int argc,
char *argv[])
{
g_type_init ();
g_test_init (&argc, &argv, NULL);
#ifdef G_OS_UNIX
g_test_add_func ("/pollable/unix", test_pollable_unix);
#endif
g_test_add_func ("/pollable/socket", test_pollable_socket);
return g_test_run();
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="foo">
<schema id="bar">
<key name="baz" type="s">
<default l10n="messages" context="foobar">'value'</default>
</key>
</schema>
</schemalist>

View File

@ -1,7 +1,7 @@
<schemalist>
<schema id="wrong-category" path="/tests/" gettext-domain="test">
<key name="test" type="s" l10n="not-a-category">
<default>'foo'</default>
<key name="test" type="s">
<default l10n="not-a-category">'foo'</default>
</key>
</schema>
</schemalist>

View File

@ -5,17 +5,15 @@
#include <stdio.h>
#include <string.h>
#include "socket-common.c"
GMainLoop *loop;
gboolean verbose = FALSE;
gboolean non_blocking = FALSE;
gboolean use_udp = FALSE;
gboolean use_source = FALSE;
int cancel_timeout = 0;
int read_timeout = 0;
gboolean unix_socket = FALSE;
gboolean tls = FALSE;
static GOptionEntry cmd_entries[] = {
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
@ -26,70 +24,39 @@ static GOptionEntry cmd_entries[] = {
"Be verbose", NULL},
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
"Enable non-blocking i/o", NULL},
{"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
"Use GSource to wait for non-blocking i/o", NULL},
#ifdef G_OS_UNIX
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
"Use a unix socket instead of IP", NULL},
#endif
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
"Time out reads after the specified number of seconds", NULL},
{"tls", 'T', 0, G_OPTION_ARG_NONE, &tls,
"Use TLS (SSL)", NULL},
{NULL}
};
#include "socket-common.c"
static gboolean
source_ready (gpointer data,
GIOCondition condition)
accept_certificate (GTlsClientConnection *conn, GTlsCertificate *cert,
GTlsCertificateFlags errors, gpointer user_data)
{
g_main_loop_quit (loop);
return FALSE;
}
g_print ("Certificate would have been rejected ( ");
if (errors & G_TLS_CERTIFICATE_UNKNOWN_CA)
g_print ("unknown-ca ");
if (errors & G_TLS_CERTIFICATE_BAD_IDENTITY)
g_print ("bad-identity ");
if (errors & G_TLS_CERTIFICATE_NOT_ACTIVATED)
g_print ("not-activated ");
if (errors & G_TLS_CERTIFICATE_EXPIRED)
g_print ("expired ");
if (errors & G_TLS_CERTIFICATE_REVOKED)
g_print ("revoked ");
if (errors & G_TLS_CERTIFICATE_INSECURE)
g_print ("insecure ");
g_print (") but accepting anyway.\n");
static void
ensure_condition (GSocket *socket,
const char *where,
GCancellable *cancellable,
GIOCondition condition)
{
GError *error = NULL;
GSource *source;
if (!non_blocking)
return;
if (use_source)
{
source = g_socket_create_source (socket,
condition,
cancellable);
g_source_set_callback (source,
(GSourceFunc) source_ready,
NULL, NULL);
g_source_attach (source, NULL);
g_source_unref (source);
g_main_loop_run (loop);
}
else
{
if (!g_socket_condition_wait (socket, condition, cancellable, &error))
{
g_printerr ("condition wait error for %s: %s\n",
where,
error->message);
exit (1);
}
}
}
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;
return TRUE;
}
int
@ -106,6 +73,9 @@ main (int argc,
GCancellable *cancellable;
GSocketAddressEnumerator *enumerator;
GSocketConnectable *connectable;
GIOStream *connection;
GInputStream *istream;
GOutputStream *ostream;
g_thread_init (NULL);
@ -125,6 +95,12 @@ main (int argc,
return 1;
}
if (use_udp && tls)
{
g_printerr ("DTLS (TLS over UDP) is not supported");
return 1;
}
if (cancel_timeout)
{
cancellable = g_cancellable_new ();
@ -201,15 +177,10 @@ main (int argc,
g_object_unref (address);
}
g_object_unref (enumerator);
g_object_unref (connectable);
g_print ("Connected to %s\n",
socket_address_to_string (address));
/* TODO: Test non-blocking connect */
if (non_blocking)
g_socket_set_blocking (socket, FALSE);
src_address = g_socket_get_local_address (socket, &error);
if (!src_address)
{
@ -221,6 +192,49 @@ main (int argc,
socket_address_to_string (src_address));
g_object_unref (src_address);
if (use_udp)
connection = NULL;
else
connection = G_IO_STREAM (g_socket_connection_factory_create_connection (socket));
if (tls)
{
GTlsClientConnection *tls_conn;
tls_conn = g_tls_client_connection_new (connection, connectable, &error);
if (!tls_conn)
{
g_printerr ("Could not create TLS connection: %s\n",
error->message);
return 1;
}
g_signal_connect (tls_conn, "accept-certificate",
G_CALLBACK (accept_certificate), NULL);
if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
cancellable, &error))
{
g_printerr ("Error during TLS handshake: %s\n",
error->message);
return 1;
}
g_object_unref (connection);
connection = G_IO_STREAM (tls_conn);
}
g_object_unref (connectable);
if (connection)
{
istream = g_io_stream_get_input_stream (connection);
ostream = g_io_stream_get_output_stream (connection);
}
/* TODO: Test non-blocking connect/handshake */
if (non_blocking)
g_socket_set_blocking (socket, FALSE);
while (TRUE)
{
gchar buffer[4096];
@ -233,14 +247,20 @@ main (int argc,
to_send = strlen (buffer);
while (to_send > 0)
{
ensure_condition (socket, "send", cancellable, G_IO_OUT);
if (use_udp)
size = g_socket_send_to (socket, address,
buffer, to_send,
cancellable, &error);
{
ensure_socket_condition (socket, G_IO_OUT, cancellable);
size = g_socket_send_to (socket, address,
buffer, to_send,
cancellable, &error);
}
else
size = g_socket_send (socket, buffer, to_send,
cancellable, &error);
{
ensure_connection_condition (connection, G_IO_OUT, cancellable);
size = g_output_stream_write (ostream,
buffer, to_send,
cancellable, &error);
}
if (size < 0)
{
@ -272,14 +292,20 @@ main (int argc,
to_send -= size;
}
ensure_condition (socket, "receive", cancellable, G_IO_IN);
if (use_udp)
size = g_socket_receive_from (socket, &src_address,
{
ensure_socket_condition (socket, G_IO_IN, cancellable);
size = g_socket_receive_from (socket, &src_address,
buffer, sizeof buffer,
cancellable, &error);
}
else
{
ensure_connection_condition (connection, G_IO_IN, cancellable);
size = g_input_stream_read (istream,
buffer, sizeof buffer,
cancellable, &error);
else
size = g_socket_receive (socket, buffer, sizeof buffer,
cancellable, &error);
}
if (size < 0)
{
@ -306,15 +332,28 @@ main (int argc,
g_print ("closing socket\n");
if (!g_socket_close (socket, &error))
if (connection)
{
g_printerr ("Error closing master socket: %s\n",
error->message);
return 1;
if (!g_io_stream_close (connection, cancellable, &error))
{
g_printerr ("Error closing connection: %s\n",
error->message);
return 1;
}
g_object_unref (connection);
}
else
{
if (!g_socket_close (socket, &error))
{
g_printerr ("Error closing master socket: %s\n",
error->message);
return 1;
}
}
g_object_unref (G_OBJECT (socket));
g_object_unref (G_OBJECT (address));
g_object_unref (socket);
g_object_unref (address);
return 0;
}

View File

@ -58,3 +58,64 @@ socket_address_from_string (const char *name)
#endif
return NULL;
}
static gboolean
source_ready (GPollableInputStream *stream,
gpointer data)
{
g_main_loop_quit (loop);
return FALSE;
}
static void
ensure_socket_condition (GSocket *socket,
GIOCondition condition,
GCancellable *cancellable)
{
GSource *source;
if (!non_blocking)
return;
source = g_socket_create_source (socket, condition, cancellable);
g_source_set_callback (source,
(GSourceFunc) source_ready,
NULL, NULL);
g_source_attach (source, NULL);
g_source_unref (source);
g_main_loop_run (loop);
}
static void
ensure_connection_condition (GIOStream *stream,
GIOCondition condition,
GCancellable *cancellable)
{
GSource *source;
if (!non_blocking)
return;
if (condition & G_IO_IN)
source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (g_io_stream_get_input_stream (stream)), cancellable);
else
source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (g_io_stream_get_output_stream (stream)), cancellable);
g_source_set_callback (source,
(GSourceFunc) source_ready,
NULL, NULL);
g_source_attach (source, NULL);
g_source_unref (source);
g_main_loop_run (loop);
}
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;
}

View File

@ -4,8 +4,6 @@
#include <stdlib.h>
#include <string.h>
#include "socket-common.c"
GMainLoop *loop;
int port = 7777;
@ -13,11 +11,11 @@ gboolean verbose = FALSE;
gboolean dont_reuse_address = FALSE;
gboolean non_blocking = FALSE;
gboolean use_udp = FALSE;
gboolean use_source = FALSE;
int cancel_timeout = 0;
int read_timeout = 0;
int delay = 0;
gboolean unix_socket = FALSE;
const char *tls_cert_file = NULL;
static GOptionEntry cmd_entries[] = {
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
@ -32,8 +30,6 @@ static GOptionEntry cmd_entries[] = {
"Don't SOADDRREUSE", NULL},
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
"Enable non-blocking i/o", NULL},
{"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
"Use GSource to wait for non-blocking i/o", NULL},
#ifdef G_OS_UNIX
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
"Use a unix socket instead of IP", NULL},
@ -42,63 +38,12 @@ static GOptionEntry cmd_entries[] = {
"Delay responses by the specified number of seconds", NULL},
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
"Time out reads after the specified number of seconds", NULL},
{"tls", 'T', 0, G_OPTION_ARG_STRING, &tls_cert_file,
"Use TLS (SSL) with indicated server certificate", "CERTFILE"},
{NULL}
};
static gboolean
source_ready (gpointer data,
GIOCondition condition)
{
g_main_loop_quit (loop);
return FALSE;
}
static void
ensure_condition (GSocket *socket,
const char *where,
GCancellable *cancellable,
GIOCondition condition)
{
GError *error = NULL;
GSource *source;
if (!non_blocking)
return;
if (use_source)
{
source = g_socket_create_source (socket,
condition,
cancellable);
g_source_set_callback (source,
(GSourceFunc) source_ready,
NULL, NULL);
g_source_attach (source, NULL);
g_source_unref (source);
g_main_loop_run (loop);
}
else
{
if (!g_socket_condition_wait (socket, condition, cancellable, &error))
{
g_printerr ("condition wait error for %s: %s\n",
where,
error->message);
exit (1);
}
}
}
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;
}
#include "socket-common.c"
int
main (int argc,
@ -113,6 +58,10 @@ main (int argc,
GOptionContext *context;
GCancellable *cancellable;
char *display_addr;
GTlsCertificate *tlscert = NULL;
GIOStream *connection;
GInputStream *istream;
GOutputStream *ostream;
g_thread_init (NULL);
@ -142,6 +91,23 @@ main (int argc,
cancellable = NULL;
}
if (tls_cert_file)
{
if (use_udp)
{
g_printerr ("DTLS (TLS over UDP) is not supported");
return 1;
}
tlscert = g_tls_certificate_new_from_file (tls_cert_file, &error);
if (!tlscert)
{
g_printerr ("Could not read server certificate '%s': %s\n",
tls_cert_file, error->message);
return 1;
}
}
loop = g_main_loop_new (NULL, FALSE);
if (use_udp)
@ -205,7 +171,7 @@ main (int argc,
g_print ("listening on %s...\n", display_addr);
g_free (display_addr);
ensure_condition (socket, "accept", cancellable, G_IO_IN);
ensure_socket_condition (socket, G_IO_IN, cancellable);
new_socket = g_socket_accept (socket, cancellable, &error);
if (!new_socket)
{
@ -233,13 +199,45 @@ main (int argc,
g_object_unref (address);
recv_socket = new_socket;
connection = G_IO_STREAM (g_socket_connection_factory_create_connection (recv_socket));
g_object_unref (new_socket);
}
else
{
recv_socket = socket;
new_socket = NULL;
connection = NULL;
}
if (tlscert)
{
GTlsServerConnection *tls_conn;
tls_conn = g_tls_server_connection_new (connection, tlscert, &error);
if (!tls_conn)
{
g_printerr ("Could not create TLS connection: %s\n",
error->message);
return 1;
}
if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
cancellable, &error))
{
g_printerr ("Error during TLS handshake: %s\n",
error->message);
return 1;
}
g_object_unref (connection);
connection = G_IO_STREAM (tls_conn);
}
if (connection)
{
istream = g_io_stream_get_input_stream (connection);
ostream = g_io_stream_get_output_stream (connection);
}
while (TRUE)
{
@ -247,14 +245,20 @@ main (int argc,
gssize size;
gsize to_send;
ensure_condition (recv_socket, "receive", cancellable, G_IO_IN);
if (use_udp)
size = g_socket_receive_from (recv_socket, &address,
{
ensure_socket_condition (recv_socket, G_IO_IN, cancellable);
size = g_socket_receive_from (recv_socket, &address,
buffer, sizeof buffer,
cancellable, &error);
}
else
{
ensure_connection_condition (connection, G_IO_IN, cancellable);
size = g_input_stream_read (istream,
buffer, sizeof buffer,
cancellable, &error);
else
size = g_socket_receive (recv_socket, buffer, sizeof buffer,
cancellable, &error);
}
if (size < 0)
{
@ -288,13 +292,19 @@ main (int argc,
while (to_send > 0)
{
ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
if (use_udp)
size = g_socket_send_to (recv_socket, address,
buffer, to_send, cancellable, &error);
{
ensure_socket_condition (recv_socket, G_IO_OUT, cancellable);
size = g_socket_send_to (recv_socket, address,
buffer, to_send, cancellable, &error);
}
else
size = g_socket_send (recv_socket, buffer, to_send,
cancellable, &error);
{
ensure_connection_condition (connection, G_IO_OUT, cancellable);
size = g_output_stream_write (ostream,
buffer, to_send,
cancellable, &error);
}
if (size < 0)
{
@ -329,16 +339,15 @@ main (int argc,
g_print ("connection closed\n");
if (new_socket)
if (connection)
{
if (!g_socket_close (new_socket, &error))
if (!g_io_stream_close (connection, NULL, &error))
{
g_printerr ("Error closing connection socket: %s\n",
g_printerr ("Error closing connection stream: %s\n",
error->message);
return 1;
}
g_object_unref (G_OBJECT (new_socket));
g_object_unref (connection);
}
if (!g_socket_close (socket, &error))
@ -347,8 +356,7 @@ main (int argc,
error->message);
return 1;
}
g_object_unref (G_OBJECT (socket));
g_object_unref (socket);
return 0;
}

View File

@ -1409,7 +1409,7 @@ g_date_time_equal (gconstpointer dt1,
* g_date_time_get_ymd:
* @datetime: a #GDateTime.
* @year: (out): the return location for the gregorian year, or %NULL.
* @month: (out): the return location for the monty of the year, or %NULL.
* @month: (out): the return location for the month of the year, or %NULL.
* @day: (out): the return location for the day of the month, or %NULL.
*
* Retrieves the Gregorian day, month, and year of a given #GDateTime.

View File

@ -722,6 +722,7 @@ g_main_loop_quit
g_main_loop_ref
g_main_loop_run
g_main_loop_unref
g_source_add_child_source
g_source_add_poll
g_source_attach
g_source_destroy
@ -739,6 +740,7 @@ g_source_ref
g_source_remove
g_source_remove_by_funcs_user_data
g_source_remove_by_user_data
g_source_remove_child_source
g_source_remove_poll
g_source_set_callback
g_source_set_callback_indirect

View File

@ -313,6 +313,12 @@ struct _GPollRec
gint priority;
};
struct _GSourcePrivate
{
GSList *child_sources;
GSource *parent_source;
};
#ifdef G_THREADS_ENABLED
#define LOCK_CONTEXT(context) g_static_mutex_lock (&context->mutex)
#define UNLOCK_CONTEXT(context) g_static_mutex_unlock (&context->mutex)
@ -344,6 +350,9 @@ static void g_source_unref_internal (GSource *source,
static void g_source_destroy_internal (GSource *source,
GMainContext *context,
gboolean have_lock);
static void g_source_set_priority_unlocked (GSource *source,
GMainContext *context,
gint priority);
static void g_main_context_poll (GMainContext *context,
gint timeout,
gint priority,
@ -848,12 +857,21 @@ g_source_list_add (GSource *source,
{
GSource *tmp_source, *last_source;
last_source = NULL;
tmp_source = context->source_list;
while (tmp_source && tmp_source->priority <= source->priority)
if (source->priv && source->priv->parent_source)
{
last_source = tmp_source;
tmp_source = tmp_source->next;
/* Put the source immediately before its parent */
tmp_source = source->priv->parent_source;
last_source = source->priv->parent_source->prev;
}
else
{
last_source = NULL;
tmp_source = context->source_list;
while (tmp_source && tmp_source->priority <= source->priority)
{
last_source = tmp_source;
tmp_source = tmp_source->next;
}
}
source->next = tmp_source;
@ -885,6 +903,39 @@ g_source_list_remove (GSource *source,
source->next = NULL;
}
static guint
g_source_attach_unlocked (GSource *source,
GMainContext *context)
{
guint result = 0;
GSList *tmp_list;
source->context = context;
result = source->source_id = context->next_id++;
source->ref_count++;
g_source_list_add (source, context);
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data);
tmp_list = tmp_list->next;
}
if (source->priv)
{
tmp_list = source->priv->child_sources;
while (tmp_list)
{
g_source_attach_unlocked (tmp_list->data, context);
tmp_list = tmp_list->next;
}
}
return result;
}
/**
* g_source_attach:
* @source: a #GSource
@ -901,7 +952,6 @@ g_source_attach (GSource *source,
GMainContext *context)
{
guint result = 0;
GSList *tmp_list;
g_return_val_if_fail (source->context == NULL, 0);
g_return_val_if_fail (!SOURCE_DESTROYED (source), 0);
@ -911,18 +961,7 @@ g_source_attach (GSource *source,
LOCK_CONTEXT (context);
source->context = context;
result = source->source_id = context->next_id++;
source->ref_count++;
g_source_list_add (source, context);
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data);
tmp_list = tmp_list->next;
}
result = g_source_attach_unlocked (source, context);
#ifdef G_THREADS_ENABLED
/* Now wake up the main loop if it is waiting in the poll() */
@ -972,6 +1011,24 @@ g_source_destroy_internal (GSource *source,
tmp_list = tmp_list->next;
}
}
if (source->priv && source->priv->child_sources)
{
/* This is safe because even if a child_source finalizer or
* closure notify tried to modify source->priv->child_sources
* from outside the lock, it would fail since
* SOURCE_DESTROYED(source) is now TRUE.
*/
tmp_list = source->priv->child_sources;
while (tmp_list)
{
g_source_destroy_internal (tmp_list->data, context, TRUE);
g_source_unref_internal (tmp_list->data, context, TRUE);
tmp_list = tmp_list->next;
}
g_slist_free (source->priv->child_sources);
source->priv->child_sources = NULL;
}
g_source_unref_internal (source, context, TRUE);
}
@ -1118,6 +1175,98 @@ g_source_remove_poll (GSource *source,
}
}
/**
* g_source_add_child_source:
* @source:a #GSource
* @child_source: a second #GSource that @source should "poll"
*
* Adds @child_source to @source as a "polled" source; when @source is
* added to a #GMainContext, @child_source will be automatically added
* with the same priority, when @child_source is triggered, it will
* cause @source to dispatch (and won't call @child_source's own
* callback), and when @source is destroyed, it will destroy
* @child_source as well. (@source will also still be dispatched if
* its own prepare/check functions indicate that it is ready.)
*
* If you need @child_source to do anything on its own when it
* triggers, you can call g_source_set_dummy_callback() on it to set a
* callback that does nothing (except return %TRUE if appropriate).
*
* @source will hold a reference on @child_source while @child_source
* is attached to it.
*
* Since: 2.28
**/
void
g_source_add_child_source (GSource *source,
GSource *child_source)
{
GMainContext *context;
g_return_if_fail (source != NULL);
g_return_if_fail (child_source != NULL);
g_return_if_fail (!SOURCE_DESTROYED (source));
g_return_if_fail (!SOURCE_DESTROYED (child_source));
g_return_if_fail (child_source->context == NULL);
g_return_if_fail (child_source->priv == NULL || child_source->priv->parent_source == NULL);
context = source->context;
if (context)
LOCK_CONTEXT (context);
if (!source->priv)
source->priv = g_slice_new0 (GSourcePrivate);
if (!child_source->priv)
child_source->priv = g_slice_new0 (GSourcePrivate);
source->priv->child_sources = g_slist_prepend (source->priv->child_sources,
g_source_ref (child_source));
child_source->priv->parent_source = source;
g_source_set_priority_unlocked (child_source, context, source->priority);
if (context)
{
UNLOCK_CONTEXT (context);
g_source_attach (child_source, context);
}
}
/**
* g_source_remove_child_source:
* @source:a #GSource
* @child_source: a #GSource previously passed to
* g_source_add_child_source().
*
* Detaches @child_source from @source and destroys it.
*
* Since: 2.28
**/
void
g_source_remove_child_source (GSource *source,
GSource *child_source)
{
GMainContext *context;
g_return_if_fail (source != NULL);
g_return_if_fail (child_source != NULL);
g_return_if_fail (child_source->priv != NULL && child_source->priv->parent_source == source);
g_return_if_fail (!SOURCE_DESTROYED (source));
g_return_if_fail (!SOURCE_DESTROYED (child_source));
context = source->context;
if (context)
LOCK_CONTEXT (context);
source->priv->child_sources = g_slist_remove (source->priv->child_sources, child_source);
g_source_destroy_internal (child_source, context, TRUE);
g_source_unref_internal (child_source, context, TRUE);
if (context)
UNLOCK_CONTEXT (context);
}
/**
* g_source_set_callback_indirect:
* @source: the source
@ -1263,35 +1412,19 @@ g_source_set_funcs (GSource *source,
source->source_funcs = funcs;
}
/**
* g_source_set_priority:
* @source: a #GSource
* @priority: the new priority.
*
* Sets the priority of a source. While the main loop is being
* run, a source will be dispatched if it is ready to be dispatched and no sources
* at a higher (numerically smaller) priority are ready to be dispatched.
**/
void
g_source_set_priority (GSource *source,
gint priority)
static void
g_source_set_priority_unlocked (GSource *source,
GMainContext *context,
gint priority)
{
GSList *tmp_list;
GMainContext *context;
g_return_if_fail (source != NULL);
context = source->context;
if (context)
LOCK_CONTEXT (context);
source->priority = priority;
if (context)
{
/* Remove the source from the context's source and then
* add it back so it is sorted in the correct plcae
* add it back so it is sorted in the correct place
*/
g_source_list_remove (source, source->context);
g_source_list_add (source, source->context);
@ -1307,9 +1440,44 @@ g_source_set_priority (GSource *source,
tmp_list = tmp_list->next;
}
}
UNLOCK_CONTEXT (source->context);
}
if (source->priv && source->priv->child_sources)
{
tmp_list = source->priv->child_sources;
while (tmp_list)
{
g_source_set_priority_unlocked (tmp_list->data, context, priority);
tmp_list = tmp_list->next;
}
}
}
/**
* g_source_set_priority:
* @source: a #GSource
* @priority: the new priority.
*
* Sets the priority of a source. While the main loop is being run, a
* source will be dispatched if it is ready to be dispatched and no
* sources at a higher (numerically smaller) priority are ready to be
* dispatched.
**/
void
g_source_set_priority (GSource *source,
gint priority)
{
GMainContext *context;
g_return_if_fail (source != NULL);
context = source->context;
if (context)
LOCK_CONTEXT (context);
g_source_set_priority_unlocked (source, context, priority);
if (context)
UNLOCK_CONTEXT (source->context);
}
/**
@ -1511,16 +1679,21 @@ g_source_unref_internal (GSource *source,
source->callback_data = NULL;
source->callback_funcs = NULL;
if (context && !SOURCE_DESTROYED (source))
if (context)
{
g_warning (G_STRLOC ": ref_count == 0, but source is still attached to a context!");
source->ref_count++;
if (!SOURCE_DESTROYED (source))
g_warning (G_STRLOC ": ref_count == 0, but source was still attached to a context!");
g_source_list_remove (source, context);
}
else if (context)
g_source_list_remove (source, context);
if (source->source_funcs->finalize)
source->source_funcs->finalize (source);
{
if (context)
UNLOCK_CONTEXT (context);
source->source_funcs->finalize (source);
if (context)
LOCK_CONTEXT (context);
}
g_free (source->name);
source->name = NULL;
@ -2591,7 +2764,15 @@ g_main_context_prepare (GMainContext *context,
context->in_check_or_prepare--;
if (result)
source->flags |= G_SOURCE_READY;
{
GSource *ready_source = source;
while (ready_source)
{
ready_source->flags |= G_SOURCE_READY;
ready_source = ready_source->priv ? ready_source->priv->parent_source : NULL;
}
}
}
if (source->flags & G_SOURCE_READY)
@ -2783,7 +2964,15 @@ g_main_context_check (GMainContext *context,
context->in_check_or_prepare--;
if (result)
source->flags |= G_SOURCE_READY;
{
GSource *ready_source = source;
while (ready_source)
{
ready_source->flags |= G_SOURCE_READY;
ready_source = ready_source->priv ? ready_source->priv->parent_source : NULL;
}
}
}
if (source->flags & G_SOURCE_READY)

View File

@ -53,6 +53,7 @@ typedef struct _GMainLoop GMainLoop;
* representing an event source.
*/
typedef struct _GSource GSource;
typedef struct _GSourcePrivate GSourcePrivate;
/**
* GSourceCallbackFuncs:
@ -157,7 +158,8 @@ struct _GSource
GSource *next;
char *name;
gpointer reserved2;
GSourcePrivate *priv;
};
struct _GSourceCallbackFuncs
@ -358,10 +360,15 @@ void g_source_set_callback_indirect (GSource *source,
gpointer callback_data,
GSourceCallbackFuncs *callback_funcs);
void g_source_add_poll (GSource *source,
GPollFD *fd);
void g_source_remove_poll (GSource *source,
GPollFD *fd);
void g_source_add_poll (GSource *source,
GPollFD *fd);
void g_source_remove_poll (GSource *source,
GPollFD *fd);
void g_source_add_child_source (GSource *source,
GSource *child_source);
void g_source_remove_child_source (GSource *source,
GSource *child_source);
#ifndef G_DISABLE_DEPRECATED
void g_source_get_current_time (GSource *source,

View File

@ -2299,9 +2299,9 @@ g_get_user_cache_dir (void)
* On UNIX platforms this is determined using the mechanisms described in
* the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
* XDG Base Directory Specification</ulink>. This is the directory
* specified in the XDG_RUNTIME_DIR environment variable. In the case
* that this variable is not set, glib will issue a warning message to
* stderr and return the value of g_get_user_cache_dir().
* specified in the <envar>XDG_RUNTIME_DIR</envar> environment variable.
* In the case that this variable is not set, GLib will issue a warning
* message to stderr and return the value of g_get_user_cache_dir().
*
* On Windows this is the folder to use for local (as opposed to
* roaming) application data. See documentation for
@ -2309,6 +2309,8 @@ g_get_user_cache_dir (void)
* what g_get_user_config_dir() returns.
*
* Returns: a string owned by GLib that must not be modified or freed.
*
* Since: 2.28
**/
const gchar *
g_get_user_runtime_dir (void)

View File

@ -134,13 +134,13 @@ void g_variant_get_child (GVarian
...);
GVariant * g_variant_get_child_value (GVariant *value,
gsize index_);
gboolean g_variant_lookup (GVariant *value,
gboolean g_variant_lookup (GVariant *dictionary,
const gchar *key,
const gchar *format_string,
...);
GVariant * g_variant_lookup_value (GVariant *value,
GVariant * g_variant_lookup_value (GVariant *dictionary,
const gchar *key,
const GVariantType *type);
const GVariantType *expected_type);
gconstpointer g_variant_get_fixed_array (GVariant *value,
gsize *n_elements,
gsize element_size);

View File

@ -1565,6 +1565,7 @@ g_object_new_valist (GType object_type,
{
n_alloced_params += 16;
params = g_renew (GParameter, params, n_alloced_params);
memset (params + n_params, 0, 16 * (sizeof *params));
}
params[n_params].name = name;
G_VALUE_COLLECT_INIT (&params[n_params].value, pspec->value_type,

View File

@ -128,6 +128,7 @@ g_value_get_flags
g_io_channel_get_type
g_io_condition_get_type
g_source_set_closure
g_source_set_dummy_callback
#endif
#endif

View File

@ -168,7 +168,7 @@ g_source_set_closure (GSource *source,
source->source_funcs != &g_timeout_funcs &&
source->source_funcs != &g_idle_funcs)
{
g_critical (G_STRLOC "closure can not be set on closure without GSourceFuncs::closure_callback\n");
g_critical (G_STRLOC ": closure can not be set on closure without GSourceFuncs::closure_callback\n");
return;
}
@ -191,3 +191,40 @@ g_source_set_closure (GSource *source,
g_closure_set_marshal (closure, marshal);
}
}
static void
dummy_closure_marshal (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
if (G_VALUE_HOLDS_BOOLEAN (return_value))
g_value_set_boolean (return_value, TRUE);
}
/**
* g_source_set_dummy_callback:
* @source: the source
*
* Sets a dummy callback for @source. The callback will do nothing, and
* if the source expects a #gboolean return value, it will return %TRUE.
* (If the source expects any other type of return value, it will return
* a 0/%NULL value; whatever g_value_init() initializes a #GValue to for
* that type.)
*
* If the source is not one of the standard GLib types, the
* @closure_callback and @closure_marshal fields of the #GSourceFuncs
* structure must have been filled in with pointers to appropriate
* functions.
*/
void
g_source_set_dummy_callback (GSource *source)
{
GClosure *closure;
closure = g_closure_new_simple (sizeof (GClosure), NULL);
g_closure_set_meta_marshal (closure, NULL, dummy_closure_marshal);
g_source_set_closure (source, closure);
}

View File

@ -27,8 +27,10 @@
G_BEGIN_DECLS
void g_source_set_closure (GSource *source,
GClosure *closure);
void g_source_set_closure (GSource *source,
GClosure *closure);
void g_source_set_dummy_callback (GSource *source);
GType g_io_channel_get_type (void);
GType g_io_condition_get_type (void);

View File

@ -207,6 +207,42 @@ properties_notify (void)
g_object_unref (obj);
}
static void
properties_construct (void)
{
TestObject *obj;
gint val;
g_test_bug ("630357");
/* more than 16 args triggers a realloc in g_object_new_valist() */
obj = g_object_new (test_object_get_type (),
"foo", 1,
"foo", 2,
"foo", 3,
"foo", 4,
"foo", 5,
"foo", 6,
"foo", 7,
"foo", 8,
"foo", 9,
"foo", 10,
"foo", 11,
"foo", 12,
"foo", 13,
"foo", 14,
"foo", 15,
"foo", 16,
"foo", 17,
"foo", 18,
NULL);
g_object_get (obj, "foo", &val, NULL);
g_assert (val == 18);
g_object_unref (obj);
}
int
main (int argc, char *argv[])
{
@ -217,6 +253,7 @@ main (int argc, char *argv[])
g_test_add_func ("/properties/install", properties_install);
g_test_add_func ("/properties/notify", properties_notify);
g_test_add_func ("/properties/construct", properties_construct);
return g_test_run ();
}

View File

@ -93,7 +93,6 @@ gio/gpermission.c
gio/gpollfilemonitor.c
gio/gproxyaddress.c
gio/gproxyaddressenumerator.c
gio/gproxyconnection.c
gio/gresolver.c
gio/gseekable.c
gio/gsettingsbackend.c
@ -114,6 +113,10 @@ gio/gsocks5proxy.c
gio/gtcpconnection.c
gio/gthemedicon.c
gio/gthreadedsocketservice.c
gio/gtlscertificate.c
gio/gtlsclientconnection.c
gio/gtlsconnection.c
gio/gtlsserverconnection.c
gio/gunionvolumemonitor.c
gio/gunixconnection.c
gio/gunixcredentialsmessage.c

View File

@ -3205,7 +3205,7 @@ msgstr ""
#: gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr ""
#: gio/gsocks5proxy.c:208

View File

@ -3636,7 +3636,7 @@ msgstr ""
#: ../gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr ""
#: ../gio/gsocks5proxy.c:208

View File

@ -3411,7 +3411,7 @@ msgstr "Посредникът чрез SOCKSv5 изисква идентифи
#: ../gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr ""
"Посредникът чрез SOCKSv5 изисква механизъм за идентификация, който не се "
"поддържа от GLib."

View File

@ -3351,7 +3351,7 @@ msgstr ""
#: ../gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr ""
#: ../gio/gsocks5proxy.c:208

View File

@ -3382,7 +3382,7 @@ msgstr "SOCKSv5 proxy vyžaduje ověření."
#: ../gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr "SOCKSv5 vyžaduje metodu ověření nepodporovanou v GLib."
#: ../gio/gsocks5proxy.c:208

View File

@ -3384,7 +3384,7 @@ msgstr "SOCKSv5-proxy'en kræver godkendelse."
#: ../gio/gsocks5proxy.c:179
msgid ""
"The SOCKSv5 require an authentication method that is not supported by GLib."
"The SOCKSv5 proxy requires an authentication method that is not supported by GLib."
msgstr "SOCKSv5 kræver en godkendelsesmetode, der ikke understøttes af GLib."
#: ../gio/gsocks5proxy.c:208

Some files were not shown because too many files have changed in this diff Show More