mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-04-16 12:28:48 +02:00
GSocket: add support for timeouts
Also add options for testing timeouts to socket test programs https://bugzilla.gnome.org/show_bug.cgi?id=587898
This commit is contained in:
parent
2c4a79c810
commit
29f3e3f766
@ -1735,6 +1735,8 @@ g_socket_get_blocking
|
|||||||
g_socket_set_blocking
|
g_socket_set_blocking
|
||||||
g_socket_get_keepalive
|
g_socket_get_keepalive
|
||||||
g_socket_set_keepalive
|
g_socket_set_keepalive
|
||||||
|
g_socket_get_timeout
|
||||||
|
g_socket_set_timeout
|
||||||
g_socket_get_family
|
g_socket_get_family
|
||||||
g_socket_get_fd
|
g_socket_get_fd
|
||||||
g_socket_get_local_address
|
g_socket_get_local_address
|
||||||
|
@ -1202,6 +1202,7 @@ g_socket_create_source
|
|||||||
g_socket_get_blocking
|
g_socket_get_blocking
|
||||||
g_socket_get_family
|
g_socket_get_family
|
||||||
g_socket_get_fd
|
g_socket_get_fd
|
||||||
|
g_socket_get_timeout
|
||||||
g_socket_get_keepalive
|
g_socket_get_keepalive
|
||||||
g_socket_get_listen_backlog
|
g_socket_get_listen_backlog
|
||||||
g_socket_get_local_address
|
g_socket_get_local_address
|
||||||
@ -1220,6 +1221,7 @@ g_socket_send
|
|||||||
g_socket_send_message
|
g_socket_send_message
|
||||||
g_socket_send_to
|
g_socket_send_to
|
||||||
g_socket_set_blocking
|
g_socket_set_blocking
|
||||||
|
g_socket_set_timeout
|
||||||
g_socket_set_keepalive
|
g_socket_set_keepalive
|
||||||
g_socket_set_listen_backlog
|
g_socket_set_listen_backlog
|
||||||
g_socket_speaks_ipv4
|
g_socket_speaks_ipv4
|
||||||
|
184
gio/gsocket.c
184
gio/gsocket.c
@ -133,7 +133,8 @@ enum
|
|||||||
PROP_LISTEN_BACKLOG,
|
PROP_LISTEN_BACKLOG,
|
||||||
PROP_KEEPALIVE,
|
PROP_KEEPALIVE,
|
||||||
PROP_LOCAL_ADDRESS,
|
PROP_LOCAL_ADDRESS,
|
||||||
PROP_REMOTE_ADDRESS
|
PROP_REMOTE_ADDRESS,
|
||||||
|
PROP_TIMEOUT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSocketPrivate
|
struct _GSocketPrivate
|
||||||
@ -143,6 +144,7 @@ struct _GSocketPrivate
|
|||||||
GSocketProtocol protocol;
|
GSocketProtocol protocol;
|
||||||
gint fd;
|
gint fd;
|
||||||
gint listen_backlog;
|
gint listen_backlog;
|
||||||
|
guint timeout;
|
||||||
GError *construct_error;
|
GError *construct_error;
|
||||||
guint inited : 1;
|
guint inited : 1;
|
||||||
guint blocking : 1;
|
guint blocking : 1;
|
||||||
@ -150,6 +152,7 @@ struct _GSocketPrivate
|
|||||||
guint closed : 1;
|
guint closed : 1;
|
||||||
guint connected : 1;
|
guint connected : 1;
|
||||||
guint listening : 1;
|
guint listening : 1;
|
||||||
|
guint timed_out : 1;
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
WSAEVENT event;
|
WSAEVENT event;
|
||||||
int current_events;
|
int current_events;
|
||||||
@ -294,6 +297,15 @@ check_socket (GSocket *socket,
|
|||||||
_("Socket is already closed"));
|
_("Socket is already closed"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (socket->priv->timed_out)
|
||||||
|
{
|
||||||
|
socket->priv->timed_out = FALSE;
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
|
||||||
|
_("Socket I/O timed out"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,6 +568,10 @@ g_socket_get_property (GObject *object,
|
|||||||
g_value_take_object (value, address);
|
g_value_take_object (value, address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_TIMEOUT:
|
||||||
|
g_value_set_uint (value, socket->priv->timeout);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -599,6 +615,10 @@ g_socket_set_property (GObject *object,
|
|||||||
g_socket_set_keepalive (socket, g_value_get_boolean (value));
|
g_socket_set_keepalive (socket, g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_TIMEOUT:
|
||||||
|
g_socket_set_timeout (socket, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -735,6 +755,23 @@ g_socket_class_init (GSocketClass *klass)
|
|||||||
G_TYPE_SOCKET_ADDRESS,
|
G_TYPE_SOCKET_ADDRESS,
|
||||||
G_PARAM_READABLE |
|
G_PARAM_READABLE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GSocket:timeout:
|
||||||
|
*
|
||||||
|
* The timeout in seconds on socket I/O
|
||||||
|
*
|
||||||
|
* Since: 2.26
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TIMEOUT,
|
||||||
|
g_param_spec_uint ("timeout",
|
||||||
|
P_("Timeout"),
|
||||||
|
P_("The timeout in seconds on socket I/O"),
|
||||||
|
0,
|
||||||
|
G_MAXUINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1021,6 +1058,66 @@ g_socket_set_listen_backlog (GSocket *socket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_socket_get_timeout:
|
||||||
|
* @socket: a #GSocket.
|
||||||
|
*
|
||||||
|
* Gets the timeout setting of the socket. For details on this, see
|
||||||
|
* g_socket_set_timeout().
|
||||||
|
*
|
||||||
|
* Returns: the timeout in seconds
|
||||||
|
*
|
||||||
|
* Since: 2.26
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
g_socket_get_timeout (GSocket *socket)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_SOCKET (socket), 0);
|
||||||
|
|
||||||
|
return socket->priv->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_socket_set_timeout:
|
||||||
|
* @socket: a #GSocket.
|
||||||
|
* @timeout: the timeout for @socket, in seconds, or 0 for none
|
||||||
|
*
|
||||||
|
* Sets the time in seconds after which I/O operations on @socket will
|
||||||
|
* time out if they have not yet completed.
|
||||||
|
*
|
||||||
|
* On a blocking socket, this means that any blocking #GSocket
|
||||||
|
* operation will time out after @timeout seconds of inactivity,
|
||||||
|
* returning %G_IO_ERROR_TIMED_OUT.
|
||||||
|
*
|
||||||
|
* On a non-blocking socket, calls to g_socket_condition_wait() will
|
||||||
|
* also fail with %G_IO_ERROR_TIMED_OUT after the given time. Sources
|
||||||
|
* created with g_socket_create_source() will trigger after
|
||||||
|
* @timeout seconds of inactivity, with the requested condition
|
||||||
|
* set, at which point calling g_socket_receive(), g_socket_send(),
|
||||||
|
* g_socket_check_connect_result(), etc, will fail with
|
||||||
|
* %G_IO_ERROR_TIMED_OUT.
|
||||||
|
*
|
||||||
|
* If @timeout is 0 (the default), operations will never time out
|
||||||
|
* on their own.
|
||||||
|
*
|
||||||
|
* Note that if an I/O operation is interrupted by a signal, this may
|
||||||
|
* cause the timeout to be reset.
|
||||||
|
*
|
||||||
|
* Since: 2.26
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_socket_set_timeout (GSocket *socket,
|
||||||
|
guint timeout)
|
||||||
|
{
|
||||||
|
g_return_if_fail (G_IS_SOCKET (socket));
|
||||||
|
|
||||||
|
if (timeout != socket->priv->timeout)
|
||||||
|
{
|
||||||
|
socket->priv->timeout = timeout;
|
||||||
|
g_object_notify (G_OBJECT (socket), "timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_socket_get_family:
|
* g_socket_get_family:
|
||||||
* @socket: a #GSocket.
|
* @socket: a #GSocket.
|
||||||
@ -1566,6 +1663,9 @@ g_socket_check_connect_result (GSocket *socket,
|
|||||||
guint optlen;
|
guint optlen;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
|
if (!check_socket (socket, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
optlen = sizeof (value);
|
optlen = sizeof (value);
|
||||||
if (getsockopt (socket->priv->fd, SOL_SOCKET, SO_ERROR, (void *)&value, &optlen) != 0)
|
if (getsockopt (socket->priv->fd, SOL_SOCKET, SO_ERROR, (void *)&value, &optlen) != 0)
|
||||||
{
|
{
|
||||||
@ -2199,6 +2299,7 @@ typedef struct {
|
|||||||
GIOCondition condition;
|
GIOCondition condition;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GPollFD cancel_pollfd;
|
GPollFD cancel_pollfd;
|
||||||
|
GTimeVal timeout_time;
|
||||||
} GSocketSource;
|
} GSocketSource;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -2207,13 +2308,29 @@ socket_source_prepare (GSource *source,
|
|||||||
{
|
{
|
||||||
GSocketSource *socket_source = (GSocketSource *)source;
|
GSocketSource *socket_source = (GSocketSource *)source;
|
||||||
|
|
||||||
|
if (g_cancellable_is_cancelled (socket_source->cancellable))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (socket_source->timeout_time.tv_sec)
|
||||||
|
{
|
||||||
|
GTimeVal now;
|
||||||
|
|
||||||
|
g_source_get_current_time (source, &now);
|
||||||
|
*timeout = ((socket_source->timeout_time.tv_sec - now.tv_sec) * 1000 +
|
||||||
|
(socket_source->timeout_time.tv_usec - now.tv_usec) / 1000);
|
||||||
|
if (*timeout < 0)
|
||||||
|
{
|
||||||
|
socket_source->socket->priv->timed_out = TRUE;
|
||||||
|
socket_source->pollfd.revents = socket_source->condition & (G_IO_IN | G_IO_OUT);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*timeout = -1;
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
socket_source->pollfd.revents = update_condition (socket_source->socket);
|
socket_source->pollfd.revents = update_condition (socket_source->socket);
|
||||||
#endif
|
#endif
|
||||||
*timeout = -1;
|
|
||||||
|
|
||||||
if (g_cancellable_is_cancelled (socket_source->cancellable))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if ((socket_source->condition & socket_source->pollfd.revents) != 0)
|
if ((socket_source->condition & socket_source->pollfd.revents) != 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2315,6 +2432,17 @@ socket_source_new (GSocket *socket,
|
|||||||
socket_source->pollfd.revents = 0;
|
socket_source->pollfd.revents = 0;
|
||||||
g_source_add_poll (source, &socket_source->pollfd);
|
g_source_add_poll (source, &socket_source->pollfd);
|
||||||
|
|
||||||
|
if (socket->priv->timeout)
|
||||||
|
{
|
||||||
|
g_get_current_time (&socket_source->timeout_time);
|
||||||
|
socket_source->timeout_time.tv_sec += socket->priv->timeout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
socket_source->timeout_time.tv_sec = 0;
|
||||||
|
socket_source->timeout_time.tv_usec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2338,6 +2466,12 @@ socket_source_new (GSocket *socket,
|
|||||||
* condition change). You can check for this in the callback using
|
* condition change). You can check for this in the callback using
|
||||||
* g_cancellable_is_cancelled().
|
* g_cancellable_is_cancelled().
|
||||||
*
|
*
|
||||||
|
* If @socket has a timeout set, and it is reached before @condition
|
||||||
|
* occurs, the source will then trigger anyway, reporting %G_IO_IN or
|
||||||
|
* %G_IO_OUT depending on @condition. However, @socket will have been
|
||||||
|
* marked as having had a timeout, and so the next #GSocket I/O method
|
||||||
|
* you call will then fail with a %G_IO_ERROR_TIMED_OUT.
|
||||||
|
*
|
||||||
* Returns: a newly allocated %GSource, free with g_source_unref().
|
* Returns: a newly allocated %GSource, free with g_source_unref().
|
||||||
*
|
*
|
||||||
* Since: 2.22
|
* Since: 2.22
|
||||||
@ -2415,8 +2549,11 @@ g_socket_condition_check (GSocket *socket,
|
|||||||
* Waits for @condition to become true on @socket. When the condition
|
* Waits for @condition to become true on @socket. When the condition
|
||||||
* is met, %TRUE is returned.
|
* is met, %TRUE is returned.
|
||||||
*
|
*
|
||||||
* If @cancellable is cancelled before the condition is met then %FALSE
|
* If @cancellable is cancelled before the condition is met, or if the
|
||||||
* is returned and @error, if non-%NULL, is set to %G_IO_ERROR_CANCELLED.
|
* socket has a timeout set and it is reached before the condition is
|
||||||
|
* met, then %FALSE is returned and @error, if non-%NULL, is set to
|
||||||
|
* the appropriate value (%G_IO_ERROR_CANCELLED or
|
||||||
|
* %G_IO_ERROR_TIMED_OUT).
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the condition was met, %FALSE otherwise
|
* Returns: %TRUE if the condition was met, %FALSE otherwise
|
||||||
*
|
*
|
||||||
@ -2438,7 +2575,7 @@ g_socket_condition_wait (GSocket *socket,
|
|||||||
{
|
{
|
||||||
GIOCondition current_condition;
|
GIOCondition current_condition;
|
||||||
WSAEVENT events[2];
|
WSAEVENT events[2];
|
||||||
DWORD res;
|
DWORD res, timeout;
|
||||||
GPollFD cancel_fd;
|
GPollFD cancel_fd;
|
||||||
int num_events;
|
int num_events;
|
||||||
|
|
||||||
@ -2453,11 +2590,16 @@ g_socket_condition_wait (GSocket *socket,
|
|||||||
if (g_cancellable_make_pollfd (cancellable, &cancel_fd))
|
if (g_cancellable_make_pollfd (cancellable, &cancel_fd))
|
||||||
events[num_events++] = (WSAEVENT)cancel_fd.fd;
|
events[num_events++] = (WSAEVENT)cancel_fd.fd;
|
||||||
|
|
||||||
|
if (socket->priv->timeout)
|
||||||
|
timeout = socket->priv->timeout * 1000;
|
||||||
|
else
|
||||||
|
timeout = WSA_INFINITE;
|
||||||
|
|
||||||
current_condition = update_condition (socket);
|
current_condition = update_condition (socket);
|
||||||
while ((condition & current_condition) == 0)
|
while ((condition & current_condition) == 0)
|
||||||
{
|
{
|
||||||
res = WSAWaitForMultipleEvents(num_events, events,
|
res = WSAWaitForMultipleEvents(num_events, events,
|
||||||
FALSE, WSA_INFINITE, FALSE);
|
FALSE, timeout, FALSE);
|
||||||
if (res == WSA_WAIT_FAILED)
|
if (res == WSA_WAIT_FAILED)
|
||||||
{
|
{
|
||||||
int errsv = get_socket_errno ();
|
int errsv = get_socket_errno ();
|
||||||
@ -2468,6 +2610,12 @@ g_socket_condition_wait (GSocket *socket,
|
|||||||
socket_strerror (errsv));
|
socket_strerror (errsv));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (res == WSA_WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
|
||||||
|
_("Socket I/O timed out"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||||
break;
|
break;
|
||||||
@ -2485,6 +2633,7 @@ g_socket_condition_wait (GSocket *socket,
|
|||||||
GPollFD poll_fd[2];
|
GPollFD poll_fd[2];
|
||||||
gint result;
|
gint result;
|
||||||
gint num;
|
gint num;
|
||||||
|
gint timeout;
|
||||||
|
|
||||||
poll_fd[0].fd = socket->priv->fd;
|
poll_fd[0].fd = socket->priv->fd;
|
||||||
poll_fd[0].events = condition;
|
poll_fd[0].events = condition;
|
||||||
@ -2493,15 +2642,26 @@ g_socket_condition_wait (GSocket *socket,
|
|||||||
if (g_cancellable_make_pollfd (cancellable, &poll_fd[1]))
|
if (g_cancellable_make_pollfd (cancellable, &poll_fd[1]))
|
||||||
num++;
|
num++;
|
||||||
|
|
||||||
|
if (socket->priv->timeout)
|
||||||
|
timeout = socket->priv->timeout * 1000;
|
||||||
|
else
|
||||||
|
timeout = -1;
|
||||||
|
|
||||||
do
|
do
|
||||||
result = g_poll (poll_fd, num, -1);
|
result = g_poll (poll_fd, num, timeout);
|
||||||
while (result == -1 && get_socket_errno () == EINTR);
|
while (result == -1 && get_socket_errno () == EINTR);
|
||||||
|
|
||||||
if (num > 1)
|
if (num > 1)
|
||||||
g_cancellable_release_fd (cancellable);
|
g_cancellable_release_fd (cancellable);
|
||||||
|
|
||||||
return cancellable == NULL ||
|
if (result == 0)
|
||||||
!g_cancellable_set_error_if_cancelled (cancellable, error);
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
|
||||||
|
_("Socket I/O timed out"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !g_cancellable_set_error_if_cancelled (cancellable, error);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,9 @@ gboolean g_socket_get_keepalive (GSocket
|
|||||||
gint g_socket_get_listen_backlog (GSocket *socket);
|
gint g_socket_get_listen_backlog (GSocket *socket);
|
||||||
void g_socket_set_listen_backlog (GSocket *socket,
|
void g_socket_set_listen_backlog (GSocket *socket,
|
||||||
gint backlog);
|
gint backlog);
|
||||||
|
guint g_socket_get_timeout (GSocket *socket);
|
||||||
|
void g_socket_set_timeout (GSocket *socket,
|
||||||
|
guint timeout);
|
||||||
gboolean g_socket_is_connected (GSocket *socket);
|
gboolean g_socket_is_connected (GSocket *socket);
|
||||||
gboolean g_socket_bind (GSocket *socket,
|
gboolean g_socket_bind (GSocket *socket,
|
||||||
GSocketAddress *address,
|
GSocketAddress *address,
|
||||||
|
@ -14,6 +14,7 @@ gboolean non_blocking = FALSE;
|
|||||||
gboolean use_udp = FALSE;
|
gboolean use_udp = FALSE;
|
||||||
gboolean use_source = FALSE;
|
gboolean use_source = FALSE;
|
||||||
int cancel_timeout = 0;
|
int cancel_timeout = 0;
|
||||||
|
int read_timeout = 0;
|
||||||
gboolean unix_socket = FALSE;
|
gboolean unix_socket = FALSE;
|
||||||
|
|
||||||
static GOptionEntry cmd_entries[] = {
|
static GOptionEntry cmd_entries[] = {
|
||||||
@ -31,6 +32,8 @@ static GOptionEntry cmd_entries[] = {
|
|||||||
{"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,
|
||||||
|
"Time out reads after the specified number of seconds", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,6 +154,9 @@ main (int argc,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read_timeout)
|
||||||
|
g_socket_set_timeout (socket, read_timeout);
|
||||||
|
|
||||||
if (unix_socket)
|
if (unix_socket)
|
||||||
{
|
{
|
||||||
GSocketAddress *addr;
|
GSocketAddress *addr;
|
||||||
|
@ -15,6 +15,8 @@ gboolean non_blocking = FALSE;
|
|||||||
gboolean use_udp = FALSE;
|
gboolean use_udp = FALSE;
|
||||||
gboolean use_source = FALSE;
|
gboolean use_source = FALSE;
|
||||||
int cancel_timeout = 0;
|
int cancel_timeout = 0;
|
||||||
|
int read_timeout = 0;
|
||||||
|
int delay = 0;
|
||||||
gboolean unix_socket = FALSE;
|
gboolean unix_socket = FALSE;
|
||||||
|
|
||||||
static GOptionEntry cmd_entries[] = {
|
static GOptionEntry cmd_entries[] = {
|
||||||
@ -36,6 +38,10 @@ static GOptionEntry cmd_entries[] = {
|
|||||||
{"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
|
||||||
|
{"delay", 'd', 0, G_OPTION_ARG_INT, &delay,
|
||||||
|
"Delay responses by the specified number of seconds", NULL},
|
||||||
|
{"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
|
||||||
|
"Time out reads after the specified number of seconds", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -210,6 +216,8 @@ main (int argc,
|
|||||||
|
|
||||||
if (non_blocking)
|
if (non_blocking)
|
||||||
g_socket_set_blocking (new_socket, FALSE);
|
g_socket_set_blocking (new_socket, FALSE);
|
||||||
|
if (read_timeout)
|
||||||
|
g_socket_set_timeout (new_socket, read_timeout);
|
||||||
|
|
||||||
address = g_socket_get_remote_address (new_socket, &error);
|
address = g_socket_get_remote_address (new_socket, &error);
|
||||||
if (!address)
|
if (!address)
|
||||||
@ -271,6 +279,13 @@ main (int argc,
|
|||||||
|
|
||||||
to_send = size;
|
to_send = size;
|
||||||
|
|
||||||
|
if (delay)
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
g_print ("delaying %d seconds before response\n", delay);
|
||||||
|
g_usleep (1000 * 1000 * delay);
|
||||||
|
}
|
||||||
|
|
||||||
while (to_send > 0)
|
while (to_send > 0)
|
||||||
{
|
{
|
||||||
ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
|
ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user