Page MenuHomePhabricator

No OneTemporary

diff --git a/sylk/configuration/__init__.py b/sylk/configuration/__init__.py
index 107cd1c..92830eb 100644
--- a/sylk/configuration/__init__.py
+++ b/sylk/configuration/__init__.py
@@ -1,55 +1,55 @@
# Copyright (C) 2010-2011 AG Projects. See LICENSE for details.
#
from application.configuration import ConfigSection, ConfigSetting
from application.configuration.datatypes import StringList
from application.system import host
-from sipsimple.configuration.datatypes import NonNegativeInteger, SIPProxyAddress, SRTPEncryption
+from sipsimple.configuration.datatypes import NonNegativeInteger, SRTPEncryption
from sylk import configuration_filename
-from sylk.configuration.datatypes import AudioCodecs, IPAddress, Port, PortRange
+from sylk.configuration.datatypes import AudioCodecs, IPAddress, Port, PortRange, SIPProxyAddress
class ServerConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'Server'
ca_file = ConfigSetting(type=str, value='/etc/sylkserver/tls/ca.crt')
certificate = ConfigSetting(type=str, value='/etc/sylkserver/tls/sylkserver.crt')
verify_server = False
default_application = 'conference'
application_map = ConfigSetting(type=StringList, value='')
trace_dir = ConfigSetting(type=str, value='/var/log/sylkserver')
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=None)
outbound_proxy = ConfigSetting(type=SIPProxyAddress, value=None)
class MSRPConfig(ConfigSection):
__cfgfile__ = configuration_filename
__section__ = 'MSRP'
use_tls = False
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)
diff --git a/sylk/configuration/datatypes.py b/sylk/configuration/datatypes.py
index a236317..0ad3edf 100644
--- a/sylk/configuration/datatypes.py
+++ b/sylk/configuration/datatypes.py
@@ -1,99 +1,144 @@
# Copyright (C) 2010-2011 AG Projects. See LICENSE for details.
#
import os
import re
import socket
import sys
-from sipsimple.configuration.datatypes import AudioCodecList
+from sipsimple.configuration.datatypes import AudioCodecList, Hostname, SIPTransport
from sipsimple.util import classproperty
class AudioCodecs(list):
def __new__(cls, value):
if isinstance(value, (tuple, list)):
return [str(x) for x in value if x in AudioCodecList.available_values] or None
elif isinstance(value, basestring):
if value.lower() in ('none', ''):
return None
return [x for x in re.split(r'\s*,\s*', value) if x in AudioCodecList.available_values] or None
else:
raise TypeError("value must be a string, list or tuple")
class IPAddress(str):
"""An IP address in quad dotted number notation"""
def __new__(cls, value):
if value == '0.0.0.0':
raise ValueError("%s is not allowed, please specify a specific IP address" % value)
else:
try:
socket.inet_aton(value)
except socket.error:
raise ValueError("invalid IP address: %r" % value)
except TypeError:
raise TypeError("value must be a string")
return str(value)
class ResourcePath(object):
def __init__(self, path):
self.path = os.path.normpath(str(path))
def __getstate__(self):
return unicode(self.path)
def __setstate__(self, state):
self.__init__(state)
@property
def normalized(self):
path = os.path.expanduser(self.path)
if os.path.isabs(path):
return os.path.realpath(path)
return os.path.realpath(os.path.join(self.resources_directory, path))
@classproperty
def resources_directory(cls):
binary_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
if os.path.basename(binary_directory) == 'bin':
application_directory = os.path.dirname(binary_directory)
resources_component = 'share/sylkserver'
else:
application_directory = binary_directory
resources_component = 'resources'
return os.path.realpath(os.path.join(application_directory, resources_component))
def __eq__(self, other):
try:
return self.path == other.path
except AttributeError:
return False
def __hash__(self):
return hash(self.path)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.path)
def __unicode__(self):
return unicode(self.path)
class Port(int):
def __new__(cls, value):
try:
value = int(value)
except ValueError:
return None
if not (0 <= value <= 65535):
raise ValueError("illegal port value: %s" % value)
return value
class PortRange(object):
"""A port range in the form start:end with start and end being even numbers in the [1024, 65536] range"""
def __init__(self, value):
self.start, self.end = [int(p) for p in value.split(':', 1)]
allowed = xrange(1024, 65537, 2)
if not (self.start in allowed and self.end in allowed and self.start < self.end):
raise ValueError("bad range: %r: ports must be even numbers in the range [1024, 65536] with start < end" % value)
+class SIPProxyAddress(object):
+ _description_re = re.compile(r"^(?P<host>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|([a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)*))(:(?P<port>\d+))?(;transport=(?P<transport>.+))?$")
+
+ def __new__(cls, description):
+ if not description:
+ return None
+ if not cls._description_re.match(description):
+ raise ValueError("illegal SIP proxy address: %s" % description)
+ return super(SIPProxyAddress, cls).__new__(cls)
+
+ def __init__(self, description):
+ match = self.__class__._description_re.match(description)
+ data = match.groupdict()
+ host = data.get('host')
+ port = data.get('port', None) or 5060
+ transport = data.get('transport', None) or 'udp'
+ self.host = Hostname(host)
+ self.port = Port(port)
+ if self.port == 0:
+ raise ValueError("illegal port value: 0")
+ self.transport = SIPTransport(transport)
+
+ def __getstate__(self):
+ return unicode(self)
+
+ def __setstate__(self, state):
+ if not self.__class__._description_re.match(state):
+ raise ValueError("illegal SIP proxy address: %s" % state)
+ self.__init__(state)
+
+ def __eq__(self, other):
+ try:
+ return (self.host, self.port, self.transport) == (other.host, other.port, other.transport)
+ except AttributeError:
+ return False
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return hash((self.host, self.port, self.transport))
+
+ def __unicode__(self):
+ return u'%s:%d;transport=%s' % (self.host, self.port, self.transport)
+
diff --git a/sylk/configuration/settings.py b/sylk/configuration/settings.py
index 9fd5bf7..7e4396c 100644
--- a/sylk/configuration/settings.py
+++ b/sylk/configuration/settings.py
@@ -1,123 +1,121 @@
# Copyright (C) 2010-2011 AG Projects. See LICENSE for details.
#
"""
SIP SIMPLE SDK settings extensions.
"""
__all__ = ['AccountExtension', 'BonjourAccountExtension', 'SylkServerSettingsExtension']
import os
from sipsimple.account import MSRPSettings as AccountMSRPSettings, NATTraversalSettings as AccountNATTraversalSettings
from sipsimple.account import RTPSettings as AccountRTPSettings, SIPSettings as AccountSIPSettings, TLSSettings as AccountTLSSettings
from sipsimple.configuration import CorrelatedSetting, Setting, SettingsObjectExtension
-from sipsimple.configuration.datatypes import AudioCodecList, MSRPTransport, NonNegativeInteger, Path, Port, PortRange, SampleRate, SIPProxyAddress, SIPTransportList, SRTPEncryption
+from sipsimple.configuration.datatypes import AudioCodecList, MSRPTransport, NonNegativeInteger, Path, Port, PortRange, SampleRate, SIPTransportList, SRTPEncryption
from sipsimple.configuration.settings import AudioSettings, LogsSettings, RTPSettings, SIPSettings, TLSSettings
from sylk import __version__ as server_version
from sylk.configuration import ServerConfig, SIPConfig, MSRPConfig, RTPConfig
+from sylk.configuration.datatypes import SIPProxyAddress
# Account settings extensions
msrp_transport = 'tls' if MSRPConfig.use_tls else 'tcp'
class AccountMSRPSettingsExtension(AccountMSRPSettings):
transport = Setting(type=MSRPTransport, default=msrp_transport)
class AccountNATTraversalSettingsExtension(AccountNATTraversalSettings):
use_msrp_relay_for_inbound = Setting(type=bool, default=False)
use_msrp_relay_for_outbound = Setting(type=bool, default=False)
-
class AccountRTPSettingsExtension(AccountRTPSettings):
audio_codec_list = Setting(type=AudioCodecList, default=RTPConfig.audio_codecs, nillable=True)
srtp_encryption = Setting(type=SRTPEncryption, default=RTPConfig.srtp_encryption)
use_srtp_without_tls = Setting(type=bool, default=True)
-
class AccountSIPSettingsExtension(AccountSIPSettings):
register = Setting(type=bool, default=False)
outbound_proxy = Setting(type=SIPProxyAddress, default=SIPConfig.outbound_proxy, nillable=True)
-
tls_certificate = Path(ServerConfig.certificate) if ServerConfig.certificate and os.path.isfile(ServerConfig.certificate) else None
class AccountTLSSettingsExtension(AccountTLSSettings):
certificate = Setting(type=Path, default=tls_certificate, nillable=True)
verify_server = Setting(type=bool, default=ServerConfig.verify_server)
class AccountExtension(SettingsObjectExtension):
enabled = Setting(type=bool, default=True)
msrp = AccountMSRPSettingsExtension
nat_traversal = AccountNATTraversalSettingsExtension
rtp = AccountRTPSettingsExtension
sip = AccountSIPSettingsExtension
tls = AccountTLSSettingsExtension
class BonjourAccountExtension(SettingsObjectExtension):
enabled = Setting(type=bool, default=False)
# General settings extensions
class AudioSettingsExtension(AudioSettings):
input_device = Setting(type=str, default=None, nillable=True)
output_device = Setting(type=str, default=None, nillable=True)
sample_rate = Setting(type=SampleRate, default=16000)
log_directory = Path(ServerConfig.trace_dir) if ServerConfig.trace_dir else None
class LogsSettingsExtension(LogsSettings):
directory = Setting(type=Path, default=log_directory)
trace_sip = Setting(type=bool, default=ServerConfig.trace_sip)
trace_msrp = Setting(type=bool, default=ServerConfig.trace_msrp)
trace_pjsip = Setting(type=bool, default=False)
trace_notifications = Setting(type=bool, default=ServerConfig.trace_notifications)
class RTPSettingsExtension(RTPSettings):
port_range = Setting(type=PortRange, default=PortRange(RTPConfig.port_range.start, RTPConfig.port_range.end))
timeout = Setting(type=NonNegativeInteger, default=RTPConfig.timeout)
def sip_port_validator(port, sibling_port):
if port == sibling_port != 0:
raise ValueError("the TCP and TLS ports must be different")
transport_list = []
if SIPConfig.local_udp_port:
transport_list.append('udp')
if SIPConfig.local_tcp_port:
transport_list.append('tcp')
if SIPConfig.local_tls_port:
transport_list.append('tls')
udp_port = SIPConfig.local_udp_port or 0
tcp_port = SIPConfig.local_tcp_port or 0
tls_port = SIPConfig.local_tls_port or 0
class SIPSettingsExtension(SIPSettings):
udp_port = Setting(type=Port, default=udp_port)
tcp_port = CorrelatedSetting(type=Port, sibling='tls_port', validator=sip_port_validator, default=tcp_port)
tls_port = CorrelatedSetting(type=Port, sibling='tcp_port', validator=sip_port_validator, default=tls_port)
transport_list = Setting(type=SIPTransportList, default=transport_list)
ca_list = Path(ServerConfig.ca_file) if ServerConfig.ca_file and os.path.isfile(ServerConfig.ca_file) else None
class TLSSettingsExtension(TLSSettings):
ca_list = Setting(type=Path, default=ca_list, nillable=True)
class SylkServerSettingsExtension(SettingsObjectExtension):
user_agent = Setting(type=str, default='SylkServer-%s' % server_version)
audio = AudioSettingsExtension
logs = LogsSettingsExtension
rtp = RTPSettingsExtension
sip = SIPSettingsExtension
tls = TLSSettingsExtension

File Metadata

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

Event Timeline