Mailing List Archive

oh, python gurus, shall thy help a beginner?
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@noc.ntua.gr
National Technical University of Athens
Network Management Center
Tel. No: +30 1 7721861