Exemplo n.º 1
0
static void connection_handler(IOCHAN iochan, int event)
{
    struct connection *co = iochan_getdata(iochan);
    struct client *cl;
    struct host *host = co->host;

    yaz_mutex_enter(host->mutex);
    cl = co->client;
    if (!cl) 
    {
        /* no client associated with it.. We are probably getting
           a closed connection from the target.. Or, perhaps, an unexpected
           package.. We will just close the connection */
        yaz_log(YLOG_LOG, "timeout connection %p event=%d", co, event);
        remove_connection_from_host(co);
        yaz_mutex_leave(host->mutex);
        connection_destroy(co);
    }
    else if (event & EVENT_TIMEOUT)
    {
        if (co->state == Conn_Connecting)
        {
            yaz_log(YLOG_WARN, "%p connect timeout %s", co, client_get_id(cl));

            client_set_state(cl, Client_Error);
            remove_connection_from_host(co);
            yaz_mutex_leave(host->mutex);
            connection_destroy(co);
        }
        else
        {
            yaz_log(YLOG_LOG,  "%p Connection idle timeout %s", co, client_get_id(cl));
            remove_connection_from_host(co);
            yaz_mutex_leave(host->mutex);
            connection_destroy(co);
        }
    }
    else
    {
        yaz_mutex_leave(host->mutex);

        client_lock(cl);
        non_block_events(co);

        ZOOM_connection_fire_event_socket(co->link, event);
        
        non_block_events(co);
        client_unlock(cl);

        if (co->link)
        {
            iochan_setflags(iochan, ZOOM_connection_get_mask(co->link));
            iochan_setfd(iochan, ZOOM_connection_get_socket(co->link));
        }
    }
}
Exemplo n.º 2
0
void connection_continue(struct connection *co)
{
    int r = ZOOM_connection_exec_task(co->link);
    if (!r)
        non_block_events(co);
    else
    {
        iochan_setflags(co->iochan, ZOOM_connection_get_mask(co->link));
        iochan_setfd(co->iochan, ZOOM_connection_get_socket(co->link));
    }
}
Exemplo n.º 3
0
void connection_continue(struct connection *co)
{
    int r = ZOOM_connection_exec_task(co->link);
    if (!r)
    {
        const char *error, *addinfo;
        int err;
        if ((err = ZOOM_connection_error(co->link, &error, &addinfo)))
        {
            if (co->client)
            {
                yaz_log(YLOG_LOG, "Error %s from %s",
                        error, client_get_id(co->client));
                client_set_diagnostic(co->client, err, addinfo);
                client_set_state_nb(co->client, Client_Error);
            }
        }
    }
    else
    {
        iochan_setflags(co->iochan, ZOOM_connection_get_mask(co->link));
        iochan_setfd(co->iochan, ZOOM_connection_get_socket(co->link));
    }
}
Exemplo n.º 4
0
// Handles I/O on a client connection to a backend web server (proxy mode)
static void proxy_io(IOCHAN pi, int event)
{
    struct http_proxy *pc = iochan_getdata(pi);
    struct http_channel *hc = pc->channel;

    switch (event)
    {
        int res;
        struct http_buf *htbuf;

        case EVENT_INPUT:
            htbuf = http_buf_create(hc->http_server);
            res = recv(iochan_getfd(pi), htbuf->buf, HTTP_BUF_SIZE -1, 0);
            if (res == 0 || (res < 0 && !is_inprogress()))
            {
                if (hc->oqueue)
                {
                    yaz_log(YLOG_WARN, "Proxy read came up short");
                    // Close channel and alert client HTTP channel that we're gone
                    http_buf_destroy(hc->http_server, htbuf);
#ifdef WIN32
                    closesocket(iochan_getfd(pi));
#else
                    close(iochan_getfd(pi));
#endif
                    iochan_destroy(pi);
                    pc->iochan = 0;
                }
                else
                {
                    http_channel_destroy(hc->iochan);
                    return;
                }
            }
            else
            {
                htbuf->buf[res] = '\0';
                htbuf->offset = 0;
                htbuf->len = res;
                // Write any remaining payload
                if (htbuf->len - htbuf->offset > 0)
                    http_buf_enqueue(&hc->oqueue, htbuf);
            }
            iochan_setflag(hc->iochan, EVENT_OUTPUT);
            break;
        case EVENT_OUTPUT:
            if (!(htbuf = pc->oqueue))
            {
                iochan_clearflag(pi, EVENT_OUTPUT);
                return;
            }
            res = send(iochan_getfd(pi), htbuf->buf + htbuf->offset, htbuf->len, 0);
            if (res <= 0)
            {
                yaz_log(YLOG_WARN|YLOG_ERRNO, "write");
                http_channel_destroy(hc->iochan);
                return;
            }
            if (res == htbuf->len)
            { 
                struct http_buf *np = htbuf->next;
                http_buf_destroy(hc->http_server, htbuf);
                pc->oqueue = np;
            }
            else
            {
                htbuf->len -= res;
                htbuf->offset += res;
            }

            if (!pc->oqueue) {
                iochan_setflags(pi, EVENT_INPUT); // Turns off output flag
            }
            break;
        default:
            yaz_log(YLOG_WARN, "Unexpected event on connection");
            http_channel_destroy(hc->iochan);
    }
}
Exemplo n.º 5
0
/* UNIX listener */
static void listener(IOCHAN h, int event)
{
    COMSTACK line = (COMSTACK) iochan_getdata(h);
    int res;

    if (event == EVENT_INPUT)
    {
        COMSTACK new_line;
        if ((res = cs_listen_check(line, 0, 0, control_block.check_ip,
                                   control_block.daemon_name)) < 0)
        {
            yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_listen failed");
            return;
        }
        else if (res == 1)
        {
            yaz_log(YLOG_WARN, "cs_listen incomplete");
            return;
        }
        new_line = cs_accept(line);
        if (!new_line)
        {
            yaz_log(YLOG_FATAL, "Accept failed.");
            iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
            return;
        }

        yaz_log(log_sessiondetail, "Connect from %s", cs_addrstr(new_line));

        no_sessions++;
        if (control_block.dynamic)
        {
            if ((res = fork()) < 0)
            {
                yaz_log(YLOG_FATAL|YLOG_ERRNO, "fork");
                iochan_destroy(h);
                return;
            }
            else if (res == 0) /* child */
            {
                char nbuf[100];
                IOCHAN pp;

                for (pp = pListener; pp; pp = iochan_getnext(pp))
                {
                    COMSTACK l = (COMSTACK)iochan_getdata(pp);
                    cs_close(l);
                    iochan_destroy(pp);
                }
                sprintf(nbuf, "%s(%d)", me, no_sessions);
                yaz_log_init_prefix(nbuf);
                /* ensure that bend_stop is not called when each child exits -
                   only for the main process ..  */
                control_block.bend_stop = 0;
            }
            else /* parent */
            {
                cs_close(new_line);
                return;
            }
        }

        if (control_block.threads)
        {
#if YAZ_POSIX_THREADS
            pthread_t child_thread;
            pthread_create(&child_thread, 0, new_session, new_line);
            pthread_detach(child_thread);
#elif YAZ_GNU_THREADS
            pth_attr_t attr;
            pth_t child_thread;

            attr = pth_attr_new();
            pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
            pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 32*1024);
            pth_attr_set(attr, PTH_ATTR_NAME, "session");
            yaz_log(YLOG_DEBUG, "pth_spawn begin");
            child_thread = pth_spawn(attr, new_session, new_line);
            yaz_log(YLOG_DEBUG, "pth_spawn finish");
            pth_attr_destroy(attr);
#else
            new_session(new_line);
#endif
        }
        else
            new_session(new_line);
    }
    else if (event == EVENT_TIMEOUT)
    {
        yaz_log(log_server, "Shutting down listener.");
        iochan_destroy(h);
    }
    else
    {
        yaz_log(YLOG_FATAL, "Bad event on listener.");
        iochan_destroy(h);
    }
}
Exemplo n.º 6
0
/* WIN32 listener */
static void listener(IOCHAN h, int event)   
{
    COMSTACK line = (COMSTACK) iochan_getdata(h);
    IOCHAN parent_chan = line->user;
    association *newas;
    int res;
    HANDLE newHandle;

    if (event == EVENT_INPUT)
    {
        COMSTACK new_line;
        IOCHAN new_chan;

        if ((res = cs_listen(line, 0, 0)) < 0)
        {
            yaz_log(YLOG_FATAL|YLOG_ERRNO, "cs_listen failed");
            return;
        }
        else if (res == 1)
            return; /* incomplete */
        yaz_log(YLOG_DEBUG, "listen ok");
        new_line = cs_accept(line);
	if (!new_line)
        {
            yaz_log(YLOG_FATAL, "Accept failed.");
            return;
        }
        yaz_log(YLOG_DEBUG, "Accept ok");

        if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
                                       EVENT_INPUT, parent_chan->chan_id)))
        {
            yaz_log(YLOG_FATAL, "Failed to create iochan");
            iochan_destroy(h);
            return;
        }

        yaz_log(YLOG_DEBUG, "Creating association");
        if (!(newas = create_association(new_chan, new_line,
                                         control_block.apdufile)))
        {
            yaz_log(YLOG_FATAL, "Failed to create new assoc.");
            iochan_destroy(h);
            return;
        }
        newas->cs_get_mask = EVENT_INPUT;
        newas->cs_put_mask = 0;
        newas->cs_accept_mask = 0;

        yaz_log(YLOG_DEBUG, "Setting timeout %d", control_block.idle_timeout);
        iochan_setdata(new_chan, newas);
        iochan_settimeout(new_chan, 60);

        /* Now what we need todo is create a new thread with this iochan as
           the parameter */
        newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);
        if (newHandle == (HANDLE) -1)
        {
            
            yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create new thread.");
            iochan_destroy(h);
            return;
        }
        /* We successfully created the thread, so add it to the list */
        statserv_add(newHandle, new_chan);

        yaz_log(YLOG_DEBUG, "Created new thread, id = %ld iochan %p",(long) newHandle, new_chan);
        iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
    }
    else
    {
        yaz_log(YLOG_FATAL, "Bad event on listener.");
        iochan_destroy(h);
        return;
    }
}