1# Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved. 2# Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved. 3# 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without modification, 7# are permitted provided that the following conditions are met: 8# 9# 1. Redistributions of source code must retain the above copyright notice, this 10# list of conditions and the following disclaimer. 11# 12# 2. Redistributions in binary form must reproduce the above copyright notice, 13# this list of conditions and the following disclaimer in the documentation and/or 14# other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27def extract_to_next_token(s, match, invert = False): 28 i = 0 29 while i < len(s): 30 if (not invert and s[i] not in match) or \ 31 (invert and s[i] in match): 32 break 33 i += 1 34 if i == 0: 35 return ('', s) 36 if i == len(s): 37 return (s, '') 38 return (s[:i], s[i:]) 39 40class UpdateLookupOpts(object): 41 destination_ip = None 42 local_ip = None 43 codecs = None 44 otherparams = None 45 remote_ip = None 46 remote_port = None 47 from_tag = None 48 to_tag = None 49 notify_socket = None 50 notify_tag = None 51 52 def __init__(self, s = None, *params): 53 if s == None: 54 self.destination_ip, self.local_ip, self.codecs, self.otherparams = params 55 return 56 self.otherparams = '' 57 while len(s) > 0: 58 if s[0] == 'R': 59 val, s = extract_to_next_token(s[1:], ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.')) 60 val = val.strip() 61 if len(val) > 0: 62 self.destination_ip = val 63 if s[0] == 'L': 64 val, s = extract_to_next_token(s[1:], ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.')) 65 val = val.strip() 66 if len(val) > 0: 67 self.local_ip = val 68 elif s[0] == 'c': 69 val, s = extract_to_next_token(s[1:], ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ',')) 70 val = val.strip() 71 if len(val) > 0: 72 self.codecs = [int(x) for x in val.split(',')] 73 else: 74 val, s = extract_to_next_token(s, ('c', 'R'), True) 75 if len(val) > 0: 76 self.otherparams += val 77 78 def getstr(self, call_id, swaptags = False): 79 s = '' 80 if self.destination_ip != None: 81 s += 'R%s' % (self.destination_ip,) 82 if self.local_ip != None: 83 s += 'L%s' % (self.local_ip,) 84 if self.codecs != None: 85 s += 'c' 86 for codec in self.codecs: 87 s += '%s,' % (codec,) 88 s = s[:-1] 89 if self.otherparams != None and len(self.otherparams) > 0: 90 s += self.otherparams 91 s = '%s %s' % (s, call_id) 92 if self.remote_ip != None: 93 s = '%s %s' % (s, self.remote_ip) 94 if self.remote_port != None: 95 s = '%s %s' % (s, self.remote_port) 96 if not swaptags: 97 from_tag, to_tag = (self.from_tag, self.to_tag) 98 else: 99 if self.to_tag == None: 100 raise Exception('UpdateLookupOpts::getstr(swaptags = True): to_tag is not set') 101 to_tag, from_tag = (self.from_tag, self.to_tag) 102 if self.from_tag != None: 103 s = '%s %s' % (s, self.from_tag) 104 if self.to_tag != None: 105 s = '%s %s' % (s, self.to_tag) 106 if self.notify_socket != None: 107 s = '%s %s' % (s, self.notify_socket) 108 if self.notify_tag != None: 109 s = '%s %s' % (s, self.notify_tag) 110 return s 111 112class Rtp_proxy_cmd(object): 113 type = None 114 ul_opts = None 115 command_opts = None 116 call_id = None 117 args = None 118 nretr = None 119 120 def __init__(self, cmd): 121 self.type = cmd[0].upper() 122 if self.type in ('U', 'L', 'D', 'P', 'S', 'R', 'C', 'Q'): 123 command_opts, self.call_id, args = cmd.split(None, 2) 124 if self.type in ('U', 'L'): 125 self.ul_opts = UpdateLookupOpts(command_opts[1:]) 126 self.ul_opts.remote_ip, self.ul_opts.remote_port, args = args.split(None, 2) 127 args = args.split(None, 1) 128 self.ul_opts.from_tag = args[0] 129 if len(args) > 1: 130 args = args[1].split(None, 2) 131 if len(args) == 1: 132 self.ul_opts.to_tag = args[0] 133 elif len(args) == 2: 134 self.ul_opts.notify_socket, self.ul_opts.notify_tag = args 135 else: 136 self.ul_opts.to_tag, self.ul_opts.notify_socket, self.ul_opts.notify_tag = args 137 else: 138 self.args = args 139 self.command_opts = command_opts[1:] 140 elif self.type in ('G',): 141 if not cmd[1].isspace(): 142 cparts = cmd[1:].split(None, 1) 143 if len(cparts) > 1: 144 self.command_opts, self.args = cparts 145 else: 146 self.command_opts = cparts[0] 147 else: 148 self.args = cmd[1:].strip() 149 else: 150 self.command_opts = cmd[1:] 151 152 def __str__(self): 153 s = self.type 154 if self.ul_opts != None: 155 s += self.ul_opts.getstr(self.call_id) 156 else: 157 if self.command_opts != None: 158 s += self.command_opts 159 if self.call_id != None: 160 s = '%s %s' % (s, self.call_id) 161 if self.args != None: 162 s = '%s %s' % (s, self.args) 163 return s 164 165class Rtpp_stats(object): 166 spookyprefix = '' 167 verbose = False 168 169 def __init__(self, snames): 170 all_types = [] 171 for sname in snames: 172 if sname != 'total_duration': 173 stype = int 174 else: 175 stype = float 176 self.__dict__[self.spookyprefix + sname] = stype() 177 all_types.append(stype) 178 self.all_names = tuple(snames) 179 self.all_types = tuple(all_types) 180 181 def __iadd__(self, other): 182 for sname in self.all_names: 183 aname = self.spookyprefix + sname 184 self.__dict__[aname] += other.__dict__[aname] 185 return self 186 187 def parseAndAdd(self, rstr): 188 rparts = rstr.split(None, len(self.all_names) - 1) 189 for i in range(0, len(self.all_names)): 190 stype = self.all_types[i] 191 rval = stype(rparts[i]) 192 aname = self.spookyprefix + self.all_names[i] 193 self.__dict__[aname] += rval 194 195 def __str__(self): 196 aname = self.spookyprefix + self.all_names[0] 197 if self.verbose: 198 rval = '%s=%s' % (self.all_names[0], str(self.__dict__[aname])) 199 else: 200 rval = str(self.__dict__[aname]) 201 for sname in self.all_names[1:]: 202 aname = self.spookyprefix + sname 203 if self.verbose: 204 rval += ' %s=%s' % (sname, str(self.__dict__[aname])) 205 else: 206 rval += ' %s' % str(self.__dict__[aname]) 207 return rval 208 209if __name__ == '__main__': 210 rc = Rtp_proxy_cmd('G nsess_created total_duration') 211 print rc 212 print rc.args 213 print rc.command_opts 214 rc = Rtp_proxy_cmd('Gv nsess_created total_duration') 215 print rc 216 print rc.args 217 print rc.command_opts 218