コード例 #1
0
ファイル: adns.c プロジェクト: MrJoe/gtk-gnutella
/**
 * Callback function for inputevt_add(). This function pipes the query to
 * the server using the pipe in non-blocking mode, partial writes are handled
 * appropriately. In case of an unrecoverable error the query pipe will be
 * closed and the blocking adns_fallback() will be invoked.
 */
static void
adns_query_callback(void *data, int dest, inputevt_cond_t condition)
{
	adns_async_write_t *remain = data;

	g_assert(NULL != remain);
	g_assert(NULL != remain->buf);
	g_assert(remain->pos < remain->size);
	g_assert(dest == adns_query_fd);
	g_assert(0 != adns_query_event_id);

	if (condition & INPUT_EVENT_EXCEPTION) {
		g_warning("%s: write exception", G_STRFUNC);
		goto abort;
	}

	while (remain->pos < remain->size) {
		ssize_t ret;
		size_t n;

		n = remain->size - remain->pos;
		ret = write(dest, &remain->buf[remain->pos], n);

		if (0 == ret) {
			errno = ECONNRESET;
			ret = (ssize_t) -1;
		}
		/* FALL THROUGH */
		if ((ssize_t) -1 == ret) {
			if (!is_temporary_error(errno))
				goto error;
			return;
		}

		g_assert(ret > 0);
		g_assert(UNSIGNED(ret) <= n);
		remain->pos += (size_t) ret;
	}
	g_assert(remain->pos == remain->size);

	inputevt_remove(&adns_query_event_id);

	goto done;	


error:
	g_warning("%s: write() failed: %m", G_STRFUNC);
abort:
	g_warning("%s: removed myself", G_STRFUNC);
	inputevt_remove(&adns_query_event_id);
	fd_close(&adns_query_fd);
	g_warning("%s: using fallback", G_STRFUNC);
	adns_fallback(&remain->req);
done:
	adns_async_write_free(remain);
	return;
}
コード例 #2
0
ファイル: tls_common.c プロジェクト: Longdengyu/gtk-gnutella
/**
 * Change the monitoring condition on the socket.
 */
static void
tls_socket_evt_change(struct gnutella_socket *s, inputevt_cond_t cond)
{
    socket_check(s);
    g_assert(socket_with_tls(s));	/* No USES yet, may not have handshaked */
    g_assert(INPUT_EVENT_EXCEPTION != cond);

    if (0 == s->gdk_tag)
        return;

    if (cond != s->tls.cb_cond) {
        int saved_errno = errno;

        if (GNET_PROPERTY(tls_debug) > 1) {
            int fd = socket_evt_fd(s);
            g_debug("tls_socket_evt_change: fd=%d, cond=%s -> %s",
                    fd, inputevt_cond_to_string(s->tls.cb_cond),
                    inputevt_cond_to_string(cond));
        }
        inputevt_remove(&s->gdk_tag);
        socket_evt_set(s, cond, s->tls.cb_handler, s->tls.cb_data);
        errno = saved_errno;
    }
}
コード例 #3
0
ファイル: adns.c プロジェクト: MrJoe/gtk-gnutella
/**
 * Callback function for inputevt_add(). This function invokes the callback
 * function given in DNS query on the client-side i.e., gtk-gnutella itself.
 * It handles partial reads if necessary. In case of an unrecoverable error
 * the reply pipe will be closed and the callback will be lost.
 */
static void
adns_reply_callback(void *data, int source, inputevt_cond_t condition)
{
	static struct adns_response ans;
	static void *buf;
	static size_t size, pos;

	g_assert(NULL == data);
	g_assert(condition & INPUT_EVENT_RX);

	/*
	 * Consume all the data available in the pipe, potentially handling
	 * several pending replies.
	 */

	for (;;) {
		ssize_t ret;
		size_t n;

		if (pos == size) {

			pos = 0;
			if (cast_to_pointer(&ans.common) == buf) {
				/*
				 * Finished reading the generic reply header, now read
				 * the specific part.
				 */

				g_assert(ADNS_COMMON_MAGIC == ans.common.magic);

				if (ans.common.reverse) {
					buf = &ans.reply.reverse;
					size = sizeof ans.reply.reverse;
				} else {
					buf = &ans.reply.by_addr;
					size = sizeof ans.reply.by_addr;
				}
			} else {
				if (buf) {
					/*
					 * Completed reading the specific part of the reply.
					 * Inform issuer of request by invoking the user callback.
					 */

					adns_reply_ready(&ans);
				}

				/*
				 * Continue reading the next reply, if any, which will start
				 * by the generic header.
				 */

				buf = &ans.common;
				size = sizeof ans.common;
				ans.common.magic = 0;
			}
		}

		g_assert(buf);
		g_assert(size > 0);
		g_assert(pos < size);

		n = size - pos;
		ret = read(source, cast_to_gchar_ptr(buf) + pos, n);
		if ((ssize_t) -1 == ret) {
		   	if (!is_temporary_error(errno)) {
				g_warning("%s: read() failed: %m", G_STRFUNC);
				goto error;
			}
			break;
		} else if (0 == ret) {
			g_warning("%s: read() failed: EOF", G_STRFUNC);
			goto error;
		} else {
			g_assert(ret > 0);
			g_assert(UNSIGNED(ret) <= n);
			pos += (size_t) ret;
		}
	}
	return;
	
error:
	inputevt_remove(&adns_reply_event_id);
	g_warning("%s: removed myself", G_STRFUNC);
	fd_close(&source);
}