1
0
mirror of https://gitlab.gnome.org/GNOME/glib.git synced 2025-07-25 19:37:52 +02:00
Files
.gitlab-ci
.reuse
LICENSES
docs
fuzzing
gio
completion
gdbus-2.0
inotify
kqueue
tests
win32
xdgmime
data-to-c.py
dbus-daemon.xml
gaction.c
gaction.h
gactiongroup.c
gactiongroup.h
gactiongroupexporter.c
gactiongroupexporter.h
gactionmap.c
gactionmap.h
gappinfo.c
gappinfo.h
gappinfoprivate.h
gapplication-tool.c
gapplication.c
gapplication.h
gapplicationcommandline.c
gapplicationcommandline.h
gapplicationimpl-dbus.c
gapplicationimpl.h
gasynchelper.c
gasynchelper.h
gasyncinitable.c
gasyncinitable.h
gasyncresult.c
gasyncresult.h
gbufferedinputstream.c
gbufferedinputstream.h
gbufferedoutputstream.c
gbufferedoutputstream.h
gbytesicon.c
gbytesicon.h
gcancellable.c
gcancellable.h
gcharsetconverter.c
gcharsetconverter.h
gcocoanotificationbackend.m
gcontenttype-fdo.c
gcontenttype-osx.m
gcontenttype-win32.c
gcontenttype.c
gcontenttype.h
gcontenttypeprivate.h
gcontextspecificgroup.c
gcontextspecificgroup.h
gconverter.c
gconverter.h
gconverterinputstream.c
gconverterinputstream.h
gconverteroutputstream.c
gconverteroutputstream.h
gcredentials.c
gcredentials.h
gcredentialsprivate.h
gdatagrambased.c
gdatagrambased.h
gdatainputstream.c
gdatainputstream.h
gdataoutputstream.c
gdataoutputstream.h
gdbus-tool.c
gdbusactiongroup-private.h
gdbusactiongroup.c
gdbusactiongroup.h
gdbusaddress.c
gdbusaddress.h
gdbusauth.c
gdbusauth.h
gdbusauthmechanism.c
gdbusauthmechanism.h
gdbusauthmechanismanon.c
gdbusauthmechanismanon.h
gdbusauthmechanismexternal.c
gdbusauthmechanismexternal.h
gdbusauthmechanismsha1.c
gdbusauthmechanismsha1.h
gdbusauthobserver.c
gdbusauthobserver.h
gdbusconnection.c
gdbusconnection.h
gdbusdaemon.c
gdbusdaemon.h
gdbuserror.c
gdbuserror.h
gdbusinterface.c
gdbusinterface.h
gdbusinterfaceskeleton.c
gdbusinterfaceskeleton.h
gdbusintrospection.c
gdbusintrospection.h
gdbusmenumodel.c
gdbusmenumodel.h
gdbusmessage.c
gdbusmessage.h
gdbusmethodinvocation.c
gdbusmethodinvocation.h
gdbusnameowning.c
gdbusnameowning.h
gdbusnamewatching.c
gdbusnamewatching.h
gdbusobject.c
gdbusobject.h
gdbusobjectmanager.c
gdbusobjectmanager.h
gdbusobjectmanagerclient.c
gdbusobjectmanagerclient.h
gdbusobjectmanagerserver.c
gdbusobjectmanagerserver.h
gdbusobjectproxy.c
gdbusobjectproxy.h
gdbusobjectskeleton.c
gdbusobjectskeleton.h
gdbusprivate.c
gdbusprivate.h
gdbusproxy.c
gdbusproxy.h
gdbusserver.c
gdbusserver.h
gdbusutils.c
gdbusutils.h
gdebugcontroller.c
gdebugcontroller.h
gdebugcontrollerdbus.c
gdebugcontrollerdbus.h
gdelayedsettingsbackend.c
gdelayedsettingsbackend.h
gdesktopappinfo.c
gdesktopappinfo.h
gdocumentportal.c
gdocumentportal.h
gdrive.c
gdrive.h
gdtlsclientconnection.c
gdtlsclientconnection.h
gdtlsconnection.c
gdtlsconnection.h
gdtlsserverconnection.c
gdtlsserverconnection.h
gdummyfile.c
gdummyfile.h
gdummyproxyresolver.c
gdummyproxyresolver.h
gdummytlsbackend.c
gdummytlsbackend.h
gemblem.c
gemblem.h
gemblemedicon.c
gemblemedicon.h
gfdonotificationbackend.c
gfile.c
gfile.h
gfileattribute-priv.h
gfileattribute.c
gfileattribute.h
gfiledescriptorbased.c
gfiledescriptorbased.h
gfileenumerator.c
gfileenumerator.h
gfileicon.c
gfileicon.h
gfileinfo-priv.h
gfileinfo.c
gfileinfo.h
gfileinputstream.c
gfileinputstream.h
gfileiostream.c
gfileiostream.h
gfilemonitor.c
gfilemonitor.h
gfilenamecompleter.c
gfilenamecompleter.h
gfileoutputstream.c
gfileoutputstream.h
gfilterinputstream.c
gfilterinputstream.h
gfilteroutputstream.c
gfilteroutputstream.h
ggtknotificationbackend.c
ghttpproxy.c
ghttpproxy.h
gicon.c
gicon.h
ginetaddress.c
ginetaddress.h
ginetaddressmask.c
ginetaddressmask.h
ginetsocketaddress.c
ginetsocketaddress.h
ginitable.c
ginitable.h
ginputstream.c
ginputstream.h
gio-autocleanups.h
gio-launch-desktop.c
gio-querymodules.c
gio-tool-cat.c
gio-tool-copy.c
gio-tool-info.c
gio-tool-launch.c
gio-tool-list.c
gio-tool-mime.c
gio-tool-mkdir.c
gio-tool-monitor.c
gio-tool-mount.c
gio-tool-move.c
gio-tool-open.c
gio-tool-remove.c
gio-tool-rename.c
gio-tool-save.c
gio-tool-set.c
gio-tool-trash.c
gio-tool-tree.c
gio-tool.c
gio-tool.h
gio.h
gio.rc.in
gio.stp.in
gio_probes.d
gio_trace.h
gioenums.h
gioenumtypes.c.template
gioenumtypes.h.template
gioerror.c
gioerror.h
giomodule-priv.c
giomodule-priv.h
giomodule.c
giomodule.h
gioprivate.h
gioscheduler.c
gioscheduler.h
giostream.c
giostream.h
giotypes.h
giounix-private.c
giounix-private.h
giowin32-afunix.h
giowin32-priv.h
giowin32-private.c
gkeyfilesettingsbackend.c
glib-compile-resources.c
glib-compile-schemas.c
glistmodel.c
glistmodel.h
gliststore.c
gliststore.h
gloadableicon.c
gloadableicon.h
glocalfile.c
glocalfile.h
glocalfileenumerator.c
glocalfileenumerator.h
glocalfileinfo.c
glocalfileinfo.h
glocalfileinputstream.c
glocalfileinputstream.h
glocalfileiostream.c
glocalfileiostream.h
glocalfilemonitor.c
glocalfilemonitor.h
glocalfileoutputstream.c
glocalfileoutputstream.h
glocalvfs.c
glocalvfs.h
gmarshal-internal.c
gmarshal-internal.h
gmarshal-internal.list
gmemoryinputstream.c
gmemoryinputstream.h
gmemorymonitor.c
gmemorymonitor.h
gmemorymonitordbus.c
gmemorymonitordbus.h
gmemorymonitorportal.c
gmemorymonitorportal.h
gmemorymonitorwin32.c
gmemoryoutputstream.c
gmemoryoutputstream.h
gmemorysettingsbackend.c
gmenu.c
gmenu.h
gmenuexporter.c
gmenuexporter.h
gmenumodel.c
gmenumodel.h
gmount.c
gmount.h
gmountoperation.c
gmountoperation.h
gmountprivate.h
gnativesocketaddress.c
gnativesocketaddress.h
gnativevolumemonitor.c
gnativevolumemonitor.h
gnetworkaddress.c
gnetworkaddress.h
gnetworking.c
gnetworking.h.in
gnetworkingprivate.h
gnetworkmonitor.c
gnetworkmonitor.h
gnetworkmonitorbase.c
gnetworkmonitorbase.h
gnetworkmonitornetlink.c
gnetworkmonitornetlink.h
gnetworkmonitornm.c
gnetworkmonitornm.h
gnetworkmonitorportal.c
gnetworkmonitorportal.h
gnetworkservice.c
gnetworkservice.h
gnextstepsettingsbackend.m
gnotification-private.h
gnotification.c
gnotification.h
gnotificationbackend.c
gnotificationbackend.h
gnullsettingsbackend.c
gopenuriportal.c
gopenuriportal.h
gosxappinfo.h
gosxappinfo.m
gosxnetworkmonitor.c
gosxnetworkmonitor.h
goutputstream.c
goutputstream.h
gpermission.c
gpermission.h
gpollableinputstream.c
gpollableinputstream.h
gpollableoutputstream.c
gpollableoutputstream.h
gpollableutils.c
gpollableutils.h
gpollfilemonitor.c
gpollfilemonitor.h
gportalnotificationbackend.c
gportalsupport.c
gportalsupport.h
gpowerprofilemonitor.c
gpowerprofilemonitor.h
gpowerprofilemonitordbus.c
gpowerprofilemonitordbus.h
gpowerprofilemonitorportal.c
gpowerprofilemonitorportal.h
gpropertyaction.c
gpropertyaction.h
gproxy.c
gproxy.h
gproxyaddress.c
gproxyaddress.h
gproxyaddressenumerator.c
gproxyaddressenumerator.h
gproxyresolver.c
gproxyresolver.h
gproxyresolverportal.c
gproxyresolverportal.h
gregistrysettingsbackend.c
gregistrysettingsbackend.h
gremoteactiongroup.c
gremoteactiongroup.h
gresolver.c
gresolver.h
gresource-tool.c
gresource.c
gresource.dtd
gresource.h
gresourcefile.c
gresourcefile.h
gsandbox.c
gsandbox.h
gschema.dtd
gschema.its
gschema.loc
gseekable.c
gseekable.h
gsettings-mapping.c
gsettings-mapping.h
gsettings-tool.c
gsettings.c
gsettings.h
gsettingsbackend.c
gsettingsbackend.h
gsettingsbackendinternal.h
gsettingsschema-internal.h
gsettingsschema.c
gsettingsschema.h
gsimpleaction.c
gsimpleaction.h
gsimpleactiongroup.c
gsimpleactiongroup.h
gsimpleasyncresult.c
gsimpleasyncresult.h
gsimpleiostream.c
gsimpleiostream.h
gsimplepermission.c
gsimplepermission.h
gsimpleproxyresolver.c
gsimpleproxyresolver.h
gsocket.c
gsocket.h
gsocketaddress.c
gsocketaddress.h
gsocketaddressenumerator.c
gsocketaddressenumerator.h
gsocketclient.c
gsocketclient.h
gsocketconnectable.c
gsocketconnectable.h
gsocketconnection.c
gsocketconnection.h
gsocketcontrolmessage.c
gsocketcontrolmessage.h
gsocketinputstream.c
gsocketinputstream.h
gsocketlistener.c
gsocketlistener.h
gsocketoutputstream.c
gsocketoutputstream.h
gsocketservice.c
gsocketservice.h
gsocks4aproxy.c
gsocks4aproxy.h
gsocks4proxy.c
gsocks4proxy.h
gsocks5proxy.c
gsocks5proxy.h
gsrvtarget.c
gsrvtarget.h
gsubprocess.c
gsubprocess.h
gsubprocesslauncher-private.h
gsubprocesslauncher.c
gsubprocesslauncher.h
gtask.c
gtask.h
gtcpconnection.c
gtcpconnection.h
gtcpwrapperconnection.c
gtcpwrapperconnection.h
gtestdbus.c
gtestdbus.h
gthemedicon.c
gthemedicon.h
gthreadedresolver-private.h
gthreadedresolver.c
gthreadedresolver.h
gthreadedsocketservice.c
gthreadedsocketservice.h
gtlsbackend.c
gtlsbackend.h
gtlscertificate.c
gtlscertificate.h
gtlsclientconnection.c
gtlsclientconnection.h
gtlsconnection.c
gtlsconnection.h
gtlsdatabase.c
gtlsdatabase.h
gtlsfiledatabase.c
gtlsfiledatabase.h
gtlsinteraction.c
gtlsinteraction.h
gtlspassword.c
gtlspassword.h
gtlsserverconnection.c
gtlsserverconnection.h
gtrashportal.c
gtrashportal.h
gunionvolumemonitor.c
gunionvolumemonitor.h
gunixconnection.c
gunixconnection.h
gunixcredentialsmessage.c
gunixcredentialsmessage.h
gunixfdlist.c
gunixfdlist.h
gunixfdmessage.c
gunixfdmessage.h
gunixinputstream.c
gunixinputstream.h
gunixmount.c
gunixmount.h
gunixmounts.c
gunixmounts.h
gunixoutputstream.c
gunixoutputstream.h
gunixsocketaddress.c
gunixsocketaddress.h
gunixvolume.c
gunixvolume.h
gunixvolumemonitor.c
gunixvolumemonitor.h
gvfs.c
gvfs.h
gvolume.c
gvolume.h
gvolumemonitor.c
gvolumemonitor.h
gwin32api-application-activation-manager.h
gwin32api-iterator.h
gwin32api-misc.h
gwin32api-package.h
gwin32api-storage.h
gwin32appinfo.c
gwin32appinfo.h
gwin32file-sync-stream.c
gwin32file-sync-stream.h
gwin32inputstream.c
gwin32inputstream.h
gwin32mount.c
gwin32mount.h
gwin32networkmonitor.c
gwin32networkmonitor.h
gwin32notificationbackend.c
gwin32outputstream.c
gwin32outputstream.h
gwin32packageparser.c
gwin32packageparser.h
gwin32registrykey.c
gwin32registrykey.h
gwin32sid.c
gwin32sid.h
gwin32volumemonitor.c
gwin32volumemonitor.h
gzlibcompressor.c
gzlibcompressor.h
gzlibdecompressor.c
gzlibdecompressor.h
meson.build
org.freedesktop.portal.Documents.xml
org.freedesktop.portal.OpenURI.xml
org.freedesktop.portal.ProxyResolver.xml
org.freedesktop.portal.Request.xml
org.freedesktop.portal.Trash.xml
strinfo.c
thumbnail-verify.c
thumbnail-verify.h
girepository
glib
gmodule
gobject
gthread
m4macros
po
subprojects
tests
tools
.clang-format
.dir-locals.el
.editorconfig
.gitignore
.gitlab-ci.yml
.gitmodules
.lcovrc
CODE_OF_CONDUCT.md
CONTRIBUTING.md
INSTALL.md
NEWS
README.md
SECURITY.md
glib.doap
meson.build
meson.options
glib/gio/gtcpconnection.c

337 lines
8.9 KiB
C
Raw Normal View History

/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2008, 2009 Codethink Limited
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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.1 of the License, or (at your option) any later version.
*
* See the included COPYING file for more information.
*/
/**
* GTcpConnection:
*
* This is the subclass of [class@Gio.SocketConnection] that is created
* for TCP/IP sockets.
*
* Since: 2.22
*/
#include "config.h"
#include "gtcpconnection.h"
#include "gasyncresult.h"
#include "gtask.h"
#include "giostream.h"
#include "glibintl.h"
struct _GTcpConnectionPrivate
{
guint graceful_disconnect : 1;
};
G_DEFINE_TYPE_WITH_CODE (GTcpConnection, g_tcp_connection,
G_TYPE_SOCKET_CONNECTION,
G_ADD_PRIVATE (GTcpConnection)
g_socket_connection_factory_register_type (g_define_type_id,
G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT);
g_socket_connection_factory_register_type (g_define_type_id,
G_SOCKET_FAMILY_IPV6,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT);
g_socket_connection_factory_register_type (g_define_type_id,
G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP);
g_socket_connection_factory_register_type (g_define_type_id,
G_SOCKET_FAMILY_IPV6,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP);
);
static gboolean g_tcp_connection_close (GIOStream *stream,
GCancellable *cancellable,
GError **error);
static void g_tcp_connection_close_async (GIOStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
enum
{
PROP_0,
PROP_GRACEFUL_DISCONNECT
};
static void
g_tcp_connection_init (GTcpConnection *connection)
{
connection->priv = g_tcp_connection_get_instance_private (connection);
connection->priv->graceful_disconnect = FALSE;
}
static void
g_tcp_connection_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GTcpConnection *connection = G_TCP_CONNECTION (object);
switch (prop_id)
{
case PROP_GRACEFUL_DISCONNECT:
g_value_set_boolean (value, connection->priv->graceful_disconnect);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tcp_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GTcpConnection *connection = G_TCP_CONNECTION (object);
switch (prop_id)
{
case PROP_GRACEFUL_DISCONNECT:
g_tcp_connection_set_graceful_disconnect (connection,
g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
g_tcp_connection_class_init (GTcpConnectionClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class);
gobject_class->set_property = g_tcp_connection_set_property;
gobject_class->get_property = g_tcp_connection_get_property;
stream_class->close_fn = g_tcp_connection_close;
stream_class->close_async = g_tcp_connection_close_async;
/**
* GTcpConnection:graceful-disconnect:
*
* Whether [method@Gio.IOStream.close] does a graceful disconnect.
*
* Since: 2.22
*/
g_object_class_install_property (gobject_class, PROP_GRACEFUL_DISCONNECT,
g_param_spec_boolean ("graceful-disconnect", NULL, NULL,
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static gboolean
g_tcp_connection_close (GIOStream *stream,
GCancellable *cancellable,
GError **error)
{
GTcpConnection *connection = G_TCP_CONNECTION (stream);
GSocket *socket;
char buffer[1024];
gssize ret;
gboolean had_error;
socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
had_error = FALSE;
if (connection->priv->graceful_disconnect &&
!g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
{
if (!g_socket_shutdown (socket, FALSE, TRUE, error))
{
error = NULL; /* Ignore further errors */
had_error = TRUE;
}
else
{
while (TRUE)
{
ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
TRUE, cancellable, error);
if (ret < 0)
{
had_error = TRUE;
error = NULL;
break;
}
if (ret == 0)
break;
}
}
}
return G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
->close_fn (stream, cancellable, error) && !had_error;
}
/* consumes @error */
static void
async_close_finish (GTask *task,
GError *error)
{
GIOStreamClass *parent = G_IO_STREAM_CLASS (g_tcp_connection_parent_class);
GIOStream *stream = g_task_get_source_object (task);
GCancellable *cancellable = g_task_get_cancellable (task);
/* Close underlying stream, ignoring further errors if we already
* have one.
*/
if (error)
parent->close_fn (stream, cancellable, NULL);
else
parent->close_fn (stream, cancellable, &error);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static gboolean
close_read_ready (GSocket *socket,
GIOCondition condition,
GTask *task)
{
GError *error = NULL;
char buffer[1024];
gssize ret;
ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
FALSE, g_task_get_cancellable (task),
&error);
if (ret < 0)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
{
g_error_free (error);
return TRUE;
}
else
{
async_close_finish (task, error);
return FALSE;
}
}
if (ret == 0)
{
async_close_finish (task, NULL);
return FALSE;
}
return TRUE;
}
static void
g_tcp_connection_close_async (GIOStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTcpConnection *connection = G_TCP_CONNECTION (stream);
GSocket *socket;
GSource *source;
GError *error;
GTask *task;
if (connection->priv->graceful_disconnect &&
!g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
{
task = g_task_new (stream, cancellable, callback, user_data);
g_task_set_source_tag (task, g_tcp_connection_close_async);
g_task_set_priority (task, io_priority);
socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
error = NULL;
if (!g_socket_shutdown (socket, FALSE, TRUE, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
source = g_socket_create_source (socket, G_IO_IN, cancellable);
g_task_attach_source (task, source, (GSourceFunc) close_read_ready);
g_source_unref (source);
return;
}
2009-07-30 11:18:35 -04:00
G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
->close_async (stream, io_priority, cancellable, callback, user_data);
}
/**
* g_tcp_connection_set_graceful_disconnect:
* @connection: a #GTcpConnection
* @graceful_disconnect: Whether to do graceful disconnects or not
*
2014-10-20 19:05:26 -05:00
* This enables graceful disconnects on close. A graceful disconnect
2011-04-20 19:08:06 +02:00
* means that we signal the receiving end that the connection is terminated
* and wait for it to close the connection before closing the connection.
*
* A graceful disconnect means that we can be sure that we successfully sent
* all the outstanding data to the other end, or get an error reported.
* However, it also means we have to wait for all the data to reach the
* other side and for it to acknowledge this by closing the socket, which may
* take a while. For this reason it is disabled by default.
*
* Since: 2.22
*/
void
g_tcp_connection_set_graceful_disconnect (GTcpConnection *connection,
gboolean graceful_disconnect)
{
graceful_disconnect = !!graceful_disconnect;
if (graceful_disconnect != connection->priv->graceful_disconnect)
{
connection->priv->graceful_disconnect = graceful_disconnect;
g_object_notify (G_OBJECT (connection), "graceful-disconnect");
}
}
/**
* g_tcp_connection_get_graceful_disconnect:
* @connection: a #GTcpConnection
*
* Checks if graceful disconnects are used. See
* g_tcp_connection_set_graceful_disconnect().
*
* Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise
*
* Since: 2.22
*/
gboolean
g_tcp_connection_get_graceful_disconnect (GTcpConnection *connection)
{
return connection->priv->graceful_disconnect;
}