We have third part mobile users which are integrated with CUCM via SIP Trunk with this third party server(where mobile phone users are registered) whenever they call CUCM Users, i want the display name to be showed on IP Phone according to their number. Like if mobile user 9874563210 is of user Mr XYZ. Whenebr he calls to CUCm side, i want XYZ to be displayed on the IP Phone. Can you pls tell how to go about it.
--------------------------------------------------------------------------------------------
The Routing Rules Interface (CURRI) would provide the functionality your application needs to accomplish this. You do need to be on Unified CM version 10.0 or later to have the appropriate features.
On Unified CM, you can create an External Call Control Profile and attach it to the SIP trunk. When a call enters Unified CM on the SIP trunk, it triggers a request (via CURRI) to a web-based application that you have created. Your web application will accept the CURRI routing request, match the calling-party number in the routing request to the corresponding name (could be a local database or static file depending upon what you implement in your application). It will then return a routing response to Unified CM with the calling-party name.
Unified CM will take the name in the routing response and make it a part of the call. When it reaches an IP Phone, you should see the calling-party name displayed on the phone.
You can get more information on the CURRI interface here: https://developer.cisco.com/site/curri/overview/
--------------------------------------------------------------------------------------------
I have downloaded the sample code from the forum which is written in python. i have installed python software on the web server.
can you pls tell what will be the URL to be given in ECCP so that it hits the python script.
--------------------------------------------------------------------------------------------
It should just be:
http://<ipaddresORhostname>:<Port#>
which will depend on the command line you start the program with.
This is the sample python code:
#!/usr/bin/python
#% Copyright (c) 2013 by Cisco Systems, Inc.
# ver. 1.1 for Python 2.7
#import time
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import socket
from SocketServer import BaseServer
#from OpenSSL import SSL
import threading
import string,os,sys
from saxXacmlHandler import *
# NOTE: the above packages are part of the Python install with the exception of saxXacmlHandler. saxXacmlHandler is the simple
# XACML parser which parses the routing request.
# the following are the canned XACML responses for continue, continue with announcement, deny, divert, notapplicable and indeterminate
# these response are to demonstrate valid XACML responses as can be seen in the DO_POST processing below.
continueResponse = '<?xml encoding="UTF-8" version="1.0"?><Response><Result><Decision>Permit</Decision><Status></Status><Obligations><Obligation FulfillOn="Permit" ObligationId="urn:cisco:xacml:policy-attribute"><AttributeAssignment AttributeId="Policy:simplecontinue"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><continue></continue> </cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
# this is the same as the above response, yet the cixml is not encoded
continueResponseUnencodedCixml = '<?xml encoding="UTF-8" version="1.0"?><Response><Result><Decision>Permit</Decision><Status></Status><Obligations><Obligation FulfillOn="Permit" ObligationId="urn:cisco:xacml:policy-attribute"><AttributeAssignment AttributeId="Policy:simplecontinue"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><continue></continue></cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
continueWithAnnouncementResponse = '<?xml encoding="UTF-8" version="1.0"?><Response><Result><Decision>Permit</Decision><Status></Status><Obligations><Obligation FulfillOn="Permit" ObligationId="urn:cisco:xacml:policy-attribute"><AttributeAssignment AttributeId="Policy:simplecontinue"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><continue><greeting identification="custom_05011"/></continue> </cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
continueWithModifyIngEdResponse = '<?xml encoding="UTF-8" version="1.0"?><Response><Result><Decision>Permit</Decision><Status></Status><Obligations><Obligation FulfillOn="Permit" ObligationId="urn:cisco:xacml:policy-attribute"><AttributeAssignment AttributeId="Policy:simplecontinue"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><continue><modify callingnumber="1000" callednumber="61002"/></continue> </cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
denyResponse = '<?xml encoding="UTF-8" version="1.0"?><Response><Result><Decision>Deny</Decision><Status></Status><Obligations><Obligation FulfillOn="Deny" ObligationId="urn:cisco:xacml:response-qualifier"><AttributeAssignment AttributeId="urn:cisco:xacml:is-resource"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">resource</AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
divertResponse = '<?xml encoding="UTF-8" version="1.0"?> <Response><Result><Decision>Permit</Decision><Obligations><Obligation FulfillOn="Permit" ObligationId="continue.simple"><AttributeAssignment AttributeId="Policy:continue.simple"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><divert><destination>1001</destination></divert><reason>chaperone</reason></cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
# this is the same as above, except that the cixml is not encoded
divertResponseUnencodedCixml = '<?xml encoding="UTF-8" version="1.0"?> <Response><Result><Decision>Permit</Decision><Obligations><Obligation FulfillOn="Permit" ObligationId="continue.simple"><AttributeAssignment AttributeId="Policy:continue.simple"><AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"><cixml ver="1.0"><divert><destination>1001</destination></divert><reason>chaperone</reason></cixml></AttributeValue></AttributeAssignment></Obligation></Obligations></Result></Response>'
notApplicableResponse = '<?xml encoding="UTF-8" version="1.0"?> <Response> <Result> <Decision>NotApplicable</Decision> <Status> <StatusCode Value="The PDP is not protecting the application requested for, please associate the application with the Entitlement Server in the PAP and retry"/> </Status> <Obligations> <Obligation ObligationId="PutInCache" FulfillOn="Deny"> <AttributeAssignment AttributeId="resource" DataType="http://www.w3.org/2001/XMLSchema#anyURI">CISCO:UC:VoiceOrVideoCall</AttributeAssignment> </Obligation> </Obligations> </Result> </Response>'
indeterminateResponse = '<?xml encoding="UTF-8" version="1.0"?> :<Response><Result ResourceId=""><Decision>Indeterminate</Decision><Status><StatusCode Value="urn:cisco:xacml:status:missing-attribute"/><StatusMessage>Required subjectid,resourceid,actionid not present in the request</StatusMessage><StatusDetail>Request failed</StatusDetail></Status></Result></Response>'
# this is the base HTTP request handler, which includes methods for DO_HEAD, DO_GET and DO_POST
# the DO_POST parses the XACML request utilizing the saxXacmlParser
class MyHandler(BaseHTTPRequestHandler):
def setup(s):
s.connection = s.request
s.rfile = socket._fileobject(s.request, "rb", s.rbufsize)
s.wfile = socket._fileobject(s.request, "wb", s.wbufsize)
def do_HEAD(s):
s.send_response(200)
s.send_header("Content-type", "text/html")
s.send_header("Connection", "Keep-Alive")
s.send_header("Keep-Alive", "timeout = 20000 max = 100")
s.end_headers()
message = threading.currentThread().getName()
print "currentThread", message
def do_GET(s):
"""Respond to a GET request."""
s.send_response(200)
topic = s.path
print "TOPIC", topic
if s.path.endswith(".jpg"):
print(curdir + sep + s.path)
f = open(curdir + sep + s.path,"b")
s.send_header('Content-type', 'image/jpg')
s.end_headers()
s.wfile.write(f.read())
f.close()
if topic in ['/favicon.ico']:
f = open(os.getcwd() + '/' + s.path,"r")
s.send_header('Content-type', 'image/ico')
s.end_headers()
s.wfile.write(f.read())
f.close()
return
s.send_header("Content-type", "text/html")
s.end_headers()
s.wfile.write("<html><head><title>Simple Python Http Server</title></head>")
s.wfile.write("<body><p>This is a test.</p>")
s.wfile.write("<p>You accessed path: %s</p>" % s.path)
s.wfile.write("</body></html>")
def do_POST(s):
message = threading.currentThread().getName()
print time.asctime(), "do_POST", "currentThread", message
parser = xml.sax.make_parser()
xacmlParser = XacmlHandler()
parser.setContentHandler(xacmlParser)
try:
length = int(s.headers.getheader('content-length'))
print 'length ', length
postdata = s.rfile.read(length)
print postdata
fd = open('tempXacmlReq.xml', "w")
fd.write(postdata)
fd.close()
except:
pass
parser.parse("tempXacmlReq.xml")
# assumes 6.XXXX translation pattern, calling party is always 1000
# callingnumber, callednumber, transformedcdpn, decision/obligation
# ('1000', '61001', '1001', 'deny')
# ('1000', '61002', '1002', 'permit/continue with announcement custom_05011')
# ('1000', '61003', '1003', 'permit/divert 1001')
# ('1000', '61004', '1004', 'permit/continue modified calling/called 1000,61002)
# ('1000', '61005', '1005', 'notapplicable/deny)
# ('1000', '61006', '1006', 'indeterminate)
# ( all others, *, *, 'permit/continue')
if (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61001'):
print 'send response', denyResponse
MyHandler.send_xml(s, denyResponse)
elif (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61002'):
print 'send response', continueWithAnnouncementResponse
MyHandler.send_xml(s, continueWithAnnouncementResponse)
elif (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61003'):
print 'send response', divertResponse
MyHandler.send_xml(s, divertResponse)
elif (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61004'):
print 'send response', continueWithModifyIngEdResponse
MyHandler.send_xml(s, continueWithModifyIngEdResponse)
elif (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61005'):
print 'send response', notApplicableResponse
MyHandler.send_xml(s, notApplicableResponse)
elif (xacmlParser.callingNumber() == '1000') and (xacmlParser.calledNumber() == '61006'):
print 'send response', indeterminateResponse
MyHandler.send_xml(s, indeterminateResponse)
else:
print 'send response', continueResponse
MyHandler.send_xml(s, continueResponse)
def send_xml(s, text, code=200):
s.send_response(code)
s.send_header('Content-type', 'text/xml; charset="utf-8"')
s.send_header('Content-Length', str(len(text)))
s.send_header("Connection", "Keep-Alive")
s.send_header("Keep-Alive", "timeout = 20000 max = 100")
s.end_headers()
s.wfile.write(text)
s.wfile.flush()
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
threading.daemon_threads = True
if __name__ == '__main__':
# validate input
args = sys.argv[1:]
REQARGS = 3
if len(args) < REQARGS:
print "Usage:",sys.argv[0], "<HOST_NAME> <PORT> http"
sys.exit(1)
HOST_NAME = sys.argv[1]
PORT = sys.argv[2]
PORT_NUM = int(PORT)
PROTO = sys.argv[3]
print "HTTP://HOST_NAME:PORT", PROTO, '://', HOST_NAME, ':', PORT
if PROTO == 'http' or PROTO == 'HTTP':
httpd = ThreadedHTTPServer((HOST_NAME, PORT_NUM), MyHandler)
else:
print 'invalid proto', PROTO, 'required http'
sys.exit(1)
print time.asctime(), "HTTP CURRI Server Started - %s:%s" % (HOST_NAME, PORT)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print time.asctime(), "Server Stopped - %s:%s" % (HOST_NAME, PORT)
This is the sample XACML handler python code:
#% Copyright (c) 2013 by Cisco Systems, Inc.
# ver 1.1
#
import string
import xml.sax
from xml.sax.handler import *
class XacmlHandler(ContentHandler):
"""Crude extractor for XACML document"""
def __init__(self):
self.isCallingNumber = 0
self.isCalledNumber = 0
self.isTransformedCgpn = 0
self.isTransformedCdpn = 0
self.CallingNumber = 0
self.CalledNumber = 0
self.TransformedCgpn = 0
self.TransformedCdpn = 0
def startDocument(self):
print'--- Begin Document ---'
def startElement(self, name, attrs):
if name == 'Attribute':
self.attrs = attrs.get('AttributeId')
print 'AttributeId', self.attrs
elif name == 'AttributeValue':
if self.attrs == 'urn:Cisco:uc:1.0:callingnumber':
self.isCallingNumber = 1
elif self.attrs == 'urn:Cisco:uc:1.0:callednumber':
self.isCalledNumber = 1
elif self.attrs == 'urn:Cisco:uc:1.0:transformedcgpn':
self.isTransformedCgpn = 1
elif self.attrs == 'urn:Cisco:uc:1.0:transformedcdpn':
self.isTransformedCdpn = 1
def endElement(self, name):
if name == 'Request':
# format xacml response based on called/calling numbers
print 'endElement Request'
def characters(self, ch):
if self.isCallingNumber == 1:
self.CallingNumber = ch
print 'CallingNumber ' + ch
self.isCallingNumber = 0
if self.isCalledNumber == 1:
self.CalledNumber = ch
print 'CalledNubmer ' + ch
self.isCalledNumber = 0
if self.isTransformedCgpn == 1:
self.TransformedCgpn = ch
print 'TransformedCgpn ' + ch
self.isTransformedCgpn = 0
if self.isTransformedCdpn == 1:
self.TransformedCdpn = ch
print 'TransformedCdpn ' + ch
self.isTransformedCdpn = 0
def callingNumber(self): return self.CallingNumber
def calledNumber(self): return self.CalledNumber
def transformedCgpn(self): return self.TransformedCgpn
def transformedCdpn(self): return self.TransformedCdpn
if __name__ == '__main__':
parser = xml.sax.make_parser()
handler = XacmlHandler()
parser.setContentHandler(handler)
parser.parse("sampleXacmlReq.xml")
i have copied the python files on 192.0.60.130 server. can you please tell how to go ahead with?
This is designed to run from the command line with a Python interpreter. It creates it's own web server just for the app. The usage is:
Usage: ./samplePolicyApp.py <HOST_NAME> <PORT> http
For your server, you would type something like:
python ./samplePolicyApp.py 192.0.60.130 8080 http
you would then make the ECCP URI on Unified CM:
--------------------------------------------------------------------------------------------
Are we sure display name will appear for incoming & outgoing calls for which details (name, CLI) are stored in the personal directory / static configuration file / local DB if we upgrade to 10.x?
--------------------------------------------------------------------------------------------
I'm not sure I understand what you are asking in terms of the ECCP feature and CURRI. Could you clarify?
Comments
0 comments
Please sign in to leave a comment.