(root)/
glib-2.79.0/
gio/
gsocketinputstream.c
       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  {
      76    GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
      77  
      78    switch (prop_id)
      79      {
      80        case PROP_SOCKET:
      81          g_value_set_object (value, stream->priv->socket);
      82          break;
      83  
      84        default:
      85          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      86      }
      87  }
      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  {
      95    GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
      96  
      97    switch (prop_id)
      98      {
      99        case PROP_SOCKET:
     100          stream->priv->socket = g_value_dup_object (value);
     101          break;
     102  
     103        default:
     104          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     105      }
     106  }
     107  
     108  static void
     109  g_socket_input_stream_finalize (GObject *object)
     110  {
     111    GSocketInputStream *stream = G_SOCKET_INPUT_STREAM (object);
     112  
     113    if (stream->priv->socket)
     114      g_object_unref (stream->priv->socket);
     115  
     116    G_OBJECT_CLASS (g_socket_input_stream_parent_class)->finalize (object);
     117  }
     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  {
     126    GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream);
     127  
     128    return g_socket_receive_with_blocking (input_stream->priv->socket,
     129  					 buffer, count, TRUE,
     130  					 cancellable, error);
     131  }
     132  
     133  static gboolean
     134  g_socket_input_stream_pollable_is_readable (GPollableInputStream *pollable)
     135  {
     136    GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
     137  
     138    return g_socket_condition_check (input_stream->priv->socket, G_IO_IN);
     139  }
     140  
     141  static GSource *
     142  g_socket_input_stream_pollable_create_source (GPollableInputStream *pollable,
     143  					      GCancellable         *cancellable)
     144  {
     145    GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
     146    GSource *socket_source, *pollable_source;
     147  
     148    pollable_source = g_pollable_source_new (G_OBJECT (input_stream));
     149    socket_source = g_socket_create_source (input_stream->priv->socket,
     150  					  G_IO_IN, cancellable);
     151    g_source_set_dummy_callback (socket_source);
     152    g_source_add_child_source (pollable_source, socket_source);
     153    g_source_unref (socket_source);
     154  
     155    return pollable_source;
     156  }
     157  
     158  static gssize
     159  g_socket_input_stream_pollable_read_nonblocking (GPollableInputStream  *pollable,
     160  						 void                  *buffer,
     161  						 gsize                  size,
     162  						 GError               **error)
     163  {
     164    GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (pollable);
     165  
     166    return g_socket_receive_with_blocking (input_stream->priv->socket,
     167  					 buffer, size, FALSE,
     168  					 NULL, error);
     169  }
     170  
     171  #ifdef G_OS_UNIX
     172  static int
     173  g_socket_input_stream_get_fd (GFileDescriptorBased *fd_based)
     174  {
     175    GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (fd_based);
     176  
     177    return g_socket_get_fd (input_stream->priv->socket);
     178  }
     179  #endif
     180  
     181  static void
     182  g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
     183  {
     184    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     185    GInputStreamClass *ginputstream_class = G_INPUT_STREAM_CLASS (klass);
     186  
     187    gobject_class->finalize = g_socket_input_stream_finalize;
     188    gobject_class->get_property = g_socket_input_stream_get_property;
     189    gobject_class->set_property = g_socket_input_stream_set_property;
     190  
     191    ginputstream_class->read_fn = g_socket_input_stream_read;
     192  
     193    g_object_class_install_property (gobject_class, PROP_SOCKET,
     194  				   g_param_spec_object ("socket", NULL, NULL,
     195  							G_TYPE_SOCKET, G_PARAM_CONSTRUCT_ONLY |
     196  							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     197  }
     198  
     199  #ifdef G_OS_UNIX
     200  static void
     201  g_socket_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface)
     202  {
     203    iface->get_fd = g_socket_input_stream_get_fd;
     204  }
     205  #endif
     206  
     207  static void
     208  g_socket_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
     209  {
     210    iface->is_readable = g_socket_input_stream_pollable_is_readable;
     211    iface->create_source = g_socket_input_stream_pollable_create_source;
     212    iface->read_nonblocking = g_socket_input_stream_pollable_read_nonblocking;
     213  }
     214  
     215  static void
     216  g_socket_input_stream_init (GSocketInputStream *stream)
     217  {
     218    stream->priv = g_socket_input_stream_get_instance_private (stream);
     219  }
     220  
     221  GSocketInputStream *
     222  _g_socket_input_stream_new (GSocket *socket)
     223  {
     224    return g_object_new (G_TYPE_SOCKET_INPUT_STREAM, "socket", socket, NULL);
     225  }