Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/gsocketinputstream.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
4
 *           © 2009 codethink
5
 *
6
 * SPDX-License-Identifier: LGPL-2.1-or-later
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General
19
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20
 *
21
 * Authors: Christian Kellner <gicmo@gnome.org>
22
 *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
23
 *          Ryan Lortie <desrt@desrt.ca>
24
 */
25
26
#include "config.h"
27
#include "gsocketinputstream.h"
28
#include "glibintl.h"
29
30
#include "gcancellable.h"
31
#include "gpollableinputstream.h"
32
#include "gioerror.h"
33
#include "gfiledescriptorbased.h"
34
35
struct _GSocketInputStreamPrivate
36
{
37
  GSocket *socket;
38
39
  /* pending operation metadata */
40
  gpointer buffer;
41
  gsize count;
42
};
43
44
static void g_socket_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
45
#ifdef G_OS_UNIX
46
static void g_socket_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface);
47
#endif
48
49
#define g_socket_input_stream_get_type _g_socket_input_stream_get_type
50
51
#ifdef G_OS_UNIX
52
G_DEFINE_TYPE_WITH_CODE (GSocketInputStream, g_socket_input_stream, G_TYPE_INPUT_STREAM,
53
                         G_ADD_PRIVATE (GSocketInputStream)
54
       G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, g_socket_input_stream_pollable_iface_init)
55
       G_IMPLEMENT_INTERFACE (G_TYPE_FILE_DESCRIPTOR_BASED, g_socket_input_stream_file_descriptor_based_iface_init)
56
       )
57
#else
58
G_DEFINE_TYPE_WITH_CODE (GSocketInputStream, g_socket_input_stream, G_TYPE_INPUT_STREAM,
59
                         G_ADD_PRIVATE (GSocketInputStream)
60
       G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, g_socket_input_stream_pollable_iface_init)
61
       )
62
#endif
63
64
enum
65
{
66
  PROP_0,
67
  PROP_SOCKET
68
};
69
70
static void
71
g_socket_input_stream_get_property (GObject    *object,
72
                                    guint       prop_id,
73
                                    GValue     *value,
74
                                    GParamSpec *pspec)
75
0
{
76
0
  GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
77
78
0
  switch (prop_id)
79
0
    {
80
0
      case PROP_SOCKET:
81
0
        g_value_set_object (value, stream->priv->socket);
82
0
        break;
83
84
0
      default:
85
0
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
86
0
    }
87
0
}
88
89
static void
90
g_socket_input_stream_set_property (GObject      *object,
91
                                    guint         prop_id,
92
                                    const GValue *value,
93
                                    GParamSpec   *pspec)
94
0
{
95
0
  GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
96
97
0
  switch (prop_id)
98
0
    {
99
0
      case PROP_SOCKET:
100
0
        stream->priv->socket = g_value_dup_object (value);
101
0
        break;
102
103
0
      default:
104
0
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105
0
    }
106
0
}
107
108
static void
109
g_socket_input_stream_finalize (GObject *object)
110
0
{
111
0
  GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
112
113
0
  if (stream->priv->socket)
114
0
    g_object_unref (stream->priv->socket);
115
116
0
  G_OBJECT_CLASS (g_socket_input_stream_parent_class)->finalize (object);
117
0
}
118
119
static gssize
120
g_socket_input_stream_read (GInputStream  *stream,
121
                            void          *buffer,
122
                            gsize          count,
123
                            GCancellable  *cancellable,
124
                            GError       **error)
125
0
{
126
0
  GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream);
127
128
0
  return g_socket_receive_with_blocking (input_stream->priv->socket,
129
0
           buffer, count, TRUE,
130
0
           cancellable, error);
131
0
}
132
133
static gboolean
134
g_socket_input_stream_pollable_is_readable (GPollableInputStream *pollable)
135
0
{
136
0
  GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
137
138
0
  return g_socket_condition_check (input_stream->priv->socket, G_IO_IN);
139
0
}
140
141
static GSource *
142
g_socket_input_stream_pollable_create_source (GPollableInputStream *pollable,
143
                GCancellable         *cancellable)
144
0
{
145
0
  GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
146
0
  GSource *socket_source, *pollable_source;
147
148
0
  pollable_source = g_pollable_source_new (G_OBJECT (input_stream));
149
0
  socket_source = g_socket_create_source (input_stream->priv->socket,
150
0
            G_IO_IN, cancellable);
151
0
  g_source_set_dummy_callback (socket_source);
152
0
  g_source_add_child_source (pollable_source, socket_source);
153
0
  g_source_unref (socket_source);
154
155
0
  return pollable_source;
156
0
}
157
158
static gssize
159
g_socket_input_stream_pollable_read_nonblocking (GPollableInputStream  *pollable,
160
             void                  *buffer,
161
             gsize                  size,
162
             GError               **error)
163
0
{
164
0
  GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
165
166
0
  return g_socket_receive_with_blocking (input_stream->priv->socket,
167
0
           buffer, size, FALSE,
168
0
           NULL, error);
169
0
}
170
171
#ifdef G_OS_UNIX
172
static int
173
g_socket_input_stream_get_fd (GFileDescriptorBased *fd_based)
174
0
{
175
0
  GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (fd_based);
176
177
0
  return g_socket_get_fd (input_stream->priv->socket);
178
0
}
179
#endif
180
181
static void
182
g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
183
0
{
184
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
185
0
  GInputStreamClass *ginputstream_class = G_INPUT_STREAM_CLASS (klass);
186
187
0
  gobject_class->finalize = g_socket_input_stream_finalize;
188
0
  gobject_class->get_property = g_socket_input_stream_get_property;
189
0
  gobject_class->set_property = g_socket_input_stream_set_property;
190
191
0
  ginputstream_class->read_fn = g_socket_input_stream_read;
192
193
0
  g_object_class_install_property (gobject_class, PROP_SOCKET,
194
0
           g_param_spec_object ("socket",
195
0
              P_("socket"),
196
0
              P_("The socket that this stream wraps"),
197
0
              G_TYPE_SOCKET, G_PARAM_CONSTRUCT_ONLY |
198
0
              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
199
0
}
200
201
#ifdef G_OS_UNIX
202
static void
203
g_socket_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface)
204
0
{
205
0
  iface->get_fd = g_socket_input_stream_get_fd;
206
0
}
207
#endif
208
209
static void
210
g_socket_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
211
0
{
212
0
  iface->is_readable = g_socket_input_stream_pollable_is_readable;
213
0
  iface->create_source = g_socket_input_stream_pollable_create_source;
214
0
  iface->read_nonblocking = g_socket_input_stream_pollable_read_nonblocking;
215
0
}
216
217
static void
218
g_socket_input_stream_init (GSocketInputStream *stream)
219
0
{
220
0
  stream->priv = g_socket_input_stream_get_instance_private (stream);
221
0
}
222
223
GSocketInputStream *
224
_g_socket_input_stream_new (GSocket *socket)
225
0
{
226
0
  return g_object_new (G_TYPE_SOCKET_INPUT_STREAM, "socket", socket, NULL);
227
0
}