mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +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
|
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_major_version], [2])
|
||||||
m4_define([glib_minor_version], [27])
|
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_interface_age], [0])
|
||||||
m4_define([glib_binary_age],
|
m4_define([glib_binary_age],
|
||||||
[m4_eval(100 * glib_minor_version + glib_micro_version)])
|
[m4_eval(100 * glib_minor_version + glib_micro_version)])
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
<title>File System Monitoring</title>
|
<title>File System Monitoring</title>
|
||||||
<xi:include href="xml/gfilemonitor.xml"/>
|
<xi:include href="xml/gfilemonitor.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
<chapter id="utils">
|
||||||
|
<title>File-related Utilities</title>
|
||||||
|
<xi:include href="xml/gfilenamecompleter.xml"/>
|
||||||
|
</chapter>
|
||||||
<chapter id="async">
|
<chapter id="async">
|
||||||
<title>Asynchronous I/O</title>
|
<title>Asynchronous I/O</title>
|
||||||
<xi:include href="xml/gcancellable.xml"/>
|
<xi:include href="xml/gcancellable.xml"/>
|
||||||
@ -68,6 +72,8 @@
|
|||||||
<xi:include href="xml/gunixoutputstream.xml"/>
|
<xi:include href="xml/gunixoutputstream.xml"/>
|
||||||
<xi:include href="xml/gconverterinputstream.xml"/>
|
<xi:include href="xml/gconverterinputstream.xml"/>
|
||||||
<xi:include href="xml/gconverteroutputstream.xml"/>
|
<xi:include href="xml/gconverteroutputstream.xml"/>
|
||||||
|
<xi:include href="xml/gpollableinputstream.xml"/>
|
||||||
|
<xi:include href="xml/gpollableoutputstream.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="types">
|
<chapter id="types">
|
||||||
<title>File types and applications</title>
|
<title>File types and applications</title>
|
||||||
@ -118,10 +124,20 @@
|
|||||||
<xi:include href="xml/gsocketconnection.xml"/>
|
<xi:include href="xml/gsocketconnection.xml"/>
|
||||||
<xi:include href="xml/gunixconnection.xml"/>
|
<xi:include href="xml/gunixconnection.xml"/>
|
||||||
<xi:include href="xml/gtcpconnection.xml"/>
|
<xi:include href="xml/gtcpconnection.xml"/>
|
||||||
|
<xi:include href="xml/gtcpwrapperconnection.xml"/>
|
||||||
<xi:include href="xml/gsocketlistener.xml"/>
|
<xi:include href="xml/gsocketlistener.xml"/>
|
||||||
<xi:include href="xml/gsocketservice.xml"/>
|
<xi:include href="xml/gsocketservice.xml"/>
|
||||||
<xi:include href="xml/gthreadedsocketservice.xml"/>
|
<xi:include href="xml/gthreadedsocketservice.xml"/>
|
||||||
</chapter>
|
</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">
|
<chapter id="resolver">
|
||||||
<title>DNS resolution</title>
|
<title>DNS resolution</title>
|
||||||
<xi:include href="xml/gresolver.xml"/>
|
<xi:include href="xml/gresolver.xml"/>
|
||||||
@ -149,10 +165,6 @@
|
|||||||
<xi:include href="xml/gdbusnamewatching.xml"/>
|
<xi:include href="xml/gdbusnamewatching.xml"/>
|
||||||
<xi:include href="xml/gdbusproxy.xml"/>
|
<xi:include href="xml/gdbusproxy.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="utils">
|
|
||||||
<title>Utilities</title>
|
|
||||||
<xi:include href="xml/gfilenamecompleter.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter id="settings">
|
<chapter id="settings">
|
||||||
<title>Settings</title>
|
<title>Settings</title>
|
||||||
<xi:include href="xml/gsettings.xml"/>
|
<xi:include href="xml/gsettings.xml"/>
|
||||||
@ -232,6 +244,10 @@
|
|||||||
<title>Index of new symbols in 2.26</title>
|
<title>Index of new symbols in 2.26</title>
|
||||||
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
||||||
</index>
|
</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>
|
<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_get_fd
|
||||||
g_cancellable_make_pollfd
|
g_cancellable_make_pollfd
|
||||||
g_cancellable_release_fd
|
g_cancellable_release_fd
|
||||||
|
g_cancellable_source_new
|
||||||
|
GCancellableSourceFunc
|
||||||
g_cancellable_get_current
|
g_cancellable_get_current
|
||||||
g_cancellable_pop_current
|
g_cancellable_pop_current
|
||||||
g_cancellable_push_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_all_for_type
|
||||||
g_app_info_get_default_for_type
|
g_app_info_get_default_for_type
|
||||||
g_app_info_get_default_for_uri_scheme
|
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_info_launch_default_for_uri
|
||||||
g_app_launch_context_get_display
|
g_app_launch_context_get_display
|
||||||
g_app_launch_context_get_startup_notify_id
|
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_protocol
|
||||||
g_socket_client_set_socket_type
|
g_socket_client_set_socket_type
|
||||||
g_socket_client_set_timeout
|
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_family
|
||||||
g_socket_client_get_local_address
|
g_socket_client_get_local_address
|
||||||
g_socket_client_get_protocol
|
g_socket_client_get_protocol
|
||||||
g_socket_client_get_socket_type
|
g_socket_client_get_socket_type
|
||||||
g_socket_client_get_timeout
|
g_socket_client_get_timeout
|
||||||
g_socket_client_get_enable_proxy
|
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>
|
<SUBSECTION Standard>
|
||||||
GSocketClientClass
|
GSocketClientClass
|
||||||
G_IS_SOCKET_CLIENT
|
G_IS_SOCKET_CLIENT
|
||||||
@ -1878,6 +1886,25 @@ GTcpConnectionPrivate
|
|||||||
g_tcp_connection_get_type
|
g_tcp_connection_get_type
|
||||||
</SECTION>
|
</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>
|
<SECTION>
|
||||||
<FILE>gsocketcontrolmessage</FILE>
|
<FILE>gsocketcontrolmessage</FILE>
|
||||||
<TITLE>GSocketControlMessage</TITLE>
|
<TITLE>GSocketControlMessage</TITLE>
|
||||||
@ -2930,3 +2957,166 @@ G_IS_PERIODIC
|
|||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
g_periodic_get_type
|
g_periodic_get_type
|
||||||
</SECTION>
|
</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_password_save_get_type
|
||||||
g_periodic_get_type
|
g_periodic_get_type
|
||||||
g_permission_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_enumerator_get_type
|
||||||
g_proxy_address_get_type
|
g_proxy_address_get_type
|
||||||
g_proxy_get_type
|
g_proxy_get_type
|
||||||
@ -102,8 +104,14 @@ g_socket_service_get_type
|
|||||||
g_socket_type_get_type
|
g_socket_type_get_type
|
||||||
g_srv_target_get_type
|
g_srv_target_get_type
|
||||||
g_tcp_connection_get_type
|
g_tcp_connection_get_type
|
||||||
|
g_tcp_wrapper_connection_get_type
|
||||||
g_themed_icon_get_type
|
g_themed_icon_get_type
|
||||||
g_threaded_socket_service_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_connection_get_type
|
||||||
g_unix_fd_list_get_type
|
g_unix_fd_list_get_type
|
||||||
g_unix_fd_message_get_type
|
g_unix_fd_message_get_type
|
||||||
|
@ -518,8 +518,10 @@
|
|||||||
implementation with the highest priority.
|
implementation with the highest priority.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
gvfs contains a GConf-based implementation that uses the
|
This extension point has been discontinued in GLib 2.28. It is
|
||||||
same GConf keys as gnome-vfs.
|
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>
|
</para>
|
||||||
</formalpara>
|
</formalpara>
|
||||||
|
|
||||||
@ -544,6 +546,24 @@
|
|||||||
#GProxy interface, and must be named after the network
|
#GProxy interface, and must be named after the network
|
||||||
protocol they are proxying.
|
protocol they are proxying.
|
||||||
</para>
|
</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>
|
</formalpara>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@ -56,14 +56,6 @@ with Glib-2.0 that you need to reproduce exactly.
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Incompatible changes from 1.2 to 2.0</title>
|
<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>
|
<itemizedlist>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -194,6 +194,10 @@ synchronize their operation.
|
|||||||
<title>Index of new symbols in 2.26</title>
|
<title>Index of new symbols in 2.26</title>
|
||||||
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
||||||
</index>
|
</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>
|
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
||||||
|
|
||||||
|
@ -535,6 +535,8 @@ GSourceFunc
|
|||||||
g_source_set_callback_indirect
|
g_source_set_callback_indirect
|
||||||
g_source_add_poll
|
g_source_add_poll
|
||||||
g_source_remove_poll
|
g_source_remove_poll
|
||||||
|
g_source_add_child_source
|
||||||
|
g_source_remove_child_source
|
||||||
g_source_get_time
|
g_source_get_time
|
||||||
g_source_get_current_time
|
g_source_get_current_time
|
||||||
g_source_remove
|
g_source_remove
|
||||||
|
@ -148,6 +148,10 @@
|
|||||||
<title>Index of new symbols in 2.26</title>
|
<title>Index of new symbols in 2.26</title>
|
||||||
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
|
||||||
</index>
|
</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>
|
<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_byte_array_get_type
|
||||||
g_ptr_array_get_type
|
g_ptr_array_get_type
|
||||||
g_error_get_type
|
g_error_get_type
|
||||||
|
g_date_time_get_type
|
||||||
g_variant_get_gtype
|
g_variant_get_gtype
|
||||||
g_variant_type_get_gtype
|
g_variant_type_get_gtype
|
||||||
</SECTION>
|
</SECTION>
|
||||||
@ -828,6 +829,7 @@ g_closure_set_marshal
|
|||||||
g_closure_add_marshal_guards
|
g_closure_add_marshal_guards
|
||||||
g_closure_set_meta_marshal
|
g_closure_set_meta_marshal
|
||||||
g_source_set_closure
|
g_source_set_closure
|
||||||
|
g_source_set_dummy_callback
|
||||||
G_TYPE_IO_CHANNEL
|
G_TYPE_IO_CHANNEL
|
||||||
G_TYPE_IO_CONDITION
|
G_TYPE_IO_CONDITION
|
||||||
|
|
||||||
|
@ -202,7 +202,6 @@ platform_libadd += win32/libgiowin32.la
|
|||||||
platform_deps += win32/libgiowin32.la
|
platform_deps += win32/libgiowin32.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
SUBDIRS += .
|
SUBDIRS += .
|
||||||
|
|
||||||
if HAVE_FAM
|
if HAVE_FAM
|
||||||
@ -307,6 +306,8 @@ libgio_2_0_la_SOURCES = \
|
|||||||
gdummyfile.c \
|
gdummyfile.c \
|
||||||
gdummyproxyresolver.c \
|
gdummyproxyresolver.c \
|
||||||
gdummyproxyresolver.h \
|
gdummyproxyresolver.h \
|
||||||
|
gdummytlsbackend.c \
|
||||||
|
gdummytlsbackend.h \
|
||||||
gemblem.h \
|
gemblem.h \
|
||||||
gemblem.c \
|
gemblem.c \
|
||||||
gemblemedicon.h \
|
gemblemedicon.h \
|
||||||
@ -349,6 +350,8 @@ libgio_2_0_la_SOURCES = \
|
|||||||
goutputstream.c \
|
goutputstream.c \
|
||||||
gperiodic.c \
|
gperiodic.c \
|
||||||
gpermission.c \
|
gpermission.c \
|
||||||
|
gpollableinputstream.c \
|
||||||
|
gpollableoutputstream.c \
|
||||||
gpollfilemonitor.c \
|
gpollfilemonitor.c \
|
||||||
gpollfilemonitor.h \
|
gpollfilemonitor.h \
|
||||||
gproxyresolver.c \
|
gproxyresolver.c \
|
||||||
@ -371,15 +374,19 @@ libgio_2_0_la_SOURCES = \
|
|||||||
gproxy.c \
|
gproxy.c \
|
||||||
gproxyaddress.c \
|
gproxyaddress.c \
|
||||||
gproxyaddressenumerator.c \
|
gproxyaddressenumerator.c \
|
||||||
gproxyconnection.c \
|
|
||||||
gproxyconnection.h \
|
|
||||||
gsocketservice.c \
|
gsocketservice.c \
|
||||||
gsrvtarget.c \
|
gsrvtarget.c \
|
||||||
gtcpconnection.c \
|
gtcpconnection.c \
|
||||||
|
gtcpwrapperconnection.c \
|
||||||
gthreadedsocketservice.c\
|
gthreadedsocketservice.c\
|
||||||
gthemedicon.c \
|
gthemedicon.c \
|
||||||
gthreadedresolver.c \
|
gthreadedresolver.c \
|
||||||
gthreadedresolver.h \
|
gthreadedresolver.h \
|
||||||
|
gtlsbackend.c \
|
||||||
|
gtlscertificate.c \
|
||||||
|
gtlsclientconnection.c \
|
||||||
|
gtlsconnection.c \
|
||||||
|
gtlsserverconnection.c \
|
||||||
gunionvolumemonitor.c \
|
gunionvolumemonitor.c \
|
||||||
gunionvolumemonitor.h \
|
gunionvolumemonitor.h \
|
||||||
gvfs.c \
|
gvfs.c \
|
||||||
@ -505,6 +512,8 @@ gio_headers = \
|
|||||||
goutputstream.h \
|
goutputstream.h \
|
||||||
gperiodic.h \
|
gperiodic.h \
|
||||||
gpermission.h \
|
gpermission.h \
|
||||||
|
gpollableinputstream.h \
|
||||||
|
gpollableoutputstream.h \
|
||||||
gproxyaddress.h \
|
gproxyaddress.h \
|
||||||
gproxy.h \
|
gproxy.h \
|
||||||
gproxyaddressenumerator.h \
|
gproxyaddressenumerator.h \
|
||||||
@ -524,8 +533,14 @@ gio_headers = \
|
|||||||
gsocketservice.h \
|
gsocketservice.h \
|
||||||
gsrvtarget.h \
|
gsrvtarget.h \
|
||||||
gtcpconnection.h \
|
gtcpconnection.h \
|
||||||
|
gtcpwrapperconnection.h \
|
||||||
gthreadedsocketservice.h\
|
gthreadedsocketservice.h\
|
||||||
gthemedicon.h \
|
gthemedicon.h \
|
||||||
|
gtlsbackend.h \
|
||||||
|
gtlscertificate.h \
|
||||||
|
gtlsclientconnection.h \
|
||||||
|
gtlsconnection.h \
|
||||||
|
gtlsserverconnection.h \
|
||||||
gvfs.h \
|
gvfs.h \
|
||||||
gvolume.h \
|
gvolume.h \
|
||||||
gvolumemonitor.h \
|
gvolumemonitor.h \
|
||||||
|
@ -28,7 +28,7 @@ G_DEFINE_INTERFACE (GAction, g_action, G_TYPE_OBJECT)
|
|||||||
/**
|
/**
|
||||||
* SECTION:gaction
|
* SECTION:gaction
|
||||||
* @title: GAction
|
* @title: GAction
|
||||||
* @short_description: an action
|
* @short_description: An action
|
||||||
*
|
*
|
||||||
* #GAction represents a single named action.
|
* #GAction represents a single named action.
|
||||||
*
|
*
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION:gactiongroup
|
* SECTION:gactiongroup
|
||||||
* @title: GActionGroup
|
* @title: GActionGroup
|
||||||
* @short_description: a group of actions
|
* @short_description: A group of actions
|
||||||
*
|
*
|
||||||
* #GActionGroup represents 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
|
* Gets the display string for the @context. This is used to ensure new
|
||||||
* applications are started on the same display as the launching
|
* 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.
|
* 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
|
* @files: (element-type GFile): a #GList of of #GFile objects
|
||||||
*
|
*
|
||||||
* Initiates startup notification for the application and returns the
|
* 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.
|
* if supported.
|
||||||
*
|
*
|
||||||
* Startup notification IDs are defined in the <ulink
|
* 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 (void);
|
||||||
GList * g_app_info_get_all_for_type (const char *content_type);
|
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);
|
void g_app_info_reset_type_associations (const char *content_type);
|
||||||
GAppInfo *g_app_info_get_default_for_type (const char *content_type,
|
GAppInfo *g_app_info_get_default_for_type (const char *content_type,
|
||||||
gboolean must_support_uris);
|
gboolean must_support_uris);
|
||||||
|
@ -33,8 +33,7 @@ G_DEFINE_TYPE (GApplicationCommandLine, g_application_command_line, G_TYPE_OBJEC
|
|||||||
/**
|
/**
|
||||||
* SECTION:gapplicationcommandline
|
* SECTION:gapplicationcommandline
|
||||||
* @title: GApplicationCommandLine
|
* @title: GApplicationCommandLine
|
||||||
* @short_description: A class representing a command-line invocation of
|
* @short_description: A command-line invocation of an application
|
||||||
* an application
|
|
||||||
* @see_also: #GApplication
|
* @see_also: #GApplication
|
||||||
*
|
*
|
||||||
* #GApplicationCommandLine represents a command-line invocation of
|
* #GApplicationCommandLine represents a command-line invocation of
|
||||||
|
@ -354,17 +354,21 @@ g_application_impl_actions_method_call (GDBusConnection *connection,
|
|||||||
GVariant *platform_data;
|
GVariant *platform_data;
|
||||||
GVariantIter *param;
|
GVariantIter *param;
|
||||||
GVariant *parameter;
|
GVariant *parameter;
|
||||||
|
GVariant *unboxed_parameter;
|
||||||
|
|
||||||
g_variant_get (parameters, "(&sav@a{sv})",
|
g_variant_get (parameters, "(&sav@a{sv})",
|
||||||
&action_name, ¶m, &platform_data);
|
&action_name, ¶m, &platform_data);
|
||||||
parameter = g_variant_iter_next_value (param);
|
parameter = g_variant_iter_next_value (param);
|
||||||
|
unboxed_parameter = parameter ? g_variant_get_variant (parameter) : NULL;
|
||||||
g_variant_iter_free (param);
|
g_variant_iter_free (param);
|
||||||
|
|
||||||
class->before_emit (impl->app, platform_data);
|
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);
|
class->after_emit (impl->app, platform_data);
|
||||||
g_variant_unref (platform_data);
|
g_variant_unref (platform_data);
|
||||||
|
|
||||||
|
if (unboxed_parameter)
|
||||||
|
g_variant_unref (unboxed_parameter);
|
||||||
if (parameter)
|
if (parameter)
|
||||||
g_variant_unref (parameter);
|
g_variant_unref (parameter);
|
||||||
|
|
||||||
|
@ -43,18 +43,14 @@ typedef struct
|
|||||||
{
|
{
|
||||||
GSource source;
|
GSource source;
|
||||||
GPollFD pollfd;
|
GPollFD pollfd;
|
||||||
GCancellable *cancellable;
|
|
||||||
gulong cancelled_tag;
|
|
||||||
} FDSource;
|
} FDSource;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fd_source_prepare (GSource *source,
|
fd_source_prepare (GSource *source,
|
||||||
gint *timeout)
|
gint *timeout)
|
||||||
{
|
{
|
||||||
FDSource *fd_source = (FDSource *)source;
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
|
return FALSE;
|
||||||
return g_cancellable_is_cancelled (fd_source->cancellable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -62,9 +58,7 @@ fd_source_check (GSource *source)
|
|||||||
{
|
{
|
||||||
FDSource *fd_source = (FDSource *)source;
|
FDSource *fd_source = (FDSource *)source;
|
||||||
|
|
||||||
return
|
return fd_source->pollfd.revents != 0;
|
||||||
g_cancellable_is_cancelled (fd_source->cancellable) ||
|
|
||||||
fd_source->pollfd.revents != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -78,42 +72,76 @@ fd_source_dispatch (GSource *source,
|
|||||||
|
|
||||||
g_warn_if_fail (func != NULL);
|
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
|
static void
|
||||||
fd_source_finalize (GSource *source)
|
fd_source_finalize (GSource *source)
|
||||||
{
|
{
|
||||||
FDSource *fd_source = (FDSource *)source;
|
}
|
||||||
|
|
||||||
/* we don't use g_cancellable_disconnect() here, since we are holding
|
static gboolean
|
||||||
* the main context lock here, and the ::disconnect signal handler
|
fd_source_closure_callback (int fd,
|
||||||
* will try to grab that, and deadlock looms.
|
GIOCondition condition,
|
||||||
*/
|
gpointer data)
|
||||||
if (fd_source->cancelled_tag)
|
{
|
||||||
g_signal_handler_disconnect (fd_source->cancellable,
|
GClosure *closure = data;
|
||||||
fd_source->cancelled_tag);
|
|
||||||
|
|
||||||
if (fd_source->cancellable)
|
GValue params[2] = { { 0, }, { 0, } };
|
||||||
g_object_unref (fd_source->cancellable);
|
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 = {
|
static GSourceFuncs fd_source_funcs = {
|
||||||
fd_source_prepare,
|
fd_source_prepare,
|
||||||
fd_source_check,
|
fd_source_check,
|
||||||
fd_source_dispatch,
|
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 *
|
GSource *
|
||||||
_g_fd_source_new (int fd,
|
_g_fd_source_new (int fd,
|
||||||
gushort events,
|
gushort events,
|
||||||
@ -125,18 +153,18 @@ _g_fd_source_new (int fd,
|
|||||||
source = g_source_new (&fd_source_funcs, sizeof (FDSource));
|
source = g_source_new (&fd_source_funcs, sizeof (FDSource));
|
||||||
fd_source = (FDSource *)source;
|
fd_source = (FDSource *)source;
|
||||||
|
|
||||||
if (cancellable)
|
|
||||||
fd_source->cancellable = g_object_ref (cancellable);
|
|
||||||
|
|
||||||
fd_source->pollfd.fd = fd;
|
fd_source->pollfd.fd = fd;
|
||||||
fd_source->pollfd.events = events;
|
fd_source->pollfd.events = events;
|
||||||
g_source_add_poll (source, &fd_source->pollfd);
|
g_source_add_poll (source, &fd_source->pollfd);
|
||||||
|
|
||||||
if (cancellable)
|
if (cancellable)
|
||||||
fd_source->cancelled_tag =
|
{
|
||||||
g_cancellable_connect (cancellable,
|
GSource *cancellable_source = g_cancellable_source_new (cancellable);
|
||||||
(GCallback)fd_source_cancelled_cb,
|
|
||||||
NULL, NULL);
|
g_source_set_dummy_callback (cancellable_source);
|
||||||
|
g_source_add_child_source (source, cancellable_source);
|
||||||
|
g_source_unref (cancellable_source);
|
||||||
|
}
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef gboolean (*GFDSourceFunc) (gpointer user_data,
|
typedef gboolean (*GFDSourceFunc) (int fd,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
int fd);
|
gpointer user_data);
|
||||||
|
|
||||||
GSource *_g_fd_source_new (int fd,
|
GSource *_g_fd_source_new (int fd,
|
||||||
gushort events,
|
gushort events,
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
#include "gcancellable.h"
|
#include "gcancellable.h"
|
||||||
|
#include "gio-marshal.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
|
|
||||||
@ -770,3 +771,118 @@ g_cancellable_disconnect (GCancellable *cancellable,
|
|||||||
g_signal_handler_disconnect (cancellable, handler_id);
|
g_signal_handler_disconnect (cancellable, handler_id);
|
||||||
G_UNLOCK (cancellable);
|
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);
|
GPollFD *pollfd);
|
||||||
void g_cancellable_release_fd (GCancellable *cancellable);
|
void g_cancellable_release_fd (GCancellable *cancellable);
|
||||||
|
|
||||||
|
GSource * g_cancellable_source_new (GCancellable *cancellable);
|
||||||
|
|
||||||
GCancellable *g_cancellable_get_current (void);
|
GCancellable *g_cancellable_get_current (void);
|
||||||
void g_cancellable_push_current (GCancellable *cancellable);
|
void g_cancellable_push_current (GCancellable *cancellable);
|
||||||
void g_cancellable_pop_current (GCancellable *cancellable);
|
void g_cancellable_pop_current (GCancellable *cancellable);
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:gdesktopappinfo
|
* SECTION:gdesktopappinfo
|
||||||
|
* @title: GDesktopAppInfo
|
||||||
* @short_description: Application information from desktop files
|
* @short_description: Application information from desktop files
|
||||||
* @include: gio/gdesktopappinfo.h
|
* @include: gio/gdesktopappinfo.h
|
||||||
*
|
*
|
||||||
@ -67,7 +68,8 @@
|
|||||||
|
|
||||||
static void g_desktop_app_info_iface_init (GAppInfoIface *iface);
|
static void g_desktop_app_info_iface_init (GAppInfoIface *iface);
|
||||||
static GList * get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
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 void mime_info_cache_reload (const char *dir);
|
||||||
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
|
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
|
||||||
GError **error);
|
GError **error);
|
||||||
@ -1249,10 +1251,10 @@ update_mimeapps_list (const char *desktop_id,
|
|||||||
add the current list of (not yet listed) apps before it. */
|
add the current list of (not yet listed) apps before it. */
|
||||||
|
|
||||||
list[i] = NULL; /* Terminate current list so we can use 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);
|
list = g_renew (char *, list, 1 + length + g_list_length (system_list) + 1);
|
||||||
|
|
||||||
for (l = system_list; l != NULL; l = l->next)
|
for (l = system_list; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
list[i++] = l->data; /* no strdup, taking ownership */
|
list[i++] = l->data; /* no strdup, taking ownership */
|
||||||
@ -1722,15 +1724,107 @@ app_info_in_list (GAppInfo *info,
|
|||||||
return FALSE;
|
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:
|
* g_app_info_get_all_for_type:
|
||||||
* @content_type: the content type to find a #GAppInfo for
|
* @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
|
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
|
||||||
* or %NULL on error.
|
* for given @content_type or %NULL on error.
|
||||||
**/
|
**/
|
||||||
GList *
|
GList *
|
||||||
g_app_info_get_all_for_type (const char *content_type)
|
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);
|
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;
|
infos = NULL;
|
||||||
for (l = desktop_entries; l != NULL; l = l->next)
|
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);
|
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;
|
info = NULL;
|
||||||
for (l = desktop_entries; l != NULL; l = l->next)
|
for (l = desktop_entries; l != NULL; l = l->next)
|
||||||
@ -2542,7 +2636,8 @@ append_desktop_entry (GList *list,
|
|||||||
*/
|
*/
|
||||||
static GList *
|
static GList *
|
||||||
get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
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;
|
GList *desktop_entries, *removed_entries, *list, *dir_list, *tmp;
|
||||||
MimeInfoCacheDir *dir;
|
MimeInfoCacheDir *dir;
|
||||||
@ -2556,29 +2651,38 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
|||||||
|
|
||||||
mime_info_cache_init ();
|
mime_info_cache_init ();
|
||||||
|
|
||||||
/* collect all ancestors */
|
if (include_fallback)
|
||||||
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));
|
/* collect all ancestors */
|
||||||
for (j = 0; anc[j]; j++)
|
mime_types = _g_unix_content_type_get_parents (base_mime_type);
|
||||||
{
|
array = g_ptr_array_new ();
|
||||||
for (k = 0; k < array->len; k++)
|
for (i = 0; mime_types[i]; i++)
|
||||||
{
|
g_ptr_array_add (array, mime_types[i]);
|
||||||
if (strcmp (anc[j], g_ptr_array_index (array, k)) == 0)
|
g_free (mime_types);
|
||||||
break;
|
for (i = 0; i < array->len; i++)
|
||||||
}
|
{
|
||||||
if (k == array->len) /* not found */
|
anc = _g_unix_content_type_get_parents (g_ptr_array_index (array, i));
|
||||||
g_ptr_array_add (array, g_strdup (anc[j]));
|
for (j = 0; anc[j]; j++)
|
||||||
}
|
{
|
||||||
g_strfreev (anc);
|
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);
|
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:
|
* GFileMonitor::changed:
|
||||||
* @monitor: a #GFileMonitor.
|
* @monitor: a #GFileMonitor.
|
||||||
* @file: a #GFile.
|
* @file: a #GFile.
|
||||||
* @other_file: a #GFile.
|
* @other_file: a #GFile or #NULL.
|
||||||
* @event_type: a #GFileMonitorEvent.
|
* @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] =
|
signals[CHANGED] =
|
||||||
g_signal_new (I_("changed"),
|
g_signal_new (I_("changed"),
|
||||||
@ -327,21 +333,21 @@ g_file_monitor_cancel (GFileMonitor* monitor)
|
|||||||
/**
|
/**
|
||||||
* g_file_monitor_set_rate_limit:
|
* g_file_monitor_set_rate_limit:
|
||||||
* @monitor: a #GFileMonitor.
|
* @monitor: a #GFileMonitor.
|
||||||
* @limit_msecs: a integer with the limit in milliseconds to
|
* @limit_msecs: a non-negative integer with the limit in milliseconds
|
||||||
* poll for changes.
|
* to poll for changes
|
||||||
*
|
*
|
||||||
* Sets the rate limit to which the @monitor will report
|
* 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
|
void
|
||||||
g_file_monitor_set_rate_limit (GFileMonitor *monitor,
|
g_file_monitor_set_rate_limit (GFileMonitor *monitor,
|
||||||
int limit_msecs)
|
gint limit_msecs)
|
||||||
{
|
{
|
||||||
GFileMonitorPrivate *priv;
|
GFileMonitorPrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (G_IS_FILE_MONITOR (monitor));
|
g_return_if_fail (G_IS_FILE_MONITOR (monitor));
|
||||||
|
g_return_if_fail (limit_msecs >= 0);
|
||||||
|
|
||||||
priv = monitor->priv;
|
priv = monitor->priv;
|
||||||
if (priv->rate_limit_msec != limit_msecs)
|
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_cancel (GFileMonitor *monitor);
|
||||||
gboolean g_file_monitor_is_cancelled (GFileMonitor *monitor);
|
gboolean g_file_monitor_is_cancelled (GFileMonitor *monitor);
|
||||||
void g_file_monitor_set_rate_limit (GFileMonitor *monitor,
|
void g_file_monitor_set_rate_limit (GFileMonitor *monitor,
|
||||||
int limit_msecs);
|
gint limit_msecs);
|
||||||
|
|
||||||
|
|
||||||
/* For implementations */
|
/* For implementations */
|
||||||
|
@ -25,3 +25,7 @@ VOID:POINTER,INT,STRING
|
|||||||
BOOLEAN:OBJECT
|
BOOLEAN:OBJECT
|
||||||
INT:OBJECT
|
INT:OBJECT
|
||||||
VOID:INT64
|
VOID:INT64
|
||||||
|
VOID:UINT64
|
||||||
|
BOOLEAN:FLAGS
|
||||||
|
BOOLEAN:OBJECT,FLAGS
|
||||||
|
OBJECT:VOID
|
||||||
|
@ -95,6 +95,8 @@
|
|||||||
#include <gio/goutputstream.h>
|
#include <gio/goutputstream.h>
|
||||||
#include <gio/gperiodic.h>
|
#include <gio/gperiodic.h>
|
||||||
#include <gio/gpermission.h>
|
#include <gio/gpermission.h>
|
||||||
|
#include <gio/gpollableinputstream.h>
|
||||||
|
#include <gio/gpollableoutputstream.h>
|
||||||
#include <gio/gproxy.h>
|
#include <gio/gproxy.h>
|
||||||
#include <gio/gproxyaddress.h>
|
#include <gio/gproxyaddress.h>
|
||||||
#include <gio/gproxyaddressenumerator.h>
|
#include <gio/gproxyaddressenumerator.h>
|
||||||
@ -115,8 +117,14 @@
|
|||||||
#include <gio/gsocketservice.h>
|
#include <gio/gsocketservice.h>
|
||||||
#include <gio/gsrvtarget.h>
|
#include <gio/gsrvtarget.h>
|
||||||
#include <gio/gtcpconnection.h>
|
#include <gio/gtcpconnection.h>
|
||||||
|
#include <gio/gtcpwrapperconnection.h>
|
||||||
#include <gio/gthemedicon.h>
|
#include <gio/gthemedicon.h>
|
||||||
#include <gio/gthreadedsocketservice.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/gvfs.h>
|
||||||
#include <gio/gvolume.h>
|
#include <gio/gvolume.h>
|
||||||
#include <gio/gvolumemonitor.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_all_for_type
|
||||||
g_app_info_get_default_for_type
|
g_app_info_get_default_for_type
|
||||||
g_app_info_get_default_for_uri_scheme
|
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
|
g_app_info_reset_type_associations
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -191,6 +193,7 @@ g_cancellable_reset
|
|||||||
g_cancellable_cancel
|
g_cancellable_cancel
|
||||||
g_cancellable_connect
|
g_cancellable_connect
|
||||||
g_cancellable_disconnect
|
g_cancellable_disconnect
|
||||||
|
g_cancellable_source_new
|
||||||
#endif
|
#endif
|
||||||
#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_dbus_send_message_flags_get_type G_GNUC_CONST
|
||||||
g_credentials_type_get_type G_GNUC_CONST
|
g_credentials_type_get_type G_GNUC_CONST
|
||||||
g_dbus_message_byte_order_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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1368,6 +1374,7 @@ g_socket_control_message_serialize
|
|||||||
#if IN_HEADER(__G_SOCKET_CLIENT_H__)
|
#if IN_HEADER(__G_SOCKET_CLIENT_H__)
|
||||||
#if IN_FILE(__G_SOCKET_CLIENT_C__)
|
#if IN_FILE(__G_SOCKET_CLIENT_C__)
|
||||||
g_socket_client_get_type G_GNUC_CONST
|
g_socket_client_get_type G_GNUC_CONST
|
||||||
|
g_socket_client_add_application_proxy
|
||||||
g_socket_client_connect
|
g_socket_client_connect
|
||||||
g_socket_client_connect_async
|
g_socket_client_connect_async
|
||||||
g_socket_client_connect_finish
|
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
|
||||||
g_socket_client_connect_to_uri_async
|
g_socket_client_connect_to_uri_async
|
||||||
g_socket_client_connect_to_uri_finish
|
g_socket_client_connect_to_uri_finish
|
||||||
|
g_socket_client_get_enable_proxy
|
||||||
g_socket_client_get_family
|
g_socket_client_get_family
|
||||||
g_socket_client_get_local_address
|
g_socket_client_get_local_address
|
||||||
g_socket_client_get_protocol
|
g_socket_client_get_protocol
|
||||||
g_socket_client_get_socket_type
|
g_socket_client_get_socket_type
|
||||||
g_socket_client_get_timeout
|
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_new
|
||||||
|
g_socket_client_set_enable_proxy
|
||||||
g_socket_client_set_family
|
g_socket_client_set_family
|
||||||
g_socket_client_set_local_address
|
g_socket_client_set_local_address
|
||||||
g_socket_client_set_protocol
|
g_socket_client_set_protocol
|
||||||
g_socket_client_set_socket_type
|
g_socket_client_set_socket_type
|
||||||
g_socket_client_set_timeout
|
g_socket_client_set_timeout
|
||||||
g_socket_client_set_enable_proxy
|
g_socket_client_set_tls
|
||||||
g_socket_client_add_application_proxy
|
g_socket_client_set_tls_validation_flags
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1975,3 +1985,96 @@ g_periodic_remove
|
|||||||
g_periodic_unblock
|
g_periodic_unblock
|
||||||
#endif
|
#endif
|
||||||
#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)
|
G_APPLICATION_SEND_ENVIRONMENT = (1 << 4)
|
||||||
} GApplicationFlags;
|
} 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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GIO_ENUMS_H__ */
|
#endif /* __GIO_ENUMS_H__ */
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "gsocks4proxy.h"
|
#include "gsocks4proxy.h"
|
||||||
#include "gsocks4aproxy.h"
|
#include "gsocks4aproxy.h"
|
||||||
#include "gsocks5proxy.h"
|
#include "gsocks5proxy.h"
|
||||||
|
#include "gtlsbackend.h"
|
||||||
#include "gvfs.h"
|
#include "gvfs.h"
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
#include "gregistrysettingsbackend.h"
|
#include "gregistrysettingsbackend.h"
|
||||||
@ -277,7 +278,7 @@ is_valid_module_name (const gchar *basename)
|
|||||||
* g_io_extension_point_get_extension_by_name().
|
* g_io_extension_point_get_extension_by_name().
|
||||||
*
|
*
|
||||||
* If you need to guarantee that all types are loaded in all the modules,
|
* 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
|
* 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_winhttp_vfs_get_type (void);
|
||||||
|
|
||||||
extern GType _g_dummy_proxy_resolver_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
|
#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);
|
ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
|
||||||
g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
|
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);
|
G_UNLOCK (registered_extensions);
|
||||||
@ -618,6 +623,7 @@ _g_io_modules_ensure_loaded (void)
|
|||||||
_g_socks4a_proxy_get_type ();
|
_g_socks4a_proxy_get_type ();
|
||||||
_g_socks4_proxy_get_type ();
|
_g_socks4_proxy_get_type ();
|
||||||
_g_socks5_proxy_get_type ();
|
_g_socks5_proxy_get_type ();
|
||||||
|
_g_dummy_tls_backend_get_type ();
|
||||||
}
|
}
|
||||||
|
|
||||||
G_UNLOCK (loaded_dirs);
|
G_UNLOCK (loaded_dirs);
|
||||||
|
@ -109,6 +109,7 @@ typedef struct _GIOExtension GIOExtension;
|
|||||||
* Opaque class for definining and scheduling IO jobs.
|
* Opaque class for definining and scheduling IO jobs.
|
||||||
**/
|
**/
|
||||||
typedef struct _GIOSchedulerJob GIOSchedulerJob;
|
typedef struct _GIOSchedulerJob GIOSchedulerJob;
|
||||||
|
typedef struct _GIOStreamAdapter GIOStreamAdapter;
|
||||||
typedef struct _GLoadableIcon GLoadableIcon; /* Dummy typedef */
|
typedef struct _GLoadableIcon GLoadableIcon; /* Dummy typedef */
|
||||||
typedef struct _GMemoryInputStream GMemoryInputStream;
|
typedef struct _GMemoryInputStream GMemoryInputStream;
|
||||||
typedef struct _GMemoryOutputStream GMemoryOutputStream;
|
typedef struct _GMemoryOutputStream GMemoryOutputStream;
|
||||||
@ -124,6 +125,8 @@ typedef struct _GNetworkAddress GNetworkAddress;
|
|||||||
typedef struct _GNetworkService GNetworkService;
|
typedef struct _GNetworkService GNetworkService;
|
||||||
typedef struct _GOutputStream GOutputStream;
|
typedef struct _GOutputStream GOutputStream;
|
||||||
typedef struct _GIOStream GIOStream;
|
typedef struct _GIOStream GIOStream;
|
||||||
|
typedef struct _GPollableInputStream GPollableInputStream; /* Dummy typedef */
|
||||||
|
typedef struct _GPollableOutputStream GPollableOutputStream; /* Dummy typedef */
|
||||||
typedef struct _GResolver GResolver;
|
typedef struct _GResolver GResolver;
|
||||||
typedef struct _GSeekable GSeekable;
|
typedef struct _GSeekable GSeekable;
|
||||||
typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
|
typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
|
||||||
@ -189,6 +192,7 @@ typedef struct _GSrvTarget GSrvTarget;
|
|||||||
* Since: 2.22
|
* Since: 2.22
|
||||||
**/
|
**/
|
||||||
typedef struct _GTcpConnection GTcpConnection;
|
typedef struct _GTcpConnection GTcpConnection;
|
||||||
|
typedef struct _GTcpWrapperConnection GTcpWrapperConnection;
|
||||||
/**
|
/**
|
||||||
* GThreadedSocketService:
|
* GThreadedSocketService:
|
||||||
*
|
*
|
||||||
@ -199,6 +203,13 @@ typedef struct _GTcpConnection GTcpConnection;
|
|||||||
**/
|
**/
|
||||||
typedef struct _GThreadedSocketService GThreadedSocketService;
|
typedef struct _GThreadedSocketService GThreadedSocketService;
|
||||||
typedef struct _GThemedIcon GThemedIcon;
|
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 */
|
typedef struct _GVfs GVfs; /* Dummy typedef */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -376,6 +387,37 @@ typedef struct _GDBusPropertyInfo GDBusPropertyInfo;
|
|||||||
typedef struct _GDBusInterfaceInfo GDBusInterfaceInfo;
|
typedef struct _GDBusInterfaceInfo GDBusInterfaceInfo;
|
||||||
typedef struct _GDBusNodeInfo GDBusNodeInfo;
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GIO_TYPES_H__ */
|
#endif /* __GIO_TYPES_H__ */
|
||||||
|
@ -1228,7 +1228,9 @@ start_element (GMarkupParseContext *context,
|
|||||||
OPTIONAL | STRING, "gettext-domain", &gettext_domain,
|
OPTIONAL | STRING, "gettext-domain", &gettext_domain,
|
||||||
OPTIONAL | STRING, "extends", &extends,
|
OPTIONAL | STRING, "extends", &extends,
|
||||||
OPTIONAL | STRING, "list-of", &list_of))
|
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);
|
extends, list_of, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
* of times per second and is capable of being put into synch with an
|
* of times per second and is capable of being put into synch with an
|
||||||
* external time source.
|
* 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".
|
* g_periodic_add() and are called each time the clock "ticks".
|
||||||
*
|
*
|
||||||
* The tick functions can report "damage" (ie: updates that need to be
|
* 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. */
|
/* We need to run. */
|
||||||
{
|
{
|
||||||
gint64 remaining;
|
gint64 remaining;
|
||||||
|
|
||||||
remaining = periodic->priv->last_run + 1000000 * (1 + periodic->priv->skip_frames) -
|
remaining = periodic->priv->last_run + 1000000 * (1 + periodic->priv->skip_frames) -
|
||||||
g_periodic_get_microticks (periodic);
|
g_periodic_get_microticks (periodic);
|
||||||
|
|
||||||
@ -354,8 +354,10 @@ g_periodic_dispatch (GSource *source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_periodic_get_property (GObject *object, guint prop_id,
|
g_periodic_get_property (GObject *object,
|
||||||
GValue *value, GParamSpec *pspec)
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GPeriodic *periodic = G_PERIODIC (object);
|
GPeriodic *periodic = G_PERIODIC (object);
|
||||||
|
|
||||||
@ -379,8 +381,10 @@ g_periodic_get_property (GObject *object, guint prop_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_periodic_set_property (GObject *object, guint prop_id,
|
g_periodic_set_property (GObject *object,
|
||||||
const GValue *value, GParamSpec *pspec)
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GPeriodic *periodic = G_PERIODIC (object);
|
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->set_property = g_periodic_set_property;
|
||||||
object_class->finalize = g_periodic_finalize;
|
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_periodic_tick = g_signal_new ("tick", G_TYPE_PERIODIC,
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET(GPeriodicClass, tick),
|
G_STRUCT_OFFSET(GPeriodicClass, tick),
|
||||||
NULL, NULL, _gio_marshal_VOID__INT64,
|
NULL, NULL, _gio_marshal_VOID__INT64,
|
||||||
G_TYPE_NONE, 1, G_TYPE_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_periodic_repair = g_signal_new ("repair", G_TYPE_PERIODIC,
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (GPeriodicClass, repair),
|
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
|
* Temporarily blocks @periodic from running in order to bring it in
|
||||||
* synch with an external time source.
|
* 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
|
* If this function is called, emission of the #GPeriodic::tick signal
|
||||||
* suspended until g_periodic_unblock() is called an equal number of
|
* will be suspended until g_periodic_unblock() is called an equal number
|
||||||
* times. Once that happens, the "tick" signal will run immediately and
|
* of times. Once that happens, the ::tick signal will run immediately
|
||||||
* future "tick" signals will be emitted relative to the time at which
|
* and future ::tick signals will be emitted relative to the time at
|
||||||
* the last call to g_periodic_unblock() occured.
|
* which the last call to g_periodic_unblock() occured.
|
||||||
*
|
*
|
||||||
* Since: 2.28
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
@ -510,9 +529,9 @@ g_periodic_block (GPeriodic *periodic)
|
|||||||
*
|
*
|
||||||
* Reverses the effect of a previous call to g_periodic_block().
|
* Reverses the effect of a previous call to g_periodic_block().
|
||||||
*
|
*
|
||||||
* If this call removes the last block, the tick signal is immediately
|
* If this call removes the last block, the ::tick signal is
|
||||||
* run. The repair signal may also be run if the clock is marked as
|
* immediately run. The ::repair signal may also be run if the clock
|
||||||
* damaged.
|
* is marked as damaged.
|
||||||
*
|
*
|
||||||
* @unblock_time is the monotonic time, as per g_get_monotonic_time(),
|
* @unblock_time is the monotonic time, as per g_get_monotonic_time(),
|
||||||
* at which the event causing the unblock occured.
|
* at which the event causing the unblock occured.
|
||||||
@ -545,20 +564,21 @@ g_periodic_unblock (GPeriodic *periodic,
|
|||||||
* @user_data: data for @callback
|
* @user_data: data for @callback
|
||||||
* @notify: for freeing @user_data when it is no longer needed
|
* @notify: for freeing @user_data when it is no longer needed
|
||||||
*
|
*
|
||||||
* Request periodic calls to @callback to start. The periodicity of the
|
* Request periodic calls to @callback to start. The periodicity of
|
||||||
* calls is determined by the 'hz' property.
|
* the calls is determined by the #GPeriodic:hz property.
|
||||||
*
|
*
|
||||||
* This function may not be called from a handler of the repair signal,
|
* This function may not be called from a handler of the ::repair
|
||||||
* but it is perfectly reasonable to call it from a handler of the tick
|
* signal, but it is perfectly reasonable to call it from a handler
|
||||||
* signal.
|
* of the ::tick signal.
|
||||||
*
|
*
|
||||||
* The callback may be cancelled later by using g_periodic_remove() on
|
* The callback may be cancelled later by using g_periodic_remove()
|
||||||
* the return value of this function.
|
* on the return value of this function.
|
||||||
*
|
*
|
||||||
* Returns: a non-zero tag identifying this callback
|
* Returns: a non-zero tag identifying this callback
|
||||||
*
|
*
|
||||||
* Since: 2.28
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GPeriodicTickFunc:
|
* GPeriodicTickFunc:
|
||||||
* @periodic: the #GPeriodic clock that is ticking
|
* @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
|
* The signature of the callback function that is called when the
|
||||||
* #GPeriodic clock ticks.
|
* #GPeriodic clock ticks.
|
||||||
*
|
*
|
||||||
* The @timestamp parameter is equal for all callbacks called during a
|
* The @timestamp parameter is equal for all callbacks called during
|
||||||
* particular tick on a given clock.
|
* a particular tick on a given clock.
|
||||||
*
|
*
|
||||||
* Since: 2.28
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
@ -605,9 +625,9 @@ g_periodic_add (GPeriodic *periodic,
|
|||||||
*
|
*
|
||||||
* @tag is the ID returned by that function.
|
* @tag is the ID returned by that function.
|
||||||
*
|
*
|
||||||
* This function may not be called from a handler of the repair signal,
|
* This function may not be called from a handler of the ::repair
|
||||||
* but it is perfectly reasonable to call it from a handler of the tick
|
* signal, but it is perfectly reasonable to call it from a handler
|
||||||
* signal.
|
* of the ::tick signal.
|
||||||
*
|
*
|
||||||
* Since: 2.28
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
@ -626,7 +646,7 @@ g_periodic_remove (GPeriodic *periodic,
|
|||||||
|
|
||||||
if (tick->id == tag)
|
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);
|
*iter = g_slist_remove (*iter, tick);
|
||||||
|
|
||||||
if (tick->notify)
|
if (tick->notify)
|
||||||
@ -644,8 +664,8 @@ g_periodic_remove (GPeriodic *periodic,
|
|||||||
* g_periodic_damaged:
|
* g_periodic_damaged:
|
||||||
* @periodic: a #GPeriodic clock
|
* @periodic: a #GPeriodic clock
|
||||||
*
|
*
|
||||||
* Report damage and schedule the "repair" signal to be emitted during
|
* Report damage and schedule the ::repair signal to be emitted
|
||||||
* the next repair phase.
|
* during the next repair phase.
|
||||||
*
|
*
|
||||||
* You may not call this function during the 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.
|
* 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
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
@ -713,13 +733,14 @@ g_periodic_get_low_priority (GPeriodic *periodic)
|
|||||||
/**
|
/**
|
||||||
* g_periodic_new:
|
* g_periodic_new:
|
||||||
* @hz: the frequency of the new clock in Hz (between 1 and 120)
|
* @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.
|
* Creates a new #GPeriodic clock.
|
||||||
*
|
*
|
||||||
* The created clock is attached to the thread-default main context in
|
* The created clock is attached to the thread-default main context
|
||||||
* effect at the time of the call to this function. See
|
* in effect at the time of the call to this function.
|
||||||
* g_main_context_push_thread_default() for more information.
|
* See g_main_context_push_thread_default() for more information.
|
||||||
*
|
*
|
||||||
* Due to the fact that #GMainContext is only accurate to the nearest
|
* Due to the fact that #GMainContext is only accurate to the nearest
|
||||||
* millisecond, the frequency can not meaningfully get too close to
|
* millisecond, the frequency can not meaningfully get too close to
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION:gpermission
|
* SECTION:gpermission
|
||||||
* @title: 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 certain action
|
||||||
*
|
*
|
||||||
* A #GPermission represents the status of the caller's permission to
|
* 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
|
* 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
|
* The #GSettings class provides a convenient API for storing and retrieving
|
||||||
* application settings.
|
* application settings.
|
||||||
@ -436,6 +436,10 @@ g_settings_get_property (GObject *object,
|
|||||||
g_value_set_string (value, settings->priv->schema_name);
|
g_value_set_string (value, settings->priv->schema_name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_BACKEND:
|
||||||
|
g_value_set_object (value, settings->priv->backend);
|
||||||
|
break;
|
||||||
|
|
||||||
case PROP_PATH:
|
case PROP_PATH:
|
||||||
g_value_set_string (value, settings->priv->path);
|
g_value_set_string (value, settings->priv->path);
|
||||||
break;
|
break;
|
||||||
@ -2202,7 +2206,7 @@ g_settings_list_keys (GSettings *settings)
|
|||||||
* time and you should connect to the "children-changed" signal to watch
|
* 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
|
* 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
|
* 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.
|
* %NULL even for a child that was listed by this function.
|
||||||
*
|
*
|
||||||
* For GSettings objects that are not lists, you should probably not be
|
* For GSettings objects that are not lists, you should probably not be
|
||||||
|
@ -49,7 +49,7 @@ struct _GSettingsBackendPrivate
|
|||||||
/**
|
/**
|
||||||
* SECTION:gsettingsbackend
|
* SECTION:gsettingsbackend
|
||||||
* @title: GSettingsBackend
|
* @title: GSettingsBackend
|
||||||
* @short_description: an interface for settings backend implementations
|
* @short_description: Interface for settings backend implementations
|
||||||
* @include: gio/gsettingsbackend.h
|
* @include: gio/gsettingsbackend.h
|
||||||
* @see_also: #GSettings, #GIOExtensionPoint
|
* @see_also: #GSettings, #GIOExtensionPoint
|
||||||
*
|
*
|
||||||
|
@ -138,6 +138,8 @@ ensure_schema_lists (void)
|
|||||||
g_hash_table_insert (single, g_strdup (list[i]), NULL);
|
g_hash_table_insert (single, g_strdup (list[i]), NULL);
|
||||||
else
|
else
|
||||||
g_hash_table_insert (reloc, g_strdup (list[i]), NULL);
|
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
|
* SECTION:gsimpleaction
|
||||||
* @title: GSimpleAction
|
* @title: GSimpleAction
|
||||||
* @short_description: a simple GSimpleAction
|
* @short_description: A simple GSimpleAction
|
||||||
*
|
*
|
||||||
* A #GSimpleAction is the obvious simple implementation of the #GSimpleAction
|
* A #GSimpleAction is the obvious simple implementation of the #GSimpleAction
|
||||||
* interface. This is the easiest way to create an action for purposes of
|
* interface. This is the easiest way to create an action for purposes of
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION:gsimpleactiongroup
|
* SECTION:gsimpleactiongroup
|
||||||
* @title: GSimpleActionGroup
|
* @title: GSimpleActionGroup
|
||||||
* @short_description: a simple GActionGroup implementation
|
* @short_description: A simple GActionGroup implementation
|
||||||
*
|
*
|
||||||
* #GSimpleActionGroup is a hash table filled with #GAction objects,
|
* #GSimpleActionGroup is a hash table filled with #GAction objects,
|
||||||
* implementing the #GActionGroup interface.
|
* implementing the #GActionGroup interface.
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION:gsimplepermission
|
* SECTION:gsimplepermission
|
||||||
* @title: 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
|
* #GSimplePermission is a trivial implementation of #GPermission that
|
||||||
* represents a permission that is either always or never allowed. The
|
* represents a permission that is either always or never allowed. The
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "gioerror.h"
|
#include "gioerror.h"
|
||||||
#include "gioenums.h"
|
#include "gioenums.h"
|
||||||
#include "gioerror.h"
|
#include "gioerror.h"
|
||||||
|
#include "gio-marshal.h"
|
||||||
#include "gnetworkingprivate.h"
|
#include "gnetworkingprivate.h"
|
||||||
#include "gsocketaddress.h"
|
#include "gsocketaddress.h"
|
||||||
#include "gsocketcontrolmessage.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 =
|
static GSourceFuncs socket_source_funcs =
|
||||||
{
|
{
|
||||||
socket_source_prepare,
|
socket_source_prepare,
|
||||||
socket_source_check,
|
socket_source_check,
|
||||||
socket_source_dispatch,
|
socket_source_dispatch,
|
||||||
socket_source_finalize
|
socket_source_finalize,
|
||||||
|
(GSourceFunc)socket_source_closure_callback,
|
||||||
|
(GSourceDummyMarshal)_gio_marshal_BOOLEAN__FLAGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GSource *
|
static GSource *
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <gio/gsocketconnection.h>
|
#include <gio/gsocketconnection.h>
|
||||||
#include <gio/gproxyaddressenumerator.h>
|
#include <gio/gproxyaddressenumerator.h>
|
||||||
#include <gio/gproxyaddress.h>
|
#include <gio/gproxyaddress.h>
|
||||||
#include <gio/gproxyconnection.h>
|
|
||||||
#include <gio/gsimpleasyncresult.h>
|
#include <gio/gsimpleasyncresult.h>
|
||||||
#include <gio/gcancellable.h>
|
#include <gio/gcancellable.h>
|
||||||
#include <gio/gioerror.h>
|
#include <gio/gioerror.h>
|
||||||
@ -44,6 +43,9 @@
|
|||||||
#include <gio/gproxy.h>
|
#include <gio/gproxy.h>
|
||||||
#include <gio/gsocketaddress.h>
|
#include <gio/gsocketaddress.h>
|
||||||
#include <gio/gtcpconnection.h>
|
#include <gio/gtcpconnection.h>
|
||||||
|
#include <gio/gtcpwrapperconnection.h>
|
||||||
|
#include <gio/gtlscertificate.h>
|
||||||
|
#include <gio/gtlsclientconnection.h>
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
|
|
||||||
@ -79,6 +81,8 @@ enum
|
|||||||
PROP_LOCAL_ADDRESS,
|
PROP_LOCAL_ADDRESS,
|
||||||
PROP_TIMEOUT,
|
PROP_TIMEOUT,
|
||||||
PROP_ENABLE_PROXY,
|
PROP_ENABLE_PROXY,
|
||||||
|
PROP_TLS,
|
||||||
|
PROP_TLS_VALIDATION_FLAGS
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSocketClientPrivate
|
struct _GSocketClientPrivate
|
||||||
@ -90,6 +94,8 @@ struct _GSocketClientPrivate
|
|||||||
guint timeout;
|
guint timeout;
|
||||||
gboolean enable_proxy;
|
gboolean enable_proxy;
|
||||||
GHashTable *app_proxies;
|
GHashTable *app_proxies;
|
||||||
|
gboolean tls;
|
||||||
|
GTlsCertificateFlags tls_validation_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GSocket *
|
static GSocket *
|
||||||
@ -218,6 +224,14 @@ g_socket_client_get_property (GObject *object,
|
|||||||
g_value_set_boolean (value, client->priv->enable_proxy);
|
g_value_set_boolean (value, client->priv->enable_proxy);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
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));
|
g_socket_client_set_enable_proxy (client, g_value_get_boolean (value));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
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_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
|
static void
|
||||||
g_socket_client_class_init (GSocketClientClass *class)
|
g_socket_client_class_init (GSocketClientClass *class)
|
||||||
{
|
{
|
||||||
@ -593,6 +700,23 @@ g_socket_client_class_init (GSocketClientClass *class)
|
|||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
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,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GSocketConnection *connection = NULL;
|
GIOStream *connection = NULL;
|
||||||
GSocketAddressEnumerator *enumerator = NULL;
|
GSocketAddressEnumerator *enumerator = NULL;
|
||||||
GError *last_error, *tmp_error;
|
GError *last_error, *tmp_error;
|
||||||
|
|
||||||
@ -679,14 +803,15 @@ g_socket_client_connect (GSocketClient *client,
|
|||||||
g_clear_error (&last_error);
|
g_clear_error (&last_error);
|
||||||
|
|
||||||
socket = create_socket (client, address, &last_error);
|
socket = create_socket (client, address, &last_error);
|
||||||
if (socket != NULL)
|
if (socket == NULL)
|
||||||
{
|
{
|
||||||
if (g_socket_connect (socket, address, cancellable, &last_error))
|
g_object_unref (address);
|
||||||
connection = g_socket_connection_factory_create_connection (socket);
|
continue;
|
||||||
|
|
||||||
g_object_unref (socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_socket_connect (socket, address, cancellable, &last_error))
|
||||||
|
connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
|
||||||
|
|
||||||
if (connection &&
|
if (connection &&
|
||||||
G_IS_PROXY_ADDRESS (address) &&
|
G_IS_PROXY_ADDRESS (address) &&
|
||||||
client->priv->enable_proxy)
|
client->priv->enable_proxy)
|
||||||
@ -715,31 +840,15 @@ g_socket_client_connect (GSocketClient *client,
|
|||||||
}
|
}
|
||||||
else if (proxy)
|
else if (proxy)
|
||||||
{
|
{
|
||||||
GIOStream *io_stream;
|
GIOStream *proxy_connection;
|
||||||
GTcpConnection *old_connection = G_TCP_CONNECTION (connection);
|
|
||||||
|
|
||||||
io_stream = g_proxy_connect (proxy,
|
proxy_connection = g_proxy_connect (proxy,
|
||||||
G_IO_STREAM (old_connection),
|
connection,
|
||||||
proxy_addr,
|
proxy_addr,
|
||||||
cancellable,
|
cancellable,
|
||||||
&last_error);
|
&last_error);
|
||||||
|
g_object_unref (connection);
|
||||||
if (io_stream)
|
connection = proxy_connection;
|
||||||
{
|
|
||||||
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);
|
|
||||||
g_object_unref (proxy);
|
g_object_unref (proxy);
|
||||||
}
|
}
|
||||||
else if (!g_hash_table_lookup_extended (client->priv->app_proxies,
|
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 (address);
|
||||||
}
|
}
|
||||||
g_object_unref (enumerator);
|
g_object_unref (enumerator);
|
||||||
|
|
||||||
return connection;
|
return G_SOCKET_CONNECTION (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -925,10 +1064,11 @@ typedef struct
|
|||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GSocketClient *client;
|
GSocketClient *client;
|
||||||
|
|
||||||
|
GSocketConnectable *connectable;
|
||||||
GSocketAddressEnumerator *enumerator;
|
GSocketAddressEnumerator *enumerator;
|
||||||
GProxyAddress *proxy_addr;
|
GProxyAddress *proxy_addr;
|
||||||
GSocket *current_socket;
|
GSocket *current_socket;
|
||||||
GSocketConnection *connection;
|
GIOStream *connection;
|
||||||
|
|
||||||
GError *last_error;
|
GError *last_error;
|
||||||
} GSocketClientAsyncConnectData;
|
} GSocketClientAsyncConnectData;
|
||||||
@ -944,6 +1084,16 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
|
|||||||
{
|
{
|
||||||
g_assert (data->connection);
|
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,
|
g_simple_async_result_set_op_res_gpointer (data->result,
|
||||||
data->connection,
|
data->connection,
|
||||||
g_object_unref);
|
g_object_unref);
|
||||||
@ -951,6 +1101,7 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
|
|||||||
|
|
||||||
g_simple_async_result_complete (data->result);
|
g_simple_async_result_complete (data->result);
|
||||||
g_object_unref (data->result);
|
g_object_unref (data->result);
|
||||||
|
g_object_unref (data->connectable);
|
||||||
g_object_unref (data->enumerator);
|
g_object_unref (data->enumerator);
|
||||||
if (data->cancellable)
|
if (data->cancellable)
|
||||||
g_object_unref (data->cancellable);
|
g_object_unref (data->cancellable);
|
||||||
@ -984,44 +1135,104 @@ enumerator_next_async (GSocketClientAsyncConnectData *data)
|
|||||||
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
|
static void
|
||||||
g_socket_client_proxy_connect_callback (GObject *object,
|
g_socket_client_proxy_connect_callback (GObject *object,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSocketClientAsyncConnectData *data = 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),
|
g_object_unref (data->connection);
|
||||||
result,
|
data->connection = g_proxy_connect_finish (G_PROXY (object),
|
||||||
&data->last_error);
|
result,
|
||||||
|
&data->last_error);
|
||||||
|
if (!data->connection)
|
||||||
|
{
|
||||||
|
g_object_unref (data->current_socket);
|
||||||
|
data->current_socket = NULL;
|
||||||
|
|
||||||
if (io_stream)
|
enumerator_next_async (data);
|
||||||
{
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref (old_connection);
|
g_socket_client_tls_handshake (data);
|
||||||
|
|
||||||
g_socket_client_async_connect_complete (data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
|
g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
|
||||||
{
|
{
|
||||||
GProxy *proxy;
|
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);
|
proxy = g_proxy_get_default_for_protocol (protocol);
|
||||||
|
|
||||||
/* The connection should not be anything else then TCP Connection,
|
/* 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);
|
g_object_unref (data->connection);
|
||||||
data->connection = NULL;
|
data->connection = NULL;
|
||||||
|
g_object_unref (data->current_socket);
|
||||||
|
data->current_socket = NULL;
|
||||||
|
|
||||||
enumerator_next_async (data);
|
enumerator_next_async (data);
|
||||||
}
|
}
|
||||||
else if (proxy)
|
else if (proxy)
|
||||||
{
|
{
|
||||||
g_proxy_connect_async (proxy,
|
g_proxy_connect_async (proxy,
|
||||||
G_IO_STREAM (data->connection),
|
data->connection,
|
||||||
data->proxy_addr,
|
data->proxy_addr,
|
||||||
data->cancellable,
|
data->cancellable,
|
||||||
g_socket_client_proxy_connect_callback,
|
g_socket_client_proxy_connect_callback,
|
||||||
@ -1060,8 +1273,12 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
|
|||||||
_("Proxy protocol '%s' is not supported."),
|
_("Proxy protocol '%s' is not supported."),
|
||||||
protocol);
|
protocol);
|
||||||
|
|
||||||
|
g_object_unref (data->current_socket);
|
||||||
|
data->current_socket = NULL;
|
||||||
g_object_unref (data->connection);
|
g_object_unref (data->connection);
|
||||||
data->connection = NULL;
|
data->connection = NULL;
|
||||||
|
g_object_unref (data->current_socket);
|
||||||
|
data->current_socket = NULL;
|
||||||
|
|
||||||
enumerator_next_async (data);
|
enumerator_next_async (data);
|
||||||
}
|
}
|
||||||
@ -1072,15 +1289,10 @@ g_socket_client_socket_connected (GSocketClientAsyncConnectData *data)
|
|||||||
{
|
{
|
||||||
g_socket_set_blocking (data->current_socket, TRUE);
|
g_socket_set_blocking (data->current_socket, TRUE);
|
||||||
|
|
||||||
data->connection =
|
data->connection = (GIOStream *)
|
||||||
g_socket_connection_factory_create_connection (data->current_socket);
|
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);
|
||||||
g_socket_client_proxy_connect (data);
|
|
||||||
else
|
|
||||||
g_socket_client_async_connect_complete (data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1237,6 +1449,10 @@ g_socket_client_connect_async (GSocketClient *client,
|
|||||||
data->client = client;
|
data->client = client;
|
||||||
if (cancellable)
|
if (cancellable)
|
||||||
data->cancellable = g_object_ref (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))
|
if (can_use_proxy (client))
|
||||||
data->enumerator = g_socket_connectable_proxy_enumerate (connectable);
|
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,
|
void g_socket_client_set_enable_proxy (GSocketClient *client,
|
||||||
gboolean enable);
|
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,
|
GSocketConnection * g_socket_client_connect (GSocketClient *client,
|
||||||
GSocketConnectable *connectable,
|
GSocketConnectable *connectable,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
|
@ -60,8 +60,7 @@
|
|||||||
* Since: 2.22
|
* Since: 2.22
|
||||||
*/
|
*/
|
||||||
|
|
||||||
G_DEFINE_TYPE (GSocketConnection,
|
G_DEFINE_TYPE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM);
|
||||||
g_socket_connection, G_TYPE_IO_STREAM);
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -27,13 +27,18 @@
|
|||||||
#include "gsocketinputstream.h"
|
#include "gsocketinputstream.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
#include <gio/gsimpleasyncresult.h>
|
#include "gsimpleasyncresult.h"
|
||||||
#include <gio/gcancellable.h>
|
#include "gcancellable.h"
|
||||||
#include <gio/gioerror.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
|
#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
|
enum
|
||||||
{
|
{
|
||||||
@ -205,6 +210,44 @@ g_socket_input_stream_read_finish (GInputStream *stream,
|
|||||||
return count;
|
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
|
static void
|
||||||
g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
|
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));
|
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
|
static void
|
||||||
g_socket_input_stream_init (GSocketInputStream *stream)
|
g_socket_input_stream_init (GSocketInputStream *stream)
|
||||||
{
|
{
|
||||||
|
@ -28,14 +28,20 @@
|
|||||||
#include "gsocketoutputstream.h"
|
#include "gsocketoutputstream.h"
|
||||||
#include "gsocket.h"
|
#include "gsocket.h"
|
||||||
|
|
||||||
#include <gio/gsimpleasyncresult.h>
|
#include "gsimpleasyncresult.h"
|
||||||
#include <gio/gcancellable.h>
|
#include "gcancellable.h"
|
||||||
#include <gio/gioerror.h>
|
#include "gpollableinputstream.h"
|
||||||
|
#include "gpollableoutputstream.h"
|
||||||
|
#include "gioerror.h"
|
||||||
#include "glibintl.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
|
#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
|
enum
|
||||||
{
|
{
|
||||||
@ -207,6 +213,44 @@ g_socket_output_stream_write_finish (GOutputStream *stream,
|
|||||||
return count;
|
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
|
static void
|
||||||
g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
|
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));
|
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
|
static void
|
||||||
g_socket_output_stream_init (GSocketOutputStream *stream)
|
g_socket_output_stream_init (GSocketOutputStream *stream)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +176,7 @@ parse_nego_reply (const guint8 *data,
|
|||||||
case SOCKS5_AUTH_NO_ACCEPT:
|
case SOCKS5_AUTH_NO_ACCEPT:
|
||||||
default:
|
default:
|
||||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED,
|
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."));
|
"supported by GLib."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION: gtcpconnection
|
* SECTION: gtcpconnection
|
||||||
* @title: GTcpConnection
|
* @title: GTcpConnection
|
||||||
* @short_description: a TCP GSocketConnection
|
* @short_description: A TCP GSocketConnection
|
||||||
* @see_also: #GSocketConnection.
|
* @see_also: #GSocketConnection.
|
||||||
*
|
*
|
||||||
* This is the subclass of #GSocketConnection that is created
|
* 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
|
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 {
|
struct _GUnixInputStreamPrivate {
|
||||||
int fd;
|
int fd;
|
||||||
@ -111,6 +116,9 @@ static gboolean g_unix_input_stream_close_finish (GInputStream *stream,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
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
|
static void
|
||||||
g_unix_input_stream_finalize (GObject *object)
|
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));
|
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
|
static void
|
||||||
g_unix_input_stream_set_property (GObject *object,
|
g_unix_input_stream_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -422,9 +437,9 @@ typedef struct {
|
|||||||
} ReadAsyncData;
|
} ReadAsyncData;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
read_async_cb (ReadAsyncData *data,
|
read_async_cb (int fd,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
int fd)
|
ReadAsyncData *data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *simple;
|
GSimpleAsyncResult *simple;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -637,3 +652,37 @@ g_unix_input_stream_close_finish (GInputStream *stream,
|
|||||||
/* Failures handled in generic close_finish code */
|
/* Failures handled in generic close_finish code */
|
||||||
return TRUE;
|
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
|
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 {
|
struct _GUnixOutputStreamPrivate {
|
||||||
int fd;
|
int fd;
|
||||||
@ -103,6 +107,9 @@ static gboolean g_unix_output_stream_close_finish (GOutputStream *stream,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
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
|
static void
|
||||||
g_unix_output_stream_finalize (GObject *object)
|
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));
|
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
|
static void
|
||||||
g_unix_output_stream_set_property (GObject *object,
|
g_unix_output_stream_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -409,9 +423,9 @@ typedef struct {
|
|||||||
} WriteAsyncData;
|
} WriteAsyncData;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
write_async_cb (WriteAsyncData *data,
|
write_async_cb (int fd,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
int fd)
|
WriteAsyncData *data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *simple;
|
GSimpleAsyncResult *simple;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -593,3 +607,37 @@ g_unix_output_stream_close_finish (GOutputStream *stream,
|
|||||||
/* Failures handled in generic close_finish code */
|
/* Failures handled in generic close_finish code */
|
||||||
return TRUE;
|
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);
|
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 *
|
GAppInfo *
|
||||||
g_app_info_get_default_for_type (const char *content_type,
|
g_app_info_get_default_for_type (const char *content_type,
|
||||||
gboolean must_support_uris)
|
gboolean must_support_uris)
|
||||||
|
1
gio/tests/.gitignore
vendored
1
gio/tests/.gitignore
vendored
@ -60,6 +60,7 @@ memory-input-stream
|
|||||||
memory-output-stream
|
memory-output-stream
|
||||||
network-address
|
network-address
|
||||||
org.gtk.test.enums.xml
|
org.gtk.test.enums.xml
|
||||||
|
pollable
|
||||||
proxy
|
proxy
|
||||||
readwrite
|
readwrite
|
||||||
resolver
|
resolver
|
||||||
|
@ -43,6 +43,7 @@ TEST_PROGS += \
|
|||||||
network-address \
|
network-address \
|
||||||
gdbus-message \
|
gdbus-message \
|
||||||
socket \
|
socket \
|
||||||
|
pollable \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
if OS_UNIX
|
if OS_UNIX
|
||||||
@ -204,6 +205,9 @@ network_address_LDADD = $(progs_ldadd)
|
|||||||
socket_SOURCE = socket.c
|
socket_SOURCE = socket.c
|
||||||
socket_LDADD = $(progs_ldadd)
|
socket_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
|
pollable_SOURCE = pollable.c
|
||||||
|
pollable_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
contexts_SOURCES = contexts.c
|
contexts_SOURCES = contexts.c
|
||||||
contexts_LDADD = $(progs_ldadd) \
|
contexts_LDADD = $(progs_ldadd) \
|
||||||
$(top_builddir)/gthread/libgthread-2.0.la
|
$(top_builddir)/gthread/libgthread-2.0.la
|
||||||
@ -370,6 +374,7 @@ schema_tests = \
|
|||||||
schema-tests/extending.gschema.xml \
|
schema-tests/extending.gschema.xml \
|
||||||
schema-tests/from-docs.gschema.xml \
|
schema-tests/from-docs.gschema.xml \
|
||||||
schema-tests/incomplete-list.gschema.xml \
|
schema-tests/incomplete-list.gschema.xml \
|
||||||
|
schema-tests/inherit-gettext-domain.gschema.xml \
|
||||||
schema-tests/invalid-path.gschema.xml \
|
schema-tests/invalid-path.gschema.xml \
|
||||||
schema-tests/key-in-list-indirect.gschema.xml \
|
schema-tests/key-in-list-indirect.gschema.xml \
|
||||||
schema-tests/key-in-list.gschema.xml \
|
schema-tests/key-in-list.gschema.xml \
|
||||||
|
@ -174,6 +174,77 @@ test_default (void)
|
|||||||
g_object_unref (info2);
|
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
|
static void
|
||||||
cleanup_dir_recurse (GFile *parent, GFile *root)
|
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/delete", test_delete);
|
||||||
g_test_add_func ("/desktop-app-info/default", test_default);
|
g_test_add_func ("/desktop-app-info/default", test_default);
|
||||||
|
g_test_add_func ("/desktop-app-info/fallback", test_fallback);
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ test_themed_icon (void)
|
|||||||
g_assert_cmpstr (names[0], ==, "first");
|
g_assert_cmpstr (names[0], ==, "first");
|
||||||
g_assert_cmpstr (names[1], ==, "testicon");
|
g_assert_cmpstr (names[1], ==, "testicon");
|
||||||
g_assert_cmpstr (names[2], ==, "last");
|
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);
|
icon2 = g_themed_icon_new_from_names ((gchar**)names2, -1);
|
||||||
g_assert (g_icon_equal (icon1, icon2));
|
g_assert (g_icon_equal (icon1, icon2));
|
||||||
@ -299,11 +299,11 @@ test_emblemed_icon (void)
|
|||||||
|
|
||||||
emblem = emblems->data;
|
emblem = emblems->data;
|
||||||
g_assert (g_emblem_get_icon (emblem) == icon2);
|
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;
|
emblem = emblems->next->data;
|
||||||
g_assert (g_emblem_get_icon (emblem) == icon2);
|
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 (icon1);
|
||||||
g_object_unref (icon2);
|
g_object_unref (icon2);
|
||||||
|
@ -46,7 +46,7 @@ static const SchemaTest tests[] = {
|
|||||||
{ "no-default", NULL, "*<default> is required in <key>*" },
|
{ "no-default", NULL, "*<default> is required in <key>*" },
|
||||||
{ "missing-quotes", NULL, "*unknown keyword*" },
|
{ "missing-quotes", NULL, "*unknown keyword*" },
|
||||||
{ "incomplete-list", NULL, "*to follow array element*" },
|
{ "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*" },
|
{ "bad-type", NULL, "*invalid GVariant type string*" },
|
||||||
{ "overflow", NULL, "*out of range*" },
|
{ "overflow", NULL, "*out of range*" },
|
||||||
{ "range-wrong-type", NULL, "*<range> not allowed for keys of type*" },
|
{ "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-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-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-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
|
int
|
||||||
main (int argc, char *argv[])
|
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>
|
<schemalist>
|
||||||
<schema id="wrong-category" path="/tests/" gettext-domain="test">
|
<schema id="wrong-category" path="/tests/" gettext-domain="test">
|
||||||
<key name="test" type="s" l10n="not-a-category">
|
<key name="test" type="s">
|
||||||
<default>'foo'</default>
|
<default l10n="not-a-category">'foo'</default>
|
||||||
</key>
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
</schemalist>
|
</schemalist>
|
||||||
|
@ -5,17 +5,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "socket-common.c"
|
|
||||||
|
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
|
|
||||||
gboolean verbose = FALSE;
|
gboolean verbose = FALSE;
|
||||||
gboolean non_blocking = FALSE;
|
gboolean non_blocking = FALSE;
|
||||||
gboolean use_udp = FALSE;
|
gboolean use_udp = FALSE;
|
||||||
gboolean use_source = FALSE;
|
|
||||||
int cancel_timeout = 0;
|
int cancel_timeout = 0;
|
||||||
int read_timeout = 0;
|
int read_timeout = 0;
|
||||||
gboolean unix_socket = FALSE;
|
gboolean unix_socket = FALSE;
|
||||||
|
gboolean tls = FALSE;
|
||||||
|
|
||||||
static GOptionEntry cmd_entries[] = {
|
static GOptionEntry cmd_entries[] = {
|
||||||
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
||||||
@ -26,70 +24,39 @@ static GOptionEntry cmd_entries[] = {
|
|||||||
"Be verbose", NULL},
|
"Be verbose", NULL},
|
||||||
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
||||||
"Enable non-blocking i/o", NULL},
|
"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
|
#ifdef G_OS_UNIX
|
||||||
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
|
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
|
||||||
"Use a unix socket instead of IP", NULL},
|
"Use a unix socket instead of IP", NULL},
|
||||||
#endif
|
#endif
|
||||||
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
|
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
|
||||||
"Time out reads after the specified number of seconds", NULL},
|
"Time out reads after the specified number of seconds", NULL},
|
||||||
|
{"tls", 'T', 0, G_OPTION_ARG_NONE, &tls,
|
||||||
|
"Use TLS (SSL)", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "socket-common.c"
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
source_ready (gpointer data,
|
accept_certificate (GTlsClientConnection *conn, GTlsCertificate *cert,
|
||||||
GIOCondition condition)
|
GTlsCertificateFlags errors, gpointer user_data)
|
||||||
{
|
{
|
||||||
g_main_loop_quit (loop);
|
g_print ("Certificate would have been rejected ( ");
|
||||||
return FALSE;
|
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
|
return TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -106,6 +73,9 @@ main (int argc,
|
|||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GSocketAddressEnumerator *enumerator;
|
GSocketAddressEnumerator *enumerator;
|
||||||
GSocketConnectable *connectable;
|
GSocketConnectable *connectable;
|
||||||
|
GIOStream *connection;
|
||||||
|
GInputStream *istream;
|
||||||
|
GOutputStream *ostream;
|
||||||
|
|
||||||
g_thread_init (NULL);
|
g_thread_init (NULL);
|
||||||
|
|
||||||
@ -125,6 +95,12 @@ main (int argc,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_udp && tls)
|
||||||
|
{
|
||||||
|
g_printerr ("DTLS (TLS over UDP) is not supported");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancel_timeout)
|
if (cancel_timeout)
|
||||||
{
|
{
|
||||||
cancellable = g_cancellable_new ();
|
cancellable = g_cancellable_new ();
|
||||||
@ -201,15 +177,10 @@ main (int argc,
|
|||||||
g_object_unref (address);
|
g_object_unref (address);
|
||||||
}
|
}
|
||||||
g_object_unref (enumerator);
|
g_object_unref (enumerator);
|
||||||
g_object_unref (connectable);
|
|
||||||
|
|
||||||
g_print ("Connected to %s\n",
|
g_print ("Connected to %s\n",
|
||||||
socket_address_to_string (address));
|
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);
|
src_address = g_socket_get_local_address (socket, &error);
|
||||||
if (!src_address)
|
if (!src_address)
|
||||||
{
|
{
|
||||||
@ -221,6 +192,49 @@ main (int argc,
|
|||||||
socket_address_to_string (src_address));
|
socket_address_to_string (src_address));
|
||||||
g_object_unref (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)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
gchar buffer[4096];
|
gchar buffer[4096];
|
||||||
@ -233,14 +247,20 @@ main (int argc,
|
|||||||
to_send = strlen (buffer);
|
to_send = strlen (buffer);
|
||||||
while (to_send > 0)
|
while (to_send > 0)
|
||||||
{
|
{
|
||||||
ensure_condition (socket, "send", cancellable, G_IO_OUT);
|
|
||||||
if (use_udp)
|
if (use_udp)
|
||||||
size = g_socket_send_to (socket, address,
|
{
|
||||||
buffer, to_send,
|
ensure_socket_condition (socket, G_IO_OUT, cancellable);
|
||||||
cancellable, &error);
|
size = g_socket_send_to (socket, address,
|
||||||
|
buffer, to_send,
|
||||||
|
cancellable, &error);
|
||||||
|
}
|
||||||
else
|
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)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
@ -272,14 +292,20 @@ main (int argc,
|
|||||||
to_send -= size;
|
to_send -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_condition (socket, "receive", cancellable, G_IO_IN);
|
|
||||||
if (use_udp)
|
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,
|
buffer, sizeof buffer,
|
||||||
cancellable, &error);
|
cancellable, &error);
|
||||||
else
|
}
|
||||||
size = g_socket_receive (socket, buffer, sizeof buffer,
|
|
||||||
cancellable, &error);
|
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
@ -306,15 +332,28 @@ main (int argc,
|
|||||||
|
|
||||||
g_print ("closing socket\n");
|
g_print ("closing socket\n");
|
||||||
|
|
||||||
if (!g_socket_close (socket, &error))
|
if (connection)
|
||||||
{
|
{
|
||||||
g_printerr ("Error closing master socket: %s\n",
|
if (!g_io_stream_close (connection, cancellable, &error))
|
||||||
error->message);
|
{
|
||||||
return 1;
|
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 (socket);
|
||||||
g_object_unref (G_OBJECT (address));
|
g_object_unref (address);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -58,3 +58,64 @@ socket_address_from_string (const char *name)
|
|||||||
#endif
|
#endif
|
||||||
return NULL;
|
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 <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "socket-common.c"
|
|
||||||
|
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
|
|
||||||
int port = 7777;
|
int port = 7777;
|
||||||
@ -13,11 +11,11 @@ gboolean verbose = FALSE;
|
|||||||
gboolean dont_reuse_address = FALSE;
|
gboolean dont_reuse_address = FALSE;
|
||||||
gboolean non_blocking = FALSE;
|
gboolean non_blocking = FALSE;
|
||||||
gboolean use_udp = FALSE;
|
gboolean use_udp = FALSE;
|
||||||
gboolean use_source = FALSE;
|
|
||||||
int cancel_timeout = 0;
|
int cancel_timeout = 0;
|
||||||
int read_timeout = 0;
|
int read_timeout = 0;
|
||||||
int delay = 0;
|
int delay = 0;
|
||||||
gboolean unix_socket = FALSE;
|
gboolean unix_socket = FALSE;
|
||||||
|
const char *tls_cert_file = NULL;
|
||||||
|
|
||||||
static GOptionEntry cmd_entries[] = {
|
static GOptionEntry cmd_entries[] = {
|
||||||
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
|
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
|
||||||
@ -32,8 +30,6 @@ static GOptionEntry cmd_entries[] = {
|
|||||||
"Don't SOADDRREUSE", NULL},
|
"Don't SOADDRREUSE", NULL},
|
||||||
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
||||||
"Enable non-blocking i/o", NULL},
|
"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
|
#ifdef G_OS_UNIX
|
||||||
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
|
{"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
|
||||||
"Use a unix socket instead of IP", NULL},
|
"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},
|
"Delay responses by the specified number of seconds", NULL},
|
||||||
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
|
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
|
||||||
"Time out reads after the specified number of seconds", NULL},
|
"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}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
#include "socket-common.c"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
@ -113,6 +58,10 @@ main (int argc,
|
|||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
char *display_addr;
|
char *display_addr;
|
||||||
|
GTlsCertificate *tlscert = NULL;
|
||||||
|
GIOStream *connection;
|
||||||
|
GInputStream *istream;
|
||||||
|
GOutputStream *ostream;
|
||||||
|
|
||||||
g_thread_init (NULL);
|
g_thread_init (NULL);
|
||||||
|
|
||||||
@ -142,6 +91,23 @@ main (int argc,
|
|||||||
cancellable = NULL;
|
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);
|
loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
if (use_udp)
|
if (use_udp)
|
||||||
@ -205,7 +171,7 @@ main (int argc,
|
|||||||
g_print ("listening on %s...\n", display_addr);
|
g_print ("listening on %s...\n", display_addr);
|
||||||
g_free (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);
|
new_socket = g_socket_accept (socket, cancellable, &error);
|
||||||
if (!new_socket)
|
if (!new_socket)
|
||||||
{
|
{
|
||||||
@ -233,13 +199,45 @@ main (int argc,
|
|||||||
g_object_unref (address);
|
g_object_unref (address);
|
||||||
|
|
||||||
recv_socket = new_socket;
|
recv_socket = new_socket;
|
||||||
|
|
||||||
|
connection = G_IO_STREAM (g_socket_connection_factory_create_connection (recv_socket));
|
||||||
|
g_object_unref (new_socket);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
recv_socket = socket;
|
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)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
@ -247,14 +245,20 @@ main (int argc,
|
|||||||
gssize size;
|
gssize size;
|
||||||
gsize to_send;
|
gsize to_send;
|
||||||
|
|
||||||
ensure_condition (recv_socket, "receive", cancellable, G_IO_IN);
|
|
||||||
if (use_udp)
|
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,
|
buffer, sizeof buffer,
|
||||||
cancellable, &error);
|
cancellable, &error);
|
||||||
else
|
}
|
||||||
size = g_socket_receive (recv_socket, buffer, sizeof buffer,
|
|
||||||
cancellable, &error);
|
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
@ -288,13 +292,19 @@ main (int argc,
|
|||||||
|
|
||||||
while (to_send > 0)
|
while (to_send > 0)
|
||||||
{
|
{
|
||||||
ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
|
|
||||||
if (use_udp)
|
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
|
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)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
@ -329,16 +339,15 @@ main (int argc,
|
|||||||
|
|
||||||
g_print ("connection closed\n");
|
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);
|
error->message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
g_object_unref (connection);
|
||||||
g_object_unref (G_OBJECT (new_socket));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_socket_close (socket, &error))
|
if (!g_socket_close (socket, &error))
|
||||||
@ -347,8 +356,7 @@ main (int argc,
|
|||||||
error->message);
|
error->message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
g_object_unref (socket);
|
||||||
g_object_unref (G_OBJECT (socket));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1409,7 +1409,7 @@ g_date_time_equal (gconstpointer dt1,
|
|||||||
* g_date_time_get_ymd:
|
* g_date_time_get_ymd:
|
||||||
* @datetime: a #GDateTime.
|
* @datetime: a #GDateTime.
|
||||||
* @year: (out): the return location for the gregorian year, or %NULL.
|
* @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.
|
* @day: (out): the return location for the day of the month, or %NULL.
|
||||||
*
|
*
|
||||||
* Retrieves the Gregorian day, month, and year of a given #GDateTime.
|
* 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_ref
|
||||||
g_main_loop_run
|
g_main_loop_run
|
||||||
g_main_loop_unref
|
g_main_loop_unref
|
||||||
|
g_source_add_child_source
|
||||||
g_source_add_poll
|
g_source_add_poll
|
||||||
g_source_attach
|
g_source_attach
|
||||||
g_source_destroy
|
g_source_destroy
|
||||||
@ -739,6 +740,7 @@ g_source_ref
|
|||||||
g_source_remove
|
g_source_remove
|
||||||
g_source_remove_by_funcs_user_data
|
g_source_remove_by_funcs_user_data
|
||||||
g_source_remove_by_user_data
|
g_source_remove_by_user_data
|
||||||
|
g_source_remove_child_source
|
||||||
g_source_remove_poll
|
g_source_remove_poll
|
||||||
g_source_set_callback
|
g_source_set_callback
|
||||||
g_source_set_callback_indirect
|
g_source_set_callback_indirect
|
||||||
|
287
glib/gmain.c
287
glib/gmain.c
@ -313,6 +313,12 @@ struct _GPollRec
|
|||||||
gint priority;
|
gint priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _GSourcePrivate
|
||||||
|
{
|
||||||
|
GSList *child_sources;
|
||||||
|
GSource *parent_source;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef G_THREADS_ENABLED
|
#ifdef G_THREADS_ENABLED
|
||||||
#define LOCK_CONTEXT(context) g_static_mutex_lock (&context->mutex)
|
#define LOCK_CONTEXT(context) g_static_mutex_lock (&context->mutex)
|
||||||
#define UNLOCK_CONTEXT(context) g_static_mutex_unlock (&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,
|
static void g_source_destroy_internal (GSource *source,
|
||||||
GMainContext *context,
|
GMainContext *context,
|
||||||
gboolean have_lock);
|
gboolean have_lock);
|
||||||
|
static void g_source_set_priority_unlocked (GSource *source,
|
||||||
|
GMainContext *context,
|
||||||
|
gint priority);
|
||||||
static void g_main_context_poll (GMainContext *context,
|
static void g_main_context_poll (GMainContext *context,
|
||||||
gint timeout,
|
gint timeout,
|
||||||
gint priority,
|
gint priority,
|
||||||
@ -848,12 +857,21 @@ g_source_list_add (GSource *source,
|
|||||||
{
|
{
|
||||||
GSource *tmp_source, *last_source;
|
GSource *tmp_source, *last_source;
|
||||||
|
|
||||||
last_source = NULL;
|
if (source->priv && source->priv->parent_source)
|
||||||
tmp_source = context->source_list;
|
|
||||||
while (tmp_source && tmp_source->priority <= source->priority)
|
|
||||||
{
|
{
|
||||||
last_source = tmp_source;
|
/* Put the source immediately before its parent */
|
||||||
tmp_source = tmp_source->next;
|
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;
|
source->next = tmp_source;
|
||||||
@ -885,6 +903,39 @@ g_source_list_remove (GSource *source,
|
|||||||
source->next = NULL;
|
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:
|
* g_source_attach:
|
||||||
* @source: a #GSource
|
* @source: a #GSource
|
||||||
@ -901,7 +952,6 @@ g_source_attach (GSource *source,
|
|||||||
GMainContext *context)
|
GMainContext *context)
|
||||||
{
|
{
|
||||||
guint result = 0;
|
guint result = 0;
|
||||||
GSList *tmp_list;
|
|
||||||
|
|
||||||
g_return_val_if_fail (source->context == NULL, 0);
|
g_return_val_if_fail (source->context == NULL, 0);
|
||||||
g_return_val_if_fail (!SOURCE_DESTROYED (source), 0);
|
g_return_val_if_fail (!SOURCE_DESTROYED (source), 0);
|
||||||
@ -911,18 +961,7 @@ g_source_attach (GSource *source,
|
|||||||
|
|
||||||
LOCK_CONTEXT (context);
|
LOCK_CONTEXT (context);
|
||||||
|
|
||||||
source->context = context;
|
result = g_source_attach_unlocked (source, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef G_THREADS_ENABLED
|
#ifdef G_THREADS_ENABLED
|
||||||
/* Now wake up the main loop if it is waiting in the poll() */
|
/* 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;
|
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);
|
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:
|
* g_source_set_callback_indirect:
|
||||||
* @source: the source
|
* @source: the source
|
||||||
@ -1263,35 +1412,19 @@ g_source_set_funcs (GSource *source,
|
|||||||
source->source_funcs = funcs;
|
source->source_funcs = funcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* g_source_set_priority:
|
g_source_set_priority_unlocked (GSource *source,
|
||||||
* @source: a #GSource
|
GMainContext *context,
|
||||||
* @priority: the new priority.
|
gint 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)
|
|
||||||
{
|
{
|
||||||
GSList *tmp_list;
|
GSList *tmp_list;
|
||||||
GMainContext *context;
|
|
||||||
|
|
||||||
g_return_if_fail (source != NULL);
|
|
||||||
|
|
||||||
context = source->context;
|
|
||||||
|
|
||||||
if (context)
|
|
||||||
LOCK_CONTEXT (context);
|
|
||||||
|
|
||||||
source->priority = priority;
|
source->priority = priority;
|
||||||
|
|
||||||
if (context)
|
if (context)
|
||||||
{
|
{
|
||||||
/* Remove the source from the context's source and then
|
/* 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_remove (source, source->context);
|
||||||
g_source_list_add (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;
|
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_data = NULL;
|
||||||
source->callback_funcs = 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!");
|
if (!SOURCE_DESTROYED (source))
|
||||||
source->ref_count++;
|
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)
|
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);
|
g_free (source->name);
|
||||||
source->name = NULL;
|
source->name = NULL;
|
||||||
@ -2591,7 +2764,15 @@ g_main_context_prepare (GMainContext *context,
|
|||||||
context->in_check_or_prepare--;
|
context->in_check_or_prepare--;
|
||||||
|
|
||||||
if (result)
|
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)
|
if (source->flags & G_SOURCE_READY)
|
||||||
@ -2783,7 +2964,15 @@ g_main_context_check (GMainContext *context,
|
|||||||
context->in_check_or_prepare--;
|
context->in_check_or_prepare--;
|
||||||
|
|
||||||
if (result)
|
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)
|
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.
|
* representing an event source.
|
||||||
*/
|
*/
|
||||||
typedef struct _GSource GSource;
|
typedef struct _GSource GSource;
|
||||||
|
typedef struct _GSourcePrivate GSourcePrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GSourceCallbackFuncs:
|
* GSourceCallbackFuncs:
|
||||||
@ -157,7 +158,8 @@ struct _GSource
|
|||||||
GSource *next;
|
GSource *next;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
gpointer reserved2;
|
|
||||||
|
GSourcePrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSourceCallbackFuncs
|
struct _GSourceCallbackFuncs
|
||||||
@ -358,10 +360,15 @@ void g_source_set_callback_indirect (GSource *source,
|
|||||||
gpointer callback_data,
|
gpointer callback_data,
|
||||||
GSourceCallbackFuncs *callback_funcs);
|
GSourceCallbackFuncs *callback_funcs);
|
||||||
|
|
||||||
void g_source_add_poll (GSource *source,
|
void g_source_add_poll (GSource *source,
|
||||||
GPollFD *fd);
|
GPollFD *fd);
|
||||||
void g_source_remove_poll (GSource *source,
|
void g_source_remove_poll (GSource *source,
|
||||||
GPollFD *fd);
|
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
|
#ifndef G_DISABLE_DEPRECATED
|
||||||
void g_source_get_current_time (GSource *source,
|
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
|
* On UNIX platforms this is determined using the mechanisms described in
|
||||||
* the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
|
* the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
|
||||||
* XDG Base Directory Specification</ulink>. This is the directory
|
* XDG Base Directory Specification</ulink>. This is the directory
|
||||||
* specified in the XDG_RUNTIME_DIR environment variable. In the case
|
* specified in the <envar>XDG_RUNTIME_DIR</envar> environment variable.
|
||||||
* that this variable is not set, glib will issue a warning message to
|
* In the case that this variable is not set, GLib will issue a warning
|
||||||
* stderr and return the value of g_get_user_cache_dir().
|
* 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
|
* On Windows this is the folder to use for local (as opposed to
|
||||||
* roaming) application data. See documentation for
|
* roaming) application data. See documentation for
|
||||||
@ -2309,6 +2309,8 @@ g_get_user_cache_dir (void)
|
|||||||
* what g_get_user_config_dir() returns.
|
* what g_get_user_config_dir() returns.
|
||||||
*
|
*
|
||||||
* Returns: a string owned by GLib that must not be modified or freed.
|
* Returns: a string owned by GLib that must not be modified or freed.
|
||||||
|
*
|
||||||
|
* Since: 2.28
|
||||||
**/
|
**/
|
||||||
const gchar *
|
const gchar *
|
||||||
g_get_user_runtime_dir (void)
|
g_get_user_runtime_dir (void)
|
||||||
|
@ -134,13 +134,13 @@ void g_variant_get_child (GVarian
|
|||||||
...);
|
...);
|
||||||
GVariant * g_variant_get_child_value (GVariant *value,
|
GVariant * g_variant_get_child_value (GVariant *value,
|
||||||
gsize index_);
|
gsize index_);
|
||||||
gboolean g_variant_lookup (GVariant *value,
|
gboolean g_variant_lookup (GVariant *dictionary,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
const gchar *format_string,
|
const gchar *format_string,
|
||||||
...);
|
...);
|
||||||
GVariant * g_variant_lookup_value (GVariant *value,
|
GVariant * g_variant_lookup_value (GVariant *dictionary,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
const GVariantType *type);
|
const GVariantType *expected_type);
|
||||||
gconstpointer g_variant_get_fixed_array (GVariant *value,
|
gconstpointer g_variant_get_fixed_array (GVariant *value,
|
||||||
gsize *n_elements,
|
gsize *n_elements,
|
||||||
gsize element_size);
|
gsize element_size);
|
||||||
|
@ -1565,6 +1565,7 @@ g_object_new_valist (GType object_type,
|
|||||||
{
|
{
|
||||||
n_alloced_params += 16;
|
n_alloced_params += 16;
|
||||||
params = g_renew (GParameter, params, n_alloced_params);
|
params = g_renew (GParameter, params, n_alloced_params);
|
||||||
|
memset (params + n_params, 0, 16 * (sizeof *params));
|
||||||
}
|
}
|
||||||
params[n_params].name = name;
|
params[n_params].name = name;
|
||||||
G_VALUE_COLLECT_INIT (¶ms[n_params].value, pspec->value_type,
|
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_channel_get_type
|
||||||
g_io_condition_get_type
|
g_io_condition_get_type
|
||||||
g_source_set_closure
|
g_source_set_closure
|
||||||
|
g_source_set_dummy_callback
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ g_source_set_closure (GSource *source,
|
|||||||
source->source_funcs != &g_timeout_funcs &&
|
source->source_funcs != &g_timeout_funcs &&
|
||||||
source->source_funcs != &g_idle_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,3 +191,40 @@ g_source_set_closure (GSource *source,
|
|||||||
g_closure_set_marshal (closure, marshal);
|
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
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void g_source_set_closure (GSource *source,
|
void g_source_set_closure (GSource *source,
|
||||||
GClosure *closure);
|
GClosure *closure);
|
||||||
|
|
||||||
|
void g_source_set_dummy_callback (GSource *source);
|
||||||
|
|
||||||
GType g_io_channel_get_type (void);
|
GType g_io_channel_get_type (void);
|
||||||
GType g_io_condition_get_type (void);
|
GType g_io_condition_get_type (void);
|
||||||
|
@ -207,6 +207,42 @@ properties_notify (void)
|
|||||||
g_object_unref (obj);
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
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/install", properties_install);
|
||||||
g_test_add_func ("/properties/notify", properties_notify);
|
g_test_add_func ("/properties/notify", properties_notify);
|
||||||
|
g_test_add_func ("/properties/construct", properties_construct);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,6 @@ gio/gpermission.c
|
|||||||
gio/gpollfilemonitor.c
|
gio/gpollfilemonitor.c
|
||||||
gio/gproxyaddress.c
|
gio/gproxyaddress.c
|
||||||
gio/gproxyaddressenumerator.c
|
gio/gproxyaddressenumerator.c
|
||||||
gio/gproxyconnection.c
|
|
||||||
gio/gresolver.c
|
gio/gresolver.c
|
||||||
gio/gseekable.c
|
gio/gseekable.c
|
||||||
gio/gsettingsbackend.c
|
gio/gsettingsbackend.c
|
||||||
@ -114,6 +113,10 @@ gio/gsocks5proxy.c
|
|||||||
gio/gtcpconnection.c
|
gio/gtcpconnection.c
|
||||||
gio/gthemedicon.c
|
gio/gthemedicon.c
|
||||||
gio/gthreadedsocketservice.c
|
gio/gthreadedsocketservice.c
|
||||||
|
gio/gtlscertificate.c
|
||||||
|
gio/gtlsclientconnection.c
|
||||||
|
gio/gtlsconnection.c
|
||||||
|
gio/gtlsserverconnection.c
|
||||||
gio/gunionvolumemonitor.c
|
gio/gunionvolumemonitor.c
|
||||||
gio/gunixconnection.c
|
gio/gunixconnection.c
|
||||||
gio/gunixcredentialsmessage.c
|
gio/gunixcredentialsmessage.c
|
||||||
|
2
po/ar.po
2
po/ar.po
@ -3205,7 +3205,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: gio/gsocks5proxy.c:179
|
#: gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: gio/gsocks5proxy.c:208
|
#: gio/gsocks5proxy.c:208
|
||||||
|
2
po/be.po
2
po/be.po
@ -3636,7 +3636,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:179
|
#: ../gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:208
|
#: ../gio/gsocks5proxy.c:208
|
||||||
|
2
po/bg.po
2
po/bg.po
@ -3411,7 +3411,7 @@ msgstr "Посредникът чрез SOCKSv5 изисква идентифи
|
|||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:179
|
#: ../gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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 ""
|
msgstr ""
|
||||||
"Посредникът чрез SOCKSv5 изисква механизъм за идентификация, който не се "
|
"Посредникът чрез SOCKSv5 изисква механизъм за идентификация, който не се "
|
||||||
"поддържа от GLib."
|
"поддържа от GLib."
|
||||||
|
@ -3351,7 +3351,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:179
|
#: ../gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:208
|
#: ../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
|
#: ../gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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."
|
msgstr "SOCKSv5 vyžaduje metodu ověření nepodporovanou v GLib."
|
||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:208
|
#: ../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
|
#: ../gio/gsocks5proxy.c:179
|
||||||
msgid ""
|
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."
|
msgstr "SOCKSv5 kræver en godkendelsesmetode, der ikke understøttes af GLib."
|
||||||
|
|
||||||
#: ../gio/gsocks5proxy.c:208
|
#: ../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