예제 #1
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);
    }
}
예제 #2
0
파일: cs_server.c 프로젝트: heltstar/cs
int main(int argc, char *argv[])
{
    sqlite3 *db;
    if (sqlite3_open("db/cs.db", &db) != SQLITE_OK) {
        E("sqlite3_open() failed.");
        return -1;
    }

    int ret = sockfd_list_init(1024);
    if (ret < 0) {
        E("sockfd_list_init() failed.");
        return -1;
    }

    int servfd = socket(AF_INET, SOCK_STREAM, 0);
    if (servfd == -1) {
        E("%s", strerror(errno));
        return -1;
    }

    int optval = 1;
    ret = setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR,
            &optval, sizeof(optval));
    if (ret == -1) {
        E("%s", strerror(errno));
        return -1;
    }

#ifdef SO_REUSEPORT
    optval = 1;
    ret = setsockopt(servfd, SOL_SOCKET, SO_REUSEPORT,
            &optval, sizeof(optval));
    if (ret == -1) {
        E("%s", strerror(errno));
        return -1;
    }
#endif

    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);

    memset(&addr, '\0', addrlen);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    ret = bind(servfd, (struct sockaddr *)&addr, addrlen);
    if (ret == -1) {
        E("%s", strerror(errno));
        return -1;
    }

    int backlog = 20;
    ret = listen(servfd, backlog);
    if (ret == -1) {
        E("%s", strerror(errno));
        return -1;
    }

    FD_ZERO(&rfds_g);
    FD_ZERO(&wfds_g);
    FD_ZERO(&efds_g);

    register_readfd(servfd);

    fd_set rfds, wfds, efds;

    struct timeval timeout;

    int n = 0;
    int i = 0;

    //DIP(INADDR_ANY);
    D("cs start 0.0.0.0 %d", PORT);
    while (1) {
        rfds = rfds_g;
        wfds = wfds_g;
        efds = efds_g;

        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        n = select(maxfd + 1, &rfds, &wfds, &efds, &timeout);
        if (n < 0) {
            if (errno == EINTR)
                continue;
            E("select() faile.");
            break;
        } else if (n == 0) {
            //D("timeout, nothing to be done.");
        } else {
            /* FIXME: while (n--) */
            for (i = 0; i <= maxfd; i++) {
                if (FD_ISSET(i, &rfds)) {
                    if (i == servfd) {
                        ret = cs_accept(i);
                        if (ret == -1) {
                            E("cs_accept() failed.");
                            break;
                        }
                    } else {
                        ret = cs_routine(i, db);
                        if (ret == -1) {
                            E("cs_routine() failed.");
                            break;
                        }
                    }
                } else if (FD_ISSET(i, &wfds)) {
                    D("write occurrence.");
                } else if (FD_ISSET(i, &efds)) {
                    E("except occurrence.");
                } else {
                    //E("undefined occurrence.");
                }
            }
        }
    }

    close(servfd);
    sqlite3_close(db);
    return 0;
}
예제 #3
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;
    }
}