Page MenuHomePhabricator

No OneTemporary

diff --git a/config.ini.sample b/config.ini.sample
index 4899396..86fe0e4 100644
--- a/config.ini.sample
+++ b/config.ini.sample
@@ -1,81 +1,84 @@
; SylkServer configuration file
[Server]
; The following settings are the default used by the software, uncomment
; them only if you want to make changes
; default_application = conference
; Map user part of the Request URI to a specific application
; application_map = 123:conference,test:irc-conference
+; Disable the specified applications
+; disabled_applications =
+
; trace_dir = /var/log/sylkserver
; trace_core = False
; trace_sip = False
; trace_msrp = False
; trace_notifications = False
; TLS can be used for encryption of SIP signaling and MSRP media. TLS is
; disabled by default. To enable TLS, you must have a valid X.509
; certificate and configure it below, then set the local_tls_port in the SIP
; section and use_tls in MSRP section
; The X.509 Certificate Authorities file
; ca_file = /etc/sylkserver/tls/ca.crt
; The file containing X.509 certificate and private key in unencrypted format
; certificate = /etc/sylkserver/tls/default.crt
; verify_server = False
[SIP]
; SIP transport settings
; IP address used for SIP signaling; empty string or any means listen on interface used
; by the default route
; local_ip =
; Ports used for SIP transports, if not set to any value the transport will be disabled
; local_udp_port = 5060
; local_tcp_port = 5060
; local_tls_port = 5061
; If set all outbound SIP requests will be sent through this SIP proxy
; outbound_proxy =
; A comma-separated list of hosts or networks to trust.
; The elements can be an IP address in CIDR format, a
; hostname or an IP address (in the latter 2 a mask of 32
; is assumed), or the special keywords 'any' and 'none'
; (being equivalent to 0.0.0.0/0 and 0.0.0.0/32
; respectively). It defaults to 'any'.
; trusted_peers =
[MSRP]
; MSRP transport settings
; A valid X.509 certificate is required for MSRP to work over TLS.
; TLS is enabled by default, a default TLS certificate is provided with SylkServer.
; use_tls = True
[RTP]
; RTP transport settings
; Allowed codec list, valid values: G722, speex, PCMU, PCMA, iLBC, GSM
; audio_codecs = G722,speex,PCMU,PCMA
; Port range used for RTP
; port_range = 50000:50500
; SRTP valid values: disabled, mandatory, optional
; srtp_encryption = optional
; RTP stream timeout, session will be disconnected after this value
; timeout = 30
diff --git a/sylk/applications/__init__.py b/sylk/applications/__init__.py
index c69025f..bfa108f 100644
--- a/sylk/applications/__init__.py
+++ b/sylk/applications/__init__.py
@@ -1,278 +1,280 @@
# Copyright (C) 2010-2011 AG Projects. See LICENSE for details
#
__all__ = ['ISylkApplication', 'ApplicationRegistry', 'SylkApplication', 'IncomingRequestHandler', 'ApplicationLogger']
import os
import socket
import struct
from application import log
from application.configuration.datatypes import NetworkRange
from application.notification import IObserver, NotificationCenter
from application.python import Null
from application.python.types import Singleton
from itertools import chain
from sipsimple.threading import run_in_twisted_thread
from zope.interface import Attribute, Interface, implements
from sylk.configuration import ServerConfig, SIPConfig, ThorNodeConfig
SYLK_APP_HEADER = 'X-Sylk-App'
class ISylkApplication(Interface):
"""
- Interface defining attributes and methods any application must
+ Interface defining attributes and methods any application must
implement.
Each application must use the SylkApplication metaclass.
"""
__appname__ = Attribute("Application name")
def start(self):
pass
def stop(self):
pass
def incoming_session(self, session):
pass
def incoming_subscription(self, subscribe_request, data):
pass
def incoming_referral(self, refer_request, data):
pass
def incoming_sip_message(self, message_request, data):
pass
class ApplicationRegistry(object):
__metaclass__ = Singleton
def __init__(self):
self.applications = []
def __iter__(self):
return iter(self.applications)
def add(self, app):
if app not in self.applications:
self.applications.append(app)
class SylkApplication(Singleton):
"""Metaclass for defining SylkServer applications: a Singleton that also adds them to the application registry"""
def __init__(cls, name, bases, dic):
super(SylkApplication, cls).__init__(name, bases, dic)
ApplicationRegistry().add(cls)
def load_applications():
toplevel = os.path.dirname(__file__)
- app_list = ['sylk.applications.%s' % item for item in os.listdir(toplevel) if os.path.isdir(os.path.join(toplevel, item)) and '__init__.py' in os.listdir(os.path.join(toplevel, item))]
- map(__import__, app_list)
+ app_list = [item for item in os.listdir(toplevel) if os.path.isdir(os.path.join(toplevel, item)) and '__init__.py' in os.listdir(os.path.join(toplevel, item))]
+ for module in ['sylk.applications.%s' % item for item in set(app_list).difference(ServerConfig.disabled_applications)]:
+ __import__(module)
+ map(__import__, [])
[app() for app in ApplicationRegistry()]
class ApplicationNotLoadedError(Exception):
pass
class IncomingRequestHandler(object):
"""
Handle incoming requests and match them to applications.
"""
__metaclass__ = Singleton
implements(IObserver)
def __init__(self):
load_applications()
log.msg('Loaded applications: %s' % ', '.join([app.__appname__ for app in ApplicationRegistry()]))
self.application_map = dict((item.split(':')) for item in ServerConfig.application_map)
self.authorization_handler = AuthorizationHandler()
def start(self):
[app().start() for app in ApplicationRegistry()]
self.authorization_handler.start()
notification_center = NotificationCenter()
notification_center.add_observer(self, name='SIPSessionNewIncoming')
notification_center.add_observer(self, name='SIPIncomingSubscriptionGotSubscribe')
notification_center.add_observer(self, name='SIPIncomingReferralGotRefer')
notification_center.add_observer(self, name='SIPIncomingRequestGotRequest')
def stop(self):
self.authorization_handler.stop()
notification_center = NotificationCenter()
notification_center.remove_observer(self, name='SIPSessionNewIncoming')
notification_center.remove_observer(self, name='SIPIncomingSubscriptionGotSubscribe')
notification_center.remove_observer(self, name='SIPIncomingReferralGotRefer')
notification_center.remove_observer(self, name='SIPIncomingRequestGotRequest')
[app().stop() for app in ApplicationRegistry()]
def get_application(self, ruri, headers):
if SYLK_APP_HEADER in headers:
application = headers[SYLK_APP_HEADER].body.strip()
else:
application = ServerConfig.default_application
if self.application_map:
prefixes = ("%s@%s" % (ruri.user, ruri.host), ruri.host, ruri.user)
for prefix in prefixes:
if prefix in self.application_map:
application = self.application_map[prefix]
break
try:
app = (app for app in ApplicationRegistry() if app.__appname__ == application).next()
except StopIteration:
log.error('Application %s is not loaded' % application)
raise ApplicationNotLoadedError
else:
return app()
@run_in_twisted_thread
def handle_notification(self, notification):
handler = getattr(self, '_NH_%s' % notification.name, Null)
handler(notification)
def _NH_SIPSessionNewIncoming(self, notification):
session = notification.sender
try:
self.authorization_handler.authorize_source(session.peer_address.ip)
except UnauthorizedRequest:
session.reject(403)
return
try:
app = self.get_application(session._invitation.request_uri, notification.data.headers)
except ApplicationNotLoadedError:
session.reject(404)
else:
app.incoming_session(session)
def _NH_SIPIncomingSubscriptionGotSubscribe(self, notification):
subscribe_request = notification.sender
try:
self.authorization_handler.authorize_source(subscribe_request.peer_address.ip)
except UnauthorizedRequest:
subscribe_request.reject(403)
return
try:
app = self.get_application(notification.data.request_uri, notification.data.headers)
except ApplicationNotLoadedError:
subscribe_request.reject(404)
else:
app.incoming_subscription(subscribe_request, notification.data)
def _NH_SIPIncomingReferralGotRefer(self, notification):
refer_request = notification.sender
try:
self.authorization_handler.authorize_source(refer_request.peer_address.ip)
except UnauthorizedRequest:
refer_request.reject(403)
return
try:
app = self.get_application(notification.data.request_uri, notification.data.headers)
except ApplicationNotLoadedError:
refer_request.reject(404)
else:
app.incoming_referral(refer_request, notification.data)
def _NH_SIPIncomingRequestGotRequest(self, notification):
request = notification.sender
if notification.data.method != 'MESSAGE':
request.answer(405)
return
try:
self.authorization_handler.authorize_source(request.peer_address.ip)
except UnauthorizedRequest:
request.answer(403)
return
try:
app = self.get_application(notification.data.request_uri, notification.data.headers)
except ApplicationNotLoadedError:
request.answer(404)
else:
app.incoming_sip_message(request, notification.data)
class UnauthorizedRequest(Exception):
pass
class AuthorizationHandler(object):
implements(IObserver)
def __init__(self):
self.state = None
self.trusted_peers = SIPConfig.trusted_peers
self.thor_nodes = []
@property
def trusted_parties(self):
if ThorNodeConfig.enabled:
return self.thor_nodes
return self.trusted_peers
def start(self):
notification_center = NotificationCenter()
notification_center.add_observer(self, name='ThorNetworkGotUpdate')
self.state = 'started'
def stop(self):
self.state = 'stopped'
notification_center = NotificationCenter()
notification_center.remove_observer(self, name='ThorNetworkGotUpdate')
def authorize_source(self, ip_address):
if self.state != 'started':
raise UnauthorizedRequest
for range in self.trusted_parties:
if struct.unpack('!L', socket.inet_aton(ip_address))[0] & range[1] == range[0]:
return True
raise UnauthorizedRequest
@run_in_twisted_thread
def handle_notification(self, notification):
handler = getattr(self, '_NH_%s' % notification.name, Null)
handler(notification)
def _NH_ThorNetworkGotUpdate(self, notification):
thor_nodes = []
for node in chain(*(n.nodes for n in notification.data.networks.values())):
thor_nodes.append(NetworkRange(node))
self.thor_nodes = thor_nodes
class ApplicationLogger(object):
__metaclass__ = Singleton
def __init__(self, prefix):
self.prefix = '[%s] ' % prefix
def info(self, message, **context):
log.info(self.prefix+message, **context)
def warning(self, message, **context):
log.warning(self.prefix+message, **context)
def debug(self, message, **context):
log.debug(self.prefix+message, **context)
def error(self, message, **context):
log.error(self.prefix+message, **context)
def critical(self, message, **context):
log.critical(self.prefix+message, **context)
def exception(self, message=None, **context):
if message is not None:
message = self.prefix+message
log.exception(message, **context)
# Some aliases that are commonly used
msg = info
warn = warning
fatal = critical
err = exception
diff --git a/sylk/configuration/__init__.py b/sylk/configuration/__init__.py
index f309d32..fe0bc14 100644
--- a/sylk/configuration/__init__.py
+++ b/sylk/configuration/__init__.py
@@ -1,70 +1,71 @@
# Copyright (C) 2010-2011 AG Projects. See LICENSE for details.
#
from application.configuration import ConfigSection, ConfigSetting
from application.configuration.datatypes import NetworkRangeList, StringList
from application.system import host
from sipsimple.configuration.datatypes import NonNegativeInteger, SRTPEncryption
from sylk import configuration_filename
from sylk.configuration.datatypes import AudioCodecs, IPAddress, NillablePath, Path, Port, PortRange, SIPProxyAddress
from sylk.tls import Certificate, PrivateKey
class ServerConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'Server'
ca_file = ConfigSetting(type=NillablePath, value=NillablePath('tls/ca.crt'))
certificate = ConfigSetting(type=NillablePath, value=NillablePath('tls/default.crt'))
verify_server = False
default_application = 'conference'
application_map = ConfigSetting(type=StringList, value='')
+ disabled_applications = ConfigSetting(type=StringList, value='')
trace_dir = ConfigSetting(type=Path, value=Path('var/log/sylkserver'))
trace_core = False
trace_sip = False
trace_msrp = False
trace_notifications = False
class SIPConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'SIP'
local_ip = ConfigSetting(type=IPAddress, value=host.default_ip)
local_udp_port = ConfigSetting(type=Port, value=5060)
local_tcp_port = ConfigSetting(type=Port, value=5060)
local_tls_port = ConfigSetting(type=Port, value=5061)
outbound_proxy = ConfigSetting(type=SIPProxyAddress, value=None)
trusted_peers = ConfigSetting(type=NetworkRangeList, value=NetworkRangeList('any'))
class MSRPConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'MSRP'
use_tls = True
class RTPConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'RTP'
audio_codecs = ConfigSetting(type=AudioCodecs, value=None)
port_range = ConfigSetting(type=PortRange, value=PortRange('50000:50500'))
srtp_encryption = ConfigSetting(type=SRTPEncryption, value='optional')
timeout = ConfigSetting(type=NonNegativeInteger, value=30)
class ThorNodeConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'ThorNetwork'
enabled = False
domain = "sipthor.net"
multiply = 1000
certificate = ConfigSetting(type=Certificate, value=None)
private_key = ConfigSetting(type=PrivateKey, value=None)
ca = ConfigSetting(type=Certificate, value=None)

File Metadata

Mime Type
text/x-diff
Expires
Sat, Feb 1, 11:30 AM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3485250
Default Alt Text
(15 KB)

Event Timeline