X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fseshigh.c;h=e29973e207e4922a5320f5f66cd1b6a8f167793d;hb=f6379872ace49628473c47d23b29e9f46b5afbe4;hp=28830c2f0a5427926d9af1c2cb2213cbe4e6db29;hpb=699e7501d441803e6abd38bb8771cef20846a0d6;p=yaz-moved-to-github.git diff --git a/src/seshigh.c b/src/seshigh.c index 28830c2..e29973e 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2005, Index Data ApS + * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.104 2006-11-14 08:37:38 adam Exp $ + * $Id: seshigh.c,v 1.105 2006-12-04 14:56:55 adam Exp $ */ /** * \file seshigh.c @@ -264,83 +264,31 @@ static void do_close(association *a, int reason, char *message) do_close_req (a, reason, message, req); } -/* - * This is where PDUs from the client are read and the further - * processing is initiated. Flow of control moves down through the - * various process_* functions below, until the encoded result comes back up - * to the output handler in here. - * - * h : the I/O channel that has an outstanding event. - * event : the current outstanding event. - */ -void ir_session(IOCHAN h, int event) + +int ir_read(IOCHAN h, int event) { - int res; association *assoc = (association *)iochan_getdata(h); COMSTACK conn = assoc->client_link; request *req; - - assert(h && conn && assoc); - if (event == EVENT_TIMEOUT) + + if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask)) { - if (assoc->state != ASSOC_UP) + yaz_log(YLOG_DEBUG, "ir_session (input)"); + /* We aren't speaking to this fellow */ + if (assoc->state == ASSOC_DEAD) { - yaz_log(YLOG_DEBUG, "Final timeout - closing connection."); - /* do we need to lod this at all */ + yaz_log(log_sessiondetail, "Connection closed - end of session"); cs_close(conn); destroy_association(assoc); iochan_destroy(h); + return 0; } - else - { - yaz_log(log_sessiondetail, - "Session idle too long. Sending close."); - do_close(assoc, Z_Close_lackOfActivity, 0); - } - return; - } - if (event & assoc->cs_accept_mask) - { - if (!cs_accept (conn)) - { - yaz_log (YLOG_WARN, "accept failed"); - destroy_association(assoc); - iochan_destroy(h); - } - iochan_clearflag (h, EVENT_OUTPUT); - if (conn->io_pending) - { /* cs_accept didn't complete */ - assoc->cs_accept_mask = - ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | - ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); + assoc->cs_get_mask = EVENT_INPUT; - iochan_setflag (h, assoc->cs_accept_mask); - } - else - { /* cs_accept completed. Prepare for reading (cs_get) */ - assoc->cs_accept_mask = 0; - assoc->cs_get_mask = EVENT_INPUT; - iochan_setflag (h, assoc->cs_get_mask); - } - return; - } - if ((event & assoc->cs_get_mask) || (event & EVENT_WORK)) /* input */ - { - if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask)) + do { - yaz_log(YLOG_DEBUG, "ir_session (input)"); - /* We aren't speaking to this fellow */ - if (assoc->state == ASSOC_DEAD) - { - yaz_log(log_sessiondetail, "Connection closed - end of session"); - cs_close(conn); - destroy_association(assoc); - iochan_destroy(h); - return; - } - assoc->cs_get_mask = EVENT_INPUT; - res = cs_get(conn, &assoc->input_buffer, - &assoc->input_buffer_len); + int res = cs_get(conn, &assoc->input_buffer, + &assoc->input_buffer_len); if (res < 0 && cs_errno(conn) == CSBUFSIZE) { yaz_log(log_session, "Connection error: %s res=%d", @@ -348,31 +296,26 @@ void ir_session(IOCHAN h, int event) req = request_get(&assoc->incoming); /* get a new request */ do_close_req(assoc, Z_Close_protocolError, "Incoming package too large", req); - return; + return 0; } else if (res <= 0) { - yaz_log(log_sessiondetail, "Connection closed by client"); - cs_close(conn); - destroy_association(assoc); - iochan_destroy(h); - return; + yaz_log(log_session, "Connection closed by client"); + assoc->state = ASSOC_DEAD; + return 0; } else if (res == 1) /* incomplete read - wait for more */ { if (conn->io_pending & CS_WANT_WRITE) assoc->cs_get_mask |= EVENT_OUTPUT; iochan_setflag(h, assoc->cs_get_mask); - return; + return 1; } - if (cs_more(conn)) /* more stuff - call us again later, please */ - iochan_setevent(h, EVENT_INPUT); - /* we got a complete PDU. Let's decode it */ yaz_log(YLOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res, - assoc->input_buffer[0] & 0xff, - assoc->input_buffer[1] & 0xff, - assoc->input_buffer[2] & 0xff); + assoc->input_buffer[0] & 0xff, + assoc->input_buffer[1] & 0xff, + assoc->input_buffer[2] & 0xff); req = request_get(&assoc->incoming); /* get a new request */ odr_reset(assoc->decode); odr_setbuf(assoc->decode, assoc->input_buffer, res, 0); @@ -396,20 +339,87 @@ void ir_session(IOCHAN h, int event) assoc->state = ASSOC_DEAD; process_gdu_response(assoc, req, p); } - return; + return 0; } req->request_mem = odr_extract_mem(assoc->decode); if (assoc->print) { if (!z_GDU(assoc->print, &req->gdu_request, 0, 0)) yaz_log(YLOG_WARN, "ODR print error: %s", - odr_errmsg(odr_geterror(assoc->print))); + odr_errmsg(odr_geterror(assoc->print))); odr_reset(assoc->print); } request_enq(&assoc->incoming, req); } + while (cs_more(conn)); + } + return 1; +} + +/* + * This is where PDUs from the client are read and the further + * processing is initiated. Flow of control moves down through the + * various process_* functions below, until the encoded result comes back up + * to the output handler in here. + * + * h : the I/O channel that has an outstanding event. + * event : the current outstanding event. + */ +void ir_session(IOCHAN h, int event) +{ + int res; + association *assoc = (association *)iochan_getdata(h); + COMSTACK conn = assoc->client_link; + request *req; + + assert(h && conn && assoc); + if (event == EVENT_TIMEOUT) + { + if (assoc->state != ASSOC_UP) + { + yaz_log(YLOG_DEBUG, "Final timeout - closing connection."); + /* do we need to lod this at all */ + cs_close(conn); + destroy_association(assoc); + iochan_destroy(h); + } + else + { + yaz_log(log_sessiondetail, + "Session idle too long. Sending close."); + do_close(assoc, Z_Close_lackOfActivity, 0); + } + return; + } + if (event & assoc->cs_accept_mask) + { + if (!cs_accept (conn)) + { + yaz_log (YLOG_WARN, "accept failed"); + destroy_association(assoc); + iochan_destroy(h); + } + iochan_clearflag (h, EVENT_OUTPUT); + if (conn->io_pending) + { /* cs_accept didn't complete */ + assoc->cs_accept_mask = + ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | + ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); - /* can we do something yet? */ + iochan_setflag (h, assoc->cs_accept_mask); + } + else + { /* cs_accept completed. Prepare for reading (cs_get) */ + assoc->cs_accept_mask = 0; + assoc->cs_get_mask = EVENT_INPUT; + iochan_setflag (h, assoc->cs_get_mask); + } + return; + } + if (event & assoc->cs_get_mask) /* input */ + { + if (!ir_read(h, event)) + return; req = request_head(&assoc->incoming); if (req->state == REQUEST_IDLE) { @@ -2116,13 +2126,18 @@ static int process_gdu_response(association *assoc, request *req, Z_GDU *res) iochan_setflag(assoc->client_chan, EVENT_OUTPUT); assoc->cs_put_mask = EVENT_OUTPUT; /* Is there more work to be done? give that to the input handler too */ -#if 1 - if (request_head(&assoc->incoming)) + for (;;) { - yaz_log (YLOG_DEBUG, "more work to be done"); - iochan_setevent(assoc->client_chan, EVENT_WORK); + req = request_head(&assoc->incoming); + if (req && req->state == REQUEST_IDLE) + { + yaz_log(YLOG_LOG, "process next request 3"); + request_deq(&assoc->incoming); + process_gdu_request(assoc, req); + } + else + break; } -#endif return 0; } @@ -2334,7 +2349,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) assoc->init->implementation_name, odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.104 $"); + version = odr_strdup(assoc->encode, "$Revision: 1.105 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, @@ -3510,6 +3525,15 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) return apdu; } +int bend_assoc_is_alive(bend_association assoc) +{ + if (assoc->state == ASSOC_DEAD) + return 0; /* already marked as dead. Don't check I/O chan anymore */ + + return iochan_is_alive(assoc->client_chan); +} + + /* * Local variables: * c-basic-offset: 4