Ejemplo n.º 1
0
def dispatch(newsock, rroot, aroot, tcfg):
	global threadcount; global threadhigh
	# We may have threads available, or we may not. Having threads
	# available is the simple case, so we handle that first.
	if threadcount < tcfg.max:
		# We increment the thread counter immediately for the
		# best load limiting; otherwise we are the mercy of
		# whenever the scheduling process gets the new thread far
		# enough along to increment the count.
		ruleslock.acquire()
		threadcount += 1
		if threadcount > threadhigh:
			threadhigh = threadcount
		ruleslock.release()
		thread.start_new_thread(threadrule, (newsock, rroot, aroot))
		return
	# Either threads are off entirely or we are over the thread limit.
	# If we've hit the limit, what we do depends on whether maxclass is
	# set; if it is, instead of evaluating the rules in the mainline we
	# synthetically produce a match against that class.
	# We respect maxclass if and only if threading is enabled at all;
	# otherwise we always evaluate in the mainline as a single-threaded
	# program.
	if tcfg.maxclass and tcfg.max:
		# Unfortunately we need to duplicate a bit of rule()'s work,
		# as we need a hostinfo object as well as the fake rule.
		hi = hinfo.fromfd(newsock)
		if not hi:
			log.debug(1, "could not get hostinfo in threadmax")
			proc.closesock(newsock)
			return
		log.debug(2, "too many threads, putting %s connection in %s" % \
			  (hi.getip(), tcfg.maxclass))
		# We have to add the GLOBAL (fake) rule in order to follow
		# the rules; this could be important if the thread overflow
		# class runs something.
		res = [newsock, hi,
		       [rules.genfakerule(tcfg.maxclass), rules.globalrule]]
	else:
		if tcfg.max:
			log.debug(1, "too many threads, handling new socket directly")
		res = rule(newsock, rroot, aroot)
	if not res:
		return
	action(res[0], res[1], res[2], aroot)
Ejemplo n.º 2
0
def rule(newsock, rroot, aroot):
	global totconnects; global totrules; global totruleTime
	
	hi = hinfo.fromfd(newsock)
	if not hi:
		log.debug(1, "Could not get hostinfo, passing.")
		proc.closesock(newsock)
		return None

	# At this point this is a real connection and we will count it.
	ruleslock.acquire()
	totconnects += 1
	ruleslock.release()

	# If we are missing one or the other root, there is
	# no point in doing anything; we can never match an
	# action. Kill it off and punt.
	if not (rroot and aroot):
		log.debug(2, "A root is missing or empty, dropping %s" %\
			  (conninfo(hi),))
		proc.closesock(newsock)
		return None

	# Run it past the rules, and see if anything comes out. If not
	# we're done.
	ruleslock.acquire(); totrules += 1; ruleslock.release()
	st = time.time()
	rmatch = rroot.eval(hi)
	et = time.time()
	ruleslock.acquire(); totruleTime += (et-st); ruleslock.release()
	if not rmatch:
		log.debug(2, "Nothing matched %s" % (conninfo(hi),))
		proc.closesock(newsock)
		return None
	return (newsock, hi, rmatch)
Ejemplo n.º 3
0
		return

	rmnames = [x.clsname for x in rmatch]

	# Run it past the actions and see if we have an action to do.
	# If not, we're done. Action evaluation itself can fail if the
	# configuration file supplies a bad string that cannot be formatted.
	action = None
	try:
		action = aroot.genaction(hi, rmatch)
	except actions.BadAction, e:
		log.error("error preparing action for %s: %s" %\
			  (conninfo(hi, rmnames), str(e)))
	if not action:
		log.debug(2, "No actions for %s" % (conninfo(hi, rmnames),))
		proc.closesock(newsock)
		return
	
	# Actions have two components: messages to log, and something to
	# do. Either can be blank (hopefully both are not blank, but).
	for le in action.logmsgs:
		log.report(le)

	# Activate the action's work function (if any) in a separate
	# process and track it if necessary. We do not track the message
	# processes, since they are expected to die fast and we can do
	# without the churning of data structures in the parent.
	if action.what:
		func = whatToFunc[action.what]
		try:
			pid = proc.forkaction(newsock, func, action)