void on_request(struct service *service, struct conn *conn) { struct request *request = conn_request(conn); printf("REQEST!\n"); printf(" > %s on %s\n", request->method, request->path); printf(" > HOST: %s\n", request_header(request, "Host")); printf(" > USER_AGENT: %s\n", request_header(request, "User-Agent")); if (strcmp("/", request->path) == 0) { respond_with_file(conn, "index.html"); } else { respond_with_file(conn, request->path + 1); } conn_close(conn); }
static int _http_request_on_headers_complete(http_parser* inner) { shttp_connection_internal_t* conn; int rc; conn = (shttp_connection_internal_t*)inner->data; conn_incomming(conn).status = shttp_request_parse_headers_ok; conn_request(conn).headers.array = conn_incomming(conn).headers.array; conn_request(conn).headers.length = conn_incomming(conn).headers.length; conn_request(conn).http_major = inner->http_major; conn_request(conn).http_minor = inner->http_minor; conn_request(conn).method = inner->method; conn_request(conn).content_length = inner->content_length; rc = _parse_url(conn); if(0 != rc) { return rc; } return _shttp_connection_on_headers_complete(conn); }
struct task_act * task_select (int *secs_p) { struct connection * cn; struct connection * cn_tmp; struct connection **next_cn; struct task_act * tk; struct task_act **next_tk; struct oper_act * on; int timeout_tmp; char process_edbs = TRUE; char do_timeout; int suspended = FALSE; int xi = 0; struct task_act * ret_tk = NULLTASK; extern char startup_update; struct oper_act * newop = NULLOPER; time (&timenow); (*secs_p) = NOTOK; conns_used = 0; /* DLOG(log_dsap, LLOG_DEBUG, ("task_select connections:")); conn_list_log(connlist); */ for(cn=connlist; cn!=NULLCONN; cn=cn_tmp) { cn_tmp = cn->cn_next; /* Nasty but necessary in conn_extract() manages to get itself called somehow */ do_timeout = FALSE; #ifdef DEBUG conn_log(cn,LLOG_DEBUG); #endif next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { if(tk->tk_timed) { if(tk->tk_timeout <= timenow) { #ifdef DEBUG struct UTCtime ut; struct UTCtime ut2; DLOG(log_dsap, LLOG_TRACE, ("task has timelimit of %ld", tk->tk_timeout)); tm2ut(gmtime(&(tk->tk_timeout)), &ut); DLOG(log_dsap, LLOG_DEBUG, ("converted timelimit = %s", utct2str(&(ut)))); tm2ut(gmtime(&(timenow)), &ut2); DLOG(log_dsap, LLOG_DEBUG, ("time now = %s", utct2str(&(ut2)))); #endif (*next_tk) = tk->tk_next; timeout_task(tk); continue; } else { timeout_tmp = (int) tk->tk_timeout - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } next_tk = &(tk->tk_next); } if(cn->cn_state == CN_OPEN) { next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { next_tk = &(tk->tk_next); if(tk->tk_state == TK_ACTIVE) { if( (ret_tk == NULLTASK) || (tk->tk_prio > ret_tk->tk_prio) || ( (tk->tk_prio == ret_tk->tk_prio) && ( (!ret_tk->tk_timed) || ( (tk->tk_timed) && (tk->tk_timeout < ret_tk->tk_timeout) ) ) ) ) { ret_tk = tk; } } if(tk->tk_state == TK_SUSPEND) { /* * A task suspended to allow the network to be polled. * Set suspended to force polling. */ tk->tk_state = TK_ACTIVE; suspended = TRUE; } } if(cn->cn_tasklist == NULLTASK) { if(cn->cn_initiator) { if(cn->cn_operlist == NULLOPER) { if((cn->cn_last_used + conn_timeout) <= timenow) { do_timeout = TRUE; } else { timeout_tmp = (int) (cn->cn_last_used + conn_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } else { timeout_tmp = conn_timeout; /* safety catch */ if ((tk = cn->cn_operlist->on_task) != NULLTASK) { if (tk->tk_timed) { timeout_tmp = (int) tk->tk_timeout - timenow; if (timeout_tmp < 0) timeout_tmp = 0; } } if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } cn->cn_last_used = timenow; } } } else { cn->cn_last_used = timenow; process_edbs = FALSE; } } else { if((cn->cn_last_used + nsap_timeout) <= timenow) { if ((cn->cn_state == CN_CONNECTING1) || (cn->cn_state == CN_CONNECTING2)) conn_retry(cn,1); else if (cn->cn_state == CN_CLOSING) { if (conn_release_retry(cn) == NOTOK) { /* had its chance - abort */ conn_rel_abort (cn); do_ds_unbind(cn); conn_extract(cn); } } else if ( (cn->cn_state == CN_OPENING) || (cn->cn_state == CN_PRE_OPENING) ) { /* something started to associate - then gave up !!! */ conn_rel_abort (cn); conn_extract (cn); } (*secs_p) = nsap_timeout; } else { timeout_tmp = (int) (cn->cn_last_used + nsap_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } if(do_timeout) { LLOG(log_dsap, LLOG_TRACE, ("Timing out connection %d",cn->cn_ad)); if (conn_release(cn) == NOTOK) { (*secs_p) = nsap_timeout; conns_used++; } } else { conns_used++; } } /* * Open the connection with the highest priority operation * waiting on it... * * Get DSA Info operations are highest priority, followed by * BIND_COMPARE, and X500, and finally GetEDB operations. */ next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= MAX_CONNS) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type == ON_TYPE_GET_DSA_INFO) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI)) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type != ON_TYPE_GET_EDB) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500)) break; (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } } if(process_edbs && !quipu_shutdown) { /* * Nothing is happening that would be disturbed by writing back * a retrieved EDB so it is a good time to process them. */ if (!get_edb_ops && pending_ops) { get_edb_ops = pending_ops; pending_ops = NULLOPER; if(oper_chain(get_edb_ops) != OK) { LLOG(log_dsap, LLOG_TRACE, ("Could not chain a pending operation")); (*secs_p) = 0; /* service network and then try next one */ pending_ops = get_edb_ops -> on_next_task; get_edb_ops -> on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; } } else if (get_edb_ops) { if (get_edb_ops->on_state == ON_COMPLETE) { if (get_edb_ops->on_type == ON_TYPE_GET_EDB) process_edb(get_edb_ops,&newop); else { /* ON_TYPE_SHADOW */ process_shadow(get_edb_ops); ds_res_free (&get_edb_ops-> on_resp.di_result.dr_res.dcr_dsres); } if (newop) { newop->on_next_task = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); if (oper_send_invoke (newop) != OK) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_send getedb next failed")); oper_free (newop); get_edb_ops = NULLOPER; } get_edb_ops = newop; } else if (get_edb_ops) { pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); get_edb_ops = NULLOPER; } (*secs_p) = 0; /* Schedule next one ! */ } else if (get_edb_ops->on_state == ON_ABANDONED) { LLOG (log_dsap,LLOG_TRACE,("Get edb has been abandoned")); pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; (*secs_p) = 0; /* Schedule next one ! */ } } else if (startup_update) { /* see if cache timer has expired - if so resend edb ops... */ if ( (timenow - lastedb_update) >= slave_timeout ) slave_update(); } } if ((get_edb_ops == NULLOPER) && startup_update ) { /* make sure we are awake for the next EDB update */ if ((timeout_tmp = lastedb_update + slave_timeout - timenow) >= 0) if (((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) (*secs_p) = timeout_tmp; } if(suspended) { /* * A task suspended in order for the network to be checked. * Force this to happen by setting the selected task to NULL * and the polling time of the network to 0 secs. */ ret_tk = NULLTASK; (*secs_p) = 0; } for(cn=connwaitlist; cn!=NULLCONN; cn=cn->cn_next) xi++; /* If someting is waiting, see if we can shut a connection down */ /* Make arbitary choice for now */ for(cn=connlist; (xi!=0 || quipu_shutdown) && (cn!=NULLCONN); cn=cn_tmp) { cn_tmp = cn->cn_next; if ((cn->cn_state == CN_OPEN) && (cn->cn_tasklist == NULLTASK) && (cn->cn_initiator) && (cn->cn_operlist == NULLOPER)) { LLOG(log_dsap, LLOG_TRACE, ("Releasing connection %d early (%d waiting)",cn->cn_ad,xi)); if (conn_release(cn) == NOTOK) conns_used++; else xi--; (*secs_p) = 0; /* let connection be re-used */ } } #ifndef NO_STATS if ( (timenow - last_log_close) >= LOGOPENTIME ) { ll_close (log_stat); last_log_close = timenow; } else { if ( (ret_tk == NULLTASK) && (*secs_p >= LOGOPENTIME)) *secs_p = LOGOPENTIME; /* Wake to close log! */ } #endif if(process_edbs && quipu_shutdown) *secs_p = NOTOK; return(ret_tk); }
int link_op_to_conn (struct oper_act *on) { char conn_ctx = DS_CTX_X500_DSP; struct di_block * di; struct di_block **next_di; struct connection * cn; int do_conn; struct access_point * loop_ap; int res; sort_dsa_list (&on->on_dsas); /* * Use an open connection if one is available. */ next_di = &(on->on_dsas); for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=di->di_next) { for(cn=connlist; cn!=NULLCONN; cn=cn->cn_next) { /* Must be a suitable context */ if(cn->cn_ctx == DS_CTX_X500_DAP) { LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DAP context")); continue; } if((cn->cn_ctx == DS_CTX_X500_DSP) && ((on->on_type == ON_TYPE_GET_EDB) || (!cn->cn_initiator))) { if (!cn->cn_initiator) LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DSP context - we must initiate it")); else LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - open conn has DSP context - QUIPU/Internet context needed")); continue; } if((cn->cn_dn != NULLDN) && (dn_cmp(cn->cn_dn, di->di_dn) == 0)) break; } if(cn != NULLCONN) break; next_di = &(di->di_next); } if(di != NULL_DI_BLOCK) { /* Got one - remove successful di_block and link op to conn */ DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - Found suitable open connection")); (*next_di) = di->di_next; if (di->di_state == DI_DEFERRED) { /* We have an open connection, but not a cache entry */ /* (must have used an access point in the past) */ /* Need to be careful about freeing - do it later ! */ di->di_oper = NULLOPER; } else di_extract(di); on->on_conn = cn; on->on_next_conn = cn->cn_operlist; cn->cn_operlist = on; if (on->on_relay != 2) on->on_relay = FALSE; /* No need we have an open connection */ return(OK); } /* * Use a waiting connection if one is available. */ next_di = &(on->on_dsas); for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=di->di_next) { for(cn=connwaitlist; cn!=NULLCONN; cn=cn->cn_next) { /* * Could do some clever stuff here and convert a waiting * connection to QUIPU from X500 if possible and useful. * Left as an exercise for the reader. */ /* Must be a suitable context */ if(cn->cn_ctx == DS_CTX_X500_DAP) continue; if((cn->cn_ctx == DS_CTX_X500_DSP) && (on->on_type == ON_TYPE_GET_EDB)) continue; if((cn->cn_dn != NULLDN) && (dn_cmp(cn->cn_dn, di->di_dn) == 0)) break; } if(cn != NULLCONN) break; next_di = &(di->di_next); } if(di != NULL_DI_BLOCK) { /* Got one - remove successful di_block and link op to conn */ LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - Found suitable waiting connection")); (*next_di) = di->di_next; di_extract(di); on->on_conn = cn; on->on_next_conn = cn->cn_operlist; cn->cn_operlist = on; if (on->on_relay != 2) on->on_relay = FALSE; /* No need we will chain sooner or later */ return(OK); } DLOG(log_dsap, LLOG_DEBUG, ("Neither an open nor a waiting conn suitable")); next_di = &(on->on_dsas); for(di=on->on_dsas; di!=NULL_DI_BLOCK; di=(*next_di)) { if(di->di_state == DI_DEFERRED) { DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - deferred di_block")); next_di = &(di->di_next); continue; } if(di->di_state == DI_ACCESSPOINT) { /* context problem: if we have not got the entry, we don't know which context it will accept. If the operation is a getedb ASSUME Internet context is OK Could be QUIPU - so we lose out on caching */ if(on->on_type == ON_TYPE_GET_EDB) conn_ctx = DS_CTX_INTERNET_DSP; else conn_ctx = DS_CTX_X500_DSP; DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - make conn block from access point")); /* There *should* only be one access point - * but QUIPU may give a choice try find one that will work... * This is *wrong* if it is a non specific subordinate reference. */ if (di->di_reftype == RT_NONSPECIFICSUBORDINATE) { LLOG(log_dsap,LLOG_EXCEPTIONS,("Should try each access point - not just one !!!")); /* throw back to user */ (*next_di) = di->di_next; di_extract(di); continue; } for (loop_ap=di->di_accesspoints; loop_ap != NULLACCESSPOINT; loop_ap=loop_ap->ap_next) if((cn = make_conn_block(loop_ap->ap_name, loop_ap->ap_address, conn_ctx)) != NULLCONN) { if (on->on_relay != 2) on->on_relay = FALSE; /* Made a connection block */ break; } if (loop_ap == NULLACCESSPOINT) { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - make_conn_block failed 1")); (*next_di) = di->di_next; di_extract(di); continue; } } if(di->di_state == DI_COMPLETE) { /* * Open a quipu context connection if possible: this is so if * the entry for the dsa in question has object class quipuDSA. */ if((res = quipu_ctx_supported(di->di_entry)) < 2) { if ((on->on_type == ON_TYPE_GET_EDB) || (res == -1)) { /* Ditch this di_block and carry on looking */ LLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - avoiding non-quipu context for GetEDB")); (*next_di) = di->di_next; di_extract(di); continue; } else { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - linking to a connection without a quipu context")); conn_ctx = DS_CTX_X500_DSP; } } else { if(res == 2) { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - linking to a connection with internet context")); conn_ctx = DS_CTX_INTERNET_DSP; } else { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - linking to a connection with a quipu context")); conn_ctx = DS_CTX_QUIPU_DSP; } } DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - make conn block from entry")); if((cn = make_conn_block(di->di_dn, di->di_entry->e_dsainfo->dsa_addr, conn_ctx)) == NULLCONN) { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - make_conn_block failed 2")); (*next_di) = di->di_next; di_extract(di); continue; } else if (on->on_relay != 2) on->on_relay = FALSE; /* Made a connection block */ } /* * Decide whether to request connection or place it * on the list of waiting connections. */ switch(on->on_type) { case ON_TYPE_GET_DSA_INFO: do_conn = (conns_used < MAX_CONNS); break; case ON_TYPE_GET_EDB: case ON_TYPE_SHADOW: do_conn = (conns_used < (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500)); break; default: do_conn = (conns_used < (MAX_CONNS - CONNS_RESERVED_DI)); break; } if(do_conn) { DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn - about to request connection")); if(conn_request(cn) != OK) { DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - conn_request failed")); (*next_di) = di->di_next; di_extract(di); continue; } DLOG(log_dsap, LLOG_DEBUG, ("link_op_to_conn - conn_request OK")); cn->cn_next = connlist; connlist = cn; conns_used++; } else { DLOG(log_dsap, LLOG_NOTICE, ("Waiting for a free connection slot")); cn->cn_next = connwaitlist; connwaitlist = cn; } (*next_di) = di->di_next; di_extract(di); on->on_conn = cn; on->on_next_conn = cn->cn_operlist; cn->cn_operlist = on; return(OK); } /* * If we get this far it means that we are waiting for a dsa info * operation to complete, or there are no di_blocks left to try. * Callers of link_op_to_conn must check on_dsas to discover which it is. */ DLOG(log_dsap, LLOG_TRACE, ("link_op_to_conn: returning NOTOK")); return(NOTOK); }