[prev in list] [next in list] [prev in thread] [next in thread]
List: helix-server-cvs
Subject: [Server-cvs] tools/testtools simloss.py,NONE,1.1
From: jgordon () helixcommunity ! org
Date: 2009-02-21 0:42:24
Message-ID: 200902210046.n1L0kweq022019 () mailer ! progressive-comp ! com
[Download RAW message or body]
Update of /cvsroot/server/tools/testtools
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv19988
Added Files:
simloss.py
Log Message:
UDP packet forwarder with loss simulation
--- NEW FILE: simloss.py ---
#!/usr/bin/env python
#
# ***** BEGIN LICENSE BLOCK *****
# Source last modified: $Id: simloss.py,v 1.1 2009/02/21 00:42:21 jgordon Exp $
#
# Copyright Notices:
#
# Portions Copyright (c) 1995-2006 RealNetworks, Inc. All Rights Reserved.
#
# Patent Notices: This file may contain technology protected by one or
# more of the patents listed at www.helixcommunity.org
#
# 1. The contents of this file, and the files included with this file,
# are protected by copyright controlled by RealNetworks and its
# licensors, and made available by RealNetworks subject to the current
# version of the RealNetworks Public Source License (the "RPSL")
# available at http://www.helixcommunity.org/content/rpsl unless
# you have licensed the file under the current version of the
# RealNetworks Community Source License (the "RCSL") available at
# http://www.helixcommunity.org/content/rcsl, in which case the RCSL
# will apply. You may also obtain the license terms directly from
# RealNetworks. You may not use this file except in compliance with
# the RPSL or, if you have a valid RCSL with RealNetworks applicable
# to this file, the RCSL. Please see the applicable RPSL or RCSL for
# the rights, obligations and limitations governing use of the
# contents of the file.
#
# This file is part of the Helix DNA Technology. RealNetworks is the
# developer of the Original Code and owns the copyrights in the
# portions it created. Copying, including reproducing, storing,
# adapting or translating, any or all of this material other than
# pursuant to the license terms referred to above requires the prior
# written consent of RealNetworks and its licensors
#
# This file, and the files included with this file, is distributed
# and made available by RealNetworks on an 'AS IS' basis, WITHOUT
# WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS
# AND ITS LICENSORS HEREBY DISCLAIM ALL SUCH WARRANTIES, INCLUDING
# WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
#
# Technology Compatibility Kit Test Suite(s) Location:
# http://www.helixcommunity.org/content/tck
#
# Contributor(s):
#
# ***** END LICENSE BLOCK *****
import sys
import string
import select
import random
import optparse
from socket import *
try:
import msvcrt
windows = True
except:
windows = False
read_size = 2048
class UDPSockPair:
def __init__(self, source_addr, dest_addr):
self.read_addr = source_addr
self.write_addr = dest_addr
self.errstr = None
# end func __init__
def start(self):
try:
self.read_sock = socket(AF_INET, SOCK_DGRAM)
self.write_sock = socket(AF_INET, SOCK_DGRAM)
self.read_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.write_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.read_sock.setblocking(0)
self.read_sock.bind(self.read_addr)
except socket.error, e:
self.errstr = "socket error (%d): %s" % (e[0], e[1])
# end try
# end func start
def close(self):
try:
self.read_sock.close()
self.write_sock.close()
except socket.error, e:
self.errstr = "socket error (%d): %s" % (e[0], e[1])
# end try
# end func close
def receive(self, loss=0):
try:
pkt = self.read_sock.recv(read_size)
if (pkt):
# randomly drop (don't forward) N% of packets read
if (loss == 0 or random.randint(1, 100) > loss):
self.write_sock.sendto(pkt, self.write_addr)
# end if
# end if
except socket.error, e:
self.errstr = "socket error (%d): %s" % (e[0], e[1])
# end try
# end func receive
#end class UDPSockPair
class UDPForwarder:
def __init__(self):
self.readers = []
self.sockpairs = []
self.readmap = {}
self.end_str = ""
self.loss = 0
#end func __init__
def check_sock_error(self, sockpair):
if (sockpair.errstr):
self.end_str = sockpair.errstr
sockpair.close()
self.close()
return True
# end if
return False
# end func check_sock_error
def setup(self, options, stop_seq=[]):
self.stop_seq = stop_seq
self.loss = options.loss_pct
for i in range(len(options.source_ports)):
sockpair = UDPSockPair(
(options.source_addr, options.source_ports[i]),
(options.dest_addr, options.dest_ports[i]))
if (self.check_sock_error(sockpair)):
break
self.sockpairs.append(sockpair)
# end loop
# end func setup
def run(self):
random.seed()
for sock in self.sockpairs:
sock.start()
if (self.check_sock_error(sock)):
return
self.readmap[sock.read_sock] = sock
self.readers.append(sock.read_sock)
# end loop
# stdin is not a socket on Windows and can't be used in select
if (not windows):
self.readers.append(sys.stdin)
# end if
terminating = False
errno = None
errstr = None
while not terminating:
try:
readers, writers, errs = select.select(self.readers, [], [], 2)
except select.error, e:
terminating = True
self.end_str = "select error (%d): %s" % (e[0], e[1])
break
except socket.error, e:
self.end_str = "socket error (%d): %s" % (e[0], e[1])
break
# end try
for r in readers:
if (r == sys.stdin):
data = sys.stdin.read
if (data in self.stop_seq):
terminating = True
self.end_str = "terminated by user"
break
# end if
else:
sock_pair = self.readmap[r]
if (sock_pair):
sock_pair.receive(self.loss)
if (self.check_sock_error(sock_pair)):
break
# end if
# end if
# end if
# end loop
# handle keyboard input on windows
if (windows and msvcrt.kbhit()):
data = msvcrt.getch()
if (data in self.stop_seq):
terminating = True
self.end_str = "terminated by user"
# end if
# end if
# end loop
self.close()
# end func run
def close(self):
for sock in self.sockpairs:
sock.close()
# end loop
self.sockpairs = []
# end func close
#end class UDPForwarder
def parse_ports(ports_str):
range_list = ports_str.split(',')
port_list = []
for range_val in range_list:
vals = string.split(range_val, '/', 2)
str_count = len(vals)
start_val = 0
count = 0
if (str_count > 0 and vals[0].isdigit()):
start_val = int(vals[0])
if (start_val > 0):
count = 1
# end if
# end if
if (count > 0 and str_count > 1 and vals[1].isdigit()):
count = int(vals[1])
if (count < 1):
count = 0
# end if
#end if
for i in range(0, count):
port_list.append(start_val + i)
# end loop
#end loop
return port_list
# end func parse_ports
def parse_command_line():
cmd_parser = optparse.OptionParser()
cmd_parser.add_option("-a", "--addr",
dest="dest_addr", default="127.0.0.1",
help="destination address [default: %default]",
metavar="ADDRESS")
cmd_parser.add_option("-p", "--port",
dest="dest_port_str", default="",
help="destination port(s) [required]",
metavar="PORT1/COUNT1,...,PORTn/COUNTn")
cmd_parser.add_option("-s", "--source-addr",
dest="source_addr", default="127.0.0.1",
help="source address (you probably don't need this) [default: %default]",
metavar="ADDRESS")
cmd_parser.add_option("-r", "--source-port",
dest="source_port_str", default="",
help="source port or port range [default: destination port]",
metavar="PORT1/COUNT1,...,PORTn/COUNTn")
cmd_parser.add_option("-l", "--loss",
dest="loss_pct", type="int", default=0,
help="percentage of packets to drop [default: 0]",
metavar="LOSS")
options, args = cmd_parser.parse_args()
if (options.dest_port_str == ""):
cmd_parser.error("port(s) to forward must be provided!")
else:
options.dest_ports = parse_ports(options.dest_port_str)
# end if
if (options.source_port_str == ""):
options.source_ports = options.dest_ports
else:
options.source_ports = parse_ports(options.source_port_str)
# end if
if (len(options.source_ports) == 0 or len(options.dest_ports) == 0):
cmd_parser.error("invalid port specification")
# end if
if (len(options.source_ports) != len(options.dest_ports)):
cmd_parser.error("mismatched source and destination ports")
# end if
for i in range(len(options.source_ports)):
if (options.source_addr == options.dest_addr and
options.source_ports[i] == options.dest_ports[i]):
cmd_parser.error("cannot forward %s:%d to itself!" % \
(options.dest_addr, options.dest_ports[i]))
# end if
print "forwarding %s:%d to %s:%d" % \
(options.source_addr, options.source_ports[i],
options.dest_addr, options.dest_ports[i])
# end loop
if (options.loss_pct < 0 or options.loss_pct > 100):
cmd_parser.error("invalid loss percentage %d" % options.loss_pct)
return options
# end func parse_command_line
def main():
# parse_command_line will terminate executation in case of failure
options = parse_command_line()
proxy = UDPForwarder()
proxy.setup(options, ['q', 'Q'])
print("")
print "Press 'q' to quit"
print("")
proxy.run()
print(proxy.end_str)
#end func main
if (__name__ == "__main__"):
main()
# end __main __
_______________________________________________
Server-cvs mailing list
Server-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/server-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic