X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsocket.c;h=f06e49bccda6b683a75493a9c7756b76779de149;hb=e608ec7b2e47d29fa189fca6e97f484f41c115a4;hp=70618e100c64696892228ab918cd3d1546b128a5;hpb=4139b26f3e2f869191b3d96d912f699470db6cea;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsocket.c b/gio/gsocket.c index 70618e1..f06e49b 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -117,6 +117,10 @@ * account the fact that your program will not automatically be killed * if it tries to write to %stdout after it has been closed. * + * Like most other APIs in GLib, #GSocket is not inherently thread safe. To use + * a #GSocket concurrently from multiple threads, you must implement your own + * locking. + * * Since: 2.22 */ @@ -201,34 +205,10 @@ get_socket_errno (void) static GIOErrorEnum socket_io_error_from_errno (int err) { -#ifndef G_OS_WIN32 - return g_io_error_from_errno (err); +#ifdef G_OS_WIN32 + return g_io_error_from_win32_error (err); #else - switch (err) - { - case WSAEADDRINUSE: - return G_IO_ERROR_ADDRESS_IN_USE; - case WSAEWOULDBLOCK: - return G_IO_ERROR_WOULD_BLOCK; - case WSAEACCES: - return G_IO_ERROR_PERMISSION_DENIED; - case WSA_INVALID_HANDLE: - case WSA_INVALID_PARAMETER: - case WSAEBADF: - case WSAENOTSOCK: - return G_IO_ERROR_INVALID_ARGUMENT; - case WSAEPROTONOSUPPORT: - return G_IO_ERROR_NOT_SUPPORTED; - case WSAECANCELLED: - return G_IO_ERROR_CANCELLED; - case WSAESOCKTNOSUPPORT: - case WSAEOPNOTSUPP: - case WSAEPFNOSUPPORT: - case WSAEAFNOSUPPORT: - return G_IO_ERROR_NOT_SUPPORTED; - default: - return G_IO_ERROR_FAILED; - } + return g_io_error_from_errno (err); #endif } @@ -328,6 +308,13 @@ check_socket (GSocket *socket, return FALSE; } + return TRUE; +} + +static gboolean +check_timeout (GSocket *socket, + GError **error) +{ if (socket->priv->timed_out) { socket->priv->timed_out = FALSE; @@ -2232,6 +2219,9 @@ g_socket_accept (GSocket *socket, if (!check_socket (socket, error)) return NULL; + if (!check_timeout (socket, error)) + return NULL; + while (TRUE) { if (socket->priv->blocking && @@ -2428,6 +2418,9 @@ g_socket_check_connect_result (GSocket *socket, if (!check_socket (socket, error)) return FALSE; + if (!check_timeout (socket, error)) + return FALSE; + if (!g_socket_get_option (socket, SOL_SOCKET, SO_ERROR, &value, error)) { g_prefix_error (error, _("Unable to get pending error: ")); @@ -2595,6 +2588,9 @@ g_socket_receive_with_blocking (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (!check_timeout (socket, error)) + return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; @@ -2770,6 +2766,9 @@ g_socket_send_with_blocking (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (!check_timeout (socket, error)) + return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; @@ -3204,57 +3203,35 @@ update_condition (GSocket *socket) typedef struct { GSource source; +#ifdef G_OS_WIN32 GPollFD pollfd; +#else + gpointer fd_tag; +#endif GSocket *socket; GIOCondition condition; - GCancellable *cancellable; - GPollFD cancel_pollfd; - gint64 timeout_time; } GSocketSource; +#ifdef G_OS_WIN32 static gboolean -socket_source_prepare (GSource *source, - gint *timeout) +socket_source_prepare_win32 (GSource *source, + gint *timeout) { GSocketSource *socket_source = (GSocketSource *)source; - if (g_cancellable_is_cancelled (socket_source->cancellable)) - return TRUE; - - if (socket_source->timeout_time) - { - gint64 now; - - now = g_source_get_time (source); - /* Round up to ensure that we don't try again too early */ - *timeout = (socket_source->timeout_time - now + 999) / 1000; - if (*timeout < 0) - { - socket_source->socket->priv->timed_out = TRUE; - *timeout = 0; - return TRUE; - } - } - else - *timeout = -1; - -#ifdef G_OS_WIN32 - socket_source->pollfd.revents = update_condition (socket_source->socket); -#endif - - if ((socket_source->condition & socket_source->pollfd.revents) != 0) - return TRUE; + *timeout = -1; - return FALSE; + return (update_condition (socket_source->socket) & socket_source->condition) != 0; } static gboolean -socket_source_check (GSource *source) +socket_source_check_win32 (GSource *source) { int timeout; - return socket_source_prepare (source, &timeout); + return socket_source_prepare_win32 (source, &timeout); } +#endif static gboolean socket_source_dispatch (GSource *source, @@ -3264,24 +3241,29 @@ socket_source_dispatch (GSource *source, GSocketSourceFunc func = (GSocketSourceFunc)callback; GSocketSource *socket_source = (GSocketSource *)source; GSocket *socket = socket_source->socket; + gint64 timeout; + guint events; gboolean ret; #ifdef G_OS_WIN32 - socket_source->pollfd.revents = update_condition (socket_source->socket); + events = update_condition (socket_source->socket); +#else + events = g_source_query_unix_fd (source, socket_source->fd_tag); #endif - if (socket_source->socket->priv->timed_out) - socket_source->pollfd.revents |= socket_source->condition & (G_IO_IN | G_IO_OUT); - ret = (*func) (socket, - socket_source->pollfd.revents & socket_source->condition, - user_data); + timeout = g_source_get_ready_time (source); + if (timeout >= 0 && timeout < g_source_get_time (source)) + { + socket->priv->timed_out = TRUE; + events |= (G_IO_IN | G_IO_OUT); + } - if (socket->priv->timeout) - socket_source->timeout_time = g_get_monotonic_time () + - socket->priv->timeout * 1000000; + ret = (*func) (socket, events & socket_source->condition, user_data); + if (socket->priv->timeout) + g_source_set_ready_time (source, g_get_monotonic_time () + socket->priv->timeout * 1000000); else - socket_source->timeout_time = 0; + g_source_set_ready_time (source, -1); return ret; } @@ -3299,12 +3281,6 @@ socket_source_finalize (GSource *source) #endif g_object_unref (socket); - - if (socket_source->cancellable) - { - g_cancellable_release_fd (socket_source->cancellable); - g_object_unref (socket_source->cancellable); - } } static gboolean @@ -3337,8 +3313,12 @@ socket_source_closure_callback (GSocket *socket, static GSourceFuncs socket_source_funcs = { - socket_source_prepare, - socket_source_check, +#ifdef G_OS_WIN32 + socket_source_prepare_win32, + socket_source_check_win32, +#else + NULL, NULL, /* check, prepare */ +#endif socket_source_dispatch, socket_source_finalize, (GSourceFunc)socket_source_closure_callback, @@ -3371,30 +3351,30 @@ socket_source_new (GSocket *socket, socket_source->socket = g_object_ref (socket); socket_source->condition = condition; - if (g_cancellable_make_pollfd (cancellable, - &socket_source->cancel_pollfd)) + if (cancellable) { - socket_source->cancellable = g_object_ref (cancellable); - g_source_add_poll (source, &socket_source->cancel_pollfd); + GSource *cancellable_source; + + cancellable_source = g_cancellable_source_new (cancellable); + g_source_add_child_source (source, cancellable_source); + g_source_set_dummy_callback (cancellable_source); + g_source_unref (cancellable_source); } #ifdef G_OS_WIN32 add_condition_watch (socket, &socket_source->condition); socket_source->pollfd.fd = (gintptr) socket->priv->event; -#else - socket_source->pollfd.fd = socket->priv->fd; -#endif - socket_source->pollfd.events = condition; socket_source->pollfd.revents = 0; g_source_add_poll (source, &socket_source->pollfd); +#else + socket_source->fd_tag = g_source_add_unix_fd (source, socket->priv->fd, condition); +#endif if (socket->priv->timeout) - socket_source->timeout_time = g_get_monotonic_time () + - socket->priv->timeout * 1000000; - + g_source_set_ready_time (source, g_get_monotonic_time () + socket->priv->timeout * 1000000); else - socket_source->timeout_time = 0; + g_source_set_ready_time (source, -1); return source; } @@ -3405,8 +3385,9 @@ socket_source_new (GSocket *socket, * @condition: a #GIOCondition mask to monitor * @cancellable: (allow-none): a %GCancellable or %NULL * - * Creates a %GSource that can be attached to a %GMainContext to monitor - * for the availibility of the specified @condition on the socket. + * Creates a #GSource that can be attached to a %GMainContext to monitor + * for the availability of the specified @condition on the socket. The #GSource + * keeps a reference to the @socket. * * The callback on the source is of the #GSocketSourceFunc type. * @@ -3766,10 +3747,18 @@ g_socket_send_message (GSocket *socket, char zero; g_return_val_if_fail (G_IS_SOCKET (socket), -1); + g_return_val_if_fail (address == NULL || G_IS_SOCKET_ADDRESS (address), -1); + g_return_val_if_fail (num_vectors == 0 || vectors != NULL, -1); + g_return_val_if_fail (num_messages == 0 || messages != NULL, -1); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); if (!check_socket (socket, error)) return -1; + if (!check_timeout (socket, error)) + return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; @@ -4146,6 +4135,9 @@ g_socket_receive_message (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (!check_timeout (socket, error)) + return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; @@ -4477,6 +4469,23 @@ g_socket_get_credentials (GSocket *socket, native_creds_buf); } } +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + { + struct unpcbid cred; + socklen_t optlen = sizeof (cred); + + if (getsockopt (socket->priv->fd, + 0, + LOCAL_PEEREID, + &cred, + &optlen) == 0) + { + ret = g_credentials_new (); + g_credentials_set_native (ret, + G_CREDENTIALS_NATIVE_TYPE, + &cred); + } + } #elif G_CREDENTIALS_USE_SOLARIS_UCRED { ucred_t *ucred = NULL;