Esempio n. 1
0
int handle_write(struct handle *h, const void *data, int len)
{
    assert(h->output);
    bufchain_add(&h->u.o.queued_data, data, len);
    handle_try_output(&h->u.o);
    return bufchain_size(&h->u.o.queued_data);
}
Esempio n. 2
0
int handle_write(struct handle *h, const void *data, int len)
{
    assert(h->type == HT_OUTPUT);
    assert(h->u.o.outgoingeof == EOF_NO);
    bufchain_add(&h->u.o.queued_data, data, len);
    handle_try_output(&h->u.o);
    return bufchain_size(&h->u.o.queued_data);
}
Esempio n. 3
0
void handle_write_eof(struct handle *h)
{
    /*
     * This function is called when we want to proactively send an
     * end-of-file notification on the handle. We can only do this by
     * actually closing the handle - so never call this on a
     * bidirectional handle if we're still interested in its incoming
     * direction!
     */
    assert(h->type == HT_OUTPUT);
    if (!h->u.o.outgoingeof == EOF_NO) {
        h->u.o.outgoingeof = EOF_PENDING;
        handle_try_output(&h->u.o);
    }
}
Esempio n. 4
0
void handle_got_event(HANDLE event)
#endif
{
    struct handle *h;

    assert(handles_by_evtomain);
    h = find234(handles_by_evtomain, &event, handle_find_evtomain);
    if (!h) {
	/*
	 * This isn't an error condition. If two or more event
	 * objects were signalled during the same select operation,
	 * and processing of the first caused the second handle to
	 * be closed, then it will sometimes happen that we receive
	 * an event notification here for a handle which is already
	 * deceased. In that situation we simply do nothing.
	 */
    #ifdef MPEXT
    return 0;
    #else
	return;
    #endif
    }

    if (h->u.g.moribund) {
	/*
	 * A moribund handle is one which we have either already
	 * signalled to die, or are waiting until its current I/O op
	 * completes to do so. Either way, it's treated as already
	 * dead from the external user's point of view, so we ignore
	 * the actual I/O result. We just signal the thread to die if
	 * we haven't yet done so, or destroy the handle if not.
	 */
	if (h->u.g.done) {
	    handle_destroy(h);
	} else {
	    h->u.g.done = TRUE;
	    h->u.g.busy = TRUE;
	    SetEvent(h->u.g.ev_from_main);
	}
    #ifdef MPEXT
    return 0;
    #else
	return;
    #endif
    }

    switch (h->type) {
	int backlog;

      case HT_INPUT:
	h->u.i.busy = FALSE;

	/*
	 * A signal on an input handle means data has arrived.
	 */
	if (h->u.i.len == 0) {
	    /*
	     * EOF, or (nearly equivalently) read error.
	     */
	    h->u.i.defunct = TRUE;
	    h->u.i.gotdata(h, NULL, -h->u.i.readerr);
	} else {
	    backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len);
	    handle_throttle(&h->u.i, backlog);
	}
    #ifdef MPEXT
        return 1;
    #else
        break;
    #endif

      case HT_OUTPUT:
	h->u.o.busy = FALSE;

	/*
	 * A signal on an output handle means we have completed a
	 * write. Call the callback to indicate that the output
	 * buffer size has decreased, or to indicate an error.
	 */
	if (h->u.o.writeerr) {
	    /*
	     * Write error. Send a negative value to the callback,
	     * and mark the thread as defunct (because the output
	     * thread is terminating by now).
	     */
	    h->u.o.defunct = TRUE;
	    h->u.o.sentdata(h, -h->u.o.writeerr);
	} else {
	    bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
	    h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data));
	    handle_try_output(&h->u.o);
	}
    #ifdef MPEXT
        return 0;
    #else
        break;
    #endif

      case HT_FOREIGN:
        /* Just call the callback. */
        h->u.f.callback(h->u.f.ctx);
    #ifdef MPEXT
        return 0;
    #else
        break;
    #endif
    }
#ifdef MPEXT
    return 0;
#endif
}
Esempio n. 5
0
void handle_got_event(HANDLE event)
{
    struct handle *h;

    assert(handles_by_evtomain);
    h = find234(handles_by_evtomain, &event, handle_find_evtomain);
    if (!h) {
	/*
	 * This isn't an error condition. If two or more event
	 * objects were signalled during the same select operation,
	 * and processing of the first caused the second handle to
	 * be closed, then it will sometimes happen that we receive
	 * an event notification here for a handle which is already
	 * deceased. In that situation we simply do nothing.
	 */
	return;
    }

    if (h->u.g.moribund) {
	/*
	 * A moribund handle is already treated as dead from the
	 * external user's point of view, so do nothing with the
	 * actual event. Just signal the thread to die if
	 * necessary, or destroy the handle if not.
	 */
	if (h->u.g.done) {
	    handle_destroy(h);
	} else {
	    h->u.g.done = TRUE;
	    h->u.g.busy = TRUE;
	    SetEvent(h->u.g.ev_from_main);
	}
	return;
    }

    if (!h->output) {
	int backlog;

	h->u.i.busy = FALSE;

	/*
	 * A signal on an input handle means data has arrived.
	 */
	if (h->u.i.len == 0) {
	    /*
	     * EOF, or (nearly equivalently) read error.
	     */
	    h->u.i.gotdata(h, NULL, -h->u.i.readerr);
	    h->u.i.defunct = TRUE;
	} else {
	    backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len);
	    handle_throttle(&h->u.i, backlog);
	}
    } else {
	h->u.o.busy = FALSE;

	/*
	 * A signal on an output handle means we have completed a
	 * write. Call the callback to indicate that the output
	 * buffer size has decreased, or to indicate an error.
	 */
	if (h->u.o.writeerr) {
	    /*
	     * Write error. Send a negative value to the callback,
	     * and mark the thread as defunct (because the output
	     * thread is terminating by now).
	     */
	    h->u.o.sentdata(h, -h->u.o.writeerr);
	    h->u.o.defunct = TRUE;
	} else {
	    bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
	    h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data));
	    handle_try_output(&h->u.o);
	}
    }
}