Beispiel #1
0
struct http_session *http_session_create(struct conf_service *service,
        http_sessions_t http_sessions,
        unsigned int sesid)
{
    NMEM nmem = nmem_create();
    struct http_session *r = nmem_malloc(nmem, sizeof(*r));
    char tmp_str[50];

    sprintf(tmp_str, "session#%u", sesid);
    r->psession = new_session(nmem, service, sesid);
    r->session_id = sesid;
    r->timestamp = 0;
    r->nmem = nmem;
    r->destroy_counter = r->activity_counter = 0;
    r->http_sessions = http_sessions;

    yaz_mutex_enter(http_sessions->mutex);
    r->next = http_sessions->session_list;
    http_sessions->session_list = r;
    yaz_mutex_leave(http_sessions->mutex);

    r->timeout_iochan = iochan_create(-1, session_timeout, 0, "http_session_timeout");
    iochan_setdata(r->timeout_iochan, r);
    yaz_log(http_sessions->log_level, "Session %u created. timeout chan=%p timeout=%d", sesid, r->timeout_iochan, service->session_timeout);
    iochan_settimeout(r->timeout_iochan, service->session_timeout);

    iochan_add(service->server->iochan_man, r->timeout_iochan);
    http_session_use(1);
    return r;
}
Beispiel #2
0
/* Accept a new command connection */
static void http_accept(IOCHAN i, int event)
{
    struct sockaddr_in addr;
    int fd = iochan_getfd(i);
    socklen_t len;
    int s;
    IOCHAN c;
    struct http_channel *ch;
    struct conf_server *server = iochan_getdata(i);

    len = sizeof addr;
    if ((s = accept(fd, (struct sockaddr *) &addr, &len)) < 0)
    {
        yaz_log(YLOG_WARN|YLOG_ERRNO, "accept");
        return;
    }
    enable_nonblock(s);

    yaz_log(YLOG_DEBUG, "New command connection");
    c = iochan_create(s, http_io, EVENT_INPUT | EVENT_EXCEPT, "http_session_socket");
    
    ch = http_channel_create(server->http_server, inet_ntoa(addr.sin_addr),
                             server);
    ch->iochan = c;
    iochan_setdata(c, ch);
    iochan_add(server->iochan_man, c);
}
Beispiel #3
0
/*
 * Set up a listening endpoint, and give it to the event-handler.
 */
static int add_listener(char *where, int listen_id)
{
    COMSTACK l;
    void *ap;
    IOCHAN lst = NULL;
    const char *mode;

    if (control_block.dynamic)
        mode = "dynamic";
    else if (control_block.threads)
        mode = "threaded";
    else
        mode = "static";

    yaz_log(log_server, "Adding %s listener on %s id=%d", mode, where,
            listen_id);

    l = cs_create_host(where, 2, &ap);
    if (!l)
    {
        yaz_log(YLOG_FATAL, "Failed to listen on %s", where);
        return -1;
    }
    if (*control_block.cert_fname)
        cs_set_ssl_certificate_file(l, control_block.cert_fname);

    if (cs_bind(l, ap, CS_SERVER) < 0)
    {
        if (cs_errno(l) == CSYSERR)
            yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to bind to %s", where);
        else
            yaz_log(YLOG_FATAL, "Failed to bind to %s: %s", where,
                    cs_strerror(l));
        cs_close(l);
        return -1;
    }
    if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
                              EVENT_EXCEPT, listen_id)))
    {
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create IOCHAN-type");
        cs_close(l);
        return -1;
    }
    iochan_setdata(lst, l); /* user-defined data for listener is COMSTACK */
    l->user = lst;  /* user-defined data for COMSTACK is listener chan */

    /* Add listener to chain */
    lst->next = pListener;
    pListener = lst;
    return 0; /* OK */
}
Beispiel #4
0
/** brief use the fd for something */
static void test_for_real_work(int no_threads)
{
    int thread_fd;
    sel_thread_t p = sel_thread_create(work_handler, work_destroy,
                                       &thread_fd, no_threads);
    YAZ_CHECK(p);
    if (p)
    {
        iochan_man_t chan_man = iochan_man_create(10);
        IOCHAN chan = iochan_create(thread_fd, iochan_handler,
                                    EVENT_INPUT|EVENT_TIMEOUT, "test_chan");
        iochan_settimeout(chan, 1);
        iochan_setdata(chan, p);
        iochan_add(chan_man, chan);

        iochan_man_events(chan_man);
        sel_thread_destroy(p);
        iochan_man_destroy(&chan_man);
    }
}
Beispiel #5
0
static void getaddrinfo_start(iochan_man_t iochan_man)
{
    int fd;
    sel_thread_t p = resolver_thread =
        sel_thread_create(work_handler, 0 /* work_destroy */, &fd,
                          3 /* no of resolver threads */);
    if (!p)
    {
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "sel_create_create failed");
        exit(1);
    }
    else
    {
        IOCHAN chan = iochan_create(fd, iochan_handler, EVENT_INPUT,
            "getaddrinfo_socket");
        iochan_setdata(chan, p);
        iochan_add(iochan_man, chan);
    }
    yaz_log(log_level, "resolver start");
    resolver_thread = p;
}
Beispiel #6
0
static void inetd_connection(int what)
{
    COMSTACK line;
    IOCHAN chan;
    association *assoc;
    char *addr;

    if ((line = cs_createbysocket(0, tcpip_type, 0, what)))
    {
        if ((chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT,
                                  0)))
        {
            if ((assoc = create_association(chan, line,
                                            control_block.apdufile)))
            {
                iochan_setdata(chan, assoc);
                iochan_settimeout(chan, 60);
                addr = cs_addrstr(line);
                yaz_log(log_sessiondetail, "Inetd association from %s",
                        addr ? addr : "[UNKNOWN]");
                assoc->cs_get_mask = EVENT_INPUT;
            }
            else
            {
                yaz_log(YLOG_FATAL, "Failed to create association structure");
            }
            chan->next = pListener;
            pListener = chan;
        }
        else
        {
            yaz_log(YLOG_FATAL, "Failed to create iochan");
        }
    }
    else
    {
        yaz_log(YLOG_ERRNO|YLOG_FATAL, "Failed to create comstack on socket 0");
    }
}
Beispiel #7
0
static int http_proxy(struct http_request *rq)
{
    struct http_channel *c = rq->channel;
    struct http_proxy *p = c->proxy;
    struct http_header *hp;
    struct http_buf *requestbuf;
    char server_port[16] = "";
    struct conf_server *ser = c->server;

    if (!p) // This is a new connection. Create a proxy channel
    {
        int sock;
        struct protoent *pe;
        int one = 1;

        if (!(pe = getprotobyname("tcp"))) {
            abort();
        }
        if ((sock = socket(PF_INET, SOCK_STREAM, pe->p_proto)) < 0)
        {
            yaz_log(YLOG_WARN|YLOG_ERRNO, "socket");
            return -1;
        }
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)
                        &one, sizeof(one)) < 0)
            abort();
        enable_nonblock(sock);
        if (connect(sock, (struct sockaddr *)
                    c->server->http_server->proxy_addr, 
                    sizeof(*c->server->http_server->proxy_addr)) < 0)
        {
            if (!is_inprogress()) 
            {
                yaz_log(YLOG_WARN|YLOG_ERRNO, "Proxy connect");
                return -1;
            }
        }
        p = xmalloc(sizeof(struct http_proxy));
        p->oqueue = 0;
        p->channel = c;
        p->first_response = 1;
        c->proxy = p;
        // We will add EVENT_OUTPUT below
        p->iochan = iochan_create(sock, proxy_io, EVENT_INPUT, "http_proxy");
        iochan_setdata(p->iochan, p);

        iochan_add(ser->iochan_man, p->iochan);
    }

    // Do _not_ modify Host: header, just checking it's existence

    if (!http_lookup_header(rq->headers, "Host"))
    {
        yaz_log(YLOG_WARN, "Failed to find Host header in proxy");
        return -1;
    }
    
    // Add new header about paraz2 version, host, remote client address, etc.
    {
        char server_via[128];

        hp = rq->headers;
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Version", PACKAGE_VERSION);
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Server-Host", ser->host);
        sprintf(server_port, "%d",  ser->port);
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Server-Port", server_port);
        yaz_snprintf(server_via, sizeof(server_via), 
                     "1.1 %s:%s (%s/%s)",  
                     ser->host ? ser->host : "@",
                     server_port, PACKAGE_NAME, PACKAGE_VERSION);
        hp = http_header_append(c, hp, "Via" , server_via);
        hp = http_header_append(c, hp, "X-Forwarded-For", c->addr);
    }
    
    requestbuf = http_serialize_request(rq);

    http_buf_enqueue(&p->oqueue, requestbuf);
    iochan_setflag(p->iochan, EVENT_OUTPUT);
    return 0;
}
Beispiel #8
0
/* Create a http-channel listener, syntax [host:]port */
int http_init(const char *addr, struct conf_server *server,
              const char *record_fname)
{
    IOCHAN c;
    int l;
    struct protoent *p;
    struct sockaddr_in myaddr;
    int one = 1;
    const char *pp;
    short port;
    FILE *record_file = 0;

    yaz_log(YLOG_LOG, "HTTP listener %s", addr);


    if (record_fname)
    {
        record_file = fopen(record_fname, "wb");
        if (!record_file)
        {
            yaz_log(YLOG_FATAL|YLOG_ERRNO, "fopen %s", record_fname);
            return 1;
        }
    }

    memset(&myaddr, 0, sizeof myaddr);
    myaddr.sin_family = AF_INET;
    pp = strchr(addr, ':');
    if (pp)
    {
        WRBUF w = wrbuf_alloc();
        struct hostent *he;

        wrbuf_write(w, addr, pp - addr);
        wrbuf_puts(w, "");

        he = gethostbyname(wrbuf_cstr(w));
        wrbuf_destroy(w);
        if (!he)
        {
            yaz_log(YLOG_FATAL, "Unable to resolve '%s'", addr);
            return 1;
        }
        memcpy(&myaddr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
        port = atoi(pp + 1);
    }
    else
    {
        port = atoi(addr);
        myaddr.sin_addr.s_addr = INADDR_ANY;
    }

    myaddr.sin_port = htons(port);

    if (!(p = getprotobyname("tcp"))) {
        return 1;
    }
    if ((l = socket(PF_INET, SOCK_STREAM, p->p_proto)) < 0)
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "socket");
    if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, (char*)
                    &one, sizeof(one)) < 0)
        return 1;

    if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) 
    {
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind");
        return 1;
    }
    if (listen(l, SOMAXCONN) < 0) 
    {
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen");
        return 1;
    }

    server->http_server = http_server_create();

    server->http_server->record_file = record_file;
    server->http_server->listener_socket = l;

    c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server");
    iochan_setdata(c, server);

    iochan_add(server->iochan_man, c);
    return 0;
}
Beispiel #9
0
static int connection_connect(struct connection *con, iochan_man_t iochan_man)
{
    struct host *host = connection_get_host(con);
    ZOOM_options zoptions = ZOOM_options_create();
    const char *auth;
    const char *charset;
    const char *sru;
    const char *sru_version = 0;

    struct session_database *sdb = client_get_database(con->client);
    const char *apdulog = session_setting_oneval(sdb, PZ_APDULOG);

    assert(con);

    ZOOM_options_set(zoptions, "async", "1");
    ZOOM_options_set(zoptions, "implementationName", PACKAGE_NAME);
    ZOOM_options_set(zoptions, "implementationVersion", VERSION);
	
    if ((charset = session_setting_oneval(sdb, PZ_NEGOTIATION_CHARSET)))
        ZOOM_options_set(zoptions, "charset", charset);
    
    assert(host->ipport);
    if (host->proxy)
    {
        yaz_log(YLOG_LOG, "proxy=%s", host->ipport);
        ZOOM_options_set(zoptions, "proxy", host->ipport);
    }
    else
    {
        assert(host->tproxy);
        yaz_log(YLOG_LOG, "tproxy=%s", host->ipport);
        ZOOM_options_set(zoptions, "tproxy", host->ipport);
    }   

    if (apdulog && *apdulog)
        ZOOM_options_set(zoptions, "apdulog", apdulog);

    if ((auth = session_setting_oneval(sdb, PZ_AUTHENTICATION)))
        ZOOM_options_set(zoptions, "user", auth);
    if ((sru = session_setting_oneval(sdb, PZ_SRU)) && *sru)
        ZOOM_options_set(zoptions, "sru", sru);
    if ((sru_version = session_setting_oneval(sdb, PZ_SRU_VERSION)) 
        && *sru_version)
        ZOOM_options_set(zoptions, "sru_version", sru_version);
    if (!(con->link = ZOOM_connection_create(zoptions)))
    {
        yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create ZOOM Connection");
        ZOOM_options_destroy(zoptions);
        return -1;
    }

    if (sru && *sru)
    {
        char http_hostport[512];
        strcpy(http_hostport, "http://");
        strcat(http_hostport, host->url);
        yaz_log(YLOG_LOG, "SRU connect to : %s", http_hostport);
        ZOOM_connection_connect(con->link, http_hostport, 0);
    }
    else
    {
        ZOOM_connection_connect(con->link, host->url, 0);
    }
    con->iochan = iochan_create(-1, connection_handler, 0, "connection_socket");
    con->state = Conn_Connecting;
    iochan_settimeout(con->iochan, con->operation_timeout);
    iochan_setdata(con->iochan, con);
    iochan_add(iochan_man, con->iochan);

    client_set_state(con->client, Client_Connecting);
    ZOOM_options_destroy(zoptions);
    return 0;
}
Beispiel #10
0
static void *new_session(void *vp)
{
    char *a;
    association *newas;
    IOCHAN new_chan;
    COMSTACK new_line = (COMSTACK) vp;
    IOCHAN parent_chan = (IOCHAN) new_line->user;

    unsigned cs_get_mask, cs_accept_mask, mask =  
        ((new_line->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) |
        ((new_line->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0);

    if (mask)
    {
        cs_accept_mask = mask;  /* accept didn't complete */
        cs_get_mask = 0;
    }
    else
    {
        cs_accept_mask = 0;     /* accept completed.  */
        cs_get_mask = mask = EVENT_INPUT;
    }

    if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, mask,
                                   parent_chan->chan_id)))
    {
        yaz_log(YLOG_FATAL, "Failed to create iochan");
        return 0;
    }
    if (!(newas = create_association(new_chan, new_line,
                                     control_block.apdufile)))
    {
        yaz_log(YLOG_FATAL, "Failed to create new assoc.");
        return 0;
    }
    newas->cs_accept_mask = cs_accept_mask;
    newas->cs_get_mask = cs_get_mask;

    iochan_setdata(new_chan, newas);
    iochan_settimeout(new_chan, 60);
#if 1
    a = cs_addrstr(new_line);
#else
    a = 0;
#endif
    yaz_log_xml_errors(0, YLOG_WARN);
    yaz_log(log_session, "Session - OK %d %s %ld",
            no_sessions, a ? a : "[Unknown]", (long) getpid());
    if (max_sessions && no_sessions >= max_sessions)
        control_block.one_shot = 1;
    if (control_block.threads)
    {
        iochan_event_loop(&new_chan);
    }
    else
    {
        new_chan->next = pListener;
        pListener = new_chan;
    }
    return 0;
}
Beispiel #11
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;
    }
}