oh, python gurus, shall thy help a beginner?

Constantinos A. Kotsokalis c.kotsokalis at noc.ntua.gr
Sun Jun 6 13:33:50 EDT 1999


Heya,
  I've started with python and I've written the following script.
  It is supposed to use (a subclassed) ThreadedTCPServer and act
  like a little proxy server. It is working perfectly on linux
  where I am mainly developing it, but it denies to work properly
  under Solaris (at least 2.7 which I tried it on). I even recompiled
  Python, using gcc one time, SUN cc the other, trying with statically
  linked/shared modules, anything I could think of. It simply does
  not work. In both cases, it's threaded python 1.5.2.
  What happens under Solaris, is that the server starts all right,
  seems to be waiting for connections, but when I try to connect
  to that port it fails (connection refused). The 2 or 3 times that
  it _did_ connnect, the process was taking up to 95% of the CPU
  usage time right after (and then started not to accept connections
  again). I really can't find out anything, so if any of you might
  know what's wrong (or even speculate about it), please reply.

    Thanks!
	  Costas

PS: Any other suggestions are also welcomed, as well as code
contributions :-) This software acts like a proxy server that will
leave advertisment banners out of your sight, when browsing. If
anyone is interested in using it, the full distribution is at
http://www.softlab.ece.ntua.gr/~ckotso/CTC/

-----------------------START OF SCRIPT--------------------------
#!/usr/bin/env python

import os, time, re, SocketServer, urlparse, string, os, sys
try:
	import thread
except:
	print "You do not have a thread-enabled Python version."
	print "Please download and (re)compile the latest Python"
	print "version -- 1.5.2 at the moment -- with thread support."
	print "You will need to use the --with-thread option when you"
	print "./configure it.\n"
	sys.exit(0)
from socket import *

def SocketErrorMsg(msg, rem_srv, rem_port):
	err_htm_file = open(ERROR_HTML_FILE, "r")
	err_msg = err_htm_file.read(ERROR_HTML_SIZE)
	err_htm_file.close()
	err_msg = string.replace(err_msg, '%SERVER', rem_srv)
	err_msg = string.replace(err_msg, '%PORT', `rem_port`)
	err_msg = string.replace(err_msg, '%ERROR', `msg`)
	err_msg_size = len(err_msg)
	return_buff = "HTTP/1.1 403 ERROR\nServer: Cut The Crap\nContent-Length: "+`err_msg_size`+"\nContent-Type: text/html\nProxy-Connection: close\n\n\n"
	return_buff = return_buff+err_msg
	return return_buff

class MyTCPServer(SocketServer.ThreadingTCPServer):
	def server_bind(self):
		self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
		self.socket.bind(self.server_address)

class handle_con:
	def __init__(req, sock, remaddr, srv):
		rhost, rport = remaddr
		req.proc_req(sock)

	def w_configure(self):
		None  # This will be used for web-based configuration

	def proc_req(self, sock):
		buff = sock.recv(BUFF_SIZE)
		if not len(buff):
			sys.exit(0)
		if string.find(buff, "POST ") == 0:
			time.sleep(1) # Sleep one sec to make sure all POST info has come
			sock.setblocking(0)
			try:
				while (1):
					buff = buff + sock.recv(BUFF_SIZE)
			except:
				None
			sock.setblocking(1)
		tokens = string.split(buff)
		if cre.search(tokens[1]):
			sock.send(ADV_RET_BUFF)
			sock.send(retgif)
			sys.exit(0)

		if ((tokens[1] == "http://ctc/") or (tokens[1] == "http://CTC/")):
			self.w_configure() # Not used yet
			sys.exit(0)

		server = socket(AF_INET, SOCK_STREAM, 0)
		if not len(PARENT_PROXY_HOST):
			url_tuple = urlparse.urlparse(tokens[1])
			host_port = url_tuple[1]
			if (string.find(host_port, ':') != -1):
				rem_srv, rem_port = string.split(host_port, ':')
				rem_port = string.atoi(rem_port)
			else:
				rem_srv, rem_port = host_port, 80
			if (len(url_tuple[4])):
				buff = string.replace(buff, tokens[1], url_tuple[2]+'?'+url_tuple[4])
			else:
				buff = string.replace(buff, tokens[1], url_tuple[2])
		else:
			rem_srv = PARENT_PROXY_HOST
			rem_port = PARENT_PROXY_PORT
		
		try:
			server.connect(rem_srv, rem_port)
			server.send(buff)
			retval = server.recv(BUFF_SIZE)
			while (retval):
				sock.send(retval)
				retval = server.recv(BUFF_SIZE)
			server.close()
		except error, msg:
			sock.send(SocketErrorMsg(msg[0], rem_srv, rem_port))

		sock.close()
		sys.exit(0)


VERSION = '0.2.4'

BIND_PORT = 5050
PARENT_PROXY_HOST = ''
PARENT_PROXY_PORT = 8080
WISH_FORK = 0

RETURN_GIF = "/usr/local/etc/white.gif"
ERROR_HTML_FILE = "/usr/local/etc/ctc_error.html"

cre_str = "\/ad\/|\/ads\/|\/ads2\/|\/ad\.|\/ads\.|\/ads2\.|\.ad\.|\.ads\.|\/ads1\.|\.ads1\.|\/adv\/|\/cadv\/|\/adserver\.|\/adlog\.|\.adbannercenter\.|\/nsads\.|adclick\.|\/banner\.|\/banner\/|\/adverts\/|\.linkexchange\.|\/acc_clickthru|\/adfinity|event\.ng|\/surfad|\/redirect\.|\/gen_addframe|\/m\=|\/ad\=|\/adclick\.|\/adfu\.|\?adnum\=|\.adzerver\.|\?advert\=|\/advert\/|\/SHOP\/|\/advertiser\/"

if (len(sys.argv) > 1):
	try:
		cf = open(sys.argv[1], "r")
	except:
		sys.stderr.write("Cannot open configuration file "+conf+"\n")
		sys.exit(0)
	lines = cf.readlines()
	cf.close()
	for line in lines:
		line = string.strip(line)
		if (len(line) == 0) or re.search("\s*#", line):
			continue
		if string.find(line, '#'):
			ltmp = string.split(line, '#')
			line = ltmp[0]
		tokens = re.split('\s+', line)
		if (tokens[0] == 'BIND_PORT'):
			BIND_PORT = string.atoi(tokens[1])
		elif (tokens[0] == 'PARENT_PROXY_HOST'):
			PARENT_PROXY_HOST = tokens[1]
		elif (tokens[0] == 'PARENT_PROXY_PORT'):
			PARENT_PROXY_PORT = string.atoi(tokens[1])
		elif (tokens[0] == 'WISH_FORK'):
			WISH_FORK = string.atoi(tokens[1])
		elif (tokens[0] == 'RETURN_GIF'):
			RETURN_GIF = tokens[1]
		elif (tokens[0] == 'ERROR_HTML_FILE'):
			ERROR_HTML_FILE = tokens[1]
		elif (tokens[0] == 'BLOCK'):
			re_add = re.escape(tokens[1])
			if (string.find(line, re_add) >= 0):
				continue
			cre_str = cre_str + '|' + re_add
		else:
			sys.stderr.write("Unknown option: "+tokens[0]+"\n")

BUFF_SIZE = 8192
MAX_COMMAND_BUFF = 1024

tmpval = os.stat(RETURN_GIF)
RETURN_GIF_SIZE = tmpval[6]

tmpval = os.stat(ERROR_HTML_FILE)
ERROR_HTML_SIZE = tmpval[6]

ADV_RET_BUFF = "HTTP/1.1 200 OK\nServer: Cut The Crap\nContent-Length: "+`RETURN_GIF_SIZE`+"\nProxy-Connection: close\nContent-Type: image/gif\n\n"

locf = open(RETURN_GIF, 'r')
retgif = locf.read(RETURN_GIF_SIZE)
locf.close()

addr = '127.0.0.1', BIND_PORT
srv = MyTCPServer(addr, handle_con)
cre = re.compile(cre_str, re.I)

if (WISH_FORK == 1):
	try:
		fv = os.fork()
	except:
		sys.stderr.write("Fork failed, exiting\n")
		sys.exit(0)
	
	if (fv != 0):  #Father process
		sys.exit(0)
	else: 
		None

print "Cut The Crap -- Version "+VERSION+" \"Goin' down\" launched..."
srv.serve_forever()
----------------------------END OF SCRIPT-------------------------

-- 
Constantinos A. Kotsokalis || c.kotsokalis at noc.ntua.gr
National Technical University of Athens
Network Management Center
Tel. No: +30 1 7721861




More information about the Python-list mailing list