route_graph.py

00001 #! /usr/bin/env python
00002 """
00003  * $Id$
00004  *
00005  * Copyright (C) 2006 iptelorg GmbH
00006  *
00007  * This file is part of ser, a free SIP server.
00008  *
00009  * ser is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * For a license to use the ser software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact iptel.org by e-mail at the following addresses:
00017  *    info@iptel.org
00018  *
00019  * ser is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  *
00028 """
00029 import sys,re
00030 
00031 max_depth = 10
00032 debug = 0
00033 
00034 re_main_route = re.compile("^([a-z]+_)*route[\s\t]*(?![\(\)])[\s\t]*\{?", re.I)
00035 re_def_route = re.compile("^([a-z]+_)*route(\[\"?([A-Za-z0-9-_:]+)\"?\])+[\s\t]*\{?", re.I)
00036 re_call_route = re.compile("^(.*\([\s\t!]*)?route\(\"?([A-Za-z0-9-_]+)\"?\)", re.I)
00037 routes = {}
00038 f_routes = {}
00039 b_routes = {}
00040 r_routes = {}
00041 s_routes = {}
00042 e_routes = {}
00043 
00044 
00045 def log(_s):
00046         if debug:
00047                 print _s
00048 
00049 def print_route_level(_l, _n):
00050         log("prl: %i, %s" % (_l, _n))
00051         if _l > max_depth:
00052                 return
00053         spacer = ""
00054         route = ""
00055         for i in range(_l):
00056                 spacer += "|  "
00057                 if i < _l - 1:
00058                         route += "|  "
00059                 else:
00060                         route += "\- " + str(_n)
00061         if len(spacer) > 0:
00062                 print spacer
00063         if len(route) > 0:
00064                 print route
00065 
00066 def traverse_routes(_level, _name):
00067         log("tr: %i, %s" % (_level, _name))
00068         if _level > max_depth:
00069                 print "warning: max_depth reached"
00070                 return
00071         print_route_level(_level, _name)
00072         if routes.has_key(_name):
00073                 for r in routes[_name]:
00074                         traverse_routes(_level + 1, r)
00075 
00076 
00077 if len(sys.argv) < 2:
00078         raise "usage: %s configuration-file [max_depth]" % sys.argv[0]
00079 if len(sys.argv) == 3:
00080         max_depth = int(sys.argv[2])
00081 cfg = file(sys.argv[1], "r")
00082 if cfg == None:
00083         raise "Missing config file"
00084 line = cfg.readline()
00085 rt = routes
00086 while line:
00087         line = line.strip()
00088         if not line.startswith("#"):
00089                 log(line)
00090                 main_match = re_main_route.search(line)
00091                 def_match = re_def_route.search(line)
00092                 call_match = re_call_route.search(line)
00093                 if not call_match == None:
00094                         log("CALL: " + line)
00095                         name = call_match.group(2)
00096                         log(rname +":"+name)
00097                         rt[rname].append(name)
00098                 elif not def_match == None:
00099                         log("DEF: " + line)
00100                         rtype = def_match.group(1)
00101                         rname = def_match.group(3)
00102                         if rtype == "failure_":
00103                                 rt = f_routes
00104                                 if rname == None:
00105                                         rname = "failure"
00106                         elif rtype == "onreply_":
00107                                 rt = r_routes
00108                                 if rname == None:
00109                                         rname = "onreply"
00110                         elif rtype == "onsend_":
00111                                 rt = s_routes
00112                                 if rname == None:
00113                                         rname = "onsend"
00114                         elif rtype == "branch_":
00115                                 rt = b_routes
00116                                 if rname == None:
00117                                         rname = "branch"
00118                         elif rtype == "event_":
00119                                 rt = e_routes
00120                                 if rname == None:
00121                                         rname = "event"
00122                         else:
00123                                 rt = routes
00124                         log(rname)
00125                         rt[rname] = []
00126                 elif not main_match == None:
00127                         log("MAIN: " + line)
00128                         rtype = main_match.group(1)
00129                         if rtype == "failure_":
00130                                 rt = f_routes
00131                                 rname = "failure"
00132                         elif rtype == "onreply_":
00133                                 rt = r_routes
00134                                 rname = "onreply"
00135                         elif rtype == "onsend_":
00136                                 rt = s_routes
00137                                 rname = "onsend"
00138                         elif rtype == "branch_":
00139                                 rt = b_routes
00140                                 rname = "branch"
00141                         elif rtype == "event_":
00142                                 rt = e_routes
00143                                 rname = "event"
00144                         else:
00145                                 rt = routes
00146                                 rname = "Main"
00147                         log(rname)
00148                         rt[rname] = []
00149         line = cfg.readline()
00150 
00151 log("routes: %s" % (routes))
00152 log("branch_routes: %s" % (b_routes))
00153 log("failure_routes: %s" % (f_routes))
00154 log("onreply_routes: %s" % (r_routes))
00155 log("onsend_routes: %s" % (s_routes))
00156 log("event_routes: %s" % (e_routes))
00157 
00158 for name in routes.keys():
00159         for val in routes[name]:
00160                 if not routes.has_key(val):
00161                         print "Missing Route %s!!!" % val
00162 # checking for unreferenced routes does not work yet because functions
00163 # can call routes as well?!
00164         #found = False
00165         #for n in routes.keys():
00166         #       for v in routes[n]:
00167         #               if v == name:
00168         #                       found = True
00169         #if not found and (not (name == "Main" or name == "Failure" or name == "Onreply" or name == "Branch")):
00170         #       print "Unreferenced Route %s!!!" % name
00171 
00172 print "\nMain"
00173 traverse_routes(0, "Main")
00174 
00175 if len(b_routes) > 0:
00176         print "\nBranch routes\n-------------"
00177         for br in b_routes.keys():
00178                 print "\n%s" % (br)
00179                 for r in b_routes[br]:
00180                         traverse_routes(1, r)
00181 
00182 if len(s_routes) > 0:
00183         print "\nSend routes\n-----------"
00184         for sr in s_routes.keys():
00185                 print "\n%s" % (sr)
00186                 for r in s_routes[sr]:
00187                         traverse_routes(1, r)
00188 
00189 if len(f_routes) > 0:
00190         print "\nFailure routes\n--------------"
00191         for fr in f_routes.keys():
00192                 print "\n%s" % (fr)
00193                 for r in f_routes[fr]:
00194                         traverse_routes(1, r)
00195 
00196 if len(r_routes) > 0:
00197         print "\nOnreply routes\n--------------"
00198         for onr in r_routes.keys():
00199                 print "\n%s" % (onr)
00200                 for r in r_routes[onr]:
00201                         traverse_routes(1, r)
00202 
00203 if len(e_routes) > 0:
00204         print "\nEvent routes\n--------------"
00205         for onr in e_routes.keys():
00206                 print "\n%s" % (onr)
00207                 for r in e_routes[onr]:
00208                         traverse_routes(1, r)
00209 
00210 print