Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}