Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

YATE. О внешних модулях

Anna | 16.06.2014 | нет комментариев
В данном посте мы с Вами настроим YATE на работу с внешними модулями, разберем протокол общения модуля с сервером, а также напишем маленький модуль на python.

Если Вам увлекательно, умоляю под кат.

Настройка

Для того что бы обучить Yate трудиться с нашим грядущим модулем, нам необходимо отредактировать файл exmodule.conf и дописать в него следующие строки:
[listener test]
type=tcp
addr=127.0.0.1
port=5678
В данном случае сервер начнет слушать подключения на порту 5678 по tcp протоколу. Давайте проверим!
telnet 0 5678
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
Отменно! Сейчас мы можем перейти к протоколу.

Протокол

Формат сообщений

<параметры> — непременные параметры
[параметры] — необязательные параметры

Позже всякой команды должен следовать перенос строки (n, ^J, decimal 10). Символы, ASCII-коды которых поменьше 32, а также символ “%” и “:” обязаны быть экранированы и превращены в %, где — символ с числовым значением, равным 64 ASCII-код символа.
Символ “%” должен быть превращен в “%%”, если он находится в ключевом слове. Символ “:” не экранируется если это разграничитель между параметрами.

Сообщения

По причине того, что изложение всех сообщений сделает статью большой, разгляжу только те, которые нам потребуются.

Ключевое слово: %%>connect
Формат: %%>connect:<role>[:<id>][:<type>]
Направление: от внешнего модуля к серверу
Изложение: Применяется для того, что бы передать серверу информацию информацию о роли подключения. Первое сообщение, которое отсылается серверу позже установки соединения. Команда может быть использована лишь один раз позже соединения.
Сервер не присылает результата на данный запрос. В случае ложного запроса, сервер закрывает соединение. Соединения с ролями play, record либо playrec обязаны быть прикреплены за определенным каналом управления.
Параметры:
<role> — роль подключения: global, channel, play, record, playrec
<id> — id канала к которому подключен сокет
<type> — тип канала

Ключевое слово: %%>install
Формат: %%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
Направление: от внешнего модуля к серверу
Изложение: Запрос на установку обработчика сообщений (сигналов). Результат на запрос приходит асинхронно.
Параметры:
<priority> — приоритет. по умолчанию 100
<name> — наименование сообщение (сигнала), обработчик на которое должен быть установлен
<filter-name> — наименование переменой для фильтра
<filter-value> — значение переменой для фильтра

Ключевое слово: %%<install
Формат: %%<install:<priority>:<name>:<success>
Направление: от сервера к внешнему модулю
Изложение: Результат на запрос для установки обработчика
Параметры:
<priority> — приоритет с которым установлен обработчик
<name> — наименование сообщение, обработчик на которое должен быть установлен
<success> — boolean («true» or «false»)

Ключевое слово: %%>uninstall
Формат: %%>uninstall:<name>
Направление: от внешнего модуля к серверу
Изложение: Запрос на удаление обработчика сообщений.
Параметры:
<name> — наименование сообщение, обработчик на которое должен быть удален

Ключевое слово: %%<uninstall
Формат: %%<uninstall:<priority>:<name>:<success>
Направление: от сервера к внешнему модулю
Изложение: Доказательство на то, что обработчик сообщения был удален
Параметры:
<priority> — приоритет с которым был установлен обработчик
<name> — наименование сообщение, обработчик на которое должен быть удален
<success> — boolean («true» or «false»)

Ключевое слово: %%>message
Формат: %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
Направление: от сервера к внешнему модулю
Изложение: Запрос на обработку сообщения. Процесс Yate, тот, что вызывает данное сообщение будет заблокирован, пока не получит результат.
Параметры:
<id> — неповторимый ID сообщения, сгенерированный Yate-сервером
<time> — timestamp, когда было сгенерировано сообщение
<name> — имя сообщения (сигнала)
<retvalue> — значение, которое будет возвращено по умолчанию
<key>=<value> — данные, переданные для обработки, представленные в формате ключ-значение.

Ключевое слово: %%<message
Формат: %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
Направление: от внешнего модуля к серверу
Изложение: Сообщение результат на %%>message. Когда сервер получает результат, он изменяет указанные в сообщении значения и заканчивает обработку сообщения, либо продолжает ее.
Параметры:
<id> — неповторимый ID сообщения, тот, что был получен при приобретении запроса на обработку
<processed> — boolean. «true» — завершить обработку сообщения, «false» — передать на обработку в дальнейший модуль
<name> — имя сообщения
<retvalue> — возвращаемое значение
<key>=<value> — новые данные в формате ключ-значение; что бы удалить значение укажите только ключ без знака равенства и значения ()

Ключевое слово: %%>message
Формат: %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
Направление: от внешнего модуля к серверу
Изложение: Запрос от внешнего модуля на обработку сообщения. Результат приходит асинхронно.
Параметры:
<id> — неповторимый ID сообщения, сгенерированный внешним модулем
<time> — timestamp, когда было сгенерировано сообщение
<name> — наименование сообщения (сигнала)
<retvalue> — значение, которое будет возвращено по умолчанию
<key>=<value> — данные, переданные для обработки, представленные в формате ключ-значение.

Ключевое слово: %%<message
Формат: %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
Направление: от сервера к внешнему модулю
Изложение: Сообщение результат на %%>message. Содержит возвращаемое значение и параметры
Параметры:
<id> — неповторимый ID сообщения, тот, что был получен при приобретении запроса на обработку
<processed> — boolean. «true» — завершить обработку сообщения, «false» — передать на обработку в дальнейший модуль
<name> — имя сообщения
<retvalue> — возвращаемое значение
<key>=<value> — данные в формате ключ-значение

Пишем свой модуль

Как видно из описанных сообщений, для общения нам необходим асинхронный заказчик. Во время поисков в интернете в глаза бросился Twisted. Решил я его немножко пощупать. Выходит сотворим файл extmodule.py и добавим в него следующие строки:

#!/usr/bin/python
import time
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory

class ExtModuleProtocol(Protocol):

    def connectionMade(self):
        #%%>connect:<role>
        self.transport.write("%%>connect:globaln")

class ExtModuleFactory(ClientFactory):

    def buildProtocol(self, addr):
        return ExtModuleProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        time.sleep(2)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        time.sleep(2)
        connector.connect()

def main():
    reactor.connectTCP("localhost", 5678, ExtModuleFactory())
    reactor.run()

if __name__ == '__main__':
    main()

Данным кодом мы осуществляем соединения с Yate-сервером и говорим Yate, что наш обработчик всеобщий. Позже этого сервер ожидает от нас сообщений. Т.к. сообщения обязаны быть определенного формата, напишем еще две функции: первая будет экранировать символы с кодом поменьше 32, “%” и “:”, а вторая возвращает их в типичный вид.

def escape(str):
    esc_str = ''
    for c in str:
        if c == "%" or c == ":" or ord(c) < 32:
            esc_str  = '%'   chr(ord(c)   64)
        else:
            esc_str  = c
    return esc_str

def unescape(str):
	unesc_str = ''
	i = 0
	while i < len(str):
		c = str[i]
		if c == "%":
			i  = 1
			c = chr(ord(str[i]) - 64)
		i  = 1
		unesc_str  = c
	return unesc_str

Сейчас нам необходимо установить свои обработчики. Напишем функцию install_handler и добавим в connectionMade вызова данной функции.

def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
    #%%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
    install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
    if filter_name:
        install_msg = "%s:%s" % (install_msg, escape(filter_name))
        if filter_value:
            install_msg = "%s:%s" % (install_msg, escape(filter_value))
    self.sendMessage(install_msg)
extmodule.py

#!/usr/bin/python
import time
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory

def escape(str):
    esc_str = ''
    for c in str:
        if c == "%" or c == ":" or ord(c) < 32:
            esc_str  = '%'   chr(ord(c)   64)
        else:
            esc_str  = c
    return esc_str

def unescape(str):
    unesc_str = ''
    i = 0
    while i < len(str):
        c = str[i]
        if c == "%":
            i  = 1
            c = chr(ord(str[i]) - 64)
        i  = 1
        unesc_str  = c
    return unesc_str

class ExtModuleProtocol(Protocol):

    def sendMessage(self, msg):
        print 'sending message %s' % msg
        self.transport.write(msg)
        self.transport.write("n")

    def connectionMade(self):
        #%%>connect:<role>
        self.sendMessage("%%>connect:global")
        self.install_handler('call.route', 100)
        self.install_handler('call.execute', 200)

    def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
        #%%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
        install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
        if filter_name:
            install_msg = "%s:%s" % (install_msg, escape(filter_name))
            if filter_value:
                install_msg = "%s:%s" % (install_msg, escape(filter_value))
        self.sendMessage(install_msg)

    def dataReceived(self, data):
        print data

class ExtModuleFactory(ClientFactory):
    def startedConnecting(self, connector):
        print 'Started to connect.'

    def buildProtocol(self, addr):
        print 'Connected.'
        return ExtModuleProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        time.sleep(2)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        time.sleep(2)
        connector.connect()

def main():
    reactor.connectTCP("localhost", 5678, ExtModuleFactory())
    reactor.run()

if __name__ == '__main__':
    main()

Но нам необходимо еще знать, что наш запрос был обработан. Для этого мы изменим функцию dataReceived. Позже запуска было выявлено, что dataReceived изредка получает сразу несколько сообщений. По данной причине класс ExtModuleProtocol немножко изменился и сейчас наследуется от LineReceiver, тот, что разделяет сообщения по указанному dilemeter и передает их в способ lineReceived.

class ExtModuleProtocol(LineReceiver):

    delimiter = 'n'

    def sendMessage(self, msg):
        print 'sending message %s' % msg
        self.transport.write(msg)
        self.transport.write("n")

    def connectionMade(self):
        #%%>connect:<role>
        self.sendMessage("%%>connect:global")
        self.install_handler('call.route', 100)
        self.install_handler('call.execute', 200)

    def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
        #%%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
        install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
        if filter_name:
            install_msg = "%s:%s" % (install_msg, escape(filter_name))
            if filter_value:
                install_msg = "%s:%s" % (install_msg, escape(filter_value))
        self.sendMessage(install_msg)

    def process_request(self, request):
        pass

    def process_response(self, response):
        print "Response received: %s" % response
        data = response.split(":")
        data = [unescape(d) for d in data]
        msg_name = data.pop(0)  # getting message name
        print 'Message name: %s. Data: %s' % (msg_name, data)
        # process received response according the message name

    def lineReceived(self, data):
        if not data.startswith("%%"):
            print "unknown message received. passing it"
        if data[2] == ">":
            self.process_request(data[3:])
        else:
            self.process_response(data[3:])
extmodule.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver

def escape(str):
    esc_str = ''
    for c in str:
        if c == "%" or c == ":" or ord(c) < 32:
            esc_str  = '%'   chr(ord(c)   64)
        else:
            esc_str  = c
    return esc_str

def unescape(str):
    unesc_str = ''
    i = 0
    while i < len(str):
        c = str[i]
        if c == "%":
            i  = 1
            c = chr(ord(str[i]) - 64)
        i  = 1
        unesc_str  = c
    return unesc_str

class ExtModuleProtocol(LineReceiver):

    delimiter = 'n'

    def sendMessage(self, msg):
        print 'sending message %s' % msg
        self.transport.write(msg)
        self.transport.write("n")

    def connectionMade(self):
        #%%>connect:<role>
        self.sendMessage("%%>connect:global")
        self.install_handler('call.route', 100)
        self.install_handler('call.execute', 200)

    def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
        #%%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
        install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
        if filter_name:
            install_msg = "%s:%s" % (install_msg, escape(filter_name))
            if filter_value:
                install_msg = "%s:%s" % (install_msg, escape(filter_value))
        self.sendMessage(install_msg)

    def process_request(self, request):
        pass

    def process_response(self, response):
        print "Response received: %s" % response
        data = response.split(":")
        data = [unescape(d) for d in data]
        msg_name = data.pop(0)  # getting message key name
        print 'Message name: %s. Data: %s' % (msg_name, data)
        # process received response according to message name

    def lineReceived(self, data):
        if not data.startswith("%%"):
            print "unknown message received. passing it"
        if data[2] == ">":
            self.process_request(data[3:])
        else:
            self.process_response(data[3:])

class ExtModuleFactory(ClientFactory):
    def startedConnecting(self, connector):
        print 'Started to connect.'

    def buildProtocol(self, addr):
        print 'Connected.'
        return ExtModuleProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        time.sleep(2)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        time.sleep(2)
        connector.connect()

def main():
    reactor.connectTCP("localhost", 5678, ExtModuleFactory())
    reactor.run()

if __name__ == '__main__':
    main()

Осталось обучить наш внешний модуль генерировать свои запросы и обрабатывать запросы от сервера. Для первого напишем способ enqueue, тот, что будет генерировать указанное сообщение и отдавать его yate.

def enqueue(self, message_name, retvalue, **kwargs):
    # %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
    print "Enqueueing message '%s' with params: %s" % (message_name, kwargs)
    params = []
    for key, value in kwargs.items()    :
        if value:
            params.append(escape("%s=%s" % (key, value)))
        else:
            params.append(escape("%s" % key))

    msg_id = uuid.uuid4().hex

    msg = "%%%%>message:%(id)s:%(time)s:%(name)s:%(retvalue)s:%(params)s" % {
        "id": msg_id,
        "time": int(time.time()),
        "name": escape(message_name),
        "retvalue": escape(retvalue),
        "params": ":".join(params)
    }
    self.sendMessage(msg)
    return msg_id

Данный код генерирует сообщение и возвращает его ID. Сейчас получив результат от сервера, мы можем ориентироваться на данный ID. Пример:
Enqueueing message ‘call.route’ with params: {‘target’: ‘sip:test@127.0.0.1′}
sending message %%>message:3f5e754aaca145b0b257b070e6566cb2:1383161706:call.route:None:target=sip%ztest@127.0.0.1

Message name: message. Data: ['3f5e754aaca145b0b257b070e6566cb2', 'false', 'call.route', 'None', 'target=sip', 'test@127.0.0.1', 'handlers=javascript', '15,cdrbuild', '50,fileinfo', '90,subscription', '100,sip', '100,iax', '100,regfile', '100,jingle', '100,regexroute', '100,analog', '100,register', '100,sig', '100']

Что бы обрабатывать запросы от сервера допишем способ process_request.

def process_request(self, request):
    print "Request received: %s" % request
    data = request.split(":")
    data = [unescape(d) for d in data]
    print "Data: %s" % data
    # process received request according the message name
extmodule.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import uuid
from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver

def escape(str):
    esc_str = ''
    for c in str:
        if c == "%" or c == ":" or ord(c) < 32:
            esc_str  = '%'   chr(ord(c)   64)
        else:
            esc_str  = c
    return esc_str

def unescape(str):
    unesc_str = ''
    i = 0
    while i < len(str):
        c = str[i]
        if c == "%":
            i  = 1
            c = chr(ord(str[i]) - 64)
        i  = 1
        unesc_str  = c
    return unesc_str

class ExtModuleProtocol(LineReceiver):

    delimiter = 'n'

    def sendMessage(self, msg):
        print 'sending message %s' % msg
        self.transport.write(msg)
        self.transport.write("n")

    def enqueue(self, message_name, retvalue, **kwargs):
        # %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
        print "Enqueueing message '%s' with params: %s" % (message_name, kwargs)
        params = []
        for key, value in kwargs.items()    :
            if value:
                params.append(escape("%s=%s" % (key, value)))
            else:
                params.append(escape("%s" % key))

        msg_id = uuid.uuid4().hex

        msg = "%%%%>message:%(id)s:%(time)s:%(name)s:%(retvalue)s:%(params)s" % {
            "id": msg_id,
            "time": int(time.time()),
            "name": escape(message_name),
            "retvalue": escape(retvalue),
            "params": ":".join(params)
        }
        self.sendMessage(msg)
        return msg_id

    def connectionMade(self):
        # %%>connect:<role>
        self.sendMessage("%%>connect:global")
        self.install_handler('call.route', 10)
        self.install_handler('call.execute', 200)
        self.call_route_msg_id = self.enqueue("call.route", "None", target="sip:test@127.0.0.1")

    def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
        # %%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
        install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
        if filter_name:
            install_msg = "%s:%s" % (install_msg, escape(filter_name))
            if filter_value:
                install_msg = "%s:%s" % (install_msg, escape(filter_value))
        self.sendMessage(install_msg)

    def process_request(self, request):
        print "Request received: %s" % request
        data = request.split(":")
        data = [unescape(d) for d in data]
        print "Data: %s" % data
        # process received request according the message name

    def process_response(self, response):
        print "Response received: %s" % response
        data = response.split(":")
        data = [unescape(d) for d in data]
        msg_name = data.pop(0)  # getting message key name
        print 'Message name: %s. Data: %s' % (msg_name, data)
        # process received response according the message name

    def lineReceived(self, data):
        if not data.startswith("%%"):
            print "unknown message received: %s. passing it" % data
        if data[2] == ">":
            self.process_request(data[3:))
        else:
            self.process_response(data[3:])

class ExtModuleFactory(ClientFactory):
    def startedConnecting(self, connector):
        print 'Started to connect.'

    def buildProtocol(self, addr):
        print 'Connected.'
        return ExtModuleProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        time.sleep(2)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        time.sleep(2)
        connector.connect()

def main():
    reactor.connectTCP("localhost", 5678, ExtModuleFactory())
    reactor.run()

if __name__ == '__main__':
    main()

Сейчас мы можем запустить сервер, внешний модуль и посмотреть что происходит. Осталось обучить наш модуль отвечать на запросы сервера. Для этого напишем способ answer и изменим способ process_request, добавив небольшую логику.

def answer(self, msg_id, msg_name, processed, retvalue, payload):
	# %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
	print "Answering the server request"
	params = []
	for key, value in payload.items():
		if value:
			params.append(escape("%s=%s" % (key, value)))
		else:
			params.append(escape("%s" % key))

	msg = "%%%%<message:%(id)s:%(processed)s:%(name)s:%(retvalue)s:%(params)s" % {
		"id": escape(msg_id),
		"processed": processed and "true" or "false",
		"name": escape(msg_name),
		"retvalue": escape(retvalue),
		"params": ":".join(params)
	}
	self.sendMessage(msg)

def process_request(self, request):
	print "Request received: %s" % request
	data = request.split(":")
	data = [unescape(d) for d in data]
	print "Data: %s. Processing message." % data
	if data[0] == "message":
		msg_id = data[1]
		msg_name = data[3]
		msg_data = dict(d.split("=") for d in data[5:])
		print "MSG Data: %s" % msg_data
		print "ID: %s. Name: %s" % (msg_id, msg_name)
		if msg_name == "call.route" and msg_data.get('called', '') == "123":
			self.answer(msg_id, msg_name, True, "sip/sip:test@127.0.0.1", {"param1": "value1"})
	self.answer(msg_id, msg_name, False, "", {})
extmodule.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import uuid
from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver

def escape(str):
    esc_str = ''
    for c in str:
        if c == "%" or c == ":" or ord(c) < 32:
            esc_str  = '%'   chr(ord(c)   64)
        else:
            esc_str  = c
    return esc_str

def unescape(str):
    unesc_str = ''
    i = 0
    while i < len(str):
        c = str[i]
        if c == "%":
            i  = 1
            c = chr(ord(str[i]) - 64)
        i  = 1
        unesc_str  = c
    return unesc_str

class ExtModuleProtocol(LineReceiver):

    delimiter = 'n'

    def sendMessage(self, msg):
        print 'sending message %s' % msg
        self.transport.write(msg)
        self.transport.write("n")

    def enqueue(self, message_name, retvalue, **kwargs):
        # %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
        print "Enqueueing message '%s' with params: %s" % (message_name, kwargs)
        params = []
        for key, value in kwargs.items():
            if value:
                params.append(escape("%s=%s" % (key, value)))
            else:
                params.append(escape("%s" % key))

        msg_id = uuid.uuid4().hex

        msg = "%%%%>message:%(id)s:%(time)s:%(name)s:%(retvalue)s:%(params)s" % {
            "id": msg_id,
            "time": int(time.time()),
            "name": escape(message_name),
            "retvalue": escape(retvalue),
            "params": ":".join(params)
        }
        self.sendMessage(msg)
        return msg_id

    def connectionMade(self):
        # %%>connect:<role>
        self.sendMessage("%%>connect:global")
        self.install_handler('call.route', 10)
        self.install_handler('call.execute', 200)
        self.call_route_msg_id = self.enqueue("call.route", "None", target="sip:test@127.0.0.1")

    def install_handler(self, message, priority=100, filter_name=None, filter_value=None):
        # %%>install:[<priority>]:<name>[:<filter-name>[:<filter-value>]]
        install_msg = "%%%%>install:%s:%s" % (priority, escape(message))
        if filter_name:
            install_msg = "%s:%s" % (install_msg, escape(filter_name))
            if filter_value:
                install_msg = "%s:%s" % (install_msg, escape(filter_value))
        self.sendMessage(install_msg)

    def answer(self, msg_id, msg_name, processed, retvalue, payload):
        # %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
        print "Answering the server request"
        params = []
        for key, value in payload.items():
            if value:
                params.append(escape("%s=%s" % (key, value)))
            else:
                params.append(escape("%s" % key))

        msg = "%%%%<message:%(id)s:%(processed)s:%(name)s:%(retvalue)s:%(params)s" % {
            "id": escape(msg_id),
            "processed": processed and "true" or "false",
            "name": escape(msg_name),
            "retvalue": escape(retvalue),
            "params": ":".join(params)
        }
        self.sendMessage(msg)

    def process_request(self, request):
        print "Request received: %s" % request
        data = request.split(":")
        data = [unescape(d) for d in data]
        print "Data: %s. Processing message." % data
        if data[0] == "message":
            msg_id = data[1]
            msg_name = data[3]
            msg_data = dict(d.split("=") for d in data[5:])
            print "MSG Data: %s" % msg_data
            print "ID: %s. Name: %s" % (msg_id, msg_name)
            if msg_name == "call.route" and msg_data.get('called', '') == "123":
                self.answer(msg_id, msg_name, True, "sip/sip:test@127.0.0.1", {"param1": "value1"})
        self.answer(msg_id, msg_name, False, "", {})

    def process_response(self, response):
        print "Response received: %s" % response
        data = response.split(":")
        data = [unescape(d) for d in data]
        msg_name = data.pop(0)  # getting message key name
        print 'Message name: %s. Data: %s' % (msg_name, data)
        # process received response according the message name

    def lineReceived(self, data):
        if not data.startswith("%%"):
            print "unknown message received: %s. passing it" % data
        if data[2] == ">":
            self.process_request(data[3:])
        else:
            self.process_response(data[3:])

class ExtModuleFactory(ClientFactory):
    def startedConnecting(self, connector):
        print 'Started to connect.'

    def buildProtocol(self, addr):
        print 'Connected.'
        return ExtModuleProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        time.sleep(2)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        time.sleep(2)
        connector.connect()

def main():
    reactor.connectTCP("localhost", 5678, ExtModuleFactory())
    reactor.run()

if __name__ == '__main__':
    main()

Способ answer может воротить True, чем даст знать Yate, что сообщение не нужно огромнее обрабатывать либо False, тогда сервер передаст сообщение в дальнейший обработчик. На этом я завершу. Каждому спасибо за внимание.

P.S. Код предоставлен для ознакомительных целей, из-за чего не вылизывался и не тяготился к совершенству. Каждому спасибо за внимание.

Ссылки:
yate.null.ro/pmwiki/index.php?n=Main.Extmodule
yate.null.ro/docs/extmodule.html

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB