diff options
Diffstat (limited to 'contrib/scripts/sip_to_res_sip')
-rw-r--r-- | contrib/scripts/sip_to_res_sip/astconfigparser.py | 394 | ||||
-rw-r--r-- | contrib/scripts/sip_to_res_sip/astdicts.py | 298 | ||||
-rwxr-xr-x | contrib/scripts/sip_to_res_sip/sip_to_res_sip.py | 392 |
3 files changed, 0 insertions, 1084 deletions
diff --git a/contrib/scripts/sip_to_res_sip/astconfigparser.py b/contrib/scripts/sip_to_res_sip/astconfigparser.py deleted file mode 100644 index 4a324e2ec..000000000 --- a/contrib/scripts/sip_to_res_sip/astconfigparser.py +++ /dev/null @@ -1,394 +0,0 @@ -import re - -from astdicts import OrderedDict -from astdicts import MultiOrderedDict - -def merge_values(left, right, key): - """Merges values from right into left.""" - if isinstance(left, list): - vals0 = left - else: # assume dictionary - vals0 = left[key] if key in left else [] - vals1 = right[key] if key in right else [] - - return vals0 + [i for i in vals1 if i not in vals0] - -############################################################################### - -class Section(MultiOrderedDict): - """A Section is a MultiOrderedDict itself that maintains a list of - key/value options. However, in the case of an Asterisk config - file a section may have other defaults sections that is can pull - data from (i.e. templates). So when an option is looked up by key - it first checks the base section and if not found looks in the - added default sections. If not found at that point then a 'KeyError' - exception is raised. - """ - count = 0 - - def __init__(self, defaults=None, templates=None): - MultiOrderedDict.__init__(self) - # track an ordered id of sections - Section.count += 1 - self.id = Section.count - self._defaults = [] if defaults is None else defaults - self._templates = [] if templates is None else templates - - def __cmp__(self, other): - return cmp(self.id, other.id) - - def get(self, key, from_self=True, from_templates=True, from_defaults=True): - if from_self and key in self: - return MultiOrderedDict.__getitem__(self, key) - - if from_templates: - if self in self._templates: - return [] - for t in self._templates: - try: - # fail if not found on the search - doing it this way - # allows template's templates to be searched. - return t.get(key, True, from_templates, from_defaults) - except KeyError: - pass - - if from_defaults: - for d in self._defaults: - try: - return d.get(key, True, from_templates, from_defaults) - except KeyError: - pass - - raise KeyError(key) - - def __getitem__(self, key): - """Get the value for the given key. If it is not found in the 'self' - then check inside templates and defaults before declaring raising - a KeyError exception. - """ - return self.get(key) - - def keys(self, self_only=False): - res = MultiOrderedDict.keys(self) - if self_only: - return res - - for d in self._templates: - for key in d.keys(): - if key not in res: - res.append(key) - - for d in self._defaults: - for key in d.keys(): - if key not in res: - res.append(key) - return res - - def add_defaults(self, defaults): - defaults.sort() - for i in defaults: - self._defaults.insert(0, i) - - def add_templates(self, templates): - templates.sort(reverse=True); - self._templates.extend(templates) - - def get_merged(self, key): - """Return a list of values for a given key merged from default(s)""" - # first merge key/values from defaults together - merged = [] - for i in reversed(self._defaults): - if not merged: - merged = i - continue - merged = merge_values(merged, i, key) - - for i in reversed(self._templates): - if not merged: - merged = i - continue - merged = merge_values(merged, i, key) - - # then merge self in - return merge_values(merged, self, key) - -############################################################################### - -COMMENT = ';' -COMMENT_START = ';--' -COMMENT_END = '--;' - -DEFAULTSECT = 'general' - -def remove_comment(line, is_comment): - """Remove any commented elements from the line.""" - if not line: return line, is_comment - - if is_comment: - part = line.partition(COMMENT_END) - if part[1]: - # found multi-line comment end check string after it - return remove_comment(part[2], False) - return "", True - - part = line.partition(COMMENT_START) - if part[1]: - # found multi-line comment start check string before - # it to make sure there wasn't an eol comment in it - has_comment = part[0].partition(COMMENT) - if has_comment[1]: - # eol comment found return anything before it - return has_comment[0], False - - # check string after it to see if the comment ends - line, is_comment = remove_comment(part[2], True) - if is_comment: - # return possible string data before comment - return part[0].strip(), True - - # otherwise it was an embedded comment so combine - return ''.join([part[0].strip(), ' ', line]).rstrip(), False - - # check for eol comment - return line.partition(COMMENT)[0].strip(), False - -def try_include(line): - """Checks to see if the given line is an include. If so return the - included filename, otherwise None. - """ - if not line.startswith('#'): - return None - - # it is an include - get file name - try: - return line[line.index('"') + 1:line.rindex('"')] - except ValueError: - print "Invalid include - could not parse filename." - return None - -def try_section(line): - """Checks to see if the given line is a section. If so return the section - name, otherwise return 'None'. - """ - # leading spaces were stripped when checking for comments - if not line.startswith('['): - return None, False, [] - - section, delim, templates = line.partition(']') - if not templates: - return section[1:], False, [] - - # strip out the parens and parse into an array - templates = templates.replace('(', "").replace(')', "").split(',') - # go ahead and remove extra whitespace - templates = [i.strip() for i in templates] - try: - templates.remove('!') - return section[1:], True, templates - except: - return section[1:], False, templates - -def try_option(line): - """Parses the line as an option, returning the key/value pair.""" - data = re.split('=>?', line) - # should split in two (key/val), but either way use first two elements - return data[0].rstrip(), data[1].lstrip() - -############################################################################### - -def find_value(sections, key): - """Given a list of sections, try to find value(s) for the given key.""" - # always start looking in the last one added - sections.sort(reverse=True); - for s in sections: - try: - # try to find in section and section's templates - return s.get(key, from_defaults=False) - except KeyError: - pass - - # wasn't found in sections or a section's templates so check in defaults - for s in sections: - try: - # try to find in section's defaultsects - return s.get(key, from_self=False, from_templates=False) - except KeyError: - pass - - raise KeyError(key) - -def find_dict(mdicts, key, val): - """Given a list of mult-dicts, return the multi-dict that contains - the given key/value pair.""" - - def found(d): - return key in d and val in d[key] - - try: - return [d for d in mdicts if found(d)][0] - except IndexError: - raise LookupError("Dictionary not located for key = %s, value = %s" - % (key, val)) - -def get_sections(parser, key, attr='_sections', searched=None): - if searched is None: - searched = [] - if parser is None or parser in searched: - return [] - - try: - sections = getattr(parser, attr) - res = sections[key] if key in sections else [] - searched.append(parser) - return res + get_sections(parser._includes, key, attr, searched) \ - + get_sections(parser._parent, key, attr, searched) - except: - # assume ordereddict of parsers - res = [] - for p in parser.itervalues(): - res.extend(get_sections(p, key, attr, searched)) - return res - -def get_defaults(parser, key): - return get_sections(parser, key, '_defaults') - -def write_dicts(file, mdicts): - for section, sect_list in mdicts.iteritems(): - # every section contains a list of dictionaries - for sect in sect_list: - file.write("[%s]\n" % section) - for key, val_list in sect.iteritems(): - # every value is also a list - for v in val_list: - key_val = key - if v is not None: - key_val += " = " + str(v) - file.write("%s\n" % (key_val)) - file.write("\n") - -############################################################################### - -class MultiOrderedConfigParser: - def __init__(self, parent=None): - self._parent = parent - self._defaults = MultiOrderedDict() - self._sections = MultiOrderedDict() - self._includes = OrderedDict() - - def defaults(self): - return self._defaults - - def default(self, key): - """Retrieves a list of dictionaries for a default section.""" - return get_defaults(self, key) - - def add_default(self, key, template_keys=None): - """Adds a default section to defaults, returning the - default Section object. - """ - if template_keys is None: - template_keys = [] - return self.add_section(key, template_keys, self._defaults) - - def sections(self): - return self._sections - - def section(self, key): - """Retrieves a list of dictionaries for a section.""" - return get_sections(self, key) - - def add_section(self, key, template_keys=None, mdicts=None): - if template_keys is None: - template_keys = [] - if mdicts is None: - mdicts = self._sections - res = Section() - for t in template_keys: - res.add_templates(get_defaults(self, t)) - res.add_defaults(get_defaults(self, DEFAULTSECT)) - mdicts.insert(0, key, res) - return res - - def includes(self): - return self._includes - - def add_include(self, filename, parser=None): - if filename in self._includes: - return self._includes[filename] - - self._includes[filename] = res = \ - MultiOrderedConfigParser(self) if parser is None else parser - return res; - - def get(self, section, key): - """Retrieves the list of values from a section for a key.""" - try: - # search for the value in the list of sections - return find_value(self.section(section), key) - except KeyError: - pass - - try: - # section may be a default section so, search - # for the value in the list of defaults - return find_value(self.default(section), key) - except KeyError: - raise LookupError("key %r not found for section %r" - % (key, section)) - - def set(self, section, key, val): - """Sets an option in the given section.""" - # TODO - set in multiple sections? (for now set in first) - # TODO - set in both sections and defaults? - if section in self._sections: - self.section(section)[0][key] = val - else: - self.defaults(section)[0][key] = val - - def read(self, filename): - try: - with open(filename, 'rt') as file: - self._read(file, filename) - except IOError: - print "Could not open file ", filename, " for reading" - - def _read(self, file, filename): - is_comment = False # used for multi-lined comments - for line in file: - line, is_comment = remove_comment(line, is_comment) - if not line: - # line was empty or was a comment - continue - - include_name = try_include(line) - if include_name: - parser = self.add_include(include_name) - parser.read(include_name) - continue - - section, is_template, templates = try_section(line) - if section: - if section == DEFAULTSECT or is_template: - sect = self.add_default(section, templates) - else: - sect = self.add_section(section, templates) - continue - - key, val = try_option(line) - sect[key] = val - - def write(self, f): - try: - for key, val in self._includes.iteritems(): - val.write(key) - f.write('#include "%s"\n' % key) - - f.write('\n') - write_dicts(f, self._defaults) - write_dicts(f, self._sections) - except: - try: - with open(f, 'wt') as fp: - self.write(fp) - except IOError: - print "Could not open file ", f, " for writing" diff --git a/contrib/scripts/sip_to_res_sip/astdicts.py b/contrib/scripts/sip_to_res_sip/astdicts.py deleted file mode 100644 index ae630755d..000000000 --- a/contrib/scripts/sip_to_res_sip/astdicts.py +++ /dev/null @@ -1,298 +0,0 @@ -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. -# copied from http://code.activestate.com/recipes/576693/ - -try: - from thread import get_ident as _get_ident -except ImportError: - from dummy_thread import get_ident as _get_ident - -try: - from _abcoll import KeysView, ValuesView, ItemsView -except ImportError: - pass - - -class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) items in od' - for k in self: - yield (k, self[k]) - - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - for key in other: - self[key] = other[key] - elif hasattr(other, 'keys'): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self)==len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) - -############################################################################### -### MultiOrderedDict -############################################################################### -class MultiOrderedDict(OrderedDict): - def __init__(self, *args, **kwds): - OrderedDict.__init__(self, *args, **kwds) - - def __setitem__(self, key, val, i=None): - if key not in self: -# print "__setitem__ key = ", key, " val = ", val - OrderedDict.__setitem__( - self, key, val if isinstance(val, list) else [val]) - return -# print "inserting key = ", key, " val = ", val - vals = self[key] - if i is None: - i = len(vals) - - if not isinstance(val, list): - if val not in vals: - vals.insert(i, val) - else: - for j in val.reverse(): - if j not in vals: - vals.insert(i, j) - - - def insert(self, i, key, val): - self.__setitem__(key, val, i) - - def copy(self): - # TODO - find out why for some reason copies - # the [] as an [[]], so do manually - c = MultiOrderedDict() #self.__class__(self) - for key, val in self.iteritems(): - for v in val: - c[key] = v - return c diff --git a/contrib/scripts/sip_to_res_sip/sip_to_res_sip.py b/contrib/scripts/sip_to_res_sip/sip_to_res_sip.py deleted file mode 100755 index ca253bdd0..000000000 --- a/contrib/scripts/sip_to_res_sip/sip_to_res_sip.py +++ /dev/null @@ -1,392 +0,0 @@ -#!/usr/bin/python - -############################################################################### -# TODO: -# (1) There is more work to do here, at least for the sip.conf items that -# aren't currently parsed. An issue will be created for that. -# (2) All of the scripts should probably be passed through pylint and have -# as many PEP8 issues fixed as possible -# (3) A public review is probably warranted at that point of the entire script -############################################################################### - -import optparse -import astdicts -import astconfigparser - -PREFIX = 'res_sip_' - -############################################################################### -### some utility functions -############################################################################### -def section_by_type(section, res_sip, type): - """Finds a section based upon the given type, adding it if not found.""" - try: - return astconfigparser.find_dict( - res_sip.section(section), 'type', type) - except LookupError: - # section for type doesn't exist, so add - sect = res_sip.add_section(section) - sect['type'] = type - return sect - -def set_value(key=None, val=None, section=None, res_sip=None, - nmapped=None, type='endpoint'): - """Sets the key to the value within the section in res_sip.conf""" - def _set_value(k, v, s, r, n): - set_value(key if key else k, v, s, r, n, type) - - # if no value or section return the set_value - # function with the enclosed key and type - if not val and not section: - return _set_value - - # otherwise try to set the value - section_by_type(section, res_sip, type)[key] = \ - val[0] if isinstance(val, list) else val - -def merge_value(key=None, val=None, section=None, res_sip=None, - nmapped=None, type='endpoint', section_to=None): - """Merge values from the given section with those from the default.""" - def _merge_value(k, v, s, r, n): - merge_value(key if key else k, v, s, r, n, type, section_to) - - # if no value or section return the merge_value - # function with the enclosed key and type - if not val and not section: - return _merge_value - - # should return a single value section list - sect = sip.section(section)[0] - # for each merged value add it to res_sip.conf - for i in sect.get_merged(key): - set_value(key, i, section_to if section_to else section, - res_sip, nmapped, type) - -def is_in(s, sub): - """Returns true if 'sub' is in 's'""" - return s.find(sub) != -1 - -def non_mapped(nmapped): - def _non_mapped(section, key, val): - """Writes a non-mapped value from sip.conf to the non-mapped object.""" - if section not in nmapped: - nmapped[section] = astconfigparser.Section() - if isinstance(val, list): - for v in val: - # since coming from sip.conf we can assume - # single section lists - nmapped[section][0][key] = v - else: - nmapped[section][0][key] = val - return _non_mapped - -############################################################################### -### mapping functions - -### define f(key, val, section) where key/val are the key/value pair to -### write to given section in res_sip.conf -############################################################################### - -def set_dtmfmode(key, val, section, res_sip, nmapped): - """Sets the dtmfmode value. If value matches allowable option in res_sip - then map it, otherwise set it to none. - """ - # available res_sip.conf values: frc4733, inband, info, none - if val != 'inband' or val != 'info': - nmapped(section, key, val + " ; did not fully map - set to none") - val = 'none' - set_value(key, val, section, res_sip, nmapped) - -def from_nat(key, val, section, res_sip, nmapped): - """Sets values from nat into the appropriate res_sip.conf options.""" - # nat from sip.conf can be comma separated list of values: - # yes/no, [auto_]force_rport, [auto_]comedia - if is_in(val, 'yes'): - set_value('rtp_symmetric', 'yes', section, res_sip, nmapped) - set_value('rewrite_contact', 'yes', section, res_sip, nmapped) - if is_in(val, 'comedia'): - set_value('rtp_symmetric', 'yes', section, res_sip, nmapped) - if is_in(val, 'force_rport'): - set_value('force_rport', 'yes', section, res_sip, nmapped) - set_value('rewrite_contact', 'yes', section, res_sip, nmapped) - -def set_timers(key, val, section, res_sip, nmapped): - """Sets the timers in res_sip.conf from the session-timers option - found in sip.conf. - """ - # res_sip.conf values can be yes/no, required, always - if val == 'originate': - set_value('timers', 'always', section, res_sip, nmapped) - elif val == 'accept': - set_value('timers', 'required', section, res_sip, nmapped) - elif val == 'never': - set_value('timers', 'no', section, res_sip, nmapped) - else: - set_value('timers', 'yes', section, res_sip, nmapped) - -def set_direct_media(key, val, section, res_sip, nmapped): - """Maps values from the sip.conf comma separated direct_media option - into res_sip.conf direct_media options. - """ - if is_in(val, 'yes'): - set_value('direct_media', 'yes', section, res_sip, nmapped) - if is_in(val, 'update'): - set_value('direct_media_method', 'update', section, res_sip, nmapped) - if is_in(val, 'outgoing'): - set_value('directed_media_glare_mitigation', 'outgoing', section, res_sip, nmapped) - if is_in(val, 'nonat'): - set_value('disable_directed_media_on_nat','yes', section, res_sip, nmapped) - if (val == 'no'): - set_value('direct_media', 'no', section, res_sip, nmapped) - -def from_sendrpid(key, val, section, res_sip, nmapped): - """Sets the send_rpid/pai values in res_sip.conf.""" - if val == 'yes' or val == 'rpid': - set_value('send_rpid', 'yes', section, res_sip, nmapped) - elif val == 'pai': - set_value('send_pai', 'yes', section, res_sip, nmapped) - -def set_media_encryption(key, val, section, res_sip, nmapped): - """Sets the media_encryption value in res_sip.conf""" - if val == 'yes': - set_value('media_encryption', 'sdes', section, res_sip, nmapped) - -def from_recordfeature(key, val, section, res_sip, nmapped): - """If record on/off feature is set to automixmon then set - one_touch_recording, otherwise it can't be mapped. - """ - if val == 'automixmon': - set_value('one_touch_recording', 'yes', section, res_sip, nmapped) - else: - nmapped(section, key, val + " ; could not be fully mapped") - -def from_progressinband(key, val, section, res_sip, nmapped): - """Sets the inband_progress value in res_sip.conf""" - # progressinband can = yes/no/never - if val == 'never': - val = 'no' - set_value('inband_progress', val, section, res_sip, nmapped) - -def from_host(key, val, section, res_sip, nmapped): - """Sets contact info in an AOR section in in res_sip.conf using 'host' - data from sip.conf - """ - # all aors have the same name as the endpoint so makes - # it easy to endpoint's 'aors' value - set_value('aors', section, section, res_sip, nmapped) - if val != 'dynamic': - set_value('contact', val, section, res_sip, nmapped, 'aor') - else: - set_value('max_contacts', 1, section, res_sip, nmapped, 'aor') - -def from_subscribemwi(key, val, section, res_sip, nmapped): - """Checks the subscribemwi value in sip.conf. If yes places the - mailbox value in mailboxes within the endpoint, otherwise puts - it in the aor. - """ - mailboxes = sip.get('mailbox', section, res_sip) - type = 'endpoint' if val == 'yes' else 'aor' - set_value('mailboxes', mailboxes, section, res_sip, nmapped, type) - -############################################################################### - -# options in res_sip.conf on an endpoint that have no sip.conf equivalent: -# type, rtp_ipv6, 100rel, trust_id_outbound, aggregate_mwi, -# connected_line_method - -# known sip.conf peer keys that can be mapped to a res_sip.conf section/key -peer_map = [ - # sip.conf option mapping function res_sip.conf option(s) - ########################################################################### - ['context', set_value], - ['dtmfmode', set_dtmfmode], - ['disallow', merge_value], - ['allow', merge_value], - ['nat', from_nat], # rtp_symmetric, force_rport, - # rewrite_contact - ['icesupport', set_value('ice_support')], - ['autoframing', set_value('use_ptime')], - ['outboundproxy', set_value('outbound_proxy')], - ['mohsuggest', set_value], - ['session-timers', set_timers], # timers - ['session-minse', set_value('timers_min_se')], - ['session-expires', set_value('timers_sess_expires')], - ['externip', set_value('external_media_address')], - ['externhost', set_value('external_media_address')], - # identify_by ? - ['directmedia', set_direct_media], # direct_media - # direct_media_method - # directed_media_glare_mitigation - # disable_directed_media_on_nat - ['callerid', set_value], # callerid - ['callingpres', set_value('callerid_privacy')], - ['cid_tag', set_value('callerid_tag')], - ['trustpid', set_value('trust_id_inbound')], - ['sendrpid', from_sendrpid], # send_pai, send_rpid - ['send_diversion', set_value], - ['encrpytion', set_media_encryption], - ['use_avpf', set_value], - ['recordonfeature', from_recordfeature], # automixon - ['recordofffeature', from_recordfeature], # automixon - ['progressinband', from_progressinband], # in_band_progress - ['callgroup', set_value], - ['pickupgroup', set_value], - ['namedcallgroup', set_value], - ['namedpickupgroup', set_value], - ['busylevel', set_value('devicestate_busy_at')], - -############################ maps to an aor ################################### - - ['host', from_host], # contact, max_contacts - ['subscribemwi', from_subscribemwi], # mailboxes - ['qualifyfreq', set_value('qualify_frequency', type='aor')], - -############################# maps to auth##################################### -# type = auth -# username -# password -# md5_cred -# realm -# nonce_lifetime -# auth_type -######################### maps to acl/security ################################ - - ['permit', merge_value(type='security', section_to='acl')], - ['deny', merge_value(type='security', section_to='acl')], - ['acl', merge_value(type='security', section_to='acl')], - ['contactpermit', merge_value(type='security', section_to='acl')], - ['contactdeny', merge_value(type='security', section_to='acl')], - ['contactacl', merge_value(type='security', section_to='acl')], - -########################### maps to transport ################################# -# type = transport -# protocol -# bind -# async_operations -# ca_list_file -# cert_file -# privkey_file -# password -# external_signaling_address - externip & externhost -# external_signaling_port -# external_media_address -# domain -# verify_server -# verify_client -# require_client_cert -# method -# cipher -# localnet -######################### maps to domain_alias ################################ -# type = domain_alias -# domain -######################### maps to registration ################################ -# type = registration -# server_uri -# client_uri -# contact_user -# transport -# outbound_proxy -# expiration -# retry_interval -# max_retries -# auth_rejection_permanent -# outbound_auth -########################### maps to identify ################################## -# type = identify -# endpoint -# match -] - -def map_peer(sip, section, res_sip, nmapped): - for i in peer_map: - try: - # coming from sip.conf the values should mostly be a list with a - # single value. In the few cases that they are not a specialized - # function (see merge_value) is used to retrieve the values. - i[1](i[0], sip.get(section, i[0])[0], section, res_sip, nmapped) - except LookupError: - pass # key not found in sip.conf - -def find_non_mapped(sections, nmapped): - for section, sect in sections.iteritems(): - try: - # since we are pulling from sip.conf this should always - # be a single value list - sect = sect[0] - # loop through the section and store any values that were not mapped - for key in sect.keys(True): - for i in peer_map: - if i[0] == key: - break; - else: - nmapped(section, key, sect[key]) - except LookupError: - pass - -def convert(sip, filename, non_mappings): - res_sip = astconfigparser.MultiOrderedConfigParser() - non_mappings[filename] = astdicts.MultiOrderedDict() - nmapped = non_mapped(non_mappings[filename]) - for section in sip.sections(): - if section == 'authentication': - pass - else: - map_peer(sip, section, res_sip, nmapped) - - find_non_mapped(sip.defaults(), nmapped) - find_non_mapped(sip.sections(), nmapped) - - for key, val in sip.includes().iteritems(): - res_sip.add_include(PREFIX + key, convert(val, PREFIX + key, non_mappings)[0]) - return res_sip, non_mappings - -def write_res_sip(filename, res_sip, non_mappings): - try: - with open(filename, 'wt') as fp: - fp.write(';--\n') - fp.write(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n') - fp.write('Non mapped elements start\n') - fp.write(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n') - astconfigparser.write_dicts(fp, non_mappings[filename]) - fp.write(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n') - fp.write('Non mapped elements end\n') - fp.write(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n') - fp.write('--;\n\n') - # write out include file(s) - for key, val in res_sip.includes().iteritems(): - write_res_sip(key, val, non_mappings) - fp.write('#include "%s"\n' % key) - fp.write('\n') - # write out mapped data elements - astconfigparser.write_dicts(fp, res_sip.defaults()) - astconfigparser.write_dicts(fp, res_sip.sections()) - - except IOError: - print "Could not open file ", filename, " for writing" - -############################################################################### - -def cli_options(): - global PREFIX - usage = "usage: %prog [options] [input-file [output-file]]\n\n" \ - "input-file defaults to 'sip.conf'\n" \ - "output-file defaults to 'res_sip.conf'" - parser = optparse.OptionParser(usage=usage) - parser.add_option('-p', '--prefix', dest='prefix', default=PREFIX, - help='output prefix for include files') - - options, args = parser.parse_args() - PREFIX = options.prefix - - sip_filename = args[0] if len(args) else 'sip.conf' - res_sip_filename = args[1] if len(args) == 2 else 'res_sip.conf' - - return sip_filename, res_sip_filename - -if __name__ == "__main__": - sip_filename, res_sip_filename = cli_options() - # configuration parser for sip.conf - sip = astconfigparser.MultiOrderedConfigParser() - sip.read(sip_filename) - res_sip, non_mappings = convert(sip, res_sip_filename, dict()) - write_res_sip(res_sip_filename, res_sip, non_mappings) |