mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
Merge branch 'master' into wip/gsettings-list
This commit is contained in:
commit
3ed846e753
40
NEWS
40
NEWS
@ -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
|
||||
==============================================
|
||||
|
||||
|
@ -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)])
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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, ¶m, &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);
|
||||
|
||||
|
@ -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 (¶ms[0], G_TYPE_INT);
|
||||
g_value_set_int (¶ms[0], fd);
|
||||
|
||||
g_value_init (¶ms[1], G_TYPE_IO_CONDITION);
|
||||
g_value_set_flags (¶ms[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 (¶ms[0]);
|
||||
g_value_unset (¶ms[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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 (¶ms, G_TYPE_CANCELLABLE);
|
||||
g_value_set_object (¶ms, cancellable);
|
||||
|
||||
g_closure_invoke (closure, &result_value, 1, ¶ms, NULL);
|
||||
|
||||
result = g_value_get_boolean (&result_value);
|
||||
g_value_unset (&result_value);
|
||||
g_value_unset (¶ms);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
274
gio/gdummytlsbackend.c
Normal 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
46
gio/gdummytlsbackend.h
Normal 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__ */
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -25,3 +25,7 @@ VOID:POINTER,INT,STRING
|
||||
BOOLEAN:OBJECT
|
||||
INT:OBJECT
|
||||
VOID:INT64
|
||||
VOID:UINT64
|
||||
BOOLEAN:FLAGS
|
||||
BOOLEAN:OBJECT,FLAGS
|
||||
OBJECT:VOID
|
||||
|
@ -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>
|
||||
|
109
gio/gio.symbols
109
gio/gio.symbols
@ -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
|
||||
|
100
gio/gioenums.h
100
gio/gioenums.h
@ -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__ */
|
||||
|
@ -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);
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
303
gio/gpollableinputstream.c
Normal 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 (¶m, G_TYPE_OBJECT);
|
||||
g_value_set_object (¶m, stream);
|
||||
|
||||
g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
|
||||
|
||||
result = g_value_get_boolean (&result_value);
|
||||
g_value_unset (&result_value);
|
||||
g_value_unset (¶m);
|
||||
|
||||
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
101
gio/gpollableinputstream.h
Normal 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
200
gio/gpollableoutputstream.c
Normal 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);
|
||||
}
|
98
gio/gpollableoutputstream.h
Normal file
98
gio/gpollableoutputstream.h
Normal 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__ */
|
||||
|
@ -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));
|
||||
}
|
@ -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__ */
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 (¶ms[0], G_TYPE_SOCKET);
|
||||
g_value_set_object (¶ms[0], socket);
|
||||
g_value_init (¶ms[1], G_TYPE_IO_CONDITION);
|
||||
g_value_set_flags (¶ms[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 (¶ms[0]);
|
||||
g_value_unset (¶ms[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 *
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
199
gio/gtcpwrapperconnection.c
Normal 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;
|
||||
}
|
68
gio/gtcpwrapperconnection.h
Normal file
68
gio/gtcpwrapperconnection.h
Normal 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
201
gio/gtlsbackend.c
Normal 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
92
gio/gtlsbackend.h
Normal 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
486
gio/gtlscertificate.c
Normal 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
75
gio/gtlscertificate.h
Normal 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
333
gio/gtlsclientconnection.c
Normal 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;
|
||||
}
|
72
gio/gtlsclientconnection.h
Normal file
72
gio/gtlsclientconnection.h
Normal 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
727
gio/gtlsconnection.c
Normal 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
137
gio/gtlsconnection.h
Normal 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__ */
|
96
gio/gtlsserverconnection.c
Normal file
96
gio/gtlsserverconnection.c
Normal 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);
|
||||
}
|
61
gio/gtlsserverconnection.h
Normal file
61
gio/gtlsserverconnection.h
Normal 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__ */
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
1
gio/tests/.gitignore
vendored
1
gio/tests/.gitignore
vendored
@ -60,6 +60,7 @@ memory-input-stream
|
||||
memory-output-stream
|
||||
network-address
|
||||
org.gtk.test.enums.xml
|
||||
pollable
|
||||
proxy
|
||||
readwrite
|
||||
resolver
|
||||
|
@ -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 \
|
||||
|
@ -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 ();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
240
gio/tests/pollable.c
Normal 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();
|
||||
}
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
287
glib/gmain.c
287
glib/gmain.c
@ -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)
|
||||
|
17
glib/gmain.h
17
glib/gmain.h
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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 (¶ms[n_params].value, pspec->value_type,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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
|
||||
|
2
po/ar.po
2
po/ar.po
@ -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
|
||||
|
2
po/be.po
2
po/be.po
@ -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
|
||||
|
2
po/bg.po
2
po/bg.po
@ -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."
|
||||
|
@ -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
|
||||
|
2
po/cs.po
2
po/cs.po
@ -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
|
||||
|
2
po/da.po
2
po/da.po
@ -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
Loading…
x
Reference in New Issue
Block a user