def restart_profiles(success_msg, error_msg, return_url): logger.info("restart_profiles called") for connection in get_fs_connections(): try: #connection.sendRecv( # ("api sofia profile %s restart" % account.name) # if account else ("api sofia restart profile all")) for sipprofile in SipProfile.objects.all(): connection.sendRecv("api sofia profile %s restart" % sipprofile.name) except Exception, e: msg = error_msg + str(e) else: msg = success_msg return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg))
def get_fs_connections(): """ Get all available ESL connections. """ logger.info("get_fs_connections()") sockets = EventSocketConfig.objects.all() if sockets: logger.info("%s eventsockets" % len(sockets)) else: logger.info("no eventsockets") for socket in sockets: logger.info("creating eslconnection") yield ESL.ESLconnection(socket.listen_ip, str(socket.listen_port), socket.password) logger.info("get_fs_connections() done")
def directory(request): """ Handle all directory requests """ if request.POST.has_key('domain'): # When freeswitch is trying to authenticate an endpoint, it passes the # domain parameter. So when we see that we assume that it wants a # particular user's information such as its password. logger.info("directory_user") return directory_user(request) else: # When freeswitch sees a <domains> tag in a profile definition (as used # for aliasing a domain to a sip profile and telling freeswitch to load # all gateways contained in a directory), then it will call wikipbx # with a request that does NOT have the domain parameter. logger.info("directory_profile_parse") return directory_profile_parse(request)
def restart_profiles(success_msg, error_msg, return_url): """ Restart Sofia profiles on freeswitch. """ logger.info("restart_profiles called") for connection in get_fs_connections(): try: #connection.sendRecv( # ("api sofia profile %s restart" % account.name) # if account else ("api sofia restart profile all")) for sipprofile in SipProfile.objects.all(): connection.sendRecv( (u"api sofia profile %s restart" % sipprofile.name ).encode('utf-8')) except Exception, e: msg = error_msg + str(e) else: msg = success_msg return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg))
def directory(request): """ handle all directory requests """ if request.POST.has_key('domain'): """ when freeswitch is trying to authenticate an endpoint, it passes the domain parameter. so when we see that we assume that it wants a particular user's information such as its password. """ logger.info("directory_user") return directory_user(request) else: """ when freeswitch sees a <domains> tag in a profile definition (as used for aliasing a domain to a sip profile and telling freeswitch to load all gateways contained in a directory), then it will call wikipbx with a request that does NOT have the domain parameter. """ logger.info("directory_profile_parse") return directory_profile_parse(request)
def get_fs_connections(): """ Get all available ESL connections. """ logger.info("get_fs_connections()") sockets = EventSocketConfig.objects.all() if sockets: logger.info("%s eventsockets" % len(sockets)) else: logger.error("No eventsockets found! Unable to connect to freeswitch.") for socket in sockets: logger.info("creating ESL connection") yield ESL.ESLconnection(str(socket.listen_ip), str(socket.listen_port), str(socket.password)) logger.info("get_fs_connections() done")
def get_fs_connections(): """ Get all available ESL connections. """ logger.info("get_fs_connections()") sockets = EventSocketConfig.objects.all() if sockets: logger.info("%s eventsockets" % len(sockets)) else: logger.error("No eventsockets found! Unable to connect to freeswitch.") for socket in sockets: logger.info("creating ESL connection") yield ESL.ESLconnection( str(socket.listen_ip), str(socket.listen_port), str(socket.password)) logger.info("get_fs_connections() done")
def sofia_profile_cmd(command): """ Operations on sofia profiles. """ logger.info("sofia_profile_cmd: " + command) for connection in get_fs_connections(): if not connection.connected(): raise IOError("No connection to FreeSWITCH") try: connection.sendRecv(command.encode('utf-8')) except Exception, e: logger.info("sofia_profile_cmd error: " + str(e)) raise logger.info("sofia_profile_cmd done") return
def directory_user(request): """ generate xml config for a "directory user". when a sip endpoint tries to register, freeswitch will make an http request with some metadata about the user trying to register. then we lookup in our user database and try to find that user, and return xml. Example request fs rev 5834: 'key_value': ['192.168.1.204'] 'key_name': ['name'] 'section': ['directory'] 'domain': ['192.168.1.204'] 'profile': ['foo'] 'tag_name': ['domain'] 'user': ['4761'] 'ip': ['192.168.1.200'] Example request fs rev 7511: 'ip': ['192.168.1.70'] 'key_value': ['192.168.1.101'] 'sip_auth_realm': ['192.168.1.101'] 'key_name': ['name'] 'section': ['directory'] 'hostname': ['spider'] 'sip_auth_method': ['REGISTER'] 'sip_user_agent': ['Linksys/SPA2002-3.1.9(d)'] 'sip_auth_qop': ['auth'] 'sip_auth_username': ['100'] 'tag_name': ['domain'] 'sip_auth_nonce': ['237c9962-3ad8-4e79-807e-f63a4396a999'] 'user': ['100'] 'key': ['id'] 'sip_profile': ['192.168.1.101'] 'action': ['sip_auth'] 'domain': ['192.168.1.101'] 'sip_auth_nc': ['00000002'] 'sip_auth_cnonce': ['8a511ce'] 'sip_auth_response': ['978dc8d62712762f50357f5c61b04113'] 'sip_auth_uri': ['sip:192.168.1.101:5072'] WikiPBX returns: <domain name="192.168.0.58"> <user id="2760"> <params> <param name="password" value="foo" /> </params> </user> </domain> """ t = loader.get_template('directory_user.conf.xml') if request.POST.has_key('profile'): # works in fs rev 5834 profile_name = request.POST['profile'] elif request.POST.has_key('sip_profile'): # works in fs rev 7511 profile_name = request.POST['sip_profile'] else: # TODO: make this error msg available in front-end gui profile_name = None domain = request.POST['domain'] if not request.POST.has_key('user'): logger.info("FreeSWITCH is requesting entire directory for " "domain: %s but this request is being ignored as this " "type of directory request is not yet supported by " "WikiPBX. Not known to cause bugs. " % domain) return None user = request.POST['user'] if domain: accounts = Account.objects.filter(domain=domain) else: raise Exception("No domain, cannot lookup account") if not accounts: # TODO: make this error msg available in front-end gui raise Exception("No account found for domain: %s" % domain) else: account = accounts[0] endpoints = Endpoint.objects.filter(account=account, userid=user) if not endpoints: # TODO: make this error msg available in front-end gui raise Exception("No endpoint found with userid: %s in account: %s" % \ (user, account)) else: endpoint = endpoints[0] # make sure domain that the endpoint 'came in on' matches what # we have in the database (or the sip_ext_ip) if no domain is set if domain != endpoint.account.get_domain(): # TODO: make this error msg available in front-end gui raise Exception("SIP endpoint trying to register with: %s, but that " "does not match the domain in the db: %s " % \ (domain, endpoint.account.get_domain())) logger.info("endpoint: %s" % endpoint) c = Context({"account": account, "endpoint": endpoint}) return t.render(c)
return random.choice(list(get_fs_connections())) def restart_profiles(success_msg, error_msg, return_url): logger.info("restart_profiles called") for connection in get_fs_connections(): try: #connection.sendRecv( # ("api sofia profile %s restart" % account.name) # if account else ("api sofia restart profile all")) for sipprofile in SipProfile.objects.all(): connection.sendRecv("api sofia profile %s restart" % sipprofile.name) except Exception, e: msg = error_msg + str(e) else: msg = success_msg return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg)) else: msg = ("No EventSocket configured in WikiPBX. Cannot connect " "to freeswitch over event socket") return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg)) logger.info("restart_profiles done") __all__ = ('start', 'stop', 'restart', 'get_fs_connections', 'get_fs_connection', 'restart_profiles')
def dialplan_entry(request): """ Generate dialplan entry. Find all extensions that have a matching destination number. """ if request.POST.has_key('Caller-Destination-Number'): # works in fs rev 7511 dest_num = request.POST['Caller-Destination-Number'] else: raise Exception("No destination_number given") # Get SIP profile sip_profile = find_spiprofile_dialplan_request(request) # Find account account = find_account_dialplan_request(request) # Get caller ID caller_id = request.POST.get('Caller-Caller-ID-Number', None) # Get extension extension, groups = dialplanbuilder.find_extension( account, dest_num, caller_id) if not extension: raise Exception('Extension %s not found' % dest_num) # Do we need to authorize this call? # 1. Call may come in a context of an Account or in a context of a SIP # Profile. If it's in the context of the Account it means it was # previously authenticated or it's some transfer to the Account context. # 2. Non authenticated calls will be in the context of the SIP Profile. # In this case, depending from the Extension settings, # we issue a challenge or transfer a call to the Extension context # (in case of the public Extension). if request.POST['Caller-Context'] == account.context: call_context = extension.account.context template_name = 'dialplan.xml' else: call_context = sip_profile.context if check_call_needs_auth(extension, request): template_name = 'dialplan_auth_challenge.xml' else: template_name = 'dialplan_public_extension.xml' t = loader.get_template(template_name) logger.info("SIP Profile: %s, Account: %s, Extension: %s, " "Caller-Context: %s, Extension.auth_call: %s, Template: %s" % (sip_profile, account, extension, request.POST['Caller-Context'], extension.auth_call, template_name)) # Get the actions xml snippet input by the user in the gui. actions_xml = extension.actions_xml # substitute placeholders, eg, $1 -> 18005551212 # TODO: only do substitution within each "data" attribute, not over # entire xml snippet actions_xml = dialplanbuilder.group_substitutions(actions_xml, groups) # render template c = Context({ "extension": extension, "processed_actions_xml": actions_xml, "dialed_extension": dest_num, "call_context": call_context, },) return t.render(c)
for sipprofile in SipProfile.objects.all(): connection.sendRecv( (u"api sofia profile %s restart" % sipprofile.name ).encode('utf-8')) except Exception, e: msg = error_msg + str(e) else: msg = success_msg return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg)) else: msg = ("No EventSocket configured in WikiPBX. Cannot connect " "to freeswitch over event socket") return http.HttpResponseRedirect("%s?infomsg=%s" % (return_url, msg)) logger.info("restart_profiles done") def sofia_profile_cmd(command): """ Operations on sofia profiles. """ logger.info("sofia_profile_cmd: " + command) for connection in get_fs_connections(): if not connection.connected(): raise IOError("No connection to FreeSWITCH") try: connection.sendRecv(command.encode('utf-8')) except Exception, e: logger.info("sofia_profile_cmd error: " + str(e)) raise