예제 #1
0
void http_session_destroy(struct http_session *s)
{
    int must_destroy = 0;

    http_sessions_t http_sessions = s->http_sessions;

    yaz_log(http_sessions->log_level, "Session %u destroy", s->session_id);
    yaz_mutex_enter(http_sessions->mutex);
    /* only if http_session has no active http sessions on it can be destroyed */
    if (s->destroy_counter == s->activity_counter)
    {
        struct http_session **p = 0;
        must_destroy = 1;
        for (p = &http_sessions->session_list; *p; p = &(*p)->next)
            if (*p == s)
            {
                *p = (*p)->next;
                break;
            }
    }
    yaz_mutex_leave(http_sessions->mutex);
    if (must_destroy)
    {   /* destroying for real */
        yaz_log(http_sessions->log_level, "Session %u destroyed", s->session_id);
        iochan_destroy(s->timeout_iochan);
        session_destroy(s->psession);
        http_session_use(-1);
        nmem_destroy(s->nmem);
    }
    else {
        yaz_log(http_sessions->log_level, "Session %u destroying delayed. Active clients (%d-%d). Waiting for new timeout.",
                s->session_id, s->activity_counter, s->destroy_counter);
    }

}
예제 #2
0
static void statserv_closedown(void)
{
    IOCHAN p;

    xml_config_bend_stop();
    for (p = pListener; p; p = p->next)
    {
        iochan_destroy(p);
    }
    xml_config_close();
}
예제 #3
0
파일: http.c 프로젝트: saiful76/pazpar2
// Cleanup channel
static void http_channel_destroy(IOCHAN i)
{
    struct http_channel *s = iochan_getdata(i);
    http_server_t http_server;

    if (s->proxy)
    {
        if (s->proxy->iochan)
        {
#ifdef WIN32
            closesocket(iochan_getfd(s->proxy->iochan));
#else
            close(iochan_getfd(s->proxy->iochan));
#endif
            iochan_destroy(s->proxy->iochan);
        }
        http_buf_destroy_queue(s->http_server, s->proxy->oqueue);
        xfree(s->proxy);
    }
    http_buf_destroy_queue(s->http_server, s->iqueue);
    http_buf_destroy_queue(s->http_server, s->oqueue);
    http_fire_observers(s);
    http_destroy_observers(s);

    http_server = s->http_server; /* save it for destroy (decref) */

    http_server_destroy(http_server);

#ifdef WIN32
    closesocket(iochan_getfd(i));
#else
    close(iochan_getfd(i));
#endif
    iochan_destroy(i);
    nmem_destroy(s->nmem);
    wrbuf_destroy(s->wrbuf);
    xfree(s);
}
예제 #4
0
void http_sessions_destroy(http_sessions_t hs)
{
    if (hs)
    {
        struct http_session *s = hs->session_list;
        while (s)
        {
            struct http_session *s_next = s->next;
            iochan_destroy(s->timeout_iochan);
            session_destroy(s->psession);
            nmem_destroy(s->nmem);
            s = s_next;
        }
        yaz_mutex_destroy(&hs->mutex);
        xfree(hs);
    }
}
예제 #5
0
// Close connection and recycle structure
static void connection_destroy(struct connection *co)
{
    if (co->link)
    {
        ZOOM_connection_destroy(co->link);
        iochan_destroy(co->iochan);
    }
    yaz_log(YLOG_DEBUG, "%p Connection destroy %s", co, co->host->url);

    if (co->client)
    {
        client_disconnect(co->client);
    }

    xfree(co->zproxy);
    xfree(co);
    connection_use(-1);
}
예제 #6
0
void iochan_handler(struct iochan *i, int event)
{
    static int number = 0;
    sel_thread_t p = iochan_getdata(i);

    if (event & EVENT_INPUT)
    {
        struct my_work_data *work;

        work = sel_thread_result(p);

        YAZ_CHECK(work);
        if (work)
        {
            YAZ_CHECK_EQ(work->x * 2, work->y);
            /* stop work after a couple of iterations */
            if (work->x > 10)
                iochan_destroy(i);

            xfree(work);
        }

    }
    if (event & EVENT_TIMEOUT)
    {
        struct my_work_data *work;

        work = xmalloc(sizeof(*work));
        work->x = number;
        sel_thread_add(p, work);

        work = xmalloc(sizeof(*work));
        work->x = number+1;
        sel_thread_add(p, work);

        number += 10;
    }
}
예제 #7
0
파일: http.c 프로젝트: saiful76/pazpar2
// 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);
    }
}
예제 #8
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);
    }
}
예제 #9
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;
    }
}
예제 #10
0
/* WIN32 statserv_closedown */
static void statserv_closedown()
{
    /* Shouldn't do anything if we are not initialized */
    if (bInitialized)
    {
        int iHandles = 0;
        HANDLE *pThreadHandles = NULL;

        /* We need to stop threads adding and removing while we */
        /* start the closedown process */
        EnterCriticalSection(&Thread_CritSect);

        {
            /* We have exclusive access to the thread stuff now */
            /* Y didn't i use a semaphore - Oh well never mind */
            ThreadList *pCurrentThread = pFirstThread;

            /* Before we do anything else, we need to shutdown the listener */
            if (pListener != NULL)
                iochan_destroy(pListener);

            for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext)
            {
                /* Just destroy the IOCHAN, that should do the trick */
                iochan_destroy(pCurrentThread->pIOChannel);
                closesocket(pCurrentThread->pIOChannel->fd);

                /* Keep a running count of our handles */
                iHandles++;
            }

            if (iHandles > 0)
            {
                HANDLE *pCurrentHandle ;

                /* Allocate the thread handle array */
                pThreadHandles = (HANDLE *)malloc(sizeof(HANDLE) * iHandles);
                pCurrentHandle = pThreadHandles; 

                for (pCurrentThread = pFirstThread;
                     pCurrentThread != NULL;
                     pCurrentThread = pCurrentThread->pNext, pCurrentHandle++)
                {
                    /* Just the handle */
                    *pCurrentHandle = pCurrentThread->hThread;
                }
            }

            /* We can now leave the critical section */
            LeaveCriticalSection(&Thread_CritSect);
        }

        /* Now we can really do something */
        if (iHandles > 0)
        {
            yaz_log(log_server, "waiting for %d to die", iHandles);
            /* This will now wait, until all the threads close */
            WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE);

            /* Free the memory we allocated for the handle array */
            free(pThreadHandles);
        }

        xml_config_bend_stop();
        /* No longer require the critical section, since all threads are dead */
        DeleteCriticalSection(&Thread_CritSect);
    }
    xml_config_close();
}