Beispiel #1
0
/*
 * Write the first <size> bytes of <data> to <fd>, for which the disOnData function must have been
 * called previously. You may write to <fd> via any other means, but if you use this function the
 * data will be written out, possibly piece by piece but always without blocking, when the given
 * file descriptor becomes writable.
 */
void disWrite(Dispatcher *dis, int fd, const char *data, size_t size)
{
    DIS_File *file = paGet(&dis->files, fd);

    dbgAssert(stderr, file != NULL, "unknown file descriptor: %d\n", fd);

    bufAdd(&file->outgoing, data, size);
}
Beispiel #2
0
/*
 * Handle readable file descriptor <fd>.
 */
void disHandleReadable(Dispatcher *dis, int fd)
{
    DIS_File *file = paGet(&dis->files, fd);

    dbgAssert(stderr, file != NULL, "unknown file descriptor: %d\n", fd);

    file->cb(dis, fd, (void *) file->udata);
}
Beispiel #3
0
/*
 * Drop the subscription on file descriptor <fd>.
 */
void disDropData(Dispatcher *dis, int fd)
{
    DIS_File *file = paGet(&dis->files, fd);

P   dbgPrint(stderr, "Dropping fd %d\n", fd);

    dbgAssert(stderr, file != NULL, "unknown file descriptor: %d\n", fd);

    paDrop(&dis->files, fd);
}
Beispiel #4
0
/*
 * Handle writable file descriptor <fd>.
 */
void disHandleWritable(Dispatcher *dis, int fd)
{
    int r;

    DIS_File *file = paGet(&dis->files, fd);

    dbgAssert(stderr, file != NULL, "unknown file descriptor: %d\n", fd);

    r = write(fd, bufGet(&file->outgoing), bufLen(&file->outgoing));

    if (r > 0) {
        bufTrim(&file->outgoing, r, 0);
    }
}
Beispiel #5
0
static void ns_handle_data(Dispatcher *dis, int fd, void *udata)
{
    char data[9000];

    NS *ns = (NS *) dis;
    NS_Connection *conn = paGet(&ns->connections, fd);

    int n;

P   dbgPrint(stderr, "Reading from fd %d...\n", fd);

    n = read(fd, data, sizeof(data));

P   dbgPrint(stderr, "read() returned %d.\n", n);

    if (n > 0) {
P       dbgPrint(stderr, "Adding to incoming buffer.\n");

        bufAdd(&conn->incoming, data, n);

        if (ns->on_socket_cb != NULL) {
P           dbgPrint(stderr, "Calling on_socket_cb.\n");

            ns->on_socket_cb(ns, fd,
                    bufGet(&conn->incoming), bufLen(&conn->incoming), ns->on_socket_udata);
        }
    }
    else if (n == 0) {
P       dbgPrint(stderr, "End of file, disconnecting.\n");

        nsDisconnect(ns, fd);

        if (ns->on_disconnect_cb != NULL) {
P           dbgPrint(stderr, "Calling on_disconnect_cb.\n");

            ns->on_disconnect_cb(ns, fd, ns->on_disconnect_udata);
        }
    }
    else {
P       dbgPrint(stderr, "Error, disconnecting.\n");

        nsDisconnect(ns, fd);

        if (ns->on_error_cb != NULL) {
P           dbgPrint(stderr, "Calling on_error_cb.\n");

            ns->on_error_cb(ns, fd, errno, ns->on_error_udata);
        }
    }
}
Beispiel #6
0
/*
 * Disconnect from a file descriptor that was returned earlier using nsConnect().
 */
void nsDisconnect(NS *ns, int fd)
{
    NS_Connection *conn = paGet(&ns->connections, fd);

P   dbgPrint(stderr, "Closing fd %d\n", fd);

    close(fd);

    disDropData(&ns->dis, fd);

    paDrop(&ns->connections, fd);

    bufReset(&conn->incoming);

    free(conn);
}
Beispiel #7
0
/*
 * Arrange for <cb> to be called when there is data available on file descriptor <fd>. <cb> will be
 * called with the given <dis>, <fd> and <udata>, which is a pointer to "user data" that will be
 * returned <cb> as it was given here, and that will not be accessed by dis in any way.
 */
void disOnData(Dispatcher *dis, int fd,
        void (*cb)(Dispatcher *dis, int fd, void *udata), const void *udata)
{
    DIS_File *file;

    dbgAssert(stderr, fd >= 0, "bad file descriptor: %d\n", fd);

P   dbgPrint(stderr, "Adding file on fd %d\n", fd);

    if ((file = paGet(&dis->files, fd)) == NULL) {
        file = calloc(1, sizeof(DIS_File));

        paSet(&dis->files, fd, file);
    }

    file->cb = cb;
    file->udata = udata;
}
Beispiel #8
0
/*
 * Close dispatcher <dis>. This removes all file descriptors and timers, which will
 * cause disRun() to return.
 */
void disClose(Dispatcher *dis)
{
    int fd;
    DIS_Timer *timer;

    for (fd = 0; fd < paCount(&dis->files); fd++) {
        DIS_File *file = paGet(&dis->files, fd);

        if (file != NULL) {
            paDrop(&dis->files, fd);

            bufReset(&file->outgoing);

            free(file);
        }
    }

    while ((timer = listRemoveHead(&dis->timers)) != NULL) {
        free(timer);
    }
}
Beispiel #9
0
/*
 * Prepare a call to select() based on the files and timeouts set in <dis>. The necessary parameters
 * to select() are returned through <nfds>, <rfds>, <wfds> and <tv> (exception-fds should be set to
 * NULL). <*tv> is set to point to an appropriate timeout value, or NULL if no timeout is to be set.
 * This function will clear <rfds> and <wfds>, so if callers want to add their own file descriptors,
 * they should do so after calling this function. This function returns -1 if the first timeout
 * should already have occurred, otherwise 0.
 */
int disPrepareSelect(Dispatcher *dis, int *nfds, fd_set *rfds, fd_set *wfds, struct timeval **tv)
{
    int fd;
    double delta_t;
    DIS_Timer *timer;

    *nfds = paCount(&dis->files);

    FD_ZERO(rfds);
    FD_ZERO(wfds);

P   dbgPrint(stderr, "File descriptors:");

    for (fd = 0; fd < *nfds; fd++) {
        DIS_File *file = paGet(&dis->files, fd);

        if (file == NULL) continue;

P       fprintf(stderr, " %d", fd);

        FD_SET(fd, rfds);

        if (bufLen(&file->outgoing) > 0) FD_SET(fd, wfds);

P       {
            fprintf(stderr, " (%s%s)",
                    FD_ISSET(fd, rfds) ? "r" : "",
                    FD_ISSET(fd, wfds) ? "w" : "");
        }
    }

P   fprintf(stderr, "\n");

P   dbgPrint(stderr, "%d pending timers:\n", listLength(&dis->timers));

P   for (timer = listHead(&dis->timers); timer; timer = listNext(timer)) {
        fprintf(stderr, "\t%f seconds\n", timer->t - nowd());
    }

    if ((timer = listHead(&dis->timers)) == NULL) {
        *tv = NULL;
    }
    else if ((delta_t = timer->t - nowd()) < 0) {
#if 0
P       dbgPrint(stderr, "First timer %f seconds ago, return -1\n", -delta_t);

        return -1;
#endif
        dis->tv.tv_sec = 0;
        dis->tv.tv_usec = 0;

        *tv = &dis->tv;
    }
    else {
P       dbgPrint(stderr, "First timer in %f seconds.\n", delta_t);

        dis->tv.tv_sec = (int) delta_t;
        dis->tv.tv_usec = 1000000 * fmod(delta_t, 1.0);

        *tv = &dis->tv;
    }

    return 0;
}
Beispiel #10
0
/*
 * Return TRUE if <fd> has been given to <dis> using disOnData(), FALSE otherwise.
 */
int disOwnsFd(Dispatcher *dis, int fd)
{
    return (paGet(&dis->files, fd) != NULL);
}
Beispiel #11
0
int main(int argc, char *argv[])
{
    PointerArray pa = { 0 };

    paSet(&pa, 0, (void *) 0x1);

    make_sure_that(paCount(&pa) == 1);
    make_sure_that(paGet(&pa, 0) == (void *) 0x1);
    make_sure_that(paGet(&pa, 1) == NULL);
    make_sure_that(paGet(&pa, 2) == NULL);

    paSet(&pa, 2, (void *) 0x3);

    make_sure_that(paCount(&pa) == 3);
    make_sure_that(paGet(&pa, 0) == (void *) 0x1);
    make_sure_that(paGet(&pa, 1) == NULL);
    make_sure_that(paGet(&pa, 2) == (void *) 0x3);

    paSet(&pa, 1, (void *) 0x2);

    make_sure_that(paCount(&pa) == 3);
    make_sure_that(paGet(&pa, 0) == (void *) 0x1);
    make_sure_that(paGet(&pa, 1) == (void *) 0x2);
    make_sure_that(paGet(&pa, 2) == (void *) 0x3);

    paDrop(&pa, 0);

    make_sure_that(paCount(&pa) == 3);
    make_sure_that(paGet(&pa, 0) == NULL);
    make_sure_that(paGet(&pa, 1) == (void *) 0x2);
    make_sure_that(paGet(&pa, 2) == (void *) 0x3);

    paDrop(&pa, 2);

    make_sure_that(paCount(&pa) == 2);
    make_sure_that(paGet(&pa, 0) == NULL);
    make_sure_that(paGet(&pa, 1) == (void *) 0x2);
    make_sure_that(paGet(&pa, 2) == NULL);

    paDrop(&pa, 1);

    make_sure_that(paCount(&pa) == 0);
    make_sure_that(paGet(&pa, 0) == NULL);
    make_sure_that(paGet(&pa, 1) == NULL);
    make_sure_that(paGet(&pa, 2) == NULL);

    paClear(&pa);
}
Beispiel #12
0
/*
 * Discard the first <length> bytes of the incoming buffer for file descriptor <fd> (becuase you've
 * processed them).
 */
void nsDiscard(NS *ns, int fd, int length)
{
    NS_Connection *conn = paGet(&ns->connections, fd);

    bufTrim(&conn->incoming, length, 0);
}
Beispiel #13
0
/*
 * Return the number of bytes available in the incoming buffer for <fd>.
 */
int nsAvailable(NS *ns, int fd)
{
    NS_Connection *conn = paGet(&ns->connections, fd);

    return bufLen(&conn->incoming);
}
Beispiel #14
0
/*
 * Return a pointer to the start of the incoming buffer.
 */
const char *nsIncoming(NS *ns, int fd)
{
    NS_Connection *conn = paGet(&ns->connections, fd);

    return bufGet(&conn->incoming);
}