summaryrefslogtreecommitdiff
path: root/contrib/scripts/sip_to_res_sip/sip_to_res_sip.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/scripts/sip_to_res_sip/sip_to_res_sip.py')
-rwxr-xr-xcontrib/scripts/sip_to_res_sip/sip_to_res_sip.py304
1 files changed, 304 insertions, 0 deletions
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
new file mode 100755
index 000000000..13444a95c
--- /dev/null
+++ b/contrib/scripts/sip_to_res_sip/sip_to_res_sip.py
@@ -0,0 +1,304 @@
+#!/usr/bin/python
+
+import astconfigparser
+
+# configuration parser for sip.conf
+sip = astconfigparser.MultiOrderedConfigParser()
+
+# configuration writer for res_sip.conf
+res_sip = astconfigparser.MultiOrderedConfigParser()
+
+###############################################################################
+### some utility functions
+###############################################################################
+def section_by_type(section, type='endpoint'):
+ """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, type='endpoint'):
+ """Sets the key to the value within the section in res_sip.conf"""
+ def _set_value(k, v, s):
+ set_value(key if key else k, v, s, 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, type)[key] = val
+
+def merge_value(key=None, val=None, section=None,
+ type='endpoint', section_to=None):
+ """Merge values from the given section with those from the default."""
+ def _merge_value(k, v, s):
+ merge_value(key if key else k, v, s, 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 single section
+ sect = sip.section(section)
+ # 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, type)
+
+def is_in(s, sub):
+ """Returns true if 'sub' is in 's'"""
+ return s.find(sub) != -1
+
+###############################################################################
+### 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):
+ """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':
+ print "sip.conf: dtmfmode = %s did not fully map into " \
+ "res_sip.conf - setting to 'none'" % val
+ val = 'none'
+ set_value(key, val, section)
+
+def from_nat(key, val, section):
+ """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)
+ set_value('rewrite_contact', 'yes', section)
+ if is_in(val, 'comedia'):
+ set_value('rtp_symmetric', 'yes', section)
+ if is_in(val, 'force_rport'):
+ set_value('force_rport', 'yes', section)
+ set_value('rewrite_contact', 'yes', section)
+
+def set_timers(key, val, section):
+ """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)
+ elif val == 'accept':
+ set_value('timers', 'required', section)
+ elif val == 'never':
+ set_value('timers', 'no', section)
+ else:
+ set_value('timers', 'yes', section)
+
+def set_direct_media(key, val, section):
+ """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)
+ if is_in(val, 'update'):
+ set_value('direct_media_method', 'update', section)
+ if is_in(val, 'outgoing'):
+ set_value('directed_media_glare_mitigation', 'outgoing', section)
+ if is_in(val, 'nonat'):
+ set_value('disable_directed_media_on_nat', 'yes', section)
+
+def from_sendrpid(key, val, section):
+ """Sets the send_rpid/pai values in res_sip.conf."""
+ if val == 'yes' or val == 'rpid':
+ set_value('send_rpid', 'yes', section)
+ elif val == 'pai':
+ set_value('send_pai', 'yes', section)
+
+def set_media_encryption(key, val, section):
+ """Sets the media_encryption value in res_sip.conf"""
+ if val == 'yes':
+ set_value('media_encryption', 'sdes', section)
+
+def from_recordfeature(key, val, section):
+ """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)
+ else:
+ print "sip.conf: %s = %s could not be fully map " \
+ "one_touch_recording not set in res_sip.conf" % (key, val)
+
+def from_progressinband(key, val, section):
+ """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)
+
+def from_host(key, val, section):
+ """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)
+ if val != 'dynamic':
+ set_value('contact', val, section, 'aor')
+ else:
+ set_value('max_contacts', 1, section, 'aor')
+
+def from_subscribemwi(key, val, section):
+ """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)
+ type = 'endpoint' if val == 'yes' else 'aor'
+ set_value('mailboxes', mailboxes, section, 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 ?
+ 'direct_media': 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(section):
+ for key, fun in peer_map.iteritems():
+ try:
+ fun(key, sip.get(key, section), section)
+ except LookupError:
+ pass
+# print "%s not found for section %s - putting nothing in res_sip.conf" % (key, section)
+
+ # since we are pulling from sip.conf this should always return
+ # a single peer value and never a list of peers
+ peer = sip.section(section)
+ # loop through the peer and print out any that can't be mapped
+ # for key in peer.keys():
+ # if key not in peer_map:
+ # print "Peer: [{}] {} could not be mapped".format(section, key)
+
+def convert():
+ for section in sip.sections():
+ if section == 'authentication':
+ pass
+ elif section != 'general':
+ map_peer(section)
+
+###############################################################################
+
+if __name__ == "__main__":
+ sip.read('sip.conf')
+ convert()
+ res_sip.write('res_sip.conf')