mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 22:46:15 +01:00
Add GBytes variants for GSocket receive methods
The current buffer API is pretty much C-specific, and cannot be adequately described in a way that is friendly to introspection and language bindings: the passed buffer is allocated by the caller, but the written size of the buffer is in the return value. Using GBytes, we get a better API at the cost of an additional allocation.
This commit is contained in:
parent
7688965491
commit
7cb953dab8
142
gio/gsocket.c
142
gio/gsocket.c
@ -3365,6 +3365,69 @@ g_socket_receive_with_timeout (GSocket *socket,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_socket_receive_bytes:
|
||||||
|
* @socket: a #GSocket
|
||||||
|
* @size: the number of bytes you want to read from the socket
|
||||||
|
* @timeout_us: the timeout to wait for, in microseconds, or `-1` to block
|
||||||
|
* indefinitely
|
||||||
|
* @cancellable: (nullable): a %GCancellable, or `NULL`
|
||||||
|
* @error: return location for a #GError, or `NULL`
|
||||||
|
*
|
||||||
|
* Receives data (up to @size bytes) from a socket.
|
||||||
|
*
|
||||||
|
* This function is a variant of [method@Gio.Socket.receive] which returns a
|
||||||
|
* [struct@GLib.Bytes] rather than a plain buffer.
|
||||||
|
*
|
||||||
|
* Pass `-1` to @timeout_us to block indefinitely until data is received (or
|
||||||
|
* the connection is closed, or there is an error). Pass `0` to use the default
|
||||||
|
* timeout from [property@Gio.Socket:timeout], or pass a positive number to wait
|
||||||
|
* for that many microseconds for data before returning `G_IO_ERROR_TIMED_OUT`.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a bytes buffer containing the
|
||||||
|
* received bytes, or `NULL` on error
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
GBytes *
|
||||||
|
g_socket_receive_bytes (GSocket *socket,
|
||||||
|
gsize size,
|
||||||
|
gint64 timeout_us,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
gssize res;
|
||||||
|
GBytes *buf;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
data = g_new0 (guint8, size);
|
||||||
|
res = g_socket_receive_with_timeout (socket, data, size, timeout_us, cancellable, error);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
g_free (data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((gsize) res == size)
|
||||||
|
{
|
||||||
|
buf = g_bytes_new_take (g_steal_pointer (&data), (gsize) res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GBytes *sub_buf;
|
||||||
|
|
||||||
|
buf = g_bytes_new_take (g_steal_pointer (&data), size);
|
||||||
|
sub_buf = g_bytes_new_from_bytes (buf, 0, (gsize) res);
|
||||||
|
g_bytes_unref (buf);
|
||||||
|
buf = g_steal_pointer (&sub_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer (&buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_socket_receive:
|
* g_socket_receive:
|
||||||
* @socket: a #GSocket
|
* @socket: a #GSocket
|
||||||
@ -3446,6 +3509,85 @@ g_socket_receive_with_blocking (GSocket *socket,
|
|||||||
blocking ? -1 : 0, cancellable, error);
|
blocking ? -1 : 0, cancellable, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_socket_receive_bytes_from:
|
||||||
|
* @socket: a #GSocket
|
||||||
|
* @address: (out) (optional): return location for a #GSocketAddress
|
||||||
|
* @size: the number of bytes you want to read from the socket
|
||||||
|
* @timeout_us: the timeout to wait for, in microseconds, or `-1` to block
|
||||||
|
* indefinitely
|
||||||
|
* @cancellable: (nullable): a #GCancellable, or `NULL`
|
||||||
|
* @error: return location for a #GError, or `NULL`
|
||||||
|
*
|
||||||
|
* Receive data (up to @size bytes) from a socket.
|
||||||
|
*
|
||||||
|
* This function is a variant of [method@Gio.Socket.receive_from] which returns
|
||||||
|
* a [struct@GLib.Bytes] rather than a plain buffer.
|
||||||
|
*
|
||||||
|
* If @address is non-%NULL then @address will be set equal to the
|
||||||
|
* source address of the received packet.
|
||||||
|
*
|
||||||
|
* The @address is owned by the caller.
|
||||||
|
*
|
||||||
|
* Pass `-1` to @timeout_us to block indefinitely until data is received (or
|
||||||
|
* the connection is closed, or there is an error). Pass `0` to use the default
|
||||||
|
* timeout from [property@Gio.Socket:timeout], or pass a positive number to wait
|
||||||
|
* for that many microseconds for data before returning `G_IO_ERROR_TIMED_OUT`.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a bytes buffer containing the
|
||||||
|
* received bytes, or `NULL` on error
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
GBytes *
|
||||||
|
g_socket_receive_bytes_from (GSocket *socket,
|
||||||
|
GSocketAddress **address,
|
||||||
|
gsize size,
|
||||||
|
gint64 timeout_us,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GInputVector v;
|
||||||
|
gssize res;
|
||||||
|
GBytes *buf;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
|
||||||
|
g_return_val_if_fail (address == NULL || *address == NULL, NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
v.buffer = g_new0 (guint8, size);
|
||||||
|
v.size = size;
|
||||||
|
|
||||||
|
res = g_socket_receive_message_with_timeout (socket,
|
||||||
|
address,
|
||||||
|
&v, 1,
|
||||||
|
NULL, 0, NULL,
|
||||||
|
timeout_us,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
g_free (v.buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((gsize) res == size)
|
||||||
|
{
|
||||||
|
buf = g_bytes_new_take (g_steal_pointer (&v.buffer), (gsize) res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GBytes *sub_buf;
|
||||||
|
|
||||||
|
buf = g_bytes_new_take (g_steal_pointer (&v.buffer), size);
|
||||||
|
sub_buf = g_bytes_new_from_bytes (buf, 0, (gsize) res);
|
||||||
|
g_bytes_unref (buf);
|
||||||
|
buf = g_steal_pointer (&sub_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer (&buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_socket_receive_from:
|
* g_socket_receive_from:
|
||||||
* @socket: a #GSocket
|
* @socket: a #GSocket
|
||||||
|
@ -210,6 +210,12 @@ gssize g_socket_receive (GSocket
|
|||||||
gsize size,
|
gsize size,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GIO_AVAILABLE_IN_2_80
|
||||||
|
GBytes * g_socket_receive_bytes (GSocket *socket,
|
||||||
|
gsize size,
|
||||||
|
gint64 timeout_us,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
GIO_AVAILABLE_IN_ALL
|
GIO_AVAILABLE_IN_ALL
|
||||||
gssize g_socket_receive_from (GSocket *socket,
|
gssize g_socket_receive_from (GSocket *socket,
|
||||||
GSocketAddress **address,
|
GSocketAddress **address,
|
||||||
@ -217,6 +223,13 @@ gssize g_socket_receive_from (GSocket
|
|||||||
gsize size,
|
gsize size,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GIO_AVAILABLE_IN_2_80
|
||||||
|
GBytes * g_socket_receive_bytes_from (GSocket *socket,
|
||||||
|
GSocketAddress **address,
|
||||||
|
gsize size,
|
||||||
|
gint64 timeout_us,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
GIO_AVAILABLE_IN_ALL
|
GIO_AVAILABLE_IN_ALL
|
||||||
gssize g_socket_send (GSocket *socket,
|
gssize g_socket_send (GSocket *socket,
|
||||||
const gchar *buffer,
|
const gchar *buffer,
|
||||||
|
Loading…
Reference in New Issue
Block a user