...

четверг, 31 октября 2013 г.

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

В данном посте мы с Вами настроим 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:global\n")

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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий