list)
12 | {
13 | this.list = list;
14 | }
15 |
16 | public void AddIfAbsent(T item)
17 | {
18 | lock (list)
19 | {
20 | if (list.IndexOf(item) < 0)
21 | list.Add(item);
22 | }
23 | }
24 |
25 | public void Replace(T item)
26 | {
27 | lock (list)
28 | {
29 | list.Remove(item);
30 | list.Add(item);
31 | }
32 | }
33 |
34 | public bool Remove(T item)
35 | {
36 | bool result;
37 |
38 | lock (list)
39 | result = list.Remove(item);
40 |
41 | return result;
42 | }
43 |
44 | public bool RemoveFirst(P param, Func predicate)
45 | {
46 | bool result = false;
47 |
48 | lock (list)
49 | {
50 | for (int i = 0; i < list.Count; i++)
51 | if (predicate(list[i], param))
52 | {
53 | list.RemoveAt(i);
54 | result = true;
55 | break;
56 | }
57 | }
58 |
59 | return result;
60 | }
61 |
62 | public void ForEach(Action action)
63 | {
64 | lock (list)
65 | {
66 | for (int i = 0; i < list.Count; i++)
67 | action(list[i]);
68 | }
69 | }
70 |
71 | public void RecursiveForEach(Action action)
72 | {
73 | Monitor.Enter(list);
74 |
75 | if (list.Count > 0)
76 | RecursiveForEach(action, 0);
77 | else
78 | Monitor.Exit(list);
79 | }
80 |
81 | public void RecursiveForEach(Action action, int index)
82 | {
83 | var item = list[index++];
84 |
85 | if (index < list.Count)
86 | RecursiveForEach(action, index);
87 | else
88 | Monitor.Exit(list);
89 |
90 | action(item);
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Server/Configuration/ByteArrayConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 | using System.ComponentModel;
4 | using System.Globalization;
5 |
6 | namespace Sip.Server.Configuration
7 | {
8 | class ByteArrayConverter
9 | : ConfigurationConverterBase
10 | {
11 | public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
12 | {
13 | return type == typeof(string);
14 | }
15 |
16 | public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
17 | {
18 | return type == typeof(string);
19 | }
20 |
21 | public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
22 | {
23 | if (value == null)
24 | return new ArgumentNullException();
25 |
26 | if (value.GetType() != typeof(byte[]))
27 | throw new ArgumentException();
28 |
29 | return Convert.ToBase64String(value as byte[]);
30 | }
31 |
32 | public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
33 | {
34 | if (data == null)
35 | return new ArgumentNullException(@"data");
36 |
37 | return Convert.FromBase64String(data as string);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Server/Configuration/ConfigurationMonitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Timers;
4 | using System.Configuration;
5 |
6 | namespace Server.Configuration
7 | {
8 | class ConfigurationMonitor
9 | : IDisposable
10 | {
11 | private Timer timer;
12 | private FileSystemWatcher watcher;
13 |
14 | public event EventHandler Changed;
15 |
16 | public void Dispose()
17 | {
18 | if (watcher != null)
19 | {
20 | watcher.EnableRaisingEvents = false;
21 | watcher.Dispose();
22 | watcher = null;
23 | }
24 |
25 | if (timer == null)
26 | {
27 | timer.Dispose();
28 | timer = null;
29 | }
30 | }
31 |
32 | public void StartMonitoring(ConfigurationSectionEx section)
33 | {
34 | if (timer == null)
35 | {
36 | timer = new Timer(500);
37 | timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
38 | timer.AutoReset = false;
39 | }
40 |
41 | if (watcher == null)
42 | {
43 | watcher = new FileSystemWatcher();
44 | watcher.Changed += Watcher_Changed;
45 | watcher.Created += Watcher_Changed;
46 | watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime;
47 | }
48 |
49 | watcher.EnableRaisingEvents = false;
50 |
51 | watcher.Path = Path.GetDirectoryName(section.FilePath);
52 | watcher.Filter = Path.GetFileName(section.FilePath);
53 |
54 | watcher.EnableRaisingEvents = true;
55 | }
56 |
57 | private void Timer_Elapsed(object sender, ElapsedEventArgs e)
58 | {
59 | var changed = Changed;
60 | if (changed != null)
61 | changed(this, EventArgs.Empty);
62 | }
63 |
64 | private void Watcher_Changed(object sender, FileSystemEventArgs e)
65 | {
66 | if (timer.Enabled)
67 | timer.Stop();
68 | timer.Start();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Server/Configuration/DefaultConfiguration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Server/Configuration/IPEndPointConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using System.Configuration;
5 | using System.ComponentModel;
6 | using System.Globalization;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace Sip.Server.Configuration
10 | {
11 | class IPEndPointConverter
12 | : ConfigurationConverterBase
13 | {
14 | public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
15 | {
16 | return type == typeof(string);
17 | }
18 |
19 | public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
20 | {
21 | return type == typeof(string);
22 | }
23 |
24 | public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
25 | {
26 | if (value == null)
27 | return new ArgumentNullException(@"value");
28 |
29 | var endpoint = value as IPEndPoint;
30 |
31 | if (endpoint == null)
32 | throw new ArgumentException(@"value");
33 |
34 | if (endpoint.AddressFamily == AddressFamily.InterNetworkV6)
35 | return @"[" + endpoint.Address.ToString() + @"]:" + endpoint.Port;
36 |
37 | return endpoint.ToString();
38 | }
39 |
40 | public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
41 | {
42 | if (data == null)
43 | throw new ArgumentOutOfRangeException(@"IP End Point");
44 |
45 | var regex = new Regex(@"^(((\[(?[^\]]+)\])|(?[^:]+)):(?[0-9]+))",
46 | RegexOptions.Singleline);
47 |
48 | var match = regex.Match(data as string);
49 |
50 | if (match.Success == false)
51 | throw new ArgumentOutOfRangeException(@"IP End Point");
52 |
53 | IPAddress address;
54 | if (IPAddress.TryParse(match.Groups["address"].Value, out address) == false)
55 | throw new ArgumentOutOfRangeException(@"IP Address");
56 |
57 | int port;
58 | if (int.TryParse(match.Groups["port"].Value, out port) == false)
59 | throw new ArgumentOutOfRangeException(@"Port");
60 |
61 | if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
62 | return null;
63 |
64 | return new IPEndPoint(address, port);
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Server/Configuration/PortForwardingConfigurationElement.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Configuration;
4 | using System.ComponentModel;
5 | using SocketServers;
6 |
7 | namespace Sip.Server.Configuration
8 | {
9 | public class PortForwardingConfigurationElement
10 | : ConfigurationElement
11 | {
12 | private const string protocolName = @"protocol";
13 | private const string localEndpointName = @"localEndpoint";
14 | private const string externalEndpointName = @"externalEndpoint";
15 |
16 | [ConfigurationProperty(protocolName, IsRequired = true)]
17 | [TypeConverter(typeof(ProtocolConverter))]
18 | public ServerProtocol Protocol
19 | {
20 | get { return (ServerProtocol)base[protocolName]; }
21 | set { base[protocolName] = value; }
22 | }
23 |
24 | [ConfigurationProperty(localEndpointName, IsRequired = true)]
25 | [TypeConverter(typeof(IPEndPointConverter))]
26 | public IPEndPoint LocalEndpoint
27 | {
28 | get { return (IPEndPoint)base[localEndpointName]; }
29 | set { base[localEndpointName] = value; }
30 | }
31 |
32 | [ConfigurationProperty(externalEndpointName, IsRequired = true)]
33 | [TypeConverter(typeof(IPEndPointConverter))]
34 | public IPEndPoint ExternalEndpoint
35 | {
36 | get { return (IPEndPoint)base[externalEndpointName]; }
37 | set { base[externalEndpointName] = value; }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Server/Configuration/PortForwardingConfigurationElementCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.ComponentModel;
6 |
7 | namespace Sip.Server.Configuration
8 | {
9 | public class PortForwardingConfigurationElementCollection
10 | : ConfigurationElementCollection, IEnumerable
11 | {
12 | protected override ConfigurationElement CreateNewElement()
13 | {
14 | return new PortForwardingConfigurationElement();
15 | }
16 |
17 | protected override object GetElementKey(ConfigurationElement element)
18 | {
19 | var forwarding = element as PortForwardingConfigurationElement;
20 | return forwarding.Protocol.ToString() + ":" + forwarding.LocalEndpoint.ToString();
21 | }
22 |
23 | public new IEnumerator GetEnumerator()
24 | {
25 | return new TypedEnumerator(base.GetEnumerator());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Server/Configuration/ProtocolConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 | using System.ComponentModel;
4 | using System.Globalization;
5 | using SocketServers;
6 |
7 | namespace Sip.Server.Configuration
8 | {
9 | class ProtocolConverter
10 | : ConfigurationConverterBase
11 | {
12 | public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
13 | {
14 | return type == typeof(string);
15 | }
16 |
17 | public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
18 | {
19 | return type == typeof(string);
20 | }
21 |
22 | public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
23 | {
24 | if (value == null)
25 | return new ArgumentNullException();
26 |
27 | if (value.GetType() != typeof(ServerProtocol))
28 | throw new ArgumentException();
29 |
30 | return value.ToString();
31 | }
32 |
33 | public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
34 | {
35 | if (data == null)
36 | return new ArgumentNullException(@"data");
37 |
38 | return (data as string).ConvertTo();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Server/Configuration/TurnServerConfigurationElement.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 |
4 | namespace Sip.Server.Configuration
5 | {
6 | public class TurnServerConfigurationElement
7 | : ConfigurationElement
8 | {
9 | private const string fqdnName = @"fqdn";
10 | private const string udpPortName = @"udpPort";
11 | private const string tcpPortName = @"tcpPort";
12 | private const string locationName = @"location";
13 |
14 | [ConfigurationProperty(fqdnName, IsRequired = true)]
15 | public string Fqdn
16 | {
17 | get { return (string)base[fqdnName]; }
18 | set { base[fqdnName] = value; }
19 | }
20 |
21 | [ConfigurationProperty(udpPortName, DefaultValue = 3478)]
22 | [IntegerValidator(MinValue = 0, MaxValue = 65535)]
23 | public int UdpPort
24 | {
25 | get { return (int)base[udpPortName]; }
26 | set { base[udpPortName] = value; }
27 | }
28 |
29 | [ConfigurationProperty(tcpPortName, DefaultValue = 3478)]
30 | [IntegerValidator(MinValue = 0, MaxValue = 65535)]
31 | public int TcpPort
32 | {
33 | get { return (int)base[tcpPortName]; }
34 | set { base[tcpPortName] = value; }
35 | }
36 |
37 | [ConfigurationProperty(locationName, DefaultValue = "Internet")]
38 | [RegexStringValidator("Internet|Intranet")]
39 | public string Location
40 | {
41 | get { return (string)base[locationName]; }
42 | set { base[locationName] = value; }
43 | }
44 |
45 | public bool IsInternet
46 | {
47 | get { return string.Compare(Location, "Internet") == 0; }
48 | set { Location = "Internet"; }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Server/Configuration/TurnServerConfigurationElementCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.ComponentModel;
6 |
7 | namespace Sip.Server.Configuration
8 | {
9 | public class TurnServerConfigurationElementCollection
10 | : ConfigurationElementCollection, IEnumerable
11 | {
12 | private const string key1Name = @"key1";
13 | private const string key2Name = @"key2";
14 |
15 | protected override ConfigurationElement CreateNewElement()
16 | {
17 | return new TurnServerConfigurationElement();
18 | }
19 |
20 | protected override object GetElementKey(ConfigurationElement element)
21 | {
22 | var turnServer = element as TurnServerConfigurationElement;
23 | return turnServer.Location + "@" + turnServer.Fqdn;
24 | }
25 |
26 | [ConfigurationProperty(key1Name)]
27 | [TypeConverter(typeof(ByteArrayConverter))]
28 | public byte[] Key1
29 | {
30 | get { return (byte[])base[key1Name]; }
31 | set { base[key1Name] = value; }
32 | }
33 |
34 | [ConfigurationProperty(key2Name)]
35 | [TypeConverter(typeof(ByteArrayConverter))]
36 | public byte[] Key2
37 | {
38 | get { return (byte[])base[key2Name]; }
39 | set { base[key2Name] = value; }
40 | }
41 |
42 | public void Clear()
43 | {
44 | BaseClear();
45 | }
46 |
47 | public void Add(string fqdn, int tcpPort, int udpPort, bool isInternet)
48 | {
49 | BaseAdd(new TurnServerConfigurationElement()
50 | {
51 | Fqdn = fqdn,
52 | TcpPort = tcpPort,
53 | UdpPort = udpPort,
54 | IsInternet = isInternet,
55 | });
56 | }
57 |
58 | public new IEnumerator GetEnumerator()
59 | {
60 | return new TypedEnumerator(base.GetEnumerator());
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Server/Configuration/TypedEnumerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace Sip.Server
6 | {
7 | class TypedEnumerator
8 | : IEnumerator
9 | {
10 | IEnumerator enumerator;
11 |
12 | public TypedEnumerator(IEnumerator enumerator1)
13 | {
14 | enumerator = enumerator1;
15 | }
16 |
17 | public void Dispose()
18 | {
19 | }
20 |
21 | public bool MoveNext()
22 | {
23 | return enumerator.MoveNext();
24 | }
25 |
26 | public void Reset()
27 | {
28 | enumerator.Reset();
29 | }
30 |
31 | Object IEnumerator.Current
32 | {
33 | get { return enumerator.Current; }
34 | }
35 |
36 | T IEnumerator.Current
37 | {
38 | get { return (T)enumerator.Current; }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Server/Configuration/VoipProviderConfigurationElementCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 |
6 | namespace Sip.Server.Configuration
7 | {
8 | class VoipProviderConfigurationElementCollection
9 | : ConfigurationElementCollection, IEnumerable
10 | {
11 | protected override ConfigurationElement CreateNewElement()
12 | {
13 | return new VoipProviderConfigurationElement();
14 | }
15 |
16 | protected override object GetElementKey(ConfigurationElement element)
17 | {
18 | var voipProvider = element as VoipProviderConfigurationElement;
19 | return voipProvider.Username + "@" + voipProvider.ServerHostname;
20 | }
21 |
22 | public void Clear()
23 | {
24 | BaseClear();
25 | }
26 |
27 | public void Add(VoipProviderConfigurationElement item)
28 | {
29 | BaseAdd(item);
30 | }
31 |
32 | public void Remove(string username, string hostname)
33 | {
34 | BaseRemove(username + "@" + hostname);
35 | }
36 |
37 | public new IEnumerator GetEnumerator()
38 | {
39 | return new TypedEnumerator(base.GetEnumerator());
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/EnhancedPresenceException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EnhancedPresence
7 | {
8 | public class EnhancedPresenceException :
9 | Exception
10 | {
11 | public EnhancedPresenceException(string message, Exception innerException)
12 | : base(message, innerException)
13 | {
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/ExpiresList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace EnhancedPresence
5 | {
6 | public class ExpiresList :
7 | ISubscriptionResourceEvents
8 | {
9 | private List resources;
10 |
11 | public ExpiresList()
12 | {
13 | this.resources = new List();
14 | }
15 |
16 | public void AddResource(SubscriptionResource resource)
17 | {
18 | int tickCount = Environment.TickCount;
19 |
20 | for (int i = 0; i < resources.Count; i++)
21 | {
22 | if (resources[i].GetExpires(tickCount) > resource.GetExpires(tickCount))
23 | {
24 | resources.Insert(i, resource);
25 | break;
26 | }
27 | }
28 | }
29 |
30 | public void RemoveResource(SubscriptionResource resource)
31 | {
32 | resources.Remove(resource);
33 | }
34 |
35 | public void UpdateResource(SubscriptionResource resource)
36 | {
37 | RemoveResource(resource);
38 | AddResource(resource);
39 | }
40 |
41 | public SubscriptionResource GetExpired()
42 | {
43 | SubscriptionResource resource = null;
44 |
45 | if (resources.Count > 0)
46 | {
47 | if (resources[0].Expires == 0)
48 | {
49 | resource = resources[0];
50 | resources.RemoveAt(0);
51 | }
52 | }
53 |
54 | return resource;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/Schemas/Categories.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/Schemas/RichPresenceCommon.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/Schemas/categoryList.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/XmlContent/BatchSubscribe.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Xml.Schema;
4 | using System.Xml;
5 | using System.IO;
6 |
7 | namespace EnhancedPresence
8 | {
9 | public enum BatchSubscribeAction
10 | {
11 | Subscribe,
12 | Unsubscribe
13 | }
14 |
15 | public class BatchSubscribe
16 | {
17 | public BatchSubscribeAction Action { private set; get; }
18 | public List Resources { private set; get; }
19 | public List Сategories { private set; get; }
20 |
21 | protected BatchSubscribe()
22 | {
23 | Resources = new List();
24 | Сategories = new List();
25 | }
26 |
27 | public static BatchSubscribe Parse(XmlReader reader)
28 | {
29 | BatchSubscribe request = new BatchSubscribe();
30 |
31 | while (reader.Read())
32 | {
33 | if (reader.NodeType == XmlNodeType.Element)
34 | {
35 | if (reader.Name == "action")
36 | {
37 | string name = reader.GetAttribute("name");
38 | if (name == "subscribe")
39 | request.Action = BatchSubscribeAction.Subscribe;
40 | else if (name == "unsubscribe")
41 | request.Action = BatchSubscribeAction.Unsubscribe;
42 | }
43 |
44 | if (reader.Name == "resource")
45 | request.Resources.Add(reader.GetAttribute("uri"));
46 |
47 | if (reader.Name == "category")
48 | request.Сategories.Add(reader.GetAttribute("name"));
49 | }
50 | }
51 |
52 | return request;
53 | }
54 |
55 | public static string InContentType
56 | {
57 | get { return @"application"; }
58 | }
59 |
60 | public static string InContentSubtype
61 | {
62 | get { return @"msrtc-adrl-categorylist+xml"; }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/XmlContent/ICategoryValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Xml;
3 |
4 | namespace EnhancedPresence
5 | {
6 | public interface ICategoryValue
7 | {
8 | void Generate(XmlWriter writer);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/XmlContent/RoamingData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Xml;
3 | using System.Text;
4 |
5 | namespace EnhancedPresence
6 | {
7 | public class RoamingData :
8 | OutContentBase
9 | {
10 | private Categories categories;
11 |
12 | protected RoamingData()
13 | {
14 | }
15 |
16 | public static RoamingData Create(Categories categories)
17 | {
18 | RoamingData roamingData = new RoamingData();
19 |
20 | roamingData.categories = categories;
21 |
22 | return roamingData;
23 | }
24 |
25 | public override void Generate(XmlWriter writer)
26 | {
27 | writer.WriteStartElement(@"roamingData", @"http://schemas.microsoft.com/2006/09/sip/roaming-self");
28 |
29 | this.categories.Generate(writer);
30 |
31 | writer.WriteEndElement();
32 |
33 | writer.Flush();
34 | }
35 |
36 | public override string OutContentType
37 | {
38 | get { return @"application"; }
39 | }
40 |
41 | public override string OutContentSubtype
42 | {
43 | get { return @"vnd-microsoft-roaming-self+xml"; }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/XmlContent/Schemas.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Xml.Schema;
4 | using System.Xml;
5 | using System.IO;
6 |
7 | namespace EnhancedPresence
8 | {
9 | public enum EnhancedPresenceSchema
10 | {
11 | BatchSubscribe = 0,
12 | Categories = 1,
13 | NoSchema
14 | }
15 |
16 | public class Schemas
17 | {
18 | public XmlSchemaSet[] schemas;
19 |
20 | public Schemas()
21 | {
22 | this.schemas = new XmlSchemaSet[2];
23 |
24 | {
25 | XmlSchemaSet schemaSet = new XmlSchemaSet();
26 | schemaSet.Add(LoadSchema("BatchSubscribeRequest.xsd"));
27 | schemaSet.Add(LoadSchema("categoryList.xsd"));
28 | this[EnhancedPresenceSchema.BatchSubscribe] = schemaSet;
29 | }
30 |
31 | {
32 | XmlSchemaSet schemaSet = new XmlSchemaSet();
33 | schemaSet.Add(LoadSchema("Categories.xsd"));
34 | schemaSet.Add(LoadSchema("RichPresenceCommon.xsd"));
35 | this[EnhancedPresenceSchema.Categories] = schemaSet;
36 | }
37 | }
38 |
39 | public XmlSchemaSet this[EnhancedPresenceSchema id]
40 | {
41 | get
42 | {
43 | return this.schemas[(int)id];
44 | }
45 | private set
46 | {
47 | this.schemas[(int)id] = value;
48 | }
49 | }
50 |
51 | private XmlSchema LoadSchema(string location)
52 | {
53 | string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
54 |
55 | foreach (string resource in resources)
56 | {
57 | if (resource.EndsWith(location))
58 | using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(@"Sip.Server.EnhancedPresence.Schemas." + location))
59 | return XmlSchema.Read(stream, null);
60 | }
61 |
62 | throw new Exception("Schema " + location + " can not be loaded.");
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Server/EnhancedPresence/XmlContent/StateCategory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Xml;
4 | using System.IO;
5 |
6 | namespace EnhancedPresence
7 | {
8 | public class StateCategory :
9 | ICategoryValue
10 | {
11 | public int Availability { /*private */set; get; }
12 |
13 | public StateCategory()
14 | {
15 | }
16 |
17 | public static StateCategory Create(int availability)
18 | {
19 | StateCategory state = new StateCategory();
20 |
21 | state.Availability = availability;
22 |
23 | return state;
24 | }
25 |
26 | public static StateCategory Parse(XmlReader reader)
27 | {
28 | StateCategory state = new StateCategory();
29 |
30 | while (reader.Read())
31 | {
32 | if (reader.Name == "availability")
33 | {
34 | while (reader.Read() && reader.NodeType != XmlNodeType.Text) ;
35 | state.Availability = reader.ReadContentAsInt();
36 | }
37 |
38 | if (reader.Name == "state" && reader.NodeType == XmlNodeType.EndElement)
39 | break;
40 | }
41 |
42 | return state;
43 | }
44 |
45 | public void Generate(XmlWriter writer)
46 | {
47 | writer.WriteStartElement(@"state", @"http://schemas.microsoft.com/2006/09/sip/state");
48 | writer.WriteAttributeString(@"xsi", @"type", @"http://www.w3.org/2001/XMLSchema-instance", @"aggregateState");
49 |
50 | writer.WriteStartElement(@"availability");
51 |
52 | writer.WriteValue(this.Availability);
53 |
54 | writer.WriteEndElement();
55 | writer.WriteEndElement();
56 |
57 | writer.Flush();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Server/Http/BaseHttpConnection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Http.Message;
3 | using SocketServers;
4 |
5 | namespace Server.Http
6 | {
7 | public abstract class BaseHttpConnection
8 | : HeaderContentConnection
9 | {
10 | public abstract HttpMessageReader HttpReader { get; }
11 | }
12 | }
--------------------------------------------------------------------------------
/Server/LocationService/ILocationService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sip.Message;
4 | using Base.Message;
5 |
6 | namespace Sip.Server
7 | {
8 | interface ILocationService
9 | {
10 | //IEnumerable GetEnumerableBindings(SipMessageReader reader);
11 | IEnumerable GetEnumerableBindings(ByteArrayPart user, ByteArrayPart domain);
12 | IEnumerable GetEnumerableBindings(ByteArrayPart aor);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Server/Mras/MrasException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Mras.XmlContent;
3 |
4 | namespace Mras
5 | {
6 | public class MrasException
7 | : Exception
8 | {
9 | public ReasonPhrase ReasonPhrase { get; private set; }
10 |
11 | public MrasException()
12 | : base(Common.ToString(ReasonPhrase.RequestMalformed))
13 | {
14 | ReasonPhrase = ReasonPhrase.RequestMalformed;
15 | }
16 |
17 | public MrasException(ReasonPhrase reasonPhrase)
18 | : base(Common.ToString(reasonPhrase))
19 | {
20 | ReasonPhrase = reasonPhrase;
21 | }
22 |
23 | public MrasException(string message)
24 | : base(message)
25 | {
26 | ReasonPhrase = ReasonPhrase.RequestMalformed;
27 | }
28 |
29 | public MrasException(ReasonPhrase reasonPhrase, Exception innerException)
30 | : base(Common.ToString(reasonPhrase), innerException)
31 | {
32 | ReasonPhrase = reasonPhrase;
33 | }
34 |
35 | public MrasException(Exception innerException)
36 | : base(Common.ToString(ReasonPhrase.RequestMalformed), innerException)
37 | {
38 | ReasonPhrase = ReasonPhrase.RequestMalformed;
39 | }
40 |
41 | public MrasException(string message, Exception innerException)
42 | : base(message, innerException)
43 | {
44 | ReasonPhrase = ReasonPhrase.RequestMalformed;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Server/Mras/Password.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography;
3 |
4 | namespace Mras
5 | {
6 | public class Password
7 | {
8 | public static byte[] GetBytes(byte[] key2, byte[] username)
9 | {
10 | using (HMACSHA1 sha1 = new HMACSHA1(key2))
11 | {
12 | sha1.ComputeHash(username);
13 | return sha1.Hash;
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Server/Mras/TokenBlob.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Mras
4 | {
5 | public class TokenBlob1
6 | {
7 | public TokenBlob1()
8 | {
9 | MajorVersion = 1;
10 | MinorVersion = 0;
11 | Size = 0x0020;
12 | ClientID = new byte[20];
13 | }
14 |
15 | public byte MajorVersion;
16 | public byte MinorVersion;
17 | public UInt16 Size;
18 | public UInt32 ExpiryTimeLow;
19 | public UInt32 ExpiryTimeHigh;
20 | public byte[] ClientID;
21 |
22 | public virtual byte[] GetBytes(int extraLength)
23 | {
24 | byte[] bytes = new byte[Size + extraLength];
25 | int offset = 0;
26 |
27 | bytes[offset++] = MajorVersion;
28 | bytes[offset++] = MinorVersion;
29 | AddBytes(bytes, ref offset, Bigendian.GetBigendianBytes(Size));
30 | AddBytes(bytes, ref offset, Bigendian.GetBigendianBytes(ExpiryTimeLow));
31 | AddBytes(bytes, ref offset, Bigendian.GetBigendianBytes(ExpiryTimeHigh));
32 | AddBytes(bytes, ref offset, ClientID);
33 |
34 | return bytes;
35 | }
36 |
37 | protected static void AddBytes(byte[] dst, ref int offset, byte[] src)
38 | {
39 | Array.Copy(src, 0, dst, offset, src.Length);
40 | offset += src.Length;
41 | }
42 | }
43 |
44 | public class TokenBlob2
45 | : TokenBlob1
46 | {
47 | public UInt32 Flags;
48 |
49 | public TokenBlob2()
50 | : base()
51 | {
52 | MajorVersion = 2;
53 | MinorVersion = 0;
54 | Size = 0x0024;
55 | }
56 |
57 | public override byte[] GetBytes(int extraLength)
58 | {
59 | byte[] bytes = base.GetBytes(extraLength);
60 | int offset = Size - sizeof(UInt32);
61 |
62 | AddBytes(bytes, ref offset, Bigendian.GetBigendianBytes(Flags));
63 |
64 | return bytes;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Server/Mras/TurnServerInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Mras
4 | {
5 | public class TurnServerInfo
6 | {
7 | public string Fqdn { get; set; }
8 | public ushort UdpPort { get; set; }
9 | public ushort TcpPort { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Server/Mras/Username.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography;
3 |
4 | namespace Mras
5 | {
6 | public class Username
7 | {
8 | public static byte[] GetBytes(byte[] key1, TokenBlob1 blob1)
9 | {
10 | using (HMACSHA1 sha1 = new HMACSHA1(key1))
11 | {
12 | byte[] username = blob1.GetBytes(sha1.HashSize / 8);
13 |
14 | sha1.ComputeHash(username, 0, blob1.Size);
15 |
16 | Array.Copy(sha1.Hash, 0, username, blob1.Size, sha1.HashSize / 8);
17 |
18 | return username;
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Server/Mras/XmlContent/CredentialsRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Xml.Schema;
3 | using System.Xml;
4 |
5 | namespace Mras.XmlContent
6 | {
7 | #region Schemas
8 | //
9 | //
10 | //
11 | //
12 | //
13 | //
14 | //
15 | //
16 | //
17 |
18 | //
19 | //
20 | //
21 | //
22 | //
23 | //
24 | //
25 | #endregion
26 |
27 | public class CredentialsRequest
28 | {
29 | public string Identity { get; private set; }
30 | public Location? Location { get; private set; }
31 | public uint Duration { get; set; }
32 | public string CredentialsRequestID { get; private set; }
33 |
34 | public static bool CanParse(XmlReader reader)
35 | {
36 | return reader.IsStartElement(@"credentialsRequest");
37 | }
38 |
39 | public static CredentialsRequest Parse(XmlReader reader)
40 | {
41 | CredentialsRequest credentialsRequest = new CredentialsRequest();
42 |
43 | reader.MoveToContent();
44 | credentialsRequest.CredentialsRequestID = reader.GetAttribute(@"credentialsRequestID");
45 |
46 | reader.Read();
47 | reader.MoveToContent();
48 | credentialsRequest.Identity =
49 | reader.ReadElementContentAsString(@"identity", @"http://schemas.microsoft.com/2006/09/sip/mrasp");
50 |
51 | if (reader.IsStartElement(@"location"))
52 | credentialsRequest.Location = Common.ParseLocation(reader.ReadElementContentAsString());
53 |
54 | if (reader.IsStartElement(@"duration"))
55 | credentialsRequest.Duration = (uint)reader.ReadElementContentAsInt();
56 |
57 | reader.MoveToContent();
58 | reader.ReadEndElement();
59 |
60 | return credentialsRequest;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Server/Mras/XmlContent/MediaRelay.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Xml.Schema;
3 | using System.Xml;
4 |
5 | namespace Mras.XmlContent
6 | {
7 | #region Schemas
8 | //
9 | //
10 | //
11 | //
12 | //
13 | //
14 | //
15 | //
16 | //
17 | //
18 | //
19 | //
20 | #endregion
21 |
22 | public class MediaRelay
23 | {
24 | public Location Location { get; set; }
25 | public string HostName { get; set; }
26 | public string DirectIpAddress { get; set; }
27 | public ushort UdpPort { get; set; }
28 | public ushort TcpPort { get; set; }
29 |
30 | public void Generate(XmlWriter writer)
31 | {
32 | writer.WriteStartElement(@"mediaRelay");
33 |
34 | writer.WriteElementString(@"location", Common.ToString(Location));
35 |
36 | if (string.IsNullOrEmpty(HostName) == false)
37 | writer.WriteElementString(@"hostName", HostName);
38 | else
39 | writer.WriteElementString(@"directIPAddress", DirectIpAddress);
40 |
41 | writer.WriteElementString(@"udpPort", UdpPort.ToString());
42 | writer.WriteElementString(@"tcpPort", TcpPort.ToString());
43 |
44 | writer.WriteEndElement();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Server/Mras/XmlContent/Response.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Xml.Schema;
4 | using System.Xml;
5 |
6 | namespace Mras.XmlContent
7 | {
8 | public class Response
9 | : EnhancedPresence.OutContentBase
10 | {
11 | public Request Request { get; set; }
12 | public Version ServerVersion { get; set; }
13 | public ReasonPhrase ReasonPhrase { get; set; }
14 | public IEnumerable CredentialsResponses { get; set; }
15 |
16 | public override void Generate(XmlWriter writer)
17 | {
18 | writer.WriteRaw("");
19 | writer.WriteStartElement(@"response", @"http://schemas.microsoft.com/2006/09/sip/mrasp");
20 |
21 | if (Request != null)
22 | {
23 | writer.WriteAttributeString(@"requestID", Request.RequestId);
24 | writer.WriteAttributeString(@"version", Request.Version);
25 | }
26 |
27 | writer.WriteAttributeString(@"serverVersion", ServerVersion);
28 |
29 | if (Request != null)
30 | {
31 | writer.WriteAttributeString(@"to", Request.To);
32 | writer.WriteAttributeString(@"from", Request.From);
33 | }
34 |
35 | writer.WriteAttributeString(@"reasonPhrase", Common.ToString(ReasonPhrase));
36 |
37 | if (CredentialsResponses != null)
38 | foreach (var credentialsResponse in CredentialsResponses)
39 | credentialsResponse.Generate(writer);
40 |
41 | writer.WriteEndElement();
42 | }
43 |
44 | public override string OutContentType
45 | {
46 | get { return @"application"; }
47 | }
48 |
49 | public override string OutContentSubtype
50 | {
51 | get { return @"msrtc-media-relay-auth+xml"; }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Server/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Resources;
4 |
5 | [assembly: AssemblyTitle("OfficeSIP Server")]
6 | [assembly: AssemblyDescription("OfficeSIP Server Service")]
7 | [assembly: AssemblyCompany("OfficeSIP Communications")]
8 | [assembly: AssemblyProduct("OfficeSIP Server")]
9 | [assembly: AssemblyCopyright("Copyright © OfficeSIP Communications 2006-2012")]
10 | [assembly: ComVisibleAttribute(false)]
11 | [assembly: NeutralResourcesLanguageAttribute("")]
12 |
13 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Test")]
--------------------------------------------------------------------------------
/Server/Properties/AssemblyInfoVersion.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyVersion( "3.5.*" )]
4 |
--------------------------------------------------------------------------------
/Server/Properties/OfficeSIP Server.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/Properties/OfficeSIP Server.ico
--------------------------------------------------------------------------------
/Server/Restapi/Bnf/api.bat:
--------------------------------------------------------------------------------
1 | BnfToDfa.exe api.bnf api.mrk API
2 | DfaToCSharp.exe api.xml Server.Restapi RestapiUriParser
3 |
4 | move Server.Restapi.dfa ..\
5 | move RestapiUriParser.cs ..\
--------------------------------------------------------------------------------
/Server/Restapi/Bnf/api.bnf:
--------------------------------------------------------------------------------
1 |
2 | API = "/api" (ACCOUNTS / OPTIONS / VERSION / ROLE) [ "?" PARAM *( "&" PARAM ) ]
3 |
4 | VERSION = "/version"
5 |
6 | OPTIONS = "/options"
7 |
8 | ROLE = "/role"
9 |
10 | ACCOUNTS = "/accounts" [ "/" DOMAIN-NAME [ USERZ ]]
11 | DOMAIN-NAME = 1*64 (LOALPHA / DIGIT / safe)
12 |
13 | USERZ = "/userz" [ "/" USERS-ID [ "/" USERNAME ] ]
14 | USERS-ID = 1*4 LOALPHA
15 | USERNAME = 1*32 (LOALPHA / DIGIT / safe)
16 |
17 | PARAM = METHOD-PARAM / TIMESTAMP-PARAM / SIGNATURE-PARAM / AUTHNAME-PARAM / STARTINDEX-PARAM / COUNT-PARAM
18 | METHOD-PARAM = "method=" ( "PUT" / "DELETE" )
19 | TIMESTAMP-PARAM = "time=" 1*16 DIGIT
20 | AUTHNAME-PARAM = "user=" USERNAME
21 | SIGNATURE-PARAM = "sig=" 32 HEX
22 | STARTINDEX-PARAM = "start=" 1*8 DIGIT
23 | COUNT-PARAM = "count=" 1*8 DIGIT
24 |
25 | DIGIT = %x30-39
26 | LOALPHA = %x61-7A
27 | UPALPHA = %x41-5A
28 | ALPHA = UPALPHA / LOALPHA
29 | HEX = "A" / "B" / "C" / "D" / "E" / "F"
30 | / "a" / "b" / "c" / "d" / "e" / "f" / DIGIT
31 | escape = "%" HEX HEX
32 | safe = "-" / "_" / "."
33 |
--------------------------------------------------------------------------------
/Server/Restapi/Bnf/api.mrk:
--------------------------------------------------------------------------------
1 |
2 | API.OPTIONS./options -> Const = BaseAction, Options;
3 |
4 | API.ACCOUNTS./accounts -> Const = BaseAction, Accounts;
5 | API.ACCOUNTS.DOMAIN-NAME -> Range = DomainName;
6 |
7 | API.VERSION./version -> Const = BaseAction, Version;
8 |
9 | API.ROLE./role -> Const = BaseAction, Role;
10 |
11 | API.ACCOUNTS.USERZ./userz -> Const = AccountAction, Userz;
12 | API.ACCOUNTS.USERZ.USERS-ID -> Range = UsersId;
13 | API.ACCOUNTS.USERZ.USERNAME -> Range = Username;
14 |
15 | API.PARAM.METHOD-PARAM.PUT -> Const = Method;
16 | API.PARAM.METHOD-PARAM.DELETE -> Const = Method;
17 | API.PARAM.TIMESTAMP-PARAM.DIGIT -> Decimal = Timestamp, long;
18 | API.PARAM.SIGNATURE-PARAM.HEX -> Range = Signature;
19 | API.PARAM.AUTHNAME-PARAM.USERNAME -> Range = Authname;
20 | API.PARAM.STARTINDEX-PARAM.DIGIT -> Decimal = StartIndex;
21 | API.PARAM.COUNT-PARAM.DIGIT -> Decimal = Count;
22 |
23 |
24 | //API.ACCOUNTS.AD-USERS./ad-users -> Const = AccountAction, AdUsers;
25 | //API.ACCOUNTS.CVS-USERS./csv-users -> Const = AccountAction, CsvUsers;
26 |
27 |
28 | //API.ACCOUNTS./accounts -> Const = BaseAction, Accounts;
29 | //API.ACCOUNTS.HEX -> Hex = AccountId;
30 |
31 | //API.VERSION./version -> Const = BaseAction, Version;
32 |
33 | //API.ROLE./role -> Const = BaseAction, Role;
34 |
35 | //API.ADMINS./admins -> Const = BaseAction, Admins;
36 | //API.ADMINS.USERNAME -> Range = Admin;
37 |
38 | //API.ADMINS./accounts -> Const = AdminAction, Accounts;
39 |
40 | //API.ACCOUNTS.OPTIONS./options -> Const = AccountAction, Options;
41 | //API.ACCOUNTS.AD-USERS./ad-users -> Const = AccountAction, AdUsers;
42 | //API.ACCOUNTS.CVS-USERS./csv-users -> Const = AccountAction, CsvUsers;
43 |
44 | //API.ACCOUNTS.CVS-USERS.USERNAME -> Range = Username;
45 | //API.ACCOUNTS.AD-USERS.USERNAME -> Range = Username;
46 |
47 | //API.PARAM.METHOD-PARAM.PUT -> Const = Method;
48 | //API.PARAM.METHOD-PARAM.DELETE -> Const = Method;
49 | //API.PARAM.TIMESTAMP-PARAM.DIGIT -> Decimal = Timestamp, long;
50 | //API.PARAM.SIGNATURE-PARAM.HEX -> Range = Signature;
51 | //API.PARAM.AUTHNAME-PARAM.USERNAME -> Range = Authname;
52 | //API.PARAM.STARTINDEX-PARAM.DIGIT -> Decimal = StartIndex;
53 | //API.PARAM.COUNT-PARAM.DIGIT -> Decimal = Count;
54 |
--------------------------------------------------------------------------------
/Server/Restapi/JsonContractResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Serialization;
5 | using Sip.Server.Users;
6 | using Sip.Server.Accounts;
7 |
8 | namespace Server.Restapi
9 | {
10 | public class JsonContractResolver : CamelCasePropertyNamesContractResolver
11 | {
12 | protected override IList CreateProperties(Type type, MemberSerialization memberSerialization)
13 | {
14 | var properties = base.CreateProperties(type, memberSerialization);
15 |
16 | //if (type == typeof(Account) || type.BaseType == typeof(BaseUser))
17 | {
18 | for (int i = properties.Count - 1; i >= 0; i--)
19 | {
20 | if (properties[i].PropertyName == "password")
21 | properties.RemoveAt(i);
22 | }
23 | }
24 |
25 | return properties;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Server/Restapi/Server.Restapi.dfa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/Restapi/Server.Restapi.dfa
--------------------------------------------------------------------------------
/Server/Rtp/DtmfEventMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Rtp.Payload
5 | {
6 | class DtmfEventMessage
7 | {
8 | // 0 1 2 3
9 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11 | // | event |E|R| volume | duration |
12 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13 |
14 | public const int Length = 4;
15 |
16 | public byte Event { get; set; }
17 | public bool End { get; set; }
18 | public int Volume { get; set; }
19 | public int Duration { get; set; }
20 |
21 | public static DtmfEventMessage[] Parse(byte[] bytes, int startIndex, int length)
22 | {
23 | if ((length - startIndex) % Length != 0)
24 | throw new ParseException(@"DtmfEventMessage: Invalid message length");
25 | int count = (length - startIndex) / Length;
26 |
27 | var messages = new DtmfEventMessage[count];
28 |
29 | for (int i = 0; i < count; i++)
30 | {
31 | messages[i] = new DtmfEventMessage();
32 | messages[i].Parse2(bytes, startIndex, length);
33 |
34 | startIndex += Length;
35 | }
36 |
37 | return messages;
38 | }
39 |
40 | protected void Parse2(byte[] bytes, int startIndex, int length)
41 | {
42 | Event = bytes[startIndex++];
43 |
44 | End = (bytes[startIndex] & 0x80) != 0;
45 | Volume = bytes[startIndex] & 0x3f;
46 | startIndex++;
47 |
48 | Duration = bytes.BigendianToUInt16(ref startIndex);
49 | }
50 |
51 | public void GetBytes(byte[] bytes, int startIndex)
52 | {
53 | throw new NotImplementedException();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Server/Rtp/JitterBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Rtp
5 | {
6 | class JitterBuffer
7 | {
8 | private List messages;
9 | private int dequeuedSequenceNumber;
10 | private CalculateNtpTimestampDelegate calculateNtpTimestampDelegate;
11 |
12 | public delegate UInt64 CalculateNtpTimestampDelegate(RtpMessage message, int rate);
13 |
14 | public JitterBuffer(CalculateNtpTimestampDelegate calculateNtpTimestampDelegate1)
15 | {
16 | messages = new List();
17 | dequeuedSequenceNumber = -1;
18 | calculateNtpTimestampDelegate = calculateNtpTimestampDelegate1;
19 | }
20 |
21 | public int Count
22 | {
23 | get
24 | {
25 | return messages.Count;
26 | }
27 | }
28 |
29 | public int Rate
30 | {
31 | get;
32 | set;
33 | }
34 |
35 | public void Insert(RtpMessage message)
36 | {
37 | if (message.SequenceNumber > dequeuedSequenceNumber)
38 | {
39 | int index = messages.FindIndex(
40 | (oldMessage) => { return message.SequenceNumber <= oldMessage.SequenceNumber; });
41 |
42 | if (index < 0)
43 | {
44 | messages.Add(message);
45 | }
46 | else
47 | {
48 | if (messages[index].SequenceNumber != message.SequenceNumber)
49 | messages.Insert(index, message);
50 | }
51 | }
52 | }
53 |
54 | public RtpMessage DequeueAvailable()
55 | {
56 | return DequeueAvailable(UInt64.MaxValue);
57 | }
58 |
59 | public bool DequeueAvailable(UInt64 maxNtpTimestamp, out RtpMessage message)
60 | {
61 | message = DequeueAvailable(maxNtpTimestamp);
62 |
63 | return message != null;
64 | }
65 |
66 | public RtpMessage DequeueAvailable(UInt64 maxNtpTimestamp)
67 | {
68 | if (messages.Count > 0)
69 | {
70 | var message = messages[0];
71 |
72 | if (calculateNtpTimestampDelegate != null)
73 | message.NtpTimestamp = calculateNtpTimestampDelegate(message, Rate);
74 |
75 | if (message.NtpTimestamp <= maxNtpTimestamp)
76 | {
77 | messages.RemoveAt(0);
78 | dequeuedSequenceNumber = message.SequenceNumber;
79 |
80 | return message;
81 | }
82 | }
83 |
84 | return null;
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Server/Rtp/ParseException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Rtp
4 | {
5 | class ParseException
6 | : Exception
7 | {
8 | public ParseException(string message)
9 | : base(message)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Server/Rtp/RtpReceiver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.NtpTimestamp;
4 |
5 | namespace Rtp
6 | {
7 | class RtpReceiver
8 | {
9 | private List ssrcs = new List();
10 | private int[] payloadTypes;
11 | private int[] payloadRates;
12 |
13 | public RtpReceiver(int[] payloadTypes1, int[] payloadRates1)
14 | {
15 | ssrcs = new List();
16 | payloadTypes = payloadTypes1;
17 | payloadRates = payloadRates1;
18 | }
19 |
20 | public IEnumerable Ssrcs
21 | {
22 | get
23 | {
24 | foreach (var ssrc in ssrcs)
25 | yield return ssrc;
26 | }
27 | }
28 |
29 | public Ssrc FindSsrc(UInt32 ssrcId)
30 | {
31 | foreach (var ssrc in ssrcs)
32 | if (ssrc.SsrcId == ssrcId)
33 | return ssrc;
34 |
35 | return null;
36 | }
37 |
38 | protected Ssrc AddSsrc(UInt32 ssrcId, UInt64 ntpTimestamp, UInt32 rtpTimestamp)
39 | {
40 | var ssrc = new Ssrc(payloadTypes, payloadRates)
41 | {
42 | SsrcId = ssrcId,
43 | };
44 | ssrc.SetBaseTimestamp(ntpTimestamp, rtpTimestamp);
45 |
46 | ssrcs.Add(ssrc);
47 |
48 | return ssrc;
49 | }
50 |
51 | public void InsertMessage(RtpMessage message)
52 | {
53 | var ssrc = FindSsrc(message.Ssrc);
54 | if (ssrc == null)
55 | ssrc = AddSsrc(message.Ssrc, 0x000fffffffffffff, message.Timestamp);
56 |
57 | ssrc.InsertMessage(message);
58 | }
59 |
60 | public void ProcessMessages(IEnumerable messages)
61 | {
62 | foreach (var message in messages)
63 | {
64 | if (message.MessageType == RtcpMessageType.SenderReport)
65 | {
66 | var ssrc = FindSsrc(message.SenderReport.Ssrc);
67 |
68 | if (ssrc == null)
69 | ssrc = AddSsrc(message.SenderReport.Ssrc, message.SenderReport.NtpTimestamp, message.SenderReport.RtpTimestamp);
70 | else
71 | ssrc.SetBaseTimestamp(message.SenderReport.NtpTimestamp, message.SenderReport.RtpTimestamp);
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Server/Rtp/Ssrc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.NtpTimestamp;
4 |
5 | namespace Rtp
6 | {
7 | class Ssrc
8 | {
9 | private UInt64 baseNtpTimestamp;
10 | private UInt32 baseRtpTimestamp;
11 | private Int32 baseTickCount;
12 |
13 | public Ssrc(int[] payloadTypes, int[] payloadRates)
14 | {
15 | JitterBuffers = new JitterBuffer[128];
16 |
17 | for (int i = 0; i < payloadTypes.Length; i++)
18 | JitterBuffers[payloadTypes[i]] = new JitterBuffer(GetNtpTimestamp)
19 | {
20 | Rate = payloadRates[i],
21 | };
22 | }
23 |
24 | public UInt32 SsrcId
25 | {
26 | get;
27 | set;
28 | }
29 |
30 | public JitterBuffer[] JitterBuffers
31 | {
32 | get;
33 | private set;
34 | }
35 |
36 | public void SetBaseTimestamp(UInt64 ntp, UInt32 rtp)
37 | {
38 | baseNtpTimestamp = ntp;
39 | baseRtpTimestamp = rtp;
40 | baseTickCount = Environment.TickCount;
41 | }
42 |
43 | public UInt64 GetCurrentNtpTimestamp(int millisecondsOffset)
44 | {
45 | int milliseconds = Environment.TickCount - baseTickCount + millisecondsOffset;
46 |
47 | return (milliseconds > 0) ?
48 | baseNtpTimestamp + milliseconds.MillisecondsToNtpTimestamp() :
49 | baseNtpTimestamp - (-milliseconds).MillisecondsToNtpTimestamp();
50 | }
51 |
52 | public UInt64 GetNtpTimestamp(RtpMessage message)
53 | {
54 | return GetNtpTimestamp(message, JitterBuffers[message.PayloadType].Rate);
55 | }
56 |
57 | public UInt64 GetNtpTimestamp(RtpMessage message, int rate)
58 | {
59 | if (rate != 0)
60 | {
61 | UInt32 delta1 = message.Timestamp - baseRtpTimestamp;
62 | UInt32 delta2 = baseRtpTimestamp - message.Timestamp;
63 |
64 | if (delta1 <= delta2)
65 | return baseNtpTimestamp +
66 | ((UInt64)delta1 << 32) / (UInt64)rate;
67 | else
68 | return baseNtpTimestamp -
69 | ((UInt64)delta2 << 32) / (UInt64)rate;
70 | }
71 |
72 | return 0;
73 | }
74 |
75 | public void InsertMessage(RtpMessage message)
76 | {
77 | if (JitterBuffers[message.PayloadType] != null)
78 | JitterBuffers[message.PayloadType].Insert(message);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Server/Sdp/Helpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Sdp
4 | {
5 | class Helpers
6 | {
7 | public static ArraySegment CutCandidates(ArraySegment content)
8 | {
9 | var str = System.Text.Encoding.UTF8.GetString(content.Array, content.Offset, content.Count);
10 |
11 | for (; ; )
12 | {
13 | int begin = str.IndexOf("a=candidate:");
14 | if (begin < 0)
15 | break;
16 | int end = str.IndexOf("\r\n", begin);
17 | if (end < 0)
18 | break;
19 |
20 | str = str.Remove(begin, end - begin + 2);
21 | }
22 |
23 | return new ArraySegment(System.Text.Encoding.UTF8.GetBytes(str));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Server/Service.cs:
--------------------------------------------------------------------------------
1 | using System.ServiceProcess;
2 | using System.Threading;
3 |
4 | namespace Sip.Server
5 | {
6 | class Service : ServiceBase
7 | {
8 | public const string Name = "OfficeSIP Server";
9 | private Server server;
10 |
11 | public Service()
12 | {
13 | this.ServiceName = Name;
14 | }
15 |
16 | public void Emulate()
17 | {
18 | server = new Server();
19 | Thread.Sleep(Timeout.Infinite);
20 | server.Dispose();
21 | server = null;
22 | }
23 |
24 | protected override void OnStart(string[] args)
25 | {
26 | RequestAdditionalTime(2 * 60 * 1000);
27 | server = new Server();
28 | }
29 | protected override void OnStop()
30 | {
31 | RequestAdditionalTime(30 * 1000);
32 | OnShutdown();
33 | }
34 | protected override void OnShutdown()
35 | {
36 | server.Dispose();
37 | server = null;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Server/Simple/Publication.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Collections.Generic;
4 | using ThreadSafe = System.Collections.Generic.ThreadSafe;
5 |
6 | namespace Sip.Simple
7 | {
8 | sealed class Publication
9 | {
10 | private readonly ThreadSafe.List subscriptions;
11 | private readonly PresenceDocument document;
12 |
13 | public Publication(string aor)
14 | {
15 | document = new PresenceDocument(aor);
16 | subscriptions = new ThreadSafe.List(
17 | new List());
18 | }
19 |
20 | public ThreadSafe.List Subscriptions
21 | {
22 | get { return subscriptions; }
23 | }
24 |
25 | public PresenceDocument Document
26 | {
27 | get { return document; }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Server/Simple/Subscription.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Simple
4 | {
5 | struct Subscription
6 | : IEquatable
7 | {
8 | private int expiresTickCount;
9 |
10 | public Subscription(string id, int expires)
11 | {
12 | Id = id;
13 | expiresTickCount = unchecked(Environment.TickCount + expires * 1000);
14 | }
15 |
16 | public readonly string Id;
17 |
18 | public int Expires
19 | {
20 | get
21 | {
22 | int expires = (expiresTickCount - Environment.TickCount) / 1000;
23 | return (expires >= 0) ? expires : 0;
24 | }
25 | }
26 |
27 | public bool Equals(Subscription other)
28 | {
29 | return Id.Equals(other.Id);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Server/Tools/Bigendian.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace System
4 | {
5 | static class Bigendian
6 | {
7 | public static UInt16 BigendianToUInt16(this byte[] bytes, int startIndex)
8 | {
9 | UInt16 result = 0;
10 |
11 | result |= bytes[startIndex];
12 | result <<= 8;
13 | result |= bytes[startIndex + 1];
14 |
15 | return result;
16 | }
17 |
18 | public static UInt32 BigendianToUInt32(this byte[] bytes, int startIndex)
19 | {
20 | UInt32 result = 0;
21 |
22 | result |= bytes[startIndex];
23 | result <<= 8;
24 | result |= bytes[startIndex + 1];
25 | result <<= 8;
26 | result |= bytes[startIndex + 2];
27 | result <<= 8;
28 | result |= bytes[startIndex + 3];
29 |
30 | return result;
31 | }
32 |
33 | public static UInt32 BigendianToUInt24(this byte[] bytes, int startIndex)
34 | {
35 | UInt32 result = 0;
36 |
37 | result |= bytes[startIndex];
38 | result <<= 8;
39 | result |= bytes[startIndex + 1];
40 | result <<= 8;
41 | result |= bytes[startIndex + 2];
42 |
43 | return result;
44 | }
45 |
46 | public static UInt16 BigendianToUInt16(this byte[] bytes, ref int startIndex)
47 | {
48 | UInt16 result = BigendianToUInt16(bytes, startIndex);
49 | startIndex += sizeof(UInt16);
50 | return result;
51 | }
52 |
53 | public static UInt32 BigendianToUInt32(this byte[] bytes, ref int startIndex)
54 | {
55 | UInt32 result = BigendianToUInt32(bytes, startIndex);
56 | startIndex += sizeof(UInt32);
57 | return result;
58 | }
59 |
60 | public static UInt32 BigendianToUInt24(this byte[] bytes, ref int startIndex)
61 | {
62 | UInt32 result = BigendianToUInt24(bytes, startIndex);
63 | startIndex += sizeof(UInt32) - sizeof(Byte);
64 | return result;
65 | }
66 |
67 | private static byte[] Correct(byte[] data)
68 | {
69 | if (BitConverter.IsLittleEndian)
70 | Array.Reverse(data);
71 | return data;
72 | }
73 |
74 | public static byte[] GetBigendianBytes(this UInt32 value)
75 | {
76 | return Correct(BitConverter.GetBytes(value));
77 | }
78 |
79 | public static byte[] GetBigendianBytes(this UInt16 value)
80 | {
81 | return Correct(BitConverter.GetBytes(value));
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Server/Tools/BitTwiddling.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace System
4 | {
5 | ///
6 | /// http://graphics.stanford.edu/~seander/bithacks.html
7 | ///
8 | class BitTwiddling
9 | {
10 | private static readonly int[] multiplyDeBruijnBitPosition = new int[32] { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
11 |
12 | ///
13 | /// Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup
14 | ///
15 | public static int GetLog2(int value)
16 | {
17 | value |= value >> 1;
18 | value |= value >> 2;
19 | value |= value >> 4;
20 | value |= value >> 8;
21 | value |= value >> 16;
22 |
23 | return multiplyDeBruijnBitPosition[unchecked(((uint)value * 0x07C4ACDDU) >> 27)];
24 | }
25 |
26 | public static long Pack(int hiInt, int loInt)
27 | {
28 | unchecked
29 | {
30 | ulong packed;
31 |
32 | packed = (ulong)(uint)hiInt;
33 | packed <<= 32;
34 | packed |= (ulong)(uint)loInt;
35 |
36 | return (long)packed;
37 | }
38 | }
39 |
40 | public static void Unpack(long value, out int hiInt, out int loInt)
41 | {
42 | unchecked
43 | {
44 | loInt = (int)value;
45 |
46 | value >>= 32;
47 | hiInt = (int)value;
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Server/Tools/ByteArray.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Base.Message;
3 | using Sip.Message;
4 |
5 | namespace Sip.Tools
6 | {
7 | public static class ByteArray
8 | {
9 | public static int CopyFrom(this byte[] bytes, ByteArrayPart part, int offset)
10 | {
11 | int length = part.Length;
12 |
13 | if (length > 0)
14 | Buffer.BlockCopy(part.Bytes, part.Begin, bytes, offset, length);
15 |
16 | return offset + length;
17 | }
18 |
19 | public static int CopyFrom(this byte[] bytes, int value, int offset)
20 | {
21 | bytes[offset++] = (byte)(value >> 24);
22 | bytes[offset++] = (byte)(value >> 16);
23 | bytes[offset++] = (byte)(value >> 08);
24 | bytes[offset++] = (byte)(value >> 00);
25 |
26 | return offset;
27 | }
28 |
29 | public static bool IsEqualValue(this byte[] x, byte[] y)
30 | {
31 | if (x.Length != y.Length)
32 | return false;
33 |
34 | for (int i = 0; i < x.Length; i++)
35 | if (x[i] != y[i])
36 | return false;
37 |
38 | return true;
39 | }
40 |
41 | public static int GetValueHashCode(this byte[] bytes)
42 | {
43 | int value = 0;
44 | int maxOffset = bytes.Length - 1;
45 |
46 | if (maxOffset >= 0)
47 | {
48 | for (int i = 0; i <= 3; i++)
49 | {
50 | value <<= 8;
51 | value |= bytes[maxOffset * i / 3];
52 | }
53 | }
54 |
55 | return value;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Server/Tools/HashAlgorithmHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Message;
3 | using Base.Message;
4 |
5 | namespace System.Security.Cryptography
6 | {
7 | public static class HashAlgorithmHelpers
8 | {
9 | public static void TransformBlock(this ICryptoTransform hash, ByteArrayPart part)
10 | {
11 | hash.TransformBlock(part.Bytes, part.Offset, part.Length, null, 0);
12 | }
13 |
14 | public static void TransformBlock(this ICryptoTransform hash, byte[] bytes)
15 | {
16 | hash.TransformBlock(bytes, 0, bytes.Length, null, 0);
17 | }
18 |
19 | public static void TransformFinalBlock(this ICryptoTransform hash, ByteArrayPart part)
20 | {
21 | hash.TransformFinalBlock(part.Bytes, part.Offset, part.Length);
22 | }
23 |
24 | public static void TransformFinalBlock(this ICryptoTransform hash, byte[] bytes)
25 | {
26 | hash.TransformFinalBlock(bytes, 0, bytes.Length);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Server/Tools/IpEndPointExt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using Sip.Message;
4 | using SocketServers;
5 |
6 | static class IpEndPointExt
7 | {
8 | public static bool IsTransportUnreliable(this ServerEndPoint endPoint)
9 | {
10 | return endPoint.Protocol == ServerProtocol.Udp;
11 | }
12 |
13 | public static ServerProtocol ToServerProtocol(this Transports transport)
14 | {
15 | switch (transport)
16 | {
17 | case Transports.Udp:
18 | return ServerProtocol.Udp;
19 | case Transports.Tcp:
20 | case Transports.Ws:
21 | return ServerProtocol.Tcp;
22 | case Transports.Tls:
23 | case Transports.Wss:
24 | return ServerProtocol.Tls;
25 | default:
26 | throw new NotImplementedException("Can not convert transport " + transport.ToString() + " to protocol.");
27 | }
28 |
29 | throw new InvalidCastException();
30 | }
31 |
32 | public static Transports ToTransport(this ServerProtocol protocol)
33 | {
34 | switch (protocol)
35 | {
36 | case ServerProtocol.Udp:
37 | return Transports.Udp;
38 | case ServerProtocol.Tcp:
39 | return Transports.Tcp;
40 | case ServerProtocol.Tls:
41 | return Transports.Tls;
42 | }
43 |
44 | throw new InvalidCastException();
45 | }
46 |
47 | public static void CopyFrom(this IPEndPoint to, IPEndPoint from)
48 | {
49 | to.Address = from.Address;
50 | to.Port = from.Port;
51 | }
52 |
53 | public static IPEndPoint MakeCopy(this IPEndPoint from)
54 | {
55 | return new IPEndPoint(from.Address, from.Port);
56 | }
57 |
58 | public static bool IsEqual(this IPEndPoint ip1, IPEndPoint ip2)
59 | {
60 | return
61 | ip1.AddressFamily == ip2.AddressFamily &&
62 | ip1.Port == ip2.Port &&
63 | ip1.Address.Equals(ip2.Address);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Server/Tools/NtpTimestamp.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace System.NtpTimestamp
4 | {
5 | static class NtpTimestamp
6 | {
7 | public const UInt64 TicksPerSecond = 10000000;
8 | public readonly static DateTime NtpZeroDateTime = new DateTime(1900, 1, 1);
9 |
10 | public static UInt64 ToNtpTimestamp(this DateTime dateTime)
11 | {
12 | UInt64 ticks = (UInt64)(dateTime - NtpZeroDateTime).Ticks;
13 |
14 | UInt64 seconds = ticks / TicksPerSecond;
15 | UInt64 fractions = ((ticks % TicksPerSecond) << 32) / TicksPerSecond;
16 |
17 | return (seconds << 32) | fractions;
18 | }
19 |
20 | public static DateTime NtpTimestampToUtcDateTime(this UInt64 timestamp)
21 | {
22 | UInt64 seconds = timestamp >> 32;
23 | UInt64 fractions = timestamp & 0xffffffffL;
24 |
25 | UInt64 ticks = seconds * TicksPerSecond + ((fractions * TicksPerSecond) >> 32);
26 |
27 | return NtpZeroDateTime.AddTicks((Int64)ticks);
28 | }
29 |
30 | public static UInt64 MillisecondsToNtpTimestamp(this Int32 milliseconds)
31 | {
32 | #if DEBUG
33 | if (milliseconds < 0)
34 | throw new Exception();
35 | #endif
36 |
37 | UInt64 seconds = (UInt64)milliseconds / 1000;
38 | UInt64 fractions = (((UInt64)milliseconds % 1000) << 32) / 1000;
39 |
40 | return (seconds << 32) | fractions;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Server/Tools/TupleStruct.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Server
4 | {
5 | public struct TupleStruct
6 | : IEquatable>
7 | {
8 | private readonly T1 First;
9 | private readonly T2 Second;
10 |
11 | public TupleStruct(T1 f, T2 s)
12 | {
13 | First = f;
14 | Second = s;
15 | }
16 |
17 | public bool Equals(TupleStruct other)
18 | {
19 | return First.Equals(other.First) && Second.Equals(other.Second);
20 | }
21 |
22 | public override bool Equals(object obj)
23 | {
24 | if (obj is TupleStruct)
25 | return this.Equals((TupleStruct)obj);
26 | else
27 | return false;
28 | }
29 |
30 | public override int GetHashCode()
31 | {
32 | return First.GetHashCode() ^ Second.GetHashCode();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Server/Transaction/GeneralVerifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Message;
3 | using Base.Message;
4 |
5 | namespace Sip.Server
6 | {
7 | class GeneralVerifier
8 | {
9 | public enum Errors
10 | {
11 | None,
12 | MandatoryHeaderAbsent,
13 | HeaderDuplication,
14 | SipVersionNotSupported,
15 | ToTagAbsent,
16 | }
17 |
18 | public struct Result
19 | {
20 | private static readonly ByteArrayPart[] errorTexts;
21 |
22 | static Result()
23 | {
24 | errorTexts = new ByteArrayPart[]
25 | {
26 | new ByteArrayPart("No errors"),
27 | new ByteArrayPart("Mandatory header is absent or invalid"),
28 | new ByteArrayPart("Header duplication"),
29 | new ByteArrayPart("SIP version not supported"),
30 | new ByteArrayPart("To tag is absent"),
31 | };
32 |
33 | var values = Enum.GetValues(typeof(Errors));
34 | if (errorTexts.Length != values.Length)
35 | throw new InvalidProgramException(@"GeneralVerifier::Result static constructor");
36 | }
37 |
38 | public Errors Error;
39 | public HeaderNames HeaderName;
40 |
41 | public ByteArrayPart Message
42 | {
43 | get
44 | {
45 | return errorTexts[(int)Error];
46 | }
47 | }
48 | }
49 |
50 | public Result Validate(IncomingMessage message)
51 | {
52 | if (message.Reader.SipVersion != 20)
53 | return new Result() { Error = Errors.SipVersionNotSupported, };
54 |
55 | var absent = message.Reader.ValidateMandatoryHeaders();
56 | if (absent != HeaderNames.None)
57 | return new Result() { Error = Errors.MandatoryHeaderAbsent, HeaderName = absent, };
58 |
59 | // callcentric does not send to tag in the NOTIFY
60 | //if (message.Reader.From.Tag.IsNotEmpty == false)
61 | // return new Result() { Error = Errors.ToTagAbsent, };
62 |
63 | //var duplicate = message.Reader.ValidateHeadersDuplication();
64 | //if (duplicate != HeaderNames.None)
65 | // return new Result() { Error = Errors.HeaderDuplication, HeaderName = duplicate, };
66 |
67 | return new Result();
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Server/Transaction/IncomingMessageEx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using Sip.Message;
5 | using SocketServers;
6 |
7 | namespace Sip.Server
8 | {
9 | public struct IncomingMessageEx
10 | {
11 | public IncomingMessageEx(IncomingMessage source, int transactionId)
12 | {
13 | TransactionId = transactionId;
14 |
15 | ConnectionAddresses = source.ConnectionAddresses;
16 |
17 | Reader = source.Reader;
18 |
19 | Headers = source.Header;
20 | Content = source.Content;
21 | }
22 |
23 | public readonly int TransactionId;
24 |
25 | public readonly ConnectionAddresses ConnectionAddresses;
26 |
27 | public readonly SipMessageReader Reader;
28 | public readonly ArraySegment Headers;
29 | public readonly ArraySegment Content;
30 |
31 | public BufferHandle DetachBuffers()
32 | {
33 | return TransportLayer.DetachBuffers();
34 | }
35 |
36 | #region Accessors to ConnectionAddresses fields
37 |
38 | public Transports Transport
39 | {
40 | get { return ConnectionAddresses.Transport; }
41 | }
42 |
43 | public IPEndPoint LocalEndPoint
44 | {
45 | get { return ConnectionAddresses.LocalEndPoint; }
46 | }
47 |
48 | public IPEndPoint RemoteEndPoint
49 | {
50 | get { return ConnectionAddresses.RemoteEndPoint; }
51 | }
52 |
53 | public int ConnectionId
54 | {
55 | get { return ConnectionAddresses.ConnectionId; }
56 | }
57 |
58 | public bool IsTransportUnreliable
59 | {
60 | get { return ConnectionAddresses.Transport == Transports.Udp; }
61 | }
62 |
63 | #endregion
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Server/Transaction/ProducedRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using Sip.Message;
4 | using SocketServers;
5 |
6 | namespace Sip.Server
7 | {
8 | sealed class ProducedRequest
9 | {
10 | public int Index { get; set; }
11 | public Action IncomingResponse { get; set; }
12 | public Action ProduceAck { get; set; }
13 | public Action TransportError { get; set; }
14 | public BaseTransactionUser TransactionUser { get; private set; }
15 |
16 | public ProducedRequest(BaseTransactionUser transactionUser)
17 | {
18 | TransactionUser = transactionUser;
19 | IncomingResponse = None;
20 | TransportError = None;
21 | ProduceAck = None;
22 | }
23 |
24 | public void OnIncomingResponse(IncomingMessageEx message)
25 | {
26 | IncomingResponse(message);
27 | }
28 |
29 | //public int GetTransactionId(Methods method)
30 | //{
31 | // return TransactionUser.GetTransactionId(method);
32 | //}
33 |
34 | public void SendRequest(ConnectionAddresses connectionAddresses, SipMessageWriter writer, int transactionId, int userData)
35 | {
36 | TransactionUser.SendRequest(Index, connectionAddresses, transactionId, writer, userData);
37 | }
38 |
39 | public void SendRequest(ConnectionAddresses connectionAddresses, SipMessageWriter writer, int transactionId)
40 | {
41 | TransactionUser.SendRequest(Index, connectionAddresses, transactionId, writer, 0);
42 | }
43 |
44 | public void SendRequest(Transports transport, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, int connectionId, SipMessageWriter writer, int transactionId)
45 | {
46 | TransactionUser.SendRequest(Index,
47 | new ConnectionAddresses(transport, localEndPoint, remoteEndPoint, connectionId), transactionId, writer, 0);
48 | }
49 |
50 | private static void None(IncomingMessageEx message) { }
51 | private static void None(int transactionId, int userData) { }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/ErrorTU.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sip.Message;
4 |
5 | namespace Sip.Server
6 | {
7 | class ErrorTU
8 | : BaseTransactionUser
9 | {
10 | public override IEnumerable GetAcceptedRequests()
11 | {
12 | foreach (Methods method in Enum.GetValues(typeof(Methods)))
13 | if (method != Methods.None)
14 | yield return new AcceptedRequest(this)
15 | {
16 | Method = method,
17 | IsAcceptedRequest = (reader) => true,
18 | IncomingRequest = ProccessRequest,
19 | AuthorizationMode = AuthorizationMode.Disabled,
20 | };
21 | }
22 |
23 | private void ProccessRequest(AcceptedRequest tu, IncomingMessageEx request)
24 | {
25 | var writer = GetWriter();
26 |
27 | writer.WriteStatusLine(StatusCodes.NotImplemented);
28 | writer.CopyViaToFromCallIdRecordRouteCSeq(request.Reader, StatusCodes.NotImplemented);
29 | writer.WriteContentLength(0);
30 | writer.WriteCRLF();
31 |
32 | tu.SendResponse(request, writer);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/MrasTU.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Threading;
4 | using System.Collections.Generic;
5 | using Sip.Message;
6 | using Base.Message;
7 | using Sip.Server.Accounts;
8 | using SocketServers;
9 | using Mras;
10 |
11 | namespace Sip.Server
12 | {
13 | sealed class MrasTU
14 | : BaseTransactionUser
15 | {
16 | private readonly ByteArrayPart type;
17 | private readonly ByteArrayPart subtype;
18 | private readonly byte[] userPrefix;
19 | private readonly Mras1 mras;
20 |
21 | public MrasTU(Mras1 mras)
22 | {
23 | this.type = new ByteArrayPart("application");
24 | this.subtype = new ByteArrayPart("msrtc-media-relay-auth+xml");
25 | this.userPrefix = Encoding.UTF8.GetBytes("MRASLoc.");
26 |
27 | this.mras = mras;
28 | }
29 |
30 | public override IEnumerable GetAcceptedRequests()
31 | {
32 | yield return new AcceptedRequest(this)
33 | {
34 | Method = Methods.Servicem,
35 | IsAcceptedRequest = (reader) => IsAccepted(reader),
36 | IncomingRequest = ProccessService,
37 | };
38 | }
39 |
40 | public bool IsAccepted(SipMessageReader reader)
41 | {
42 | return
43 | reader.ContentType.Type.Equals(type) &&
44 | reader.ContentType.Subtype.Equals(subtype) &&
45 | reader.To.AddrSpec.User.StartsWith(userPrefix);
46 | }
47 |
48 | private void ProccessService(AcceptedRequest tu, IncomingMessageEx request)
49 | {
50 | var writer = GetWriter();
51 |
52 | try
53 | {
54 | var outContent = mras.ProcessRequest(request.Content);
55 |
56 | writer.WriteStatusLine(StatusCodes.OK);
57 | writer.CopyViaToFromCallIdRecordRouteCSeq(request.Reader, StatusCodes.OK);
58 | writer.WriteContentType(type, subtype);
59 | writer.WriteCustomHeaders();
60 | writer.WriteContentLength();
61 | writer.WriteCRLF();
62 |
63 | writer.Write(outContent.GenerateToByteArray());
64 | writer.RewriteContentLength();
65 | }
66 | catch (MrasException)
67 | {
68 | writer.WriteResponse(request.Reader, StatusCodes.BadRequest);
69 | }
70 |
71 | tu.SendResponse(request, writer);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/OptionsTU.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sip;
4 | using Sip.Simple;
5 | using Sip.Message;
6 | using SocketServers;
7 |
8 | namespace Sip.Server
9 | {
10 | class OptionsTU
11 | : BaseTransactionUser
12 | {
13 | public static readonly Methods[] AllowMethods = new Methods[] { Methods.Registerm, Methods.Invitem,
14 | Methods.Ackm, Methods.Cancelm, Methods.Byem, Methods.Optionsm, Methods.Subscribem,
15 | Methods.Notifym, Methods.Publishm, Methods.Servicem, };
16 |
17 |
18 | public override IEnumerable GetAcceptedRequests()
19 | {
20 | yield return new AcceptedRequest(this)
21 | {
22 | Method = Methods.Optionsm,
23 | IsAcceptedRequest = (reader) => true,
24 | AuthorizationMode = AuthorizationMode.Disabled,
25 | IncomingRequest = ProccessOptions,
26 | };
27 | }
28 |
29 | private void ProccessOptions(AcceptedRequest tu, IncomingMessageEx request)
30 | {
31 | var writer = GetWriter();
32 |
33 | writer.WriteStatusLine(StatusCodes.OK);
34 | writer.CopyViaToFromCallIdRecordRouteCSeq(request.Reader, StatusCodes.OK); // statusCode есть во writer'е!!!!!!
35 | writer.WriteAllow(AllowMethods);
36 | writer.WriteCRLF();
37 |
38 | tu.SendResponse(request, writer);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/ProxyServerTU/BaseProxie.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Message;
3 |
4 | namespace Sip.Server
5 | {
6 | class BaseProxie
7 | {
8 | public BaseProxie(int transactionId)
9 | {
10 | TransactionId = transactionId;
11 | }
12 |
13 | public int TransactionId { get; private set; }
14 | public bool IsFinalReceived { get; set; }
15 | public bool IsCancelSent { get; set; }
16 | public int TimerC { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/ProxyServerTU/IProxie.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Message;
3 |
4 | namespace Sip.Server
5 | {
6 | interface IProxie
7 | {
8 | int TransactionId { get; }
9 | ConnectionAddresses ToConnectionAddresses { get; }
10 | bool IsFinalReceived { get; set; }
11 | bool IsCancelSent { get; set; }
12 | int TimerC { get; set; }
13 |
14 | void GenerateForwardedRequest(SipMessageWriter writer, SipMessageReader reader, ArraySegment content, ConnectionAddresses ca, int serverTransactionId);
15 | void GenerateForwardedResponse(SipMessageWriter writer, SipMessageReader reader, ArraySegment content, ConnectionAddresses ca);
16 | void GenerateCancel(SipMessageWriter writer, SipMessageReader message);
17 | void GenerateAck(SipMessageWriter writer, SipMessageReader message);
18 |
19 | bool CanFork(SipMessageReader response);
20 | IProxie Fork(int transactionId);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/ProxyServerTU/ProxieFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Message;
3 | using Base.Message;
4 |
5 | namespace Sip.Server
6 | {
7 | static class ProxieFactory
8 | {
9 | public static IProxie Create(int transactionId, LocationService.Binding binding)
10 | {
11 | return new LocalProxie(binding, transactionId);
12 | }
13 |
14 | public static IProxie Create(int transactionId, Trunk trunk)
15 | {
16 | return new LocalTrunkProxie(transactionId, trunk);
17 | }
18 |
19 | public static IProxie Create(int transactionId, Trunk trunk, ByteArrayPart toTag)
20 | {
21 | int tag;
22 | Dialog dialog1 = null;
23 | if (HexEncoding.TryParseHex8(toTag, out tag))
24 | dialog1 = trunk.GetDialog1(tag);
25 |
26 | return (dialog1 == null) ? null : new TrunkDialogProxie(transactionId, trunk, tag, dialog1);
27 | }
28 |
29 | public static IProxie Create(int transactionId, Trunk trunk, LocationService.Binding binding)
30 | {
31 | return new TrunkLocalProxie(transactionId, trunk, binding);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Server/TransactionUsers/ProxyServerTU/RequestProxyFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using Sip.Message;
5 |
6 | namespace Sip.Server
7 | {
8 | partial class ProxyServerTU
9 | {
10 | struct RequestProxyFactory
11 | {
12 | private readonly ProxyServerTU parent;
13 | private readonly IncomingMessageEx request;
14 |
15 | private RequestProxy requestProxy;
16 |
17 | public RequestProxyFactory(ProxyServerTU parent, IncomingMessageEx request)
18 | {
19 | this.parent = parent;
20 | this.request = request;
21 |
22 | this.requestProxy = null;
23 | }
24 |
25 | public void Forward(IProxie proxie)
26 | {
27 | if (proxie != null)
28 | {
29 | CreateLockedRequestProxy();
30 | parent.ForwardRequest(proxie, requestProxy, request.Reader);
31 | }
32 | }
33 |
34 | public bool HasValue
35 | {
36 | get { return requestProxy != null; }
37 | }
38 |
39 | public RequestProxy Value
40 | {
41 | get { return requestProxy; }
42 | }
43 |
44 | public void SetAllRequestsSent()
45 | {
46 | if (requestProxy != null)
47 | requestProxy.SetAllRequestsSent();
48 | }
49 |
50 | public void Release()
51 | {
52 | if (requestProxy != null)
53 | Monitor.Exit(requestProxy);
54 | }
55 |
56 | private void CreateLockedRequestProxy()
57 | {
58 | if (requestProxy == null)
59 | {
60 | requestProxy = new RequestProxy(request);
61 | Monitor.Enter(requestProxy);
62 |
63 | if (request.Reader.Method != Methods.Ackm)
64 | parent.requestProxyes.Add(requestProxy.ServerTransactionId, requestProxy);
65 |
66 | if (request.Reader.Method == Methods.Invitem)
67 | {
68 | var writer = parent.GetWriter();
69 | writer.WriteResponse(request.Reader, StatusCodes.Trying);
70 | parent.SendResponse(request, writer);
71 | }
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Server/Transport/AjaxWebsocketWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using Http.Message;
4 |
5 | namespace Sip.Server
6 | {
7 | static class AjaxWebsocketWriter
8 | {
9 | private static byte[] accessControlAllowHeaders = Encoding.UTF8.GetBytes("Authorization");
10 | private static byte[] accessControlExposeHeaders = Encoding.UTF8.GetBytes("WWW-Authenticate");
11 |
12 | public static void WriteNotFinishedResponse(this HttpMessageWriter writer, StatusCodes statusCode, ContentType contentType)
13 | {
14 | writer.WriteStatusLine(statusCode);
15 | writer.WriteAccessControlHeaders();
16 | if (contentType != ContentType.None)
17 | writer.WriteContentType(contentType);
18 | else
19 | writer.WriteContentLength(0);
20 | }
21 |
22 | public static void WriteResponse(this HttpMessageWriter writer, StatusCodes statusCodes, ContentType contentType, byte[] content)
23 | {
24 | writer.WriteStatusLine(statusCodes);
25 | writer.WriteAccessControlHeaders();
26 | writer.WriteContentType(contentType);
27 | writer.WriteContentLength(content.Length);
28 | writer.WriteCRLF();
29 | writer.Write(content);
30 | }
31 |
32 | public static void WriteEmptyResponse(this HttpMessageWriter writer, StatusCodes statusCode)
33 | {
34 | writer.WriteStatusLine(statusCode);
35 | writer.WriteAccessControlHeaders();
36 | writer.WriteContentLength(0);
37 | writer.WriteCRLF();
38 | }
39 |
40 | public static void WriteAccessControlHeaders(this HttpMessageWriter writer)
41 | {
42 | writer.WriteAccessControlAllowOrigin(true);
43 | writer.WriteAccessControlAllowCredentials(true);
44 | writer.WriteAccessControlAllowHeaders(accessControlAllowHeaders);
45 | writer.WriteAccessControlExposeHeaders(accessControlExposeHeaders);
46 | writer.WriteAccessControlAllowMethods(Methods.Get, Methods.Post, Methods.Options);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Server/Transport/BufferHandle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SocketServers;
3 |
4 | namespace Sip.Server
5 | {
6 | public struct BufferHandle
7 | {
8 | private ArraySegment segment1;
9 | private ArraySegment segment2;
10 |
11 | public BufferHandle(ArraySegment segment1, ArraySegment segment2)
12 | {
13 | this.segment1 = segment1;
14 | this.segment2 = segment2;
15 | }
16 |
17 | public void Free()
18 | {
19 | BufferManager.Free(ref segment1);
20 | BufferManager.Free(ref segment2);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Server/Transport/OutgoingMessage.cs:
--------------------------------------------------------------------------------
1 | //using System;
2 | //using System.Net;
3 | //using System.Net.Sockets;
4 | //using Sip.Message;
5 | //using SocketServers;
6 |
7 | //namespace Sip.Server
8 | //{
9 | // class OutgoingMessage
10 | // {
11 | // public IncomingMessageEx(IncomingMessage source, int transactionId)
12 | // {
13 | // TransactionId = transactionId;
14 |
15 | // ConnectionAddresses = source.ConnectionAddresses;
16 |
17 | // Reader = source.Reader;
18 |
19 | // Headers = source.Headers;
20 | // Content = source.Content;
21 | // }
22 |
23 | // public readonly int TransactionId;
24 |
25 | // public readonly ConnectionAddresses ConnectionAddresses;
26 |
27 | // public readonly SipMessageReader Reader;
28 | // public readonly ArraySegment Headers;
29 | // public readonly ArraySegment Content;
30 | // }
31 | //}
32 |
--------------------------------------------------------------------------------
/Server/Trunk/ITrunkManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sip.Message;
4 | using Base.Message;
5 |
6 | namespace Sip.Server
7 | {
8 | interface ITrunkManager
9 | {
10 | event Action TrunkAdded;
11 | event Action TrunkRemoved;
12 |
13 | //Trunk GetTrunk(ByteArrayPart host);
14 | Trunk GetTrunkByDomain(ByteArrayPart host);
15 | Trunk GetTrunkById(int id);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Server/Users/AdUser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.DirectoryServices;
4 | using Sip.Server.Tools;
5 |
6 | namespace Sip.Server.Users
7 | {
8 | class AdUser
9 | : BaseUser
10 | {
11 | private readonly static string[] properties = new string[]
12 | {
13 | @"sAMAccountName",
14 | @"memberOf",
15 | @"displayName",
16 | @"mail",
17 | @"telephoneNumber",
18 | @"facsimileTelephoneNumber",
19 | @"streetAddress",
20 | @"l",
21 | @"st",
22 | @"countryCode",
23 | @"postalCode",
24 | @"wWWHomePage",
25 | @"title",
26 | @"company",
27 | @"physicalDeliveryOfficeName"
28 | };
29 |
30 | public AdUser()
31 | {
32 | }
33 |
34 | public AdUser(SearchResult user)
35 | {
36 | Name = GetAsString(user, @"sAMAccountName").ToLower();
37 | DisplayName = GetAsString(user, @"displayName");
38 | Email = GetAsString(user, @"mail");
39 | Telephone = GetAsString(user, @"telephoneNumber");
40 | Fax = GetAsString(user, @"facsimileTelephoneNumber");
41 | StreetAddress = GetAsString(user, @"streetAddress");
42 | City = GetAsString(user, @"l");
43 | State = GetAsString(user, @"st");
44 | CountryCode = ISO3166.ToA2(GetAsInt(user, @"countryCode"), null);
45 | PostalCode = GetAsString(user, @"postalCode");
46 | WwwHomepage = GetAsString(user, @"wWWHomePage");
47 | Title = GetAsString(user, @"title");
48 | Company = GetAsString(user, @"company");
49 | PhysicalDeliveryOfficeName = GetAsString(user, @"physicalDeliveryOfficeName");
50 | }
51 |
52 | public static string[] Properties
53 | {
54 | get { return properties; }
55 | }
56 |
57 | private string GetAsString(SearchResult result, string name)
58 | {
59 | var s = String.Empty;
60 |
61 | try
62 | {
63 | s = result.Properties[name][0] as string;
64 | }
65 | catch
66 | {
67 | }
68 |
69 | return s;
70 | }
71 |
72 |
73 | private int GetAsInt(SearchResult result, string name)
74 | {
75 | int i = 0;
76 |
77 | try
78 | {
79 | i = (int)result.Properties[name][0];
80 | }
81 | catch
82 | {
83 | }
84 |
85 | return i;
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Server/Users/IUser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Server.Users
4 | {
5 | public interface IUser
6 | {
7 | string Name { get; }
8 |
9 | string DisplayName { get; set; }
10 | string Email { get; set; }
11 |
12 | string Password { get; set; }
13 |
14 | string Telephone { get; set; }
15 | string Fax { get; set; }
16 |
17 | string City { get; set; }
18 | string State { get; set; }
19 | string StreetAddress { get; set; }
20 | string CountryCode { get; set; }
21 | string PostalCode { get; set; }
22 | string WwwHomepage { get; set; }
23 | string Title { get; set; }
24 | string Company { get; set; }
25 | string PhysicalDeliveryOfficeName { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Server/Users/IUsers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Sip.Server.Users
5 | {
6 | public delegate void IUsersEventHandler1(int accountId, IUsers source, IUser user);
7 | public delegate void IUsersEventHandler2(int accountId, IUsers source);
8 |
9 | public interface IUsers
10 | : IDisposable
11 | {
12 | event IUsersEventHandler2 Reset;
13 | event IUsersEventHandler1 Added;
14 | event IUsersEventHandler1 Updated;
15 | event IUsersEventHandler1 Removed;
16 |
17 | string Id { get; }
18 | string SourceName { get; }
19 | bool HasPasswords { get; }
20 |
21 | bool IsReadOnly { get; }
22 |
23 | void Add(int accountId, IUser user);
24 | void Update(int accountId, IUser user);
25 | void Remove(int accountId, string name);
26 |
27 | int GetCount(int accountId);
28 |
29 | IList GetUsers(int accountId, int startIndex, int count);
30 |
31 | IUser GetByName(int accountId, string name);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Server/Users/IUserz.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Server.Users
4 | {
5 | public interface IUserz
6 | {
7 | event IUsersEventHandler2 Reset;
8 | event IUsersEventHandler1 Added;
9 | event IUsersEventHandler1 Updated;
10 | event IUsersEventHandler1 Removed;
11 |
12 | IUsers this[int index] { get; }
13 | int Count { get; }
14 |
15 | int GetIndex(string id);
16 | IUsers Get(string id);
17 |
18 | IUsers[] ToArray();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Server/Users/UsersException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Sip.Server.Users
4 | {
5 | enum ErrorCodes
6 | {
7 | UserExist,
8 | UsernameEmpty,
9 | }
10 |
11 | public class UsersException
12 | : Exception
13 | {
14 | internal UsersException(ErrorCodes code)
15 | : base(GetMessage(code))
16 | {
17 |
18 | }
19 |
20 | internal static string GetMessage(ErrorCodes code)
21 | {
22 | switch (code)
23 | {
24 | case ErrorCodes.UserExist:
25 | return @"User with specified username already exist";
26 | case ErrorCodes.UsernameEmpty:
27 | return @"Empty username is not allowed";
28 | }
29 |
30 | return null;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Server/WcfService/IWcfService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.ServiceModel;
4 | using System.Collections.Generic;
5 | using System.Runtime.Serialization;
6 | using Sip.Server.Users;
7 |
8 | namespace Sip.Server.WcfService
9 | {
10 | [ServiceContract(Namespace = "http://officesip.com/server.control", CallbackContract = typeof(IWcfServiceCallback))]
11 | public interface IWcfService
12 | {
13 | [OperationContract]
14 | WcfConfiguration GetConfigurations();
15 |
16 | [OperationContract]
17 | void SetConfigurations(WcfConfiguration configurations);
18 |
19 |
20 |
21 | [OperationContract]
22 | int GetUsersCount(string id);
23 |
24 | [OperationContract]
25 | IList GetUsers(string id, int startIndex, int count, out int overallCount);
26 |
27 |
28 |
29 | [OperationContract]
30 | void AddUser(string usersId, WcfUser user, string password);
31 |
32 | [OperationContract]
33 | void UpdateUser(string usersId, WcfUser user);
34 |
35 | [OperationContract]
36 | void RemoveUser(string usersId, string name);
37 |
38 | [OperationContract]
39 | void SetUserPassword(string usersId, string name, string password);
40 |
41 |
42 |
43 | [OperationContract]
44 | IEnumerable GetVoipProviders();
45 |
46 | [OperationContract]
47 | void AddVoipProvider(WcfVoipProvider provider);
48 |
49 | [OperationContract]
50 | void RemoveVoipProvider(string username, string hostname);
51 |
52 |
53 |
54 | [OperationContract]
55 | void Ping();
56 |
57 | [OperationContract]
58 | Version GetVersion();
59 |
60 |
61 | [OperationContract]
62 | string GetDefaultXmlConfiguration();
63 |
64 | [OperationContract]
65 | string GetXmlConfiguration();
66 |
67 | [OperationContract]
68 | string[] SetXmlConfiguration(string xml);
69 |
70 | [OperationContract]
71 | string[] ValidateXmlConfiguration(string xml);
72 |
73 |
74 |
75 | [OperationContract]
76 | WcfTurnConfiguration GetTurnConfigurations();
77 |
78 | [OperationContract]
79 | void SetTurnConfigurations(WcfTurnConfiguration configurations);
80 |
81 | [OperationContract]
82 | void SetAdministratorPassword(string newPassword);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Server/WcfService/IWcfServiceCallback.cs:
--------------------------------------------------------------------------------
1 | using System.ServiceModel;
2 | using System.Runtime.Serialization;
3 | using System.Collections.Generic;
4 | using System.Net;
5 | using Sip.Server.Users;
6 |
7 | namespace Sip.Server.WcfService
8 | {
9 | interface IWcfServiceCallback
10 | {
11 | [OperationContract(IsOneWay = true)]
12 | void AvailabilityChanged(string name, int availability);
13 |
14 | [OperationContract(IsOneWay = true)]
15 | void NewClient();
16 |
17 | [OperationContract(IsOneWay = true)]
18 | void UsersReset(string usersId);
19 |
20 | [OperationContract(IsOneWay = true)]
21 | void UserAddedOrUpdated(string usersId, WcfUser user);
22 |
23 | [OperationContract(IsOneWay = true)]
24 | void UserRemoved(string usersId, string name);
25 |
26 | [OperationContract(IsOneWay = true)]
27 | void VoipProviderUpdated(WcfVoipProvider info);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Server/WcfService/WcfConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Runtime.Serialization;
3 | using System.Collections.Generic;
4 | using Sip.Server.Users;
5 |
6 | namespace Sip.Server.WcfService
7 | {
8 | [DataContract(Name = "Configurations", Namespace = "http://officesip.com/server.control")]
9 | public class WcfConfiguration
10 | {
11 | [DataMember]
12 | public string DomainName { set; get; }
13 |
14 |
15 |
16 | [DataMember]
17 | public bool IsAuthorizationEnabled { set; get; }
18 |
19 |
20 |
21 |
22 | [DataMember]
23 | public bool IsActiveDirectoryUsersEnabled { set; get; }
24 |
25 | [DataMember]
26 | public string ActiveDirectoryUsersGroup { set; get; }
27 |
28 |
29 |
30 | [DataMember]
31 | public bool IsTracingEnabled { set; get; }
32 |
33 | [DataMember]
34 | public string TracingFileName { set; get; }
35 |
36 |
37 |
38 | [DataMember]
39 | public IEnumerable Users { get; set; }
40 |
41 |
42 | //public IPEndPoint PortForwardingPublicIPEndPoint
43 | //public IPEndPoint PortForwardingPrivateIPEndPoint
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Server/WcfService/WcfTurnConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 | using System.Collections.Generic;
3 |
4 | namespace Sip.Server.WcfService
5 | {
6 | [DataContract(Name = "TURNConfigurations", Namespace = "http://officesip.com/server.control")]
7 | public class WcfTurnConfiguration
8 | {
9 | [DataMember]
10 | public byte[] Key1 { get; set; }
11 | [DataMember]
12 | public byte[] Key2 { get; set; }
13 | [DataMember]
14 | public string FQDN { get; set; }
15 | [DataMember]
16 | public int UDPPort { get; set; }
17 | [DataMember]
18 | public int TCPPort { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Server/WcfService/WcfUser.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 | using Sip.Server.Users;
3 |
4 | namespace Sip.Server.WcfService
5 | {
6 | [DataContract(Name = "User", Namespace = "http://officesip.com/server.control")]
7 | public class WcfUser
8 | {
9 | public WcfUser(IUser user)
10 | {
11 | Name = user.Name;
12 | DisplayName = user.DisplayName;
13 | Email = user.Email;
14 | }
15 |
16 | [DataMember]
17 | public string Name { set; get; }
18 | [DataMember]
19 | public string DisplayName { set; get; }
20 | [DataMember]
21 | public string Email { set; get; }
22 | [DataMember]
23 | public int Availability { set; get; }
24 |
25 | public IUser ToIUser(string password)
26 | {
27 | return new BaseUser()
28 | {
29 | Name = Name,
30 | DisplayName = DisplayName,
31 | Email = Email,
32 | Password = password,
33 | };
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Server/WcfService/WcfUsers.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 | using Sip.Server.Users;
3 |
4 | namespace Sip.Server.WcfService
5 | {
6 | [DataContract(Name = "Users", Namespace = "http://officesip.com/server.control")]
7 | public class WcfUsers
8 | {
9 | public WcfUsers(IUsers users)
10 | {
11 | Id = users.Id;
12 | SourceName = users.SourceName;
13 | IsReadOnly = users.IsReadOnly;
14 | }
15 |
16 | [DataMember]
17 | public string Id { get; private set; }
18 | [DataMember]
19 | public string SourceName { get; private set; }
20 | [DataMember]
21 | public bool IsReadOnly { get; set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Server/Www/assets/bootstrap/bootstrap-transition.js:
--------------------------------------------------------------------------------
1 | /* ===================================================
2 | * bootstrap-transition.js v2.2.2
3 | * http://twitter.github.com/bootstrap/javascript.html#transitions
4 | * ===================================================
5 | * Copyright 2012 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ========================================================== */
19 |
20 |
21 | !function ($) {
22 |
23 | "use strict"; // jshint ;_;
24 |
25 |
26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
27 | * ======================================================= */
28 |
29 | $(function () {
30 |
31 | $.support.transition = (function () {
32 |
33 | var transitionEnd = (function () {
34 |
35 | var el = document.createElement('bootstrap')
36 | , transEndEventNames = {
37 | 'WebkitTransition' : 'webkitTransitionEnd'
38 | , 'MozTransition' : 'transitionend'
39 | , 'OTransition' : 'oTransitionEnd otransitionend'
40 | , 'transition' : 'transitionend'
41 | }
42 | , name
43 |
44 | for (name in transEndEventNames){
45 | if (el.style[name] !== undefined) {
46 | return transEndEventNames[name]
47 | }
48 | }
49 |
50 | }())
51 |
52 | return transitionEnd && {
53 | end: transitionEnd
54 | }
55 |
56 | })()
57 |
58 | })
59 |
60 | }(window.jQuery);
--------------------------------------------------------------------------------
/Server/Www/assets/bootstrap/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/Www/assets/bootstrap/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/Server/Www/assets/bootstrap/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/Www/assets/bootstrap/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/Server/Www/assets/codemirror/simple-hint.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-completions {
2 | position: absolute;
3 | z-index: 10;
4 | overflow: hidden;
5 | -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
6 | -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
7 | box-shadow: 2px 3px 5px rgba(0,0,0,.2);
8 | }
9 | .CodeMirror-completions select {
10 | background: #fafafa;
11 | outline: none;
12 | border: none;
13 | padding: 0;
14 | margin: 0;
15 | font-family: monospace;
16 | }
17 |
--------------------------------------------------------------------------------
/Server/Www/index.css:
--------------------------------------------------------------------------------
1 |
2 | .x-menu {
3 | padding: 8px 0;
4 | }
5 |
6 | .CodeMirror {
7 | border-top: 1px solid #eee;
8 | border-bottom: 1px solid #eee;
9 | border-right: 1px solid #eee;
10 | height: 32em;
11 | }
12 |
13 | /* bootstrap docs.css */
14 | .jumbotron {
15 | position: relative;
16 | }
17 | .jumbotron h1 {
18 | margin-bottom: 9px;
19 | font-size: 81px;
20 | font-weight: bold;
21 | letter-spacing: -1px;
22 | line-height: 1;
23 | }
24 | .jumbotron p {
25 | margin-bottom: 18px;
26 | font-weight: 300;
27 | }
28 | .jumbotron .btn-large {
29 | font-size: 20px;
30 | font-weight: normal;
31 | padding: 14px 24px;
32 | margin-right: 10px;
33 | -webkit-border-radius: 6px;
34 | -moz-border-radius: 6px;
35 | border-radius: 6px;
36 | }
37 | .jumbotron .btn-large small {
38 | font-size: 14px;
39 | }
40 |
41 | /* Masthead (docs home) */
42 | .masthead {
43 | padding-top: 36px;
44 | margin-bottom: 72px;
45 | }
46 | .masthead h1,
47 | .masthead p {
48 | text-align: center;
49 | }
50 | .masthead h1 {
51 | margin-bottom: 18px;
52 | }
53 | .masthead p {
54 | margin-left: 5%;
55 | margin-right: 5%;
56 | font-size: 30px;
57 | line-height: 36px;
58 | }
59 |
60 | /* ----------------- */
--------------------------------------------------------------------------------
/Server/Www/xmlEditorHints.js:
--------------------------------------------------------------------------------
1 |
2 | CodeMirror.xmlHints['<'] = [
3 | 'sipServer'
4 | ];
5 |
6 | CodeMirror.xmlHints['<'] = [
7 | 'portForwardings',
8 | 'turnServers',
9 | 'voipProviders'
10 | ];
11 |
12 | CodeMirror.xmlHints['<'] =
13 | CodeMirror.xmlHints['<'] =
14 | CodeMirror.xmlHints['<'] = [
15 | 'add',
16 | 'clear',
17 | 'remove'
18 | ];
19 |
20 | CodeMirror.xmlHints['/g;
5 |
6 | var removeComments = function (xml) {
7 | return xml.replace(reComment, '{C097EBC1-2006-4203-A96F-37F7075DC344}');
8 | }
9 |
10 | var restoreComments = function (xml, originalXml) {
11 |
12 | var comments = originalXml.match(reComment);
13 |
14 | if (comments != null) {
15 | for (var i = 0; i < comments.length; i++) {
16 | xml = xml.replace(/{C097EBC1-2006-4203-A96F-37F7075DC344}/, comments[i]);
17 | }
18 | }
19 | return xml;
20 | }
21 |
22 | this.changeAttribute = function (originalXml, element, attribute, newValue) {
23 |
24 | var xml = removeComments(originalXml);
25 |
26 | var attrAndValue = attribute + '="' + newValue + '"';
27 |
28 | var reAttr = new RegExp(attribute + '=".*?"', 'g');
29 |
30 | var newXml = '';
31 | if (xml.match(reAttr) != null) {
32 | newXml = xml.replace(reAttr, attrAndValue);
33 | }
34 | else {
35 | var index = xml.indexOf(element);
36 | if (index >= 0) {
37 | index += element.length;
38 | newXml = xml.slice(0, index) + '\n\t' + attrAndValue + xml.slice(index)
39 | }
40 | }
41 |
42 | return restoreComments(newXml, originalXml)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Server/Xcap/PidfManipulationHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Sip.Simple;
3 | using Base.Message;
4 | using Http.Message;
5 |
6 | namespace Server.Xcap
7 | {
8 | class PidfManipulationHandler
9 | : BasePidfManipulationHandler
10 | {
11 | private readonly SimpleModule simpleModule;
12 |
13 | public PidfManipulationHandler(SimpleModule simpleModule)
14 | {
15 | this.simpleModule = simpleModule;
16 | }
17 |
18 | public override HttpMessageWriter ProcessGetItem(ByteArrayPart username, ByteArrayPart domain)
19 | {
20 | var document = simpleModule.GetDocument(username.ToString() + "@" + domain.ToString());
21 |
22 | if (document == null)
23 | {
24 | return base.CreateResponse(StatusCodes.NotFound);
25 | }
26 | else
27 | {
28 | var response = base.CreateNotFinishedResponse(StatusCodes.OK, ContentType.ApplicationPidfXml);
29 |
30 | document.WriteLenghtAndContent(response);
31 |
32 | return response;
33 | }
34 | }
35 |
36 | public override HttpMessageWriter ProcessPutItem(ByteArrayPart username, ByteArrayPart domain, HttpMessageReader reader, ArraySegment content)
37 | {
38 | var statusCode = StatusCodes.OK;
39 |
40 | int sipIfMatch = simpleModule.InvalidEtag;
41 | if (reader.Count.IfMatches > 0)
42 | {
43 | if (HexEncoding.TryParseHex8(reader.IfMatches[0].Bytes, reader.IfMatches[0].Begin, out sipIfMatch) == false)
44 | statusCode = StatusCodes.PreconditionFailed;
45 | }
46 |
47 | if (statusCode == StatusCodes.OK)
48 | {
49 | if (simpleModule.Publish(username.ToString() + "@" + domain.ToString(), ref sipIfMatch, 60, content) == false)
50 | statusCode = StatusCodes.BadRequest;
51 | }
52 |
53 | HttpMessageWriter response;
54 | if (statusCode != StatusCodes.OK)
55 | {
56 | response = CreateResponse(statusCode);
57 | }
58 | else
59 | {
60 | response = CreateNotFinishedResponse(statusCode, ContentType.None);
61 |
62 | response.WriteEtag(sipIfMatch);
63 | response.WriteCRLF();
64 | }
65 |
66 | return response;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Server/Xcap/ResourceListsHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sip.Server.Users;
4 | using Sip.Server.Accounts;
5 | using Base.Message;
6 |
7 | namespace Server.Xcap
8 | {
9 | class ResourceListsHandler
10 | : BaseResourceListsHandler
11 | {
12 | private readonly IUserz userz;
13 | private readonly IAccounts accounts;
14 |
15 | public ResourceListsHandler(IAccounts accounts, IUserz userz)
16 | {
17 | this.accounts = accounts;
18 | this.userz = userz;
19 | }
20 |
21 | protected override IEnumerable GetEntries(ByteArrayPart username, ByteArrayPart domain)
22 | {
23 | var account = accounts.GetAccount(domain);
24 |
25 | if (account != null)
26 | {
27 | for (int i = 0; i < userz.Count; i++)
28 | {
29 | int count = userz[i].GetCount(account.Id);
30 | var users = userz[i].GetUsers(account.Id, 0, count);
31 |
32 | for (int j = 0; j < users.Count; j++)
33 | {
34 | var user = users[j];
35 |
36 | yield return new Entry("sip:" + user.Name + "@" + account.DomainName, user.DisplayName);
37 | }
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Server/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Server/dll/CsvReader.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/CsvReader.dll
--------------------------------------------------------------------------------
/Server/dll/CsvReader_src.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/CsvReader_src.zip
--------------------------------------------------------------------------------
/Server/dll/DataVirtualization.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/DataVirtualization.dll
--------------------------------------------------------------------------------
/Server/dll/DataVirtualization.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/DataVirtualization.zip
--------------------------------------------------------------------------------
/Server/dll/DnDns.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/DnDns.dll
--------------------------------------------------------------------------------
/Server/dll/Http.Message.dfa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Http.Message.dfa
--------------------------------------------------------------------------------
/Server/dll/Http.Message.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Http.Message.dll
--------------------------------------------------------------------------------
/Server/dll/ICSharpCode.AvalonEdit.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/ICSharpCode.AvalonEdit.dll
--------------------------------------------------------------------------------
/Server/dll/Json45r7.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Json45r7.zip
--------------------------------------------------------------------------------
/Server/dll/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/Server/dll/Sip.Message.dfa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Sip.Message.dfa
--------------------------------------------------------------------------------
/Server/dll/Sip.Message.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/Sip.Message.dll
--------------------------------------------------------------------------------
/Server/dll/SocketServers.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Server/dll/SocketServers.dll
--------------------------------------------------------------------------------
/Setup/WwwFiles.bat:
--------------------------------------------------------------------------------
1 | "C:\Program Files (x86)\WiX Toolset v3.6\bin\heat.exe" dir "..\Server\Www" -var wix.WwwPath -suid -cg WwwFiles -gg -out WwwFiles.wxs
--------------------------------------------------------------------------------
/Setup/bannrbmp.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Setup/bannrbmp.bmp
--------------------------------------------------------------------------------
/Setup/dlgbmp.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vf1/sipserver/f8f4a389b4779709304f017c21a360bb8bcc8ae5/Setup/dlgbmp.bmp
--------------------------------------------------------------------------------
/Tests/LoadTables.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Collections.Generic;
4 | using NUnit.Framework;
5 | using Sip.Server;
6 | using Sip.Message;
7 | using Http.Message;
8 | using SocketServers;
9 |
10 | namespace Test
11 | {
12 | [SetUpFixture]
13 | public class LoadTables
14 | {
15 | [SetUp]
16 | public void SetUp()
17 | {
18 | {
19 | var dfa = new SipMessageReader();
20 | dfa.LoadTables(@"..\..\..\Server\dll\Sip.Message.dfa");
21 | dfa.SetDefaultValue();
22 | dfa.Parse(new byte[] { 0 }, 0, 1);
23 | }
24 | {
25 | HttpMessageReader.LoadTables(@"..\..\..\Server\dll\");
26 |
27 | var dfa = new HttpMessageReader();
28 | dfa.SetDefaultValue();
29 | dfa.Parse(new byte[] { 0 }, 0, 1);
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("TestRtp")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("TestRtp")]
13 | [assembly: AssemblyCopyright("Copyright © 2009")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM componenets. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("92da22f7-832d-4c4b-b295-e434950e7ac3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Tests/ProxyServerTU/ConnectionAddressTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Net;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Collections.Generic;
7 | using NUnit.Framework;
8 | using Sip.Tools;
9 | using Sip.Server;
10 | using Sip.Message;
11 | using Base.Message;
12 | using SocketServers;
13 |
14 | namespace Test
15 | {
16 | //[TestFixture]
17 | //class ConnectionAddressTest
18 | //{
19 | // [Test]
20 | // public void it_should_parse_this_connection_address()
21 | // {
22 | // int transactionId;
23 | // var addresses = ConnectionAddresses.Parse(new ByteArrayPart("020000000313c404d014f60aef2b041e14f60a01000002"), out transactionId);
24 |
25 | // Assert.AreEqual(0x01000002, transactionId);
26 | // Assert.IsTrue(addresses.HasValue);
27 | // Assert.AreEqual("10.246.20.30:61227", addresses.Value.RemoteEndPoint.ToString());
28 | // Assert.AreEqual("10.246.20.208:5060", addresses.Value.LocalEndPoint.ToString());
29 | // Assert.AreEqual(Transports.Tcp, addresses.Value.Transport);
30 | // }
31 | //}
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/Rtp/DtmfEventMessageTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rtp;
3 | using Rtp.Payload;
4 | using NUnit.Framework;
5 |
6 | namespace TestRtp
7 | {
8 | [TestFixture]
9 | public class DtmfEventMessageTest
10 | {
11 | [Test]
12 | public void ParseTest1()
13 | {
14 | byte[] bytes1 = new byte[] { 0xff, 0x01, 0x8A, 0x03, 0xC0, };
15 |
16 | var messages1 = DtmfEventMessage.Parse(bytes1, 1, bytes1.Length);
17 |
18 | Assert.AreEqual(1, messages1.Length);
19 | Assert.AreEqual(1, messages1[0].Event, "Dtmf.Event");
20 | Assert.AreEqual(true, messages1[0].End, "Dtmf.End");
21 | Assert.AreEqual(0x0a, messages1[0].Volume, "Dtmf.Volume");
22 | Assert.AreEqual(0x03c0, messages1[0].Duration, "Dtmf.Duration");
23 | }
24 |
25 | [Test]
26 | public void ParseTest2()
27 | {
28 | byte[] bytes = new byte[] { 0xff, 0x01, 0x8A, 0x03, 0xC0, 0x02, 0x0B, 0x04, 0xC1, };
29 |
30 | var messages = DtmfEventMessage.Parse(bytes, 1, bytes.Length);
31 |
32 | Assert.AreEqual(2, messages.Length, "messages.Length");
33 |
34 | Assert.AreEqual(1, messages[0].Event, "Dtmf.Event");
35 | Assert.AreEqual(true, messages[0].End, "Dtmf.End");
36 | Assert.AreEqual(0x0a, messages[0].Volume, "Dtmf.Volume");
37 | Assert.AreEqual(0x03c0, messages[0].Duration, "Dtmf.Duration");
38 |
39 | Assert.AreEqual(2, messages[1].Event, "Dtmf.Event");
40 | Assert.AreEqual(false, messages[1].End, "Dtmf.End");
41 | Assert.AreEqual(0x0b, messages[1].Volume, "Dtmf.Volume");
42 | Assert.AreEqual(0x04c1, messages[1].Duration, "Dtmf.Duration");
43 | }
44 |
45 | [Test]
46 | [ExpectedException(typeof(NotImplementedException))]
47 | public void GetBytesTest()
48 | {
49 | DtmfEventMessage target = new DtmfEventMessage(); // TODO: Initialize to an appropriate value
50 | byte[] bytes = null; // TODO: Initialize to an appropriate value
51 | int startIndex = 0; // TODO: Initialize to an appropriate value
52 | target.GetBytes(bytes, startIndex);
53 | Assert.Inconclusive("A method that does not return a value cannot be verified.");
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Tests/Rtp/JitterBufferTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rtp;
3 | using NUnit.Framework;
4 |
5 | namespace TestRtp
6 | {
7 | [TestFixture]
8 | public class JitterBufferTest
9 | {
10 | RtpMessage message1 = new RtpMessage() { SequenceNumber = 1, };
11 | RtpMessage message2 = new RtpMessage() { SequenceNumber = 2, };
12 | RtpMessage message3 = new RtpMessage() { SequenceNumber = 3, };
13 |
14 | [Test]
15 | public void JitterBufferTest1()
16 | {
17 | JitterBuffer buffer = new JitterBuffer(null);
18 |
19 | buffer.Insert(message1);
20 | buffer.Insert(message1);
21 | buffer.Insert(message2);
22 | buffer.Insert(message2);
23 | buffer.Insert(message3);
24 | buffer.Insert(message3);
25 |
26 | Assert.AreEqual(3, buffer.Count);
27 | Assert.AreEqual((UInt16)1, buffer.DequeueAvailable().SequenceNumber);
28 | Assert.AreEqual((UInt16)2, buffer.DequeueAvailable().SequenceNumber);
29 | Assert.AreEqual((UInt16)3, buffer.DequeueAvailable().SequenceNumber);
30 | Assert.IsNull(buffer.DequeueAvailable());
31 | }
32 |
33 | [Test]
34 | public void JitterBufferTest2()
35 | {
36 | JitterBuffer buffer = new JitterBuffer(null);
37 |
38 | buffer.Insert(message3);
39 | buffer.Insert(message3);
40 | buffer.Insert(message1);
41 | buffer.Insert(message1);
42 | buffer.Insert(message2);
43 | buffer.Insert(message2);
44 |
45 | Assert.AreEqual(3, buffer.Count);
46 | Assert.AreEqual((UInt16)1, buffer.DequeueAvailable().SequenceNumber);
47 | Assert.AreEqual((UInt16)2, buffer.DequeueAvailable().SequenceNumber);
48 | Assert.AreEqual((UInt16)3, buffer.DequeueAvailable().SequenceNumber);
49 | Assert.IsNull(buffer.DequeueAvailable());
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Tests/Rtp/NtpTimestampTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.NtpTimestamp;
3 | using NUnit.Framework;
4 |
5 | namespace TestRtp
6 | {
7 | [TestFixture]
8 | public class NtpTimestampTest
9 | {
10 | [Test]
11 | public void NtpTimestampTest1()
12 | {
13 | UInt64 timestamp1 = 0xCEA3F33E5D0D5A5BL;
14 |
15 | DateTime actual1 = NtpTimestamp.NtpTimestampToUtcDateTime(timestamp1);
16 | DateTime expected1 = new DateTime(0x08cc3026efdea9a1L); // {10.11.2009 14:12:14.3634849}
17 |
18 | Assert.AreEqual(expected1, actual1);
19 |
20 |
21 | UInt64 timestamp2 = actual1.ToNtpTimestamp();
22 |
23 | Assert.AreEqual(0xcea3f33e5d0d58ae, timestamp2);
24 |
25 |
26 | UInt64 timestamp3 = (new DateTime(1900, 1, 1)).ToNtpTimestamp();
27 | UInt64 actual3 = 0;
28 |
29 | Assert.AreEqual(actual3, timestamp3);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/Rtp/SsrcTest.cs:
--------------------------------------------------------------------------------
1 | using Rtp;
2 | using System;
3 | using NUnit.Framework;
4 |
5 | namespace TestRtp
6 | {
7 | [TestFixture]
8 | public class SsrcTest
9 | {
10 | [Test]
11 | public void GetNtpTimestampTest()
12 | {
13 | Ssrc ssrc = new Ssrc(new int[] { 0 }, new int[] { 1 });
14 |
15 | ssrc.SetBaseTimestamp(0x0000001000000000UL, 0xfffffff0);
16 |
17 | // message's rtp timestamp >= base rtp timestamp
18 | Assert.AreEqual(0x0000001000000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0xfffffff0, }, 1));
19 | Assert.AreEqual(0x0000001100000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0xfffffff1, }, 1));
20 | Assert.AreEqual(0x0000001f00000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0xffffffff, }, 1));
21 | Assert.AreEqual(0x0000002000000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0x00000000, }, 1));
22 | Assert.AreEqual(0x0000002100000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0x00000001, }, 1));
23 |
24 | // message's rtp timestamp < base rtp timestamp
25 | Assert.AreEqual(0x0000000f00000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0xffffffef, }, 1));
26 | Assert.AreEqual(0x0000000000000000UL, ssrc.GetNtpTimestamp(new RtpMessage() { Timestamp = 0xffffffe0, }, 1));
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Tests/ServiceSoap/DirectorySearchRequestTest.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Xml;
3 | using ServiceSoap.XmlContent;
4 | using NUnit.Framework;
5 |
6 | namespace ServiceSoap
7 | {
8 | [TestFixture]
9 | public class DirectorySearchRequestTest
10 | {
11 | [Test]
12 | public void ParseTest()
13 | {
14 | string xml1 = "100";
15 | string xml2 = "100";
16 |
17 | var request1 = DirectorySearchRequest.Parse(CreateXmlReader(xml1));
18 |
19 | Assert.AreEqual(100, request1.MaxResults);
20 | Assert.AreEqual(3, request1.SearchTerms.Count);
21 | Assert.AreEqual("n", request1.SearchTerms["givenName"]);
22 | Assert.AreEqual("e", request1.SearchTerms["givenEmail"]);
23 | Assert.AreEqual("<>&", request1.SearchTerms["ltgtamp"]);
24 |
25 | var request2 = DirectorySearchRequest.Parse(CreateXmlReader(xml2));
26 |
27 | Assert.AreEqual(100, request2.MaxResults);
28 | Assert.AreEqual(0, request2.SearchTerms.Count);
29 | }
30 |
31 | public XmlReader CreateXmlReader(string xml)
32 | {
33 | using (MemoryStream stream = new MemoryStream())
34 | using (StreamWriter writer = new StreamWriter(stream))
35 | {
36 | writer.Write(xml);
37 | writer.Flush();
38 | stream.Seek(0, SeekOrigin.Begin);
39 |
40 | return XmlReader.Create(stream);
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/ServiceSoap/Helpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ServiceSoap
4 | {
5 | static class Helpers
6 | {
7 | public static int GetEqualLength(this string s1, string s2)
8 | {
9 | int i;
10 | for (i = 0; i < s1.Length && i < s2.Length; i++)
11 | {
12 | if (s1[i] != s2[i])
13 | break;
14 | }
15 | return i;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Tests/Transaction/BaseServerTransactionTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using NUnit.Framework;
6 | using Sip.Server;
7 | using Sip.Message;
8 | using SocketServers;
9 |
10 | namespace Test.Transaction1
11 | {
12 | abstract class BaseServerTransactionTest
13 | : BaseTransactionTest
14 | where T : IServerTransaction, new()
15 | {
16 | protected void EmulateTuEvent(Transaction.States fromState, int startStatus, int endStatus, Transaction.States toState)
17 | {
18 | EmulateTuEvent(true, fromState, startStatus, endStatus, toState);
19 | EmulateTuEvent(false, fromState, startStatus, endStatus, toState);
20 | }
21 |
22 | protected void EmulateTuEvent(bool isTransportUnreliable, Transaction.States fromState, int startStatus, int endStatus, Transaction.States toState)
23 | {
24 | var e = GetServerEventArgs(isTransportUnreliable);
25 |
26 | for (int i = startStatus; i <= endStatus; i++)
27 | {
28 | var transaction = GetTransaction(fromState, isTransportUnreliable);
29 | transaction.ProccessTransactionUser(i, e);
30 |
31 | Assert.AreEqual(toState, transaction.State);
32 | }
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------