diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c4efe2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,261 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
\ No newline at end of file
diff --git a/Client/App.config b/Client/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/Client/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/Client.csproj b/Client/Client.csproj
new file mode 100644
index 0000000..88bc3cb
--- /dev/null
+++ b/Client/Client.csproj
@@ -0,0 +1,74 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}
+ Exe
+ Client
+ Client
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+
+
+ {cfa7453b-8b9b-4112-af04-f72c3d431100}
+ UdtProtocol
+
+
+
+
\ No newline at end of file
diff --git a/Client/PeerInfo.cs b/Client/PeerInfo.cs
new file mode 100644
index 0000000..57c717d
--- /dev/null
+++ b/Client/PeerInfo.cs
@@ -0,0 +1,10 @@
+using System.Net;
+
+namespace Client
+{
+ public class PeerInfo
+ {
+ public IPAddress Address { get; set; }
+ public int Port { get; set; }
+ }
+}
diff --git a/Client/Program.cs b/Client/Program.cs
new file mode 100644
index 0000000..8651523
--- /dev/null
+++ b/Client/Program.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Client
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("Usage: Client.exe LOCAL_PORT SERVER_ADDRESS SERVER_PORT");
+ Console.WriteLine("Example: Client.exe 2020 127.0.0.1 5880");
+ }
+
+ UdtClient client = new UdtClient(Convert.ToUInt16(args[0]), args[1],Convert.ToUInt16(args[2]));
+ client.Connect();
+
+ Console.WriteLine("Press Any Key To Close Client");
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/Client/Properties/AssemblyInfo.cs b/Client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1fcb0a0
--- /dev/null
+++ b/Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Client")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Client")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c8e99a9c-9229-47bf-bd7b-7aba7332c529")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
diff --git a/Client/Resource1.Designer.cs b/Client/Resource1.Designer.cs
new file mode 100644
index 0000000..a8afe2c
--- /dev/null
+++ b/Client/Resource1.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Client {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource1 {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource1() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Client.Resource1", typeof(Resource1).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Client/UdtClient.cs b/Client/UdtClient.cs
new file mode 100644
index 0000000..ac7632c
--- /dev/null
+++ b/Client/UdtClient.cs
@@ -0,0 +1,174 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using log4net;
+using Udt;
+
+namespace Client
+{
+ public class UdtClient
+ {
+ private static ILog LOGGER = LogManager.GetLogger(typeof(UdtClient));
+ private ushort localPort;
+ private string serverAddressStr;
+ private ushort serverPort;
+ private bool started;
+ private Udt.Socket socket;
+
+ public UdtClient(ushort localPort, string serverAddr, ushort serverPort)
+ {
+ this.localPort = localPort;
+ this.serverAddressStr = serverAddr;
+ this.serverPort = serverPort;
+ }
+
+ public void Connect()
+ {
+ started = true;
+ try
+ {
+ LOGGER.Info("creating socket");
+ socket = CreateSocket();
+ LOGGER.Info("connecting to signalling server, address: " + serverAddressStr + " port: " + serverPort);
+ IPAddress serverAddress = IPAddress.Parse(serverAddressStr);
+ socket.Connect(serverAddress, serverPort);
+ LOGGER.Info("connected to signalling server");
+ PeerInfo peerInfo = ReceivePeerInfo();
+ StartPeerConnection(peerInfo);
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("connect exception", ex);
+ started = false;
+ ShutdownSocket();
+ }
+ }
+
+ private Udt.Socket CreateSocket()
+ {
+ Udt.Socket socket = new Udt.Socket(AddressFamily.InterNetwork, SocketType.Stream);
+ socket.ReuseAddress = true;
+ socket.Bind(IPAddress.Any, localPort);
+ return socket;
+
+ }
+
+ private void StartPeerConnection(PeerInfo peerInfo)
+ {
+ LOGGER.Info("Created new socket for peer connection");
+ socket = new Udt.Socket(AddressFamily.InterNetwork, SocketType.Stream);
+ socket.ReuseAddress = true;
+ socket.SetSocketOption(Udt.SocketOptionName.Rendezvous, true);
+ socket.Bind(IPAddress.Any, localPort);
+ LOGGER.Info("Waiting for peer connection");
+ socket.Connect(peerInfo.Address, peerInfo.Port);
+
+ LOGGER.Info("peer connected, starting sender and listener threads");
+
+ Thread receiveThread = new Thread(() => ListenMessages(socket));
+ receiveThread.Start();
+
+ Thread sendThread = new Thread(() => SendDate(socket));
+ sendThread.Start();
+ LOGGER.Info("connection done");
+ }
+
+ public PeerInfo ReceivePeerInfo()
+ {
+ PeerInfo peerInfo = null;
+ using (Udt.NetworkStream st = new Udt.NetworkStream(socket, false))
+ {
+ LOGGER.Info("Waiting peer connection info from signalling server");
+ byte[] peerInfoBytes = new byte[8];
+ st.Read(peerInfoBytes, 0, peerInfoBytes.Length);
+
+ LOGGER.Info("parsing peer connection info");
+ byte[] peerAddressBytes = new byte[4];
+ byte[] peerPortBytes = new byte[4];
+ Array.Copy(peerInfoBytes, 0, peerAddressBytes, 0, peerAddressBytes.Length);
+ Array.Copy(peerInfoBytes, 4, peerPortBytes, 0, peerPortBytes.Length);
+
+ peerInfo = new PeerInfo();
+ peerInfo.Address = new IPAddress(peerAddressBytes);
+ peerInfo.Port = BitConverter.ToInt32(peerPortBytes, 0);
+ LOGGER.Info("peer address: " + peerInfo.Address.ToString() + " port: " + peerInfo.Port);
+ }
+ return peerInfo;
+ }
+
+
+ public void Disconnect()
+ {
+ if (started)
+ {
+ ShutdownSocket();
+ }
+ else
+ {
+ LOGGER.Error("not started");
+ throw new Exception("not started");
+ }
+ }
+
+ private void ShutdownSocket()
+ {
+ if (socket != null)
+ {
+ try
+ {
+ socket.Close();
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("socket close exception", ex);
+ }
+ }
+ }
+
+ private void SendDate(Udt.Socket socket)
+ {
+ try
+ {
+ using (Udt.NetworkStream st = new Udt.NetworkStream(socket))
+ using (BinaryWriter writer = new BinaryWriter(st))
+ {
+ Thread.Sleep(10000);
+ while (started)
+ {
+ LOGGER.Info("Sending date");
+ writer.Write(DateTime.Now.ToLongTimeString());
+ Thread.Sleep(1000);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("send date exception", ex);
+ }
+ LOGGER.Info("send date stopped");
+ }
+
+ private void ListenMessages(Udt.Socket socket)
+ {
+ try
+ {
+ using (Udt.NetworkStream st = new Udt.NetworkStream(socket))
+ using (BinaryReader reader = new BinaryReader(st))
+ {
+ while (started)
+ {
+ LOGGER.Info("waiting for new message");
+ LOGGER.Info("RECEIVED: " + reader.ReadString());
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("message listen exception", ex);
+ }
+ LOGGER.Info("listen messages stopped");
+ }
+ }
+}
diff --git a/Client/log4net.config b/Client/log4net.config
new file mode 100644
index 0000000..069d018
--- /dev/null
+++ b/Client/log4net.config
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/msvcp100.dll b/Client/msvcp100.dll
new file mode 100644
index 0000000..8502dfa
Binary files /dev/null and b/Client/msvcp100.dll differ
diff --git a/Client/msvcr100.dll b/Client/msvcr100.dll
new file mode 100644
index 0000000..3e82b1a
Binary files /dev/null and b/Client/msvcr100.dll differ
diff --git a/Client/packages.config b/Client/packages.config
new file mode 100644
index 0000000..f651f6c
--- /dev/null
+++ b/Client/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/HolePuncher.sln b/HolePuncher.sln
new file mode 100644
index 0000000..196aabb
--- /dev/null
+++ b/HolePuncher.sln
@@ -0,0 +1,104 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2042
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignallingServer", "SignallingServer\SignallingServer.csproj", "{E7364570-F20D-4875-8129-67B293EC46B4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{C8E99A9C-9229-47BF-BD7B-7ABA7332C529}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UdtProtocol", "UdtProtocol\UdtProtocol.vcxproj", "{CFA7453B-8B9B-4112-AF04-F72C3D431100}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udt", "udt4\win\udt.vcxproj", "{D84D100A-7C21-4CCB-B16E-0FB37137C16C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release - Signed|Any CPU = Release - Signed|Any CPU
+ Release - Signed|x64 = Release - Signed|x64
+ Release - Signed|x86 = Release - Signed|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|x64.Build.0 = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Debug|x86.Build.0 = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|Any CPU.Build.0 = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|x64.ActiveCfg = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|x64.Build.0 = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|x86.ActiveCfg = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release - Signed|x86.Build.0 = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|x64.ActiveCfg = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|x64.Build.0 = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|x86.ActiveCfg = Release|Any CPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}.Release|x86.Build.0 = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|x64.Build.0 = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Debug|x86.Build.0 = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|Any CPU.ActiveCfg = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|Any CPU.Build.0 = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|x64.ActiveCfg = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|x64.Build.0 = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|x86.ActiveCfg = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release - Signed|x86.Build.0 = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|x64.ActiveCfg = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|x64.Build.0 = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|x86.ActiveCfg = Release|Any CPU
+ {C8E99A9C-9229-47BF-BD7B-7ABA7332C529}.Release|x86.Build.0 = Release|Any CPU
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|Any CPU.Build.0 = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|x64.ActiveCfg = Debug|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|x64.Build.0 = Debug|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|x86.ActiveCfg = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Debug|x86.Build.0 = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|Any CPU.ActiveCfg = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|Any CPU.Build.0 = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|x64.ActiveCfg = Release - Signed|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|x64.Build.0 = Release - Signed|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|x86.ActiveCfg = Release - Signed|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release - Signed|x86.Build.0 = Release - Signed|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|Any CPU.ActiveCfg = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|Any CPU.Build.0 = Debug|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|x64.ActiveCfg = Release|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|x64.Build.0 = Release|x64
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|x86.ActiveCfg = Release|Win32
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}.Release|x86.Build.0 = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Debug|Any CPU.Build.0 = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Debug|x64.ActiveCfg = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Debug|x86.ActiveCfg = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Debug|x86.Build.0 = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|Any CPU.ActiveCfg = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|Any CPU.Build.0 = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|x64.ActiveCfg = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|x64.Build.0 = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|x86.ActiveCfg = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release - Signed|x86.Build.0 = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release|Any CPU.ActiveCfg = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release|Any CPU.Build.0 = Debug|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release|x64.ActiveCfg = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release|x86.ActiveCfg = Release|Win32
+ {D84D100A-7C21-4CCB-B16E-0FB37137C16C}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C840C71C-E65B-4378-883D-7F0DCB4E5027}
+ EndGlobalSection
+EndGlobal
diff --git a/SignallingServer/App.config b/SignallingServer/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/SignallingServer/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SignallingServer/Program.cs b/SignallingServer/Program.cs
new file mode 100644
index 0000000..48c861e
--- /dev/null
+++ b/SignallingServer/Program.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace SignallingServer
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ if (args.Length != 1)
+ {
+ Console.WriteLine("Usage: SignallingServer.exe LISTEN_PORT");
+ Console.WriteLine("Example: SignallingServer.exe 5880");
+ }
+
+ UdtServer server = new UdtServer(Convert.ToUInt16(args[0]));
+ server.Start();
+ }
+ }
+}
diff --git a/SignallingServer/Properties/AssemblyInfo.cs b/SignallingServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..44544ea
--- /dev/null
+++ b/SignallingServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SignallingServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SignallingServer")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e7364570-f20d-4875-8129-67b293ec46b4")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
diff --git a/SignallingServer/SignallingServer.csproj b/SignallingServer/SignallingServer.csproj
new file mode 100644
index 0000000..41842e7
--- /dev/null
+++ b/SignallingServer/SignallingServer.csproj
@@ -0,0 +1,73 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E7364570-F20D-4875-8129-67B293EC46B4}
+ Exe
+ SignallingServer
+ SignallingServer
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+
+
+ {cfa7453b-8b9b-4112-af04-f72c3d431100}
+ UdtProtocol
+
+
+
+
\ No newline at end of file
diff --git a/SignallingServer/UdtServer.cs b/SignallingServer/UdtServer.cs
new file mode 100644
index 0000000..c7efa07
--- /dev/null
+++ b/SignallingServer/UdtServer.cs
@@ -0,0 +1,103 @@
+using log4net;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace SignallingServer
+{
+ public class UdtServer
+ {
+ private static ILog LOGGER = LogManager.GetLogger(typeof(UdtServer));
+
+ private ushort port;
+ private bool started;
+ private Udt.Socket socket;
+
+ public UdtServer(ushort port)
+ {
+ this.port = port;
+ }
+
+
+ public void Start()
+ {
+ try
+ {
+ if (started)
+ {
+ LOGGER.Error("Already started");
+ }
+
+ started = true;
+ socket = new Udt.Socket(AddressFamily.InterNetwork, SocketType.Stream);
+ socket.Bind(IPAddress.Any, port);
+
+ LOGGER.Info("server started with port: " + port);
+ ListenPeers();
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("Socket Loop Exception", ex);
+ throw ex;
+ }
+ finally
+ {
+ started = false;
+ ShutdownSocket();
+ }
+ }
+
+ private void ListenPeers()
+ {
+ socket.Listen(1);
+ while (started)
+ {
+ LOGGER.Info("waiting for first client connection");
+ Udt.Socket client1 = socket.Accept();
+ IPEndPoint client1Endpoint = client1.RemoteEndPoint;
+ LOGGER.Info("first client connected. IP:" + client1Endpoint.ToString());
+
+ Udt.Socket client2 = socket.Accept();
+ IPEndPoint client2Endpoint = client2.RemoteEndPoint;
+ LOGGER.Info("second client connected. IP:" + client2Endpoint.ToString());
+
+
+ LOGGER.Info("sending client1 endpoint to client 2");
+ SendAddressTo(client1Endpoint, client2);
+
+ LOGGER.Info("sending client2 endpoint to client 1");
+ SendAddressTo(client2Endpoint, client1);
+
+ LOGGER.Info("PEERS CONNECTED");
+
+ }
+ }
+ private void ShutdownSocket()
+ {
+ try
+ {
+ socket.Close();
+ socket.Dispose();
+ }
+ catch (Exception ex)
+ {
+ LOGGER.Error("Socket close exception", ex);
+ }
+ }
+
+ private void SendAddressTo(IPEndPoint endPoint, Udt.Socket socket)
+ {
+ using (Udt.NetworkStream st = new Udt.NetworkStream(socket))
+ {
+ byte[] addrBytes = endPoint.Address.GetAddressBytes();
+ byte[] portBytes = BitConverter.GetBytes(endPoint.Port);
+
+ byte[] endPointInfoArr = new byte[8];
+ Array.Copy(addrBytes, 0, endPointInfoArr, 0, addrBytes.Length);
+
+ Array.Copy(portBytes, 0, endPointInfoArr, 4, portBytes.Length);
+ st.Write(endPointInfoArr, 0, endPointInfoArr.Length);
+ }
+ }
+ }
+}
diff --git a/SignallingServer/log4net.config b/SignallingServer/log4net.config
new file mode 100644
index 0000000..ad9365d
--- /dev/null
+++ b/SignallingServer/log4net.config
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SignallingServer/msvcp100.dll b/SignallingServer/msvcp100.dll
new file mode 100644
index 0000000..8502dfa
Binary files /dev/null and b/SignallingServer/msvcp100.dll differ
diff --git a/SignallingServer/msvcr100.dll b/SignallingServer/msvcr100.dll
new file mode 100644
index 0000000..3e82b1a
Binary files /dev/null and b/SignallingServer/msvcr100.dll differ
diff --git a/SignallingServer/packages.config b/SignallingServer/packages.config
new file mode 100644
index 0000000..f651f6c
--- /dev/null
+++ b/SignallingServer/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/UdtProtocol/Ack2Packet.cpp b/UdtProtocol/Ack2Packet.cpp
new file mode 100644
index 0000000..c75ff79
--- /dev/null
+++ b/UdtProtocol/Ack2Packet.cpp
@@ -0,0 +1,62 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "Ack2Packet.h"
+
+#include
+#include
+
+using namespace Udt;
+
+Ack2Packet::Ack2Packet(const CPacket* packet)
+ : ControlPacket(packet)
+{
+}
+
+Ack2Packet::Ack2Packet(void)
+{
+ int seqNo = 0;
+ _packet->pack(TypeCode, &seqNo);
+}
+
+int Ack2Packet::SequenceNumber::get(void)
+{
+ AssertNotDisposed();
+ return _packet->m_iMsgNo;
+}
+
+void Ack2Packet::SequenceNumber::set(int value)
+{
+ AssertIsMutable();
+ _packet->m_iMsgNo = value;
+}
diff --git a/UdtProtocol/Ack2Packet.h b/UdtProtocol/Ack2Packet.h
new file mode 100644
index 0000000..a636305
--- /dev/null
+++ b/UdtProtocol/Ack2Packet.h
@@ -0,0 +1,64 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ControlPacket.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol acknowledgement of acknowledgement (ACK-2) control packet.
+ ///
+ public ref class Ack2Packet : public ControlPacket
+ {
+ internal:
+ Ack2Packet(const CPacket* packet);
+
+ literal int TypeCode = 6;
+
+ public:
+
+ Ack2Packet(void);
+
+ ///
+ /// Acknowledgement (ACK) packet sequence number. Default value is 0.
+ ///
+ /// If attempting to set the value and is false.
+ property int SequenceNumber {
+ int get(void);
+ void set(int value);
+ }
+ };
+}
diff --git a/UdtProtocol/AssemblyInfo.cpp b/UdtProtocol/AssemblyInfo.cpp
new file mode 100644
index 0000000..b90e256
--- /dev/null
+++ b/UdtProtocol/AssemblyInfo.cpp
@@ -0,0 +1,72 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "stdafx.h"
+
+using namespace System;
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("Udt")];
+[assembly:AssemblyDescriptionAttribute("UDT.Net wrapper library")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("")];
+[assembly:AssemblyProductAttribute("Udt")];
+[assembly:AssemblyCopyrightAttribute("Copyright (c) 2011")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("0.10.0.0")];
+
+[assembly:ComVisible(false)];
+
+[assembly:CLSCompliantAttribute(true)];
+
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
diff --git a/UdtProtocol/CCCWrapper.cpp b/UdtProtocol/CCCWrapper.cpp
new file mode 100644
index 0000000..1921f7a
--- /dev/null
+++ b/UdtProtocol/CCCWrapper.cpp
@@ -0,0 +1,192 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "CCCWrapper.h"
+#include "Packet.h"
+
+using namespace Udt;
+using namespace System;
+
+CCCWrapper::CCCWrapper(Udt::CongestionControl^ wrapped)
+ : _wrapped(nullptr)
+{
+ if (wrapped->_cccWrapper != NULL) throw gcnew InvalidOperationException("Congestion control object already in use. Can not reuse congestion control objects.");
+ if (wrapped->IsDisposed) throw gcnew InvalidOperationException("Invalid congestion control object. Object is disposed.");
+
+ _wrapped = wrapped;
+ _wrapped->_cccWrapper = this;
+}
+
+CCCWrapper::~CCCWrapper(void)
+{
+}
+
+void CCCWrapper::onPktReceived(const CPacket* packet)
+{
+ Packet^ managedPacket = Packet::Wrap(packet);
+
+ __try
+ {
+ _wrapped->OnPacketReceived(managedPacket);
+ }
+ __finally
+ {
+ delete managedPacket;
+ }
+}
+
+void CCCWrapper::onPktSent(const CPacket* packet)
+{
+ Packet^ managedPacket = Packet::Wrap(packet);
+
+ __try
+ {
+ _wrapped->OnPacketSent(managedPacket);
+ }
+ __finally
+ {
+ delete managedPacket;
+ }
+}
+
+void CCCWrapper::processCustomMsg(const CPacket* packet)
+{
+ Packet^ managedPacket = Packet::Wrap(packet);
+
+ __try
+ {
+ _wrapped->ProcessCustomMessage(managedPacket);
+ }
+ __finally
+ {
+ delete managedPacket;
+ }
+}
+
+void CCCWrapper::onLoss(const int32_t* losslist, int size)
+{
+ NativeIntArray^ list = gcnew NativeIntArray(losslist, size);
+
+ __try
+ {
+ _wrapped->OnLoss(list);
+ }
+ __finally
+ {
+ delete list;
+ }
+}
+
+void CCCWrapper::setACKTimer(TimeSpan value)
+{
+ if (value.CompareTo(TimeSpan::Zero) < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ int ms = (int)value.TotalMilliseconds;
+ this->CCC::setACKTimer(ms);
+}
+
+void CCCWrapper::setACKInterval(int packets)
+{
+ if (packets < 0)
+ throw gcnew System::ArgumentOutOfRangeException("packets", packets, "Value must be greater than or equal to 0.");
+
+ this->CCC::setACKInterval(packets);
+}
+
+void CCCWrapper::setRTO(TimeSpan value)
+{
+ if (value.CompareTo(TimeSpan::Zero) < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ int us = (int)(value.Ticks / 10);
+ this->CCC::setRTO(us);
+}
+
+TraceInfo^ CCCWrapper::getPerfInfo(void)
+{
+ const UDT::TRACEINFO* trace_info = this->CCC::getPerfInfo();
+ return gcnew TraceInfo(*trace_info);
+}
+
+void CCCWrapper::setPacketSendPeriod(System::TimeSpan value)
+{
+ if (value.CompareTo(TimeSpan::Zero) < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ m_dPktSndPeriod = value.Ticks / 10.0;
+}
+
+System::TimeSpan CCCWrapper::getPacketSendPeriod(void) const
+{
+ return System::TimeSpan((__int64)(m_dPktSndPeriod * 10));
+}
+
+void CCCWrapper::setWindowSize(int value)
+{
+ if (value < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ m_dCWndSize = value;
+}
+
+int CCCWrapper::getWindowSize() const
+{
+ return (int)m_dCWndSize;
+}
+
+void CCCWrapper::setRoundTripTime(System::TimeSpan value)
+{
+ if (value.CompareTo(TimeSpan::Zero) < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ m_iRTT = (int)(value.Ticks / 10);
+}
+
+System::TimeSpan CCCWrapper::getRoundTripTime(void) const
+{
+ return System::TimeSpan(m_iRTT * 10);
+}
+
+void CCCWrapper::setMaxPacketSize(int value)
+{
+ if (value < 0)
+ throw gcnew System::ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ m_iMSS = value;
+}
+
+int CCCWrapper::getMaxPacketSize() const
+{
+ return m_iMSS;
+}
diff --git a/UdtProtocol/CCCWrapper.h b/UdtProtocol/CCCWrapper.h
new file mode 100644
index 0000000..a04c944
--- /dev/null
+++ b/UdtProtocol/CCCWrapper.h
@@ -0,0 +1,81 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "CongestionControl.h"
+#include "NativeIntArray.h"
+#include "TraceInfo.h"
+#include
+#include
+
+namespace Udt
+{
+ ref class Packet;
+
+ class CCCWrapper : public CCC
+ {
+ private:
+ gcroot _wrapped;
+
+ public:
+
+ CCCWrapper(CongestionControl^ wrapped);
+ virtual ~CCCWrapper(void);
+
+ virtual void init() { _wrapped->Initialize(); }
+ virtual void close() { _wrapped->Close(); }
+ virtual void onTimeout() { _wrapped->OnTimeout(); }
+ virtual void onACK(int32_t ack) { _wrapped->OnAck(ack); }
+ virtual void onLoss(const int32_t* losslist, int size);
+ virtual void onPktReceived(const CPacket* packet);
+ virtual void onPktSent(const CPacket*);
+ virtual void processCustomMsg(const CPacket*);
+
+ void setACKTimer(System::TimeSpan value);
+ void setACKInterval(int packets);
+ void setRTO(System::TimeSpan value);
+ TraceInfo^ getPerfInfo(void);
+
+ void setPacketSendPeriod(System::TimeSpan value);
+ System::TimeSpan getPacketSendPeriod(void) const;
+
+ void setWindowSize(int value);
+ int getWindowSize() const;
+
+ void setRoundTripTime(System::TimeSpan value);
+ System::TimeSpan getRoundTripTime(void) const;
+
+ void setMaxPacketSize(int value);
+ int getMaxPacketSize() const;
+ };
+}
diff --git a/UdtProtocol/CCCWrapperFactory.cpp b/UdtProtocol/CCCWrapperFactory.cpp
new file mode 100644
index 0000000..405347b
--- /dev/null
+++ b/UdtProtocol/CCCWrapperFactory.cpp
@@ -0,0 +1,59 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+
+#include "ICongestionControlFactory.h"
+
+#include "CCCWrapperFactory.h"
+#include "CCCWrapper.h"
+
+using namespace Udt;
+
+CCCWrapperFactory::CCCWrapperFactory(ICongestionControlFactory^ managedFactory)
+ : _managedFactory(managedFactory)
+{
+}
+
+CCCWrapperFactory::~CCCWrapperFactory(void)
+{
+}
+
+CCC* CCCWrapperFactory::create()
+{
+ return new CCCWrapper(_managedFactory->CreateCongestionControl());
+}
+
+CCCVirtualFactory* CCCWrapperFactory::clone()
+{
+ return new CCCWrapperFactory(_managedFactory);
+}
diff --git a/UdtProtocol/CCCWrapperFactory.h b/UdtProtocol/CCCWrapperFactory.h
new file mode 100644
index 0000000..27067ba
--- /dev/null
+++ b/UdtProtocol/CCCWrapperFactory.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+#include
+
+namespace Udt
+{
+ interface class ICongestionControlFactory;
+
+ class CCCWrapperFactory : public CCCVirtualFactory
+ {
+ private:
+ gcroot _managedFactory;
+
+ public:
+
+ CCCWrapperFactory(ICongestionControlFactory^ managedFactory);
+ virtual ~CCCWrapperFactory(void);
+
+ virtual CCC* create();
+ virtual CCCVirtualFactory* clone();
+ };
+}
diff --git a/UdtProtocol/CongestionControl.cpp b/UdtProtocol/CongestionControl.cpp
new file mode 100644
index 0000000..a22bd14
--- /dev/null
+++ b/UdtProtocol/CongestionControl.cpp
@@ -0,0 +1,122 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "CongestionControl.h"
+#include "Packet.h"
+
+#include "CCCWrapper.h"
+
+using namespace Udt;
+using namespace System;
+
+CongestionControl::CongestionControl(void)
+ : _cccWrapper(NULL), _isDisposed(false)
+{
+}
+
+void CongestionControl::AssertNotDisposed()
+{
+ if (this->IsDisposed) throw gcnew ObjectDisposedException(this->ToString());
+}
+
+void CongestionControl::SetAckTimer(System::TimeSpan value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setACKTimer(value);
+}
+
+void CongestionControl::SetAckInterval(int value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setACKInterval(value);
+}
+
+void CongestionControl::SetReadTimeout(System::TimeSpan value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setRTO(value);
+}
+
+TraceInfo^ CongestionControl::PerformanceInfo::get(void)
+{
+ AssertNotDisposed();
+ return _cccWrapper->getPerfInfo();
+}
+
+void CongestionControl::PacketSendPeriod::set(System::TimeSpan value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setPacketSendPeriod(value);
+}
+
+System::TimeSpan CongestionControl::PacketSendPeriod::get(void)
+{
+ AssertNotDisposed();
+ return _cccWrapper->getPacketSendPeriod();
+}
+
+void CongestionControl::WindowSize::set(int value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setWindowSize(value);
+}
+
+int CongestionControl::WindowSize::get(void)
+{
+ AssertNotDisposed();
+ return _cccWrapper->getWindowSize();
+}
+
+void CongestionControl::MaxPacketSize::set(int value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setMaxPacketSize(value);
+}
+
+int CongestionControl::MaxPacketSize::get(void)
+{
+ AssertNotDisposed();
+ return _cccWrapper->getMaxPacketSize();
+}
+
+void CongestionControl::RoundtripTime::set(System::TimeSpan value)
+{
+ AssertNotDisposed();
+ _cccWrapper->setRoundTripTime(value);
+}
+
+System::TimeSpan CongestionControl::RoundtripTime::get(void)
+{
+ AssertNotDisposed();
+ return _cccWrapper->getRoundTripTime();
+}
diff --git a/UdtProtocol/CongestionControl.h b/UdtProtocol/CongestionControl.h
new file mode 100644
index 0000000..f5aef81
--- /dev/null
+++ b/UdtProtocol/CongestionControl.h
@@ -0,0 +1,112 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "TraceInfo.h"
+
+namespace Udt
+{
+ ref class Packet;
+ class CCCWrapper;
+
+ public ref class CongestionControl abstract
+ {
+ internal:
+ CCCWrapper* _cccWrapper;
+ bool _isDisposed;
+
+ protected:
+ CongestionControl(void);
+
+ public:
+ virtual void Initialize() { }
+ virtual void Close() { }
+
+ property bool IsDisposed { bool get(void) { return _isDisposed; } }
+
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ virtual void OnAck(int ack) { }
+ virtual void OnLoss(System::Collections::Generic::IList^ lossList) { }
+ virtual void OnTimeout() { }
+ virtual void OnPacketSent(Packet^ packet) { }
+ virtual void OnPacketReceived(Packet^ packet) { }
+ virtual void ProcessCustomMessage(Packet^ packet) { }
+
+ protected:
+
+ void AssertNotDisposed();
+
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ void SetAckTimer(System::TimeSpan value);
+
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ void SetAckInterval(int value);
+
+ void SetReadTimeout(System::TimeSpan value);
+
+ property TraceInfo^ PerformanceInfo { TraceInfo^ get(void); }
+
+ property System::TimeSpan PacketSendPeriod
+ {
+ System::TimeSpan get(void);
+ void set(System::TimeSpan value);
+ }
+
+ property int WindowSize
+ {
+ int get(void);
+ void set(int value);
+ }
+
+ property int MaxPacketSize
+ {
+ int get(void);
+ void set(int value);
+ }
+
+ property System::TimeSpan RoundtripTime
+ {
+ System::TimeSpan get(void);
+ void set(System::TimeSpan value);
+ }
+ };
+}
diff --git a/UdtProtocol/CongestionControlFactory.cpp b/UdtProtocol/CongestionControlFactory.cpp
new file mode 100644
index 0000000..ae29941
--- /dev/null
+++ b/UdtProtocol/CongestionControlFactory.cpp
@@ -0,0 +1,37 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "CongestionControlFactory.h"
+
+using namespace Udt;
+using namespace System;
diff --git a/UdtProtocol/CongestionControlFactory.h b/UdtProtocol/CongestionControlFactory.h
new file mode 100644
index 0000000..73924fe
--- /dev/null
+++ b/UdtProtocol/CongestionControlFactory.h
@@ -0,0 +1,82 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ICongestionControlFactory.h"
+
+namespace Udt
+{
+ ///
+ /// Factory that creates instances for a
+ /// .
+ ///
+ ///
+ /// must return a new instance every
+ /// time it is invoked. If the same instance returns the same instance more
+ /// than once, the result is undefined behavior.
+ ///
+ public ref class CongestionControlFactory : public ICongestionControlFactory
+ {
+ private:
+
+ initonly System::Func^ _callback;
+
+ public:
+
+ ///
+ /// Initialize a new instance that creates instances of
+ /// using the provided callback.
+ ///
+ /// Function to invoke to create new instances of
+ /// If is null.
+ CongestionControlFactory(System::Func^ callback)
+ : _callback(callback)
+ {
+ if (callback == nullptr) throw gcnew System::ArgumentNullException("callback");
+ }
+
+ ///
+ /// Create a new instance.
+ ///
+ ///
+ /// This method must return a new instance every time it is invoked.
+ /// If the same instance returns the same instance more than once,
+ /// the result is undefined behavior.
+ ///
+ /// New congestion control object.
+ virtual CongestionControl^ CreateCongestionControl(void)
+ {
+ return _callback();
+ }
+ };
+}
diff --git a/UdtProtocol/CongestionPacket.cpp b/UdtProtocol/CongestionPacket.cpp
new file mode 100644
index 0000000..3a35d52
--- /dev/null
+++ b/UdtProtocol/CongestionPacket.cpp
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "CongestionPacket.h"
+
+#include
+#include
+
+using namespace Udt;
+
+CongestionPacket::CongestionPacket(const CPacket* packet)
+ : ControlPacket(packet)
+{
+}
+
+CongestionPacket::CongestionPacket(void)
+{
+ _packet->pack(TypeCode, NULL, NULL);
+}
diff --git a/UdtProtocol/CongestionPacket.h b/UdtProtocol/CongestionPacket.h
new file mode 100644
index 0000000..c5a5db0
--- /dev/null
+++ b/UdtProtocol/CongestionPacket.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ControlPacket.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol congestion/delay warning control packet.
+ ///
+ public ref class CongestionPacket : public ControlPacket
+ {
+ internal:
+ CongestionPacket(const CPacket* packet);
+
+ literal int TypeCode = 4;
+
+ public:
+
+ CongestionPacket(void);
+ };
+}
diff --git a/UdtProtocol/ControlPacket.cpp b/UdtProtocol/ControlPacket.cpp
new file mode 100644
index 0000000..7136f6b
--- /dev/null
+++ b/UdtProtocol/ControlPacket.cpp
@@ -0,0 +1,52 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "ControlPacket.h"
+
+#include
+#include
+
+using namespace Udt;
+
+ControlPacket::ControlPacket(void)
+{
+}
+
+ControlPacket::ControlPacket(const CPacket* packet)
+ : Packet(packet)
+{
+}
+
+ControlPacket::~ControlPacket(void)
+{
+}
diff --git a/UdtProtocol/ControlPacket.h b/UdtProtocol/ControlPacket.h
new file mode 100644
index 0000000..1d2a6fd
--- /dev/null
+++ b/UdtProtocol/ControlPacket.h
@@ -0,0 +1,53 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "Packet.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol control packet.
+ ///
+ public ref class ControlPacket : public Packet
+ {
+ internal:
+ ControlPacket(void);
+ ControlPacket(const CPacket* packet);
+
+ public:
+ virtual ~ControlPacket(void);
+ };
+}
diff --git a/UdtProtocol/DataPacket.cpp b/UdtProtocol/DataPacket.cpp
new file mode 100644
index 0000000..200790c
--- /dev/null
+++ b/UdtProtocol/DataPacket.cpp
@@ -0,0 +1,205 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "DataPacket.h"
+
+#include
+#include
+
+using namespace Udt;
+using namespace System;
+
+DataPacket::DataPacket(const CPacket* packet)
+ : Packet(packet), _capacity(packet->getLength())
+{
+}
+
+DataPacket::DataPacket(void)
+ : _capacity(0)
+{
+}
+
+DataPacket::~DataPacket(void)
+{
+}
+
+void DataPacket::FreePacketData()
+{
+ delete [] _packet->m_pcData;
+}
+
+Udt::MessageBoundary DataPacket::MessageBoundary::get(void)
+{
+ AssertNotDisposed();
+ return (Udt::MessageBoundary)_packet->getMsgBoundary();
+}
+
+void DataPacket::MessageBoundary::set(Udt::MessageBoundary value)
+{
+ AssertIsMutable();
+
+ int iValue = (int)value;
+ if (iValue < 0 || iValue > 3) throw gcnew ArgumentOutOfRangeException("value", value, "Invalid message boundary flag.");
+
+ _packet->m_iMsgNo = (_packet->m_iMsgNo & 0x3FFFFFFF) | (iValue << 30);
+}
+
+bool DataPacket::InOrder::get(void)
+{
+ AssertNotDisposed();
+ return _packet->getMsgOrderFlag();
+}
+
+void DataPacket::InOrder::set(bool value)
+{
+ AssertIsMutable();
+
+ if (value)
+ _packet->m_iMsgNo |= 0x20000000;
+ else
+ _packet->m_iMsgNo &= 0xDFFFFFFF;
+}
+
+int DataPacket::MessageNumber::get(void)
+{
+ AssertNotDisposed();
+ return _packet->getMsgSeq();
+}
+
+void DataPacket::MessageNumber::set(int value)
+{
+ AssertIsMutable();
+ if (value < 0 || value > MaxMessageNumber) throw gcnew ArgumentOutOfRangeException("value", value, String::Concat("Value must be between 0 and ", MaxMessageNumber, "."));
+
+ _packet->m_iMsgNo = (_packet->m_iMsgNo & ~MaxMessageNumber) | value;
+}
+
+int DataPacket::PacketNumber::get(void)
+{
+ AssertNotDisposed();
+ return _packet->m_iSeqNo;
+}
+
+void DataPacket::PacketNumber::set(int value)
+{
+ AssertIsMutable();
+ if (value < 0) throw gcnew ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+ _packet->m_iSeqNo = value;
+}
+
+int DataPacket::DataLength::get(void)
+{
+ AssertNotDisposed();
+ return _packet->getLength();
+}
+
+void DataPacket::DataLength::set(int value)
+{
+ AssertIsMutable();
+ if (value < 0) throw gcnew ArgumentOutOfRangeException("value", value, "Value must be greater than or equal to 0.");
+
+ EnsureCapacity(value);
+ _packet->setLength(value);
+}
+
+int DataPacket::DataCapacity::get(void)
+{
+ AssertNotDisposed();
+ return _capacity;
+}
+
+void DataPacket::EnsureCapacity(int value)
+{
+ if (value > _capacity)
+ {
+ int newCapacity = value;
+
+ if (newCapacity < 256)
+ newCapacity = 256;
+ else if (newCapacity < _capacity * 2)
+ newCapacity = _capacity * 2;
+
+ char* newBuf = new char[newCapacity];
+ memcpy(newBuf, _packet->m_pcData, _packet->getLength());
+ delete [] _packet->m_pcData;
+ _packet->m_pcData = newBuf;
+ _capacity = newCapacity;
+ }
+}
+
+int DataPacket::Read(int dataOffset, cli::array^ buffer, int bufferOffset, int bufferCount)
+{
+ AssertNotDisposed();
+
+ int packetLen = _packet->getLength();
+
+ if (dataOffset < 0 || dataOffset > packetLen) throw gcnew ArgumentOutOfRangeException("dataOffset", dataOffset, String::Format("Value must be greater than or equal to 0 and less than the packet length ({0})", packetLen));
+ if (buffer == nullptr) throw gcnew ArgumentNullException("buffer");
+ if (bufferOffset < 0) throw gcnew ArgumentOutOfRangeException("bufferOffset", bufferOffset, "Value must be greater than or equal to 0.");
+ if (bufferCount < 0) throw gcnew ArgumentOutOfRangeException("bufferCount", bufferCount, "Value must be greater than or equal to 0.");
+ if (bufferOffset + bufferCount > buffer->Length) throw gcnew ArgumentException("Invalid buffer offset and count.");
+
+ int readCount = min(packetLen - dataOffset, bufferCount);
+
+ if (readCount > 0)
+ {
+ pin_ptr bufferPin = &buffer[0];
+ memcpy(bufferPin + bufferOffset, _packet->m_pcData + dataOffset, readCount);
+ }
+
+ return readCount;
+}
+
+void DataPacket::Write(int dataOffset, cli::array^ buffer, int bufferOffset, int bufferCount)
+{
+ AssertNotDisposed();
+
+ if (dataOffset < 0) throw gcnew ArgumentOutOfRangeException("dataOffset", dataOffset, "Value must be greater than or equal to 0");
+ if (buffer == nullptr) throw gcnew ArgumentNullException("buffer");
+ if (bufferOffset < 0) throw gcnew ArgumentOutOfRangeException("bufferOffset", bufferOffset, "Value must be greater than or equal to 0.");
+ if (bufferCount < 0) throw gcnew ArgumentOutOfRangeException("bufferCount", bufferCount, "Value must be greater than or equal to 0.");
+ if (bufferOffset + bufferCount > buffer->Length) throw gcnew ArgumentException("Invalid buffer offset and count.");
+
+ int requiredLength = dataOffset + bufferCount;
+
+ if (requiredLength > 0)
+ {
+ EnsureCapacity(requiredLength);
+
+ if (requiredLength > _packet->getLength())
+ _packet->setLength(requiredLength);
+
+ pin_ptr bufferPin = &buffer[0];
+ memcpy(_packet->m_pcData + dataOffset, bufferPin + bufferOffset, bufferCount);
+ }
+}
diff --git a/UdtProtocol/DataPacket.h b/UdtProtocol/DataPacket.h
new file mode 100644
index 0000000..f4f9700
--- /dev/null
+++ b/UdtProtocol/DataPacket.h
@@ -0,0 +1,178 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "Packet.h"
+#include "MessageBoundary.h"
+
+namespace Udt
+{
+ ///
+ /// UDT protocol data packet.
+ ///
+ public ref class DataPacket : public Packet
+ {
+ private:
+
+ int _capacity;
+
+ void EnsureCapacity(int value);
+
+ protected:
+
+ virtual void FreePacketData() override;
+
+ internal:
+
+ DataPacket(const CPacket* packet);
+
+ public:
+ DataPacket(void);
+ virtual ~DataPacket(void);
+
+ ///
+ /// Get or set the location of the packet in the stream.
+ /// Default value is None.
+ ///
+ /// If is invalid.
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property Udt::MessageBoundary MessageBoundary {
+ Udt::MessageBoundary get(void);
+ void set(Udt::MessageBoundary value);
+ }
+
+ ///
+ /// Get or set true if the packet in-order delivery for the packet is
+ /// required. Default value is false.
+ ///
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property bool InOrder {
+ bool get(void);
+ void set(bool value);
+ }
+
+ ///
+ /// Get or set the message sequence number for the packet.
+ /// Default value is 0.
+ ///
+ /// If is less than 0 or greater than .
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property int MessageNumber {
+ int get(void);
+ void set(int value);
+ }
+
+ ///
+ /// Get or set the packet sequence number.
+ /// Default value is 0.
+ ///
+ /// If is less than 0.
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property int PacketNumber {
+ int get(void);
+ void set(int value);
+ }
+
+ ///
+ /// Get or set the length of the packet payload, in bytes.
+ /// Default value is 0.
+ ///
+ /// If is less than 0.
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property int DataLength {
+ int get(void);
+ void set(int value);
+ }
+
+ ///
+ /// Get the space allocated to the packet payload. This may be greater
+ /// than or equal to .
+ ///
+ /// If the object has been disposed.
+ property int DataCapacity {
+ int get(void);
+ }
+
+ ///
+ /// Read from the packet payload data.
+ ///
+ /// Offset into the packet data to start reading at.
+ /// Buffer to read packet data into.
+ /// Offset into the to copy data to.
+ /// Maximum number of bytes to copy from the packet.
+ /// Number of bytes read into .
+ /// If is null.
+ ///
+ /// If is less than 0 or greater than .
+ /// - or -
+ /// If or is less than 0
+ ///
+ /// If the sum of and is larger than the length.
+ /// If the object has been disposed.
+ int Read(int dataOffset, cli::array^ buffer, int bufferOffset, int bufferCount);
+
+ ///
+ /// Write to the packet payload data.
+ ///
+ ///
+ /// If the sum of and
+ /// is greater than , the packet's payload space
+ /// is expanded as needed.
+ ///
+ /// Offset into the packet data to start writing to.
+ /// Buffer to copy packet data from.
+ /// Offset into the to start reading.
+ /// Maximum number of bytes to read from .
+ /// If is null.
+ ///
+ /// If is less than 0.
+ /// - or -
+ /// If or is less than 0
+ ///
+ /// If the sum of and is larger than the length.
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ void Write(int dataOffset, cli::array^ buffer, int bufferOffset, int bufferCount);
+
+ ///
+ /// Maximum allowed value for .
+ ///
+ /// 536,870,911 (0x1FFFFFFF)
+ literal int MaxMessageNumber = 0x1FFFFFFF;
+ };
+}
diff --git a/UdtProtocol/ErrorPacket.cpp b/UdtProtocol/ErrorPacket.cpp
new file mode 100644
index 0000000..a503dd9
--- /dev/null
+++ b/UdtProtocol/ErrorPacket.cpp
@@ -0,0 +1,67 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "ErrorPacket.h"
+
+#include
+#include
+
+using namespace Udt;
+
+ErrorPacket::ErrorPacket(const CPacket* packet)
+ : ControlPacket(packet)
+{
+}
+
+ErrorPacket::ErrorPacket(void)
+{
+ int errorCode = 0;
+ _packet->pack(TypeCode, &errorCode, NULL);
+}
+
+ErrorPacket::ErrorPacket(int errorCode)
+{
+ _packet->pack(TypeCode, &errorCode, NULL);
+}
+
+int ErrorPacket::ErrorCode::get(void)
+{
+ AssertNotDisposed();
+ return _packet->m_iMsgNo;
+}
+
+void ErrorPacket::ErrorCode::set(int value)
+{
+ AssertIsMutable();
+ _packet->m_iMsgNo = value;
+}
diff --git a/UdtProtocol/ErrorPacket.h b/UdtProtocol/ErrorPacket.h
new file mode 100644
index 0000000..4931f24
--- /dev/null
+++ b/UdtProtocol/ErrorPacket.h
@@ -0,0 +1,65 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ControlPacket.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol error signal control packet.
+ ///
+ public ref class ErrorPacket : public ControlPacket
+ {
+ internal:
+ ErrorPacket(const CPacket* packet);
+
+ literal int TypeCode = 8;
+
+ public:
+
+ ErrorPacket(void);
+ ErrorPacket(int errorCode);
+
+ ///
+ /// Get or set the error code. Default value is 0.
+ ///
+ /// If attempting to set the value and is false.
+ property int ErrorCode {
+ int get(void);
+ void set(int value);
+ }
+ };
+}
diff --git a/UdtProtocol/ICongestionControlFactory.cpp b/UdtProtocol/ICongestionControlFactory.cpp
new file mode 100644
index 0000000..bcb4a48
--- /dev/null
+++ b/UdtProtocol/ICongestionControlFactory.cpp
@@ -0,0 +1,34 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "ICongestionControlFactory.h"
diff --git a/UdtProtocol/ICongestionControlFactory.h b/UdtProtocol/ICongestionControlFactory.h
new file mode 100644
index 0000000..cd15688
--- /dev/null
+++ b/UdtProtocol/ICongestionControlFactory.h
@@ -0,0 +1,62 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+namespace Udt
+{
+ ref class CongestionControl;
+ ref class Socket;
+
+ ///
+ /// Factory that creates instances for a
+ /// .
+ ///
+ ///
+ /// must return a new instance every
+ /// time it is invoked. If the same instance returns the same instance more
+ /// than once, the result is undefined behavior.
+ ///
+ public interface class ICongestionControlFactory
+ {
+ ///
+ /// Create a new instance.
+ ///
+ ///
+ /// This method must return a new instance every time it is invoked.
+ /// If the same instance returns the same instance more than once,
+ /// the result is undefined behavior.
+ ///
+ /// New congestion control object.
+ CongestionControl^ CreateCongestionControl();
+ };
+}
diff --git a/UdtProtocol/KeepAlivePacket.cpp b/UdtProtocol/KeepAlivePacket.cpp
new file mode 100644
index 0000000..b67d9c5
--- /dev/null
+++ b/UdtProtocol/KeepAlivePacket.cpp
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "KeepAlivePacket.h"
+
+#include
+#include
+
+using namespace Udt;
+
+KeepAlivePacket::KeepAlivePacket(const CPacket* packet)
+ : ControlPacket(packet)
+{
+}
+
+KeepAlivePacket::KeepAlivePacket(void)
+{
+ _packet->pack(TypeCode, NULL, NULL);
+}
diff --git a/UdtProtocol/KeepAlivePacket.h b/UdtProtocol/KeepAlivePacket.h
new file mode 100644
index 0000000..eba295a
--- /dev/null
+++ b/UdtProtocol/KeepAlivePacket.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ControlPacket.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol keep-alive control packet.
+ ///
+ public ref class KeepAlivePacket : public ControlPacket
+ {
+ internal:
+ KeepAlivePacket(const CPacket* packet);
+
+ literal int TypeCode = 1;
+
+ public:
+
+ KeepAlivePacket(void);
+ };
+}
diff --git a/UdtProtocol/LocalTraceInfo.cpp b/UdtProtocol/LocalTraceInfo.cpp
new file mode 100644
index 0000000..eeb9e07
--- /dev/null
+++ b/UdtProtocol/LocalTraceInfo.cpp
@@ -0,0 +1,57 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "LocalTraceInfo.h"
+
+using namespace Udt;
+using namespace System;
+
+LocalTraceInfo::LocalTraceInfo(const UDT::TRACEINFO& copy)
+{
+ this->PacketsSent = copy.pktSent;
+ this->PacketsReceived = copy.pktRecv;
+ this->SendPacketsLost = copy.pktSndLoss;
+ this->ReceivePacketsLost = copy.pktRcvLoss;
+ this->PacketsRetransmitted = copy.pktRetrans;
+ this->AcksSent = copy.pktSentACK;
+ this->AcksReceived = copy.pktRecvACK;
+ this->NaksSent = copy.pktSentNAK;
+ this->NaksReceived = copy.pktRecvNAK;
+ this->SendMbps = copy.mbpsSendRate;
+ this->ReceiveMbps = copy.mbpsRecvRate;
+ this->SendDuration = FromMicroseconds(copy.usSndDuration);
+}
+
+LocalTraceInfo::LocalTraceInfo(void)
+{
+}
diff --git a/UdtProtocol/LocalTraceInfo.h b/UdtProtocol/LocalTraceInfo.h
new file mode 100644
index 0000000..7934823
--- /dev/null
+++ b/UdtProtocol/LocalTraceInfo.h
@@ -0,0 +1,129 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// Performance trace information local since the last time they were recorded.
+ ///
+ public ref class LocalTraceInfo
+ {
+ internal:
+ LocalTraceInfo(const UDT::TRACEINFO& copy);
+
+ public:
+ ///
+ /// Initialize a new instance with default values.
+ ///
+ LocalTraceInfo(void);
+
+ ///
+ /// Number of sent packets, including retransmissions.
+ ///
+ property __int64 PacketsSent;
+
+ ///
+ /// Number of received packets.
+ ///
+ property __int64 PacketsReceived;
+
+ ///
+ /// Number of lost packets, measured in the sending side.
+ ///
+ property int SendPacketsLost;
+
+ ///
+ /// Number of lost packets, measured in the receiving side.
+ ///
+ property int ReceivePacketsLost;
+
+ ///
+ /// Number of retransmitted packets, measured in the sending side.
+ ///
+ property int PacketsRetransmitted;
+
+ ///
+ /// Number of sent ACK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ property int AcksSent;
+
+ ///
+ /// Number of received ACK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ property int AcksReceived;
+
+ ///
+ /// Number of sent NAK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "NAK is the accepted abbreviation for negative acknowledgement in this context.")]
+ property int NaksSent;
+
+ ///
+ /// Number of received NAK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "NAK is the accepted abbreviation for negative acknowledgement in this context.")]
+ property int NaksReceived;
+
+ ///
+ /// Sending rate in Mbps.
+ ///
+ property double SendMbps;
+
+ ///
+ /// Receiving rate in Mbps.
+ ///
+ property double ReceiveMbps;
+
+ ///
+ /// Busy sending time (i.e., idle time exclusive).
+ ///
+ property System::TimeSpan SendDuration;
+ };
+}
diff --git a/UdtProtocol/Message.cpp b/UdtProtocol/Message.cpp
new file mode 100644
index 0000000..1d80892
--- /dev/null
+++ b/UdtProtocol/Message.cpp
@@ -0,0 +1,57 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "Message.h"
+
+using namespace Udt;
+
+Message::Message(cli::array^ array)
+{
+ _buffer = System::ArraySegment(array);
+ _timeToLive = Message::Infinite;
+}
+
+Message::Message(cli::array^ array, int offset, int count)
+{
+ _buffer = System::ArraySegment(array, offset, count);
+ _timeToLive = Message::Infinite;
+}
+
+Message::Message(System::ArraySegment buffer)
+{
+ if (buffer.Array == nullptr)
+ throw gcnew System::ArgumentException("Array can not be a null reference.", "buffer");
+
+ _buffer = buffer;
+ _timeToLive = Message::Infinite;
+}
diff --git a/UdtProtocol/Message.h b/UdtProtocol/Message.h
new file mode 100644
index 0000000..934d593
--- /dev/null
+++ b/UdtProtocol/Message.h
@@ -0,0 +1,130 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+namespace Udt
+{
+ ///
+ /// Message sent over a UDT socket.
+ ///
+ public ref class Message
+ {
+ public:
+
+ ///
+ /// Infinite .
+ ///
+ static initonly System::TimeSpan Infinite = System::TimeSpan(0, 0, 0, 0, -1);
+
+ ///
+ /// Maximum value for .
+ ///
+ static initonly System::TimeSpan Max = System::TimeSpan(0, 0, 0, 0, System::Int32::MaxValue);
+
+ private:
+ System::ArraySegment _buffer;
+ System::TimeSpan _timeToLive;
+
+ public:
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Array that contains the message bytes.
+ /// If is a null reference.
+ Message(cli::array^ array);
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Array that contains the message bytes.
+ /// Offset into that the message starts.
+ /// Number of bytes from to include in the message.
+ ///
+ /// If is a null reference.
+ ///
+ ///
+ /// If is negative.
+ ///
+ ///
+ /// If and do not
+ /// specify a valid range in .
+ ///
+ Message(cli::array^ array, int offset, int count);
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Array segment that contains the message bytes.
+ ///
+ /// If the array in is a null reference.
+ ///
+ Message(System::ArraySegment buffer);
+
+ ///
+ /// Gets the message content.
+ ///
+ property System::ArraySegment Buffer
+ {
+ System::ArraySegment get(void) { return _buffer; }
+ }
+
+ ///
+ /// True if the message should be delivered in order.
+ /// Default value is false.
+ ///
+ property bool InOrder;
+
+ ///
+ /// The time-to-live of the message.
+ /// Default value is .
+ ///
+ ///
+ /// If is not and is less
+ /// than or greater than
+ /// .
+ ///
+ property System::TimeSpan TimeToLive
+ {
+ System::TimeSpan get(void) { return _timeToLive; }
+
+ void set(System::TimeSpan value)
+ {
+ if (value != Message::Infinite && (value.CompareTo(System::TimeSpan::Zero) < 0 || value.CompareTo(Message::Max) > 0))
+ throw gcnew System::ArgumentOutOfRangeException("value", value, System::String::Concat("Value must be ", Infinite, " or between ", System::TimeSpan::Zero, " and ", Max, "."));
+
+ _timeToLive = value;
+ }
+ }
+ };
+}
diff --git a/UdtProtocol/MessageBoundary.h b/UdtProtocol/MessageBoundary.h
new file mode 100644
index 0000000..2975e36
--- /dev/null
+++ b/UdtProtocol/MessageBoundary.h
@@ -0,0 +1,44 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+namespace Udt
+{
+ public enum class MessageBoundary : char
+ {
+ None = 0,
+ Last = 1,
+ First = 2,
+ Solo = 3,
+ };
+}
diff --git a/UdtProtocol/NativeIntArray.cpp b/UdtProtocol/NativeIntArray.cpp
new file mode 100644
index 0000000..4b0d8b0
--- /dev/null
+++ b/UdtProtocol/NativeIntArray.cpp
@@ -0,0 +1,34 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "NativeIntArray.h"
diff --git a/UdtProtocol/NativeIntArray.h b/UdtProtocol/NativeIntArray.h
new file mode 100644
index 0000000..50ece19
--- /dev/null
+++ b/UdtProtocol/NativeIntArray.h
@@ -0,0 +1,222 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+namespace Udt
+{
+ ref class NativeIntArray : public System::Collections::Generic::IList
+ {
+ private:
+ const int* _data;
+ int _length;
+
+ void AssertIsValid()
+ {
+ if (_data == NULL)
+ throw gcnew System::InvalidOperationException("Internal native array is no longer valid.");
+ }
+
+ internal:
+ NativeIntArray(const int* data, int length)
+ {
+ _data = data;
+ _length = length;
+ }
+
+ ~NativeIntArray(void)
+ {
+ _data = NULL;
+ }
+
+ public:
+
+ virtual property int default[int]
+ {
+ int get(int index)
+ {
+ AssertIsValid();
+
+ if (index < 0 || index > _length)
+ throw gcnew System::ArgumentOutOfRangeException("index", index, "Value must be greater than or equal to 0 and less than the length of the list.");
+
+ return _data[index];
+ }
+
+ void set(int index, int value)
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+ }
+
+ virtual void Add(int item) = System::Collections::Generic::ICollection::Add
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+
+ virtual void Insert(int index, int item) = System::Collections::Generic::IList::Insert
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+
+ virtual void RemoveAt(int index) = System::Collections::Generic::IList::RemoveAt
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+
+ virtual bool Remove(int item) = System::Collections::Generic::ICollection::Remove
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+
+ virtual void Clear() = System::Collections::Generic::ICollection::Clear
+ {
+ throw gcnew System::NotSupportedException("Collection is read-only.");
+ }
+
+ virtual bool Contains(int item)
+ {
+ return IndexOf(item) >= 0;
+ }
+
+ virtual int IndexOf(int item)
+ {
+ AssertIsValid();
+
+ int itemIndex = -1;
+
+ for (int index = 0; index < _length; ++index)
+ {
+ if (_data[index] == item)
+ {
+ itemIndex = index;
+ break;
+ }
+ }
+
+ return itemIndex;
+ }
+
+ virtual property int Count
+ {
+ int get(void) { return _length; }
+ }
+
+ virtual property bool IsReadOnly
+ {
+ bool get(void) = System::Collections::Generic::IList::IsReadOnly::get
+ { return true; }
+ }
+
+ virtual void CopyTo(cli::array^ array, int arrayIndex) = System::Collections::Generic::ICollection::CopyTo
+ {
+ AssertIsValid();
+
+ if (array == nullptr)
+ throw gcnew System::ArgumentNullException("array");
+
+ if (arrayIndex < 0)
+ throw gcnew System::ArgumentOutOfRangeException("arrayIndex", arrayIndex, "Value must be greater than or equal to 0.");
+
+ if (Count > (array->Length - arrayIndex))
+ throw gcnew System::ArgumentException("Not enough space in target array.", "array");
+
+ for (int index = 0; index < _length; ++index)
+ {
+ array->SetValue(_data[index], index + arrayIndex);
+ arrayIndex += 1;
+ }
+ }
+
+ virtual System::Collections::Generic::IEnumerator^ GetEnumerator()
+ {
+ AssertIsValid();
+ return gcnew Enumerator(this);
+ }
+
+ virtual System::Collections::IEnumerator^ EnumerableGetEnumerator() = System::Collections::IEnumerable::GetEnumerator
+ {
+ return GetEnumerator();
+ }
+
+ private:
+
+ ref class Enumerator : System::Collections::Generic::IEnumerator
+ {
+ private:
+ NativeIntArray^ _a;
+ int _index;
+
+ public:
+ Enumerator(NativeIntArray^ a) {_a = a; _index = -1;}
+ ~Enumerator(void) {}
+
+ virtual property int Current
+ {
+ int get(void)
+ {
+ if (_index < 0 || _index > _a->_length)
+ throw gcnew System::InvalidOperationException();
+
+ _a->AssertIsValid();
+ return _a->_data[_index];
+ }
+ }
+
+ virtual property System::Object^ CurrentObject
+ {
+ System::Object^ get(void) = System::Collections::IEnumerator::Current::get
+ {
+ return Current;
+ }
+ }
+
+ virtual bool MoveNext()
+ {
+ bool moved = false;
+
+ if (_index < _a->_length)
+ {
+ _index += 1;
+ moved = true;
+ }
+
+ return moved;
+ }
+
+ virtual void Reset()
+ {
+ throw gcnew System::NotSupportedException("Reset not supported.");
+ }
+ };
+ };
+}
diff --git a/UdtProtocol/NetworkStream.cpp b/UdtProtocol/NetworkStream.cpp
new file mode 100644
index 0000000..4f0d246
--- /dev/null
+++ b/UdtProtocol/NetworkStream.cpp
@@ -0,0 +1,180 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+
+#include "NetworkStream.h"
+#include "Socket.h"
+
+using namespace Udt;
+using namespace System;
+using namespace System::IO;
+
+bool Readable(FileAccess access)
+{
+ return (int)((access & FileAccess::Read)) != 0;
+}
+
+bool Writeable(FileAccess access)
+{
+ return (int)((access & FileAccess::Write)) != 0;
+}
+
+NetworkStream::NetworkStream(Udt::Socket^ socket)
+{
+ _socket = socket;
+ _access = FileAccess::ReadWrite;
+ _ownsSocket = true;
+
+ Initialize(socket);
+}
+
+NetworkStream::NetworkStream(Udt::Socket^ socket, bool ownsSocket)
+{
+ _socket = socket;
+ _access = FileAccess::ReadWrite;
+ _ownsSocket = ownsSocket;
+
+ Initialize(socket);
+}
+
+NetworkStream::NetworkStream(Udt::Socket^ socket, FileAccess access)
+{
+ _socket = socket;
+ _access = access;
+ _ownsSocket = true;
+
+ Initialize(socket);
+}
+
+NetworkStream::NetworkStream(Udt::Socket^ socket, FileAccess access, bool ownsSocket)
+{
+ _socket = socket;
+ _access = access;
+ _ownsSocket = ownsSocket;
+
+ Initialize(socket);
+}
+
+void NetworkStream::Initialize(Udt::Socket^ socket)
+{
+ if (socket == nullptr)
+ throw gcnew ArgumentNullException("socket");
+
+ if (socket->SocketType != System::Net::Sockets::SocketType::Stream)
+ throw gcnew ArgumentException("Socket type must be Stream.", "socket");
+
+ if ((Readable(_access) && !socket->BlockingReceive) ||
+ (Writeable(_access) && !socket->BlockingSend))
+ {
+ throw gcnew ArgumentException("Socket must be in blocking state.", "socket");
+ }
+}
+
+NetworkStream::~NetworkStream()
+{
+ Udt::Socket^ socket = _socket;
+ _socket = nullptr;
+
+ if (_ownsSocket) delete socket;
+}
+
+void NetworkStream::AssertNotDisposed(void)
+{
+ if (_socket == nullptr)
+ throw gcnew ObjectDisposedException(this->ToString());
+}
+
+Udt::Socket^ NetworkStream::Socket::get(void)
+{
+ AssertNotDisposed();
+ return _socket;
+}
+
+bool NetworkStream::CanRead::get(void)
+{
+ return _socket != nullptr && Readable(_access);
+}
+
+bool NetworkStream::CanWrite::get(void)
+{
+ return _socket != nullptr && Writeable(_access);
+}
+
+void NetworkStream::Flush(void)
+{
+}
+
+int NetworkStream::Read(cli::array^ buffer, int offset, int count)
+{
+ AssertNotDisposed();
+
+ if (!CanRead)
+ throw gcnew NotSupportedException("Stream does not support reading.");
+
+ return _socket->Receive(buffer, offset, count);
+}
+
+void NetworkStream::Write(cli::array^ buffer, int offset, int count)
+{
+ AssertNotDisposed();
+
+ if (!CanWrite)
+ throw gcnew NotSupportedException("Stream does not support writing.");
+
+ _socket->Send(buffer, offset, count);
+}
+
+__int64 NetworkStream::Seek(__int64 offset, System::IO::SeekOrigin origin)
+{
+ throw gcnew NotSupportedException("Stream does not support seeking.");
+}
+
+void NetworkStream::SetLength(__int64 value)
+{
+ throw gcnew NotSupportedException("Stream does not support seeking.");
+}
+
+__int64 NetworkStream::Length::get(void)
+{
+ throw gcnew NotSupportedException("Stream does not support seeking.");
+}
+
+__int64 NetworkStream::Position::get(void)
+{
+ throw gcnew NotSupportedException("Stream does not support seeking.");
+}
+
+void NetworkStream::Position::set(__int64 value)
+{
+ throw gcnew NotSupportedException("Stream does not support seeking.");
+}
diff --git a/UdtProtocol/NetworkStream.h b/UdtProtocol/NetworkStream.h
new file mode 100644
index 0000000..3763677
--- /dev/null
+++ b/UdtProtocol/NetworkStream.h
@@ -0,0 +1,134 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+namespace Udt
+{
+ ref class Socket; // Forward declaration
+
+ ///
+ /// Provides a interface to a UDT socket.
+ ///
+ public ref class NetworkStream : System::IO::Stream
+ {
+ private:
+ Socket^ _socket;
+ initonly bool _ownsSocket;
+ initonly System::IO::FileAccess _access;
+
+ void Initialize(Udt::Socket^ socket);
+
+ protected:
+
+ ///
+ /// Get the underlying socket.
+ ///
+ property Udt::Socket^ Socket
+ {
+ Udt::Socket^ get(void);
+ }
+
+ void AssertNotDisposed(void);
+
+ public:
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Socket this stream will use to send/receive data.
+ /// If is a null reference.
+ ///
+ /// If .SocketType is not
+ /// - or -
+ /// is in non-blocking mode
+ ///
+ NetworkStream(Udt::Socket^ socket);
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Socket this stream will use to send/receive data.
+ /// True if this stream will assume ownership of the .
+ /// If is a null reference.
+ ///
+ /// If .SocketType is not
+ /// - or -
+ /// is in non-blocking mode
+ ///
+ NetworkStream(Udt::Socket^ socket, bool ownsSocket);
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Socket this stream will use to send/receive data.
+ /// Type of access to the given to the stream.
+ /// If is a null reference.
+ ///
+ /// If .SocketType is not
+ /// - or -
+ /// is in non-blocking mode
+ ///
+ NetworkStream(Udt::Socket^ socket, System::IO::FileAccess access);
+
+ ///
+ /// Initialize a new instance.
+ ///
+ /// Socket this stream will use to send/receive data.
+ /// Type of access to the given to the stream.
+ /// True if this stream will assume ownership of the .
+ /// If is a null reference.
+ ///
+ /// If .SocketType is not
+ /// - or -
+ /// is in non-blocking mode
+ ///
+ NetworkStream(Udt::Socket^ socket, System::IO::FileAccess access, bool ownsSocket);
+
+ ///
+ /// Dispose of the stream.
+ ///
+ virtual ~NetworkStream();
+
+ virtual property bool CanWrite { bool get(void) override; }
+ virtual property bool CanRead { bool get(void) override; }
+ virtual property bool CanSeek { bool get(void) override { return false; } }
+ virtual property __int64 Length { __int64 get(void) override; }
+ virtual property __int64 Position { __int64 get(void) override; void set(__int64 value) override; }
+
+ virtual void Flush() override;
+ virtual int Read(cli::array^ buffer, int offset, int count) override;
+ virtual void Write(cli::array^ buffer, int offset, int count) override;
+ virtual __int64 Seek(__int64 offset, System::IO::SeekOrigin origin) override;
+ virtual void SetLength(__int64 value) override;
+ };
+}
diff --git a/UdtProtocol/Packet.cpp b/UdtProtocol/Packet.cpp
new file mode 100644
index 0000000..4c31497
--- /dev/null
+++ b/UdtProtocol/Packet.cpp
@@ -0,0 +1,150 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+
+#include "Packet.h"
+#include "DataPacket.h"
+#include "ControlPacket.h"
+#include "KeepAlivePacket.h"
+#include "ShutdownPacket.h"
+#include "CongestionPacket.h"
+#include "ErrorPacket.h"
+#include "Ack2Packet.h"
+
+#include
+#include
+
+using namespace Udt;
+using namespace System;
+
+Packet^ Packet::Wrap(const CPacket* packet)
+{
+ Packet^ wrapper;
+
+ if (packet->getFlag())
+ {
+ switch (packet->getType())
+ {
+ case Ack2Packet::TypeCode:
+ wrapper = gcnew Ack2Packet(packet);
+ break;
+
+ case ErrorPacket::TypeCode:
+ wrapper = gcnew ErrorPacket(packet);
+ break;
+
+ case CongestionPacket::TypeCode:
+ wrapper = gcnew CongestionPacket(packet);
+ break;
+
+ case ShutdownPacket::TypeCode:
+ wrapper = gcnew ShutdownPacket(packet);
+ break;
+
+ case KeepAlivePacket::TypeCode:
+ wrapper = gcnew KeepAlivePacket(packet);
+ break;
+
+ default:
+ wrapper = gcnew ControlPacket(packet);
+ break;
+ }
+ }
+ else
+ {
+ wrapper = gcnew DataPacket(packet);
+ }
+
+ return wrapper;
+}
+
+Packet::Packet()
+ : _packet(new CPacket()), _deletePacket(true)
+{
+}
+
+Packet::Packet(const CPacket* packet)
+ : _packet((CPacket*)packet), _deletePacket(false)
+{
+}
+
+Packet::~Packet()
+{
+ if (_deletePacket)
+ {
+ FreePacketData();
+ delete _packet;
+ }
+
+ _packet = NULL;
+}
+
+void Packet::AssertNotDisposed()
+{
+ if (_packet == NULL)
+ throw gcnew ObjectDisposedException(this->ToString());
+}
+
+void Packet::AssertIsMutable()
+{
+ AssertNotDisposed();
+ if (!IsEditable) throw gcnew InvalidOperationException("Packet can not be modified.");
+}
+
+TimeSpan Packet::TimeStamp::get(void)
+{
+ AssertNotDisposed();
+ return FromMicroseconds((uint32_t)_packet->m_iTimeStamp);
+}
+
+void Packet::TimeStamp::set(TimeSpan value)
+{
+ AssertIsMutable();
+
+ if (value < TimeSpan::Zero || value > MaxTimeStamp)
+ throw gcnew ArgumentOutOfRangeException("value", value, String::Concat("Value must be between ", TimeSpan::Zero, " and ", MaxTimeStamp, "."));
+
+ _packet->m_iTimeStamp = (int32_t)ToMicroseconds(value);
+}
+
+int Packet::DestinationId::get(void)
+{
+ AssertNotDisposed();
+ return _packet->m_iID;
+}
+
+void Packet::DestinationId::set(int value)
+{
+ AssertIsMutable();
+ _packet->m_iID = value;
+}
diff --git a/UdtProtocol/Packet.h b/UdtProtocol/Packet.h
new file mode 100644
index 0000000..c36c626
--- /dev/null
+++ b/UdtProtocol/Packet.h
@@ -0,0 +1,120 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT data packet.
+ ///
+ public ref class Packet abstract
+ {
+ private:
+ bool _deletePacket;
+
+ protected:
+
+ CPacket* _packet;
+ void AssertNotDisposed();
+ void AssertIsMutable();
+ virtual void FreePacketData() {}
+
+ internal:
+
+ static Packet^ Wrap(const CPacket* packet);
+
+ Packet(void);
+ Packet(const CPacket* packet);
+
+ public:
+ virtual ~Packet(void);
+
+ ///
+ /// Get true if the packet can be modified.
+ ///
+ property bool IsEditable {
+ bool get(void) { return _packet != NULL && _deletePacket; }
+ }
+
+ ///
+ /// Get true if the packet has been disposed.
+ ///
+ property bool IsDisposed {
+ bool get(void) { return _packet == NULL; }
+ }
+
+ ///
+ /// Get or set the time stamp associated with the packet.
+ /// Default value is .
+ ///
+ ///
+ ///
+ /// The time stamp is generally the difference between when the
+ /// packet was created and when the socket it was sent on was
+ /// created.
+ ///
+ ///
+ /// The resolution of this property is 1 microsecond
+ /// (1000 nanoseconds). The resolution of
+ /// is 100 nanoseconds. When setting the property, the value will
+ /// be rounded down to the nearest microsecond.
+ ///
+ ///
+ /// If is less than or greater than .
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property System::TimeSpan TimeStamp {
+ System::TimeSpan get(void);
+ void set(System::TimeSpan value);
+ }
+
+ ///
+ /// Get or set ID of the destination socket for the packet.
+ /// Default value is 0.
+ ///
+ /// If the object has been disposed.
+ /// If attempting to set the value and is false.
+ property int DestinationId {
+ int get(void);
+ void set(int value);
+ }
+
+ ///
+ /// Maximum allowed value for .
+ ///
+ /// 4,294,967,295 microseconds (01:11:34.9672950).
+ static initonly System::TimeSpan MaxTimeStamp = FromMicroseconds(System::UInt32::MaxValue);
+ };
+}
diff --git a/UdtProtocol/ProbeTraceInfo.cpp b/UdtProtocol/ProbeTraceInfo.cpp
new file mode 100644
index 0000000..21b7bc9
--- /dev/null
+++ b/UdtProtocol/ProbeTraceInfo.cpp
@@ -0,0 +1,53 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "ProbeTraceInfo.h"
+
+using namespace Udt;
+using namespace System;
+
+ProbeTraceInfo::ProbeTraceInfo(const UDT::TRACEINFO& copy)
+{
+ this->PacketSendPeriod = FromMicroseconds((__int64)copy.usPktSndPeriod);
+ this->FlowWindow = copy.pktFlowWindow;
+ this->CongestionWindow = copy.pktCongestionWindow;
+ this->FlightSize = copy.pktFlightSize;
+ this->RoundtripTime = FromMilliseconds((__int64)copy.msRTT);
+ this->BandwidthMbps = copy.mbpsBandwidth;
+ this->AvailableSendBuffer = copy.byteAvailSndBuf;
+ this->AvailableReceiveBuffer = copy.byteAvailRcvBuf;
+}
+
+ProbeTraceInfo::ProbeTraceInfo(void)
+{
+}
diff --git a/UdtProtocol/ProbeTraceInfo.h b/UdtProtocol/ProbeTraceInfo.h
new file mode 100644
index 0000000..4fa7fd4
--- /dev/null
+++ b/UdtProtocol/ProbeTraceInfo.h
@@ -0,0 +1,93 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// Performance trace information instant values at the time they are observed.
+ ///
+ public ref class ProbeTraceInfo
+ {
+ internal:
+ ProbeTraceInfo(const UDT::TRACEINFO& copy);
+
+ public:
+ ///
+ /// Initialize a new instance with default values.
+ ///
+ ProbeTraceInfo(void);
+
+ ///
+ /// Packet sending period.
+ ///
+ property System::TimeSpan PacketSendPeriod;
+
+ ///
+ /// Flow window size, in number of packets.
+ ///
+ property int FlowWindow;
+
+ ///
+ /// Congestion window size, in number of packets.
+ ///
+ property int CongestionWindow;
+
+ ///
+ /// Number packets on the flight.
+ ///
+ property int FlightSize;
+
+ ///
+ /// Round trip time, in milliseconds.
+ ///
+ property System::TimeSpan RoundtripTime;
+
+ ///
+ /// Estimated bandwidth, in Mbps.
+ ///
+ property double BandwidthMbps;
+
+ ///
+ /// Available sending buffer size, in bytes.
+ ///
+ property int AvailableSendBuffer;
+
+ ///
+ /// Available receiving buffer size, in bytes.
+ ///
+ property int AvailableReceiveBuffer;
+ };
+}
diff --git a/UdtProtocol/ShutdownPacket.cpp b/UdtProtocol/ShutdownPacket.cpp
new file mode 100644
index 0000000..f07b36c
--- /dev/null
+++ b/UdtProtocol/ShutdownPacket.cpp
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "ShutdownPacket.h"
+
+#include
+#include
+
+using namespace Udt;
+
+ShutdownPacket::ShutdownPacket(const CPacket* packet)
+ : ControlPacket(packet)
+{
+}
+
+ShutdownPacket::ShutdownPacket(void)
+{
+ _packet->pack(TypeCode);
+}
diff --git a/UdtProtocol/ShutdownPacket.h b/UdtProtocol/ShutdownPacket.h
new file mode 100644
index 0000000..5102183
--- /dev/null
+++ b/UdtProtocol/ShutdownPacket.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "ControlPacket.h"
+
+class CPacket;
+
+namespace Udt
+{
+ ///
+ /// UDT protocol shutdown control packet.
+ ///
+ public ref class ShutdownPacket : public ControlPacket
+ {
+ internal:
+ ShutdownPacket(const CPacket* packet);
+
+ literal int TypeCode = 5;
+
+ public:
+
+ ShutdownPacket(void);
+ };
+}
diff --git a/UdtProtocol/Socket.cpp b/UdtProtocol/Socket.cpp
new file mode 100644
index 0000000..6a73adf
--- /dev/null
+++ b/UdtProtocol/Socket.cpp
@@ -0,0 +1,1223 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+
+#include
+#include
+
+#include "Socket.h"
+#include "SocketException.h"
+#include "CCCWrapperFactory.h"
+#include "StdFileStream.h"
+
+#include
+#include
+#include
+
+using namespace Udt;
+using namespace System;
+using namespace System::Net;
+using namespace System::Net::Sockets;
+using namespace System::Collections::Generic;
+using namespace System::Globalization;
+
+#ifdef _WIN64
+#define INTPTR_TO_UDTSOCKET(ptr) (ptr.ToInt64())
+#else
+#define INTPTR_TO_UDTSOCKET(ptr) (ptr.ToInt32())
+#endif
+
+void ToTimeVal(TimeSpan ts, timeval& tv)
+{
+ __int64 ticks = ts.Ticks;
+ tv.tv_sec = (long)(ticks / 10000000);
+ tv.tv_usec = (ticks % 10000000) / 10;
+}
+
+int UdtSendMessage(UDTSOCKET socket, cli::array^ buffer, int offset, int size, int ttl = -1, bool inorder = false)
+{
+ cli::pin_ptr buffer_pin = &buffer[0];
+ unsigned char* buffer_ptr = &buffer_pin[offset];
+
+ int result = UDT::sendmsg(socket, (const char*)buffer_ptr, size, ttl, inorder);
+
+ if (UDT::ERROR == result)
+ {
+ throw Udt::SocketException::GetLastError("Error sending message.");
+ }
+
+ return result;
+}
+
+IPEndPoint^ ToEndPoint(sockaddr_storage* addr)
+{
+ int port;
+ System::Net::IPAddress^ address;
+
+ if (addr->ss_family == AF_INET)
+ {
+ sockaddr_in* addr_in = (sockaddr_in*)addr;
+ port = ntohs(addr_in->sin_port);
+ address = gcnew System::Net::IPAddress(addr_in->sin_addr.s_addr);
+ }
+ else
+ {
+ sockaddr_in6* addr_in6 = (sockaddr_in6*)addr;
+ port = ntohs(addr_in6->sin6_port);
+
+ cli::array^ address_bytes = gcnew cli::array(16);
+ cli::pin_ptr address_bytes_pin = &address_bytes[0];
+ unsigned char* address_bytes_ptr = address_bytes_pin;
+ memcpy(address_bytes_ptr, addr_in6->sin6_addr.s6_addr, 16);
+
+ address = gcnew System::Net::IPAddress(address_bytes, addr_in6->sin6_scope_id);
+ }
+
+ return gcnew System::Net::IPEndPoint(address, port);
+}
+
+void ToSockAddr(System::Net::IPAddress^ address, int port, sockaddr_storage& sockaddr, int& size)
+{
+ memset(&sockaddr, 0, sizeof(sockaddr_storage));
+
+ if (address->AddressFamily == AddressFamily::InterNetworkV6)
+ {
+ size = sizeof(sockaddr_in6);
+
+ sockaddr_in6* sockaddr6 = (sockaddr_in6*)&sockaddr;
+ sockaddr6->sin6_family = AF_INET6;
+ sockaddr6->sin6_port = htons(port);
+
+ cli::array^ address_bytes = address->GetAddressBytes();
+ cli::pin_ptr address_bytes_pin = &address_bytes[0];
+ memcpy(sockaddr6->sin6_addr.s6_addr, address_bytes_pin, 16);
+ }
+ else
+ {
+ size = sizeof(sockaddr_in);
+
+ sockaddr_in* sockaddr4 = (sockaddr_in*)&sockaddr;
+ sockaddr4->sin_family = AF_INET;
+ sockaddr4->sin_port = htons(port);
+ sockaddr4->sin_addr.s_addr = (int)address->Address;
+ }
+}
+
+Udt::Socket::Socket(UDTSOCKET socket, System::Net::Sockets::AddressFamily family, System::Net::Sockets::SocketType type, ICongestionControlFactory^ congestionControl)
+{
+ _socket = socket;
+ _isDisposed = false;
+ _addressFamily = family;
+ _socketType = type;
+ _congestionControl = congestionControl;
+ _blockingSend = GetSocketOptionBoolean(Udt::SocketOptionName::BlockingSend);
+}
+
+Udt::Socket::Socket(System::Net::Sockets::AddressFamily family, System::Net::Sockets::SocketType type)
+{
+ _isDisposed = false;
+ _addressFamily = family;
+ _socketType = type;
+ _blockingSend = true;
+
+ int socketFamily;
+ int socketType;
+
+ switch (family)
+ {
+ case System::Net::Sockets::AddressFamily::InterNetwork:
+ socketFamily = AF_INET;
+ break;
+
+ case System::Net::Sockets::AddressFamily::InterNetworkV6:
+ socketFamily = AF_INET6;
+ break;
+
+ default:
+ throw gcnew ArgumentException(String::Concat("Unsupported address family: ", family.ToString()), "family");
+ }
+
+ switch (type)
+ {
+ case System::Net::Sockets::SocketType::Dgram:
+ socketType = SOCK_DGRAM;
+ break;
+
+ case System::Net::Sockets::SocketType::Stream:
+ socketType = SOCK_STREAM;
+ break;
+
+ default:
+ throw gcnew ArgumentException(String::Concat("Unsupported socket type: ", type.ToString()), "type");
+ }
+
+ _socket = UDT::socket(socketFamily, socketType, 0);
+
+ if (_socket == UDT::INVALID_SOCK)
+ throw Udt::SocketException::GetLastError(String::Concat("Error creating ", family.ToString(), "/", type.ToString(), " UDT socket"));
+
+ // Windows UDP issue
+ // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold
+ int mss = 1052;
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, UDT_MSS, &mss, sizeof(int)))
+ {
+ throw Udt::SocketException::GetLastError("Error setting UDT_MSS socket option");
+ }
+}
+
+Udt::Socket::~Socket(void)
+{
+ this->Close();
+}
+
+void Udt::Socket::Close(void)
+{
+ if (!_isDisposed)
+ {
+ _isDisposed = true;
+
+ if (UDT::ERROR == UDT::close(_socket))
+ {
+ Udt::SocketException^ ex = Udt::SocketException::GetLastError("Error closing socket");
+
+ switch (ex->SocketErrorCode)
+ {
+ case Udt::SocketError::InvalidSocket:
+ // Ignore
+ break;
+
+ default:
+ throw ex;
+ }
+ }
+ }
+}
+
+void Udt::Socket::Bind(IPAddress^ address, int port)
+{
+ AssertNotDisposed();
+
+ if (address == nullptr)
+ throw gcnew ArgumentNullException("address");
+
+ if (address->AddressFamily != _addressFamily)
+ throw gcnew ArgumentException(String::Concat("Value must be same as socket address family (", _addressFamily, ")."), "address");
+
+ if (port < IPEndPoint::MinPort || port > IPEndPoint::MaxPort)
+ throw gcnew ArgumentOutOfRangeException("port", port, String::Concat("Value must be between ", (Object^)IPEndPoint::MinPort, " and ", (Object^)IPEndPoint::MaxPort, "."));
+
+ sockaddr_storage bind_addr;
+ int size;
+
+ ToSockAddr(address, port, bind_addr, size);
+
+ if (UDT::ERROR == UDT::bind(_socket, (sockaddr*)&bind_addr, size))
+ {
+ if (address->AddressFamily == System::Net::Sockets::AddressFamily::InterNetworkV6)
+ throw Udt::SocketException::GetLastError(String::Concat("Error binding to [", address, "]:", (Object^)port));
+ else
+ throw Udt::SocketException::GetLastError(String::Concat("Error binding to ", address, ":", (Object^)port));
+ }
+}
+
+void Udt::Socket::Bind(IPEndPoint^ endPoint)
+{
+ if (endPoint == nullptr)
+ throw gcnew ArgumentNullException("endPoint");
+
+ if (endPoint->AddressFamily != _addressFamily)
+ throw gcnew ArgumentException(String::Concat("Address must be same as socket address family (", _addressFamily, ")."), "endPoint");
+
+ Bind(endPoint->Address, endPoint->Port);
+}
+
+void Udt::Socket::Bind(System::Net::Sockets::Socket^ udpSocket)
+{
+ AssertNotDisposed();
+
+ if (udpSocket == nullptr)
+ throw gcnew ArgumentNullException("udpSocket");
+
+ if (udpSocket->ProtocolType != ProtocolType::Udp)
+ throw gcnew ArgumentException(String::Concat("Socket must be a UDP Socket. Socket is ", udpSocket->ProtocolType), "udpSocket");
+
+ if (UDT::ERROR == UDT::bind2(_socket, INTPTR_TO_UDTSOCKET(udpSocket->Handle)))
+ {
+ throw Udt::SocketException::GetLastError("Error binding to existing UDP socket.");
+ }
+}
+
+void Udt::Socket::Listen(int backlog)
+{
+ AssertNotDisposed();
+
+ if (backlog < 1)
+ throw gcnew ArgumentOutOfRangeException("backlog", backlog, "Value must be greater than 0.");
+
+ if (UDT::ERROR == UDT::listen(_socket, backlog))
+ {
+ throw Udt::SocketException::GetLastError("Error entering listening state");
+ }
+}
+
+Udt::Socket^ Udt::Socket::Accept()
+{
+ AssertNotDisposed();
+
+ sockaddr_storage client_addr;
+ int client_addr_len = sizeof(client_addr);
+ UDTSOCKET client = UDT::accept(_socket, (sockaddr*)&client_addr, &client_addr_len);
+
+ if (client == UDT::INVALID_SOCK)
+ throw Udt::SocketException::GetLastError("Error accepting new connection.");
+
+ return gcnew Socket(client, _addressFamily, _socketType, _congestionControl);
+}
+
+void Udt::Socket::Connect(System::String^ host, int port)
+{
+ if (host == nullptr)
+ throw gcnew ArgumentNullException("host");
+
+ Connect(Dns::GetHostAddresses(host), port);
+}
+
+void Udt::Socket::Connect(System::Net::IPAddress^ address, int port)
+{
+ AssertNotDisposed();
+
+ if (address == nullptr)
+ throw gcnew ArgumentNullException("address");
+
+ if (port < IPEndPoint::MinPort || port > IPEndPoint::MaxPort)
+ throw gcnew ArgumentOutOfRangeException("port", port, String::Concat("Value must be between ", (Object^)IPEndPoint::MinPort, " and ", (Object^)IPEndPoint::MaxPort, "."));
+
+ sockaddr_storage connect_addr;
+ int size;
+
+ ToSockAddr(address, port, connect_addr, size);
+
+ if (UDT::ERROR == UDT::connect(_socket, (sockaddr*)&connect_addr, size))
+ {
+ if (address->AddressFamily == System::Net::Sockets::AddressFamily::InterNetworkV6)
+ throw Udt::SocketException::GetLastError(String::Concat("Error connecting to [", address, "]:", (Object^)port));
+ else
+ throw Udt::SocketException::GetLastError(String::Concat("Error connecting to ", address, ":", (Object^)port));
+ }
+}
+
+void Udt::Socket::Connect(cli::array^ addresses, int port)
+{
+ if (addresses == nullptr)
+ throw gcnew ArgumentNullException("addresses");
+
+ if (addresses->Length == 0)
+ throw gcnew ArgumentException("Value can not be empty.", "addresses");
+
+ Connect(addresses[0], port);
+}
+
+UDT::UDSET* Udt::Socket::CreateUDSet(String^ paramName, System::Collections::Generic::ICollection^ fds)
+{
+ if (fds == nullptr || fds->Count == 0)
+ return NULL;
+
+ std::auto_ptr set(new UDT::UDSET);
+ UD_ZERO(set);
+
+ for each (Udt::Socket^ socket in fds)
+ {
+ if (socket == nullptr)
+ throw gcnew ArgumentException("Value can not contain null reference.", paramName);
+
+ UDTSOCKET socketHandle = socket->_socket;
+ UD_SET(socketHandle, set);
+ }
+
+ return set.release();
+}
+
+void Udt::Socket::FillSocketList(const std::vector* list, System::Collections::Generic::Dictionary^ sockets, System::Collections::Generic::ICollection^ fds)
+{
+ if (list != NULL)
+ {
+ for (std::vector::const_iterator it = list->begin(); it != list->end(); ++it)
+ {
+ fds->Add(sockets[*it]);
+ }
+ }
+}
+
+bool IsEmpty(System::Collections::Generic::ICollection^ fds)
+{
+ return fds == nullptr || fds->Count == 0;
+}
+
+void Udt::Socket::Filter(UDT::UDSET* set, System::Collections::Generic::ICollection^ fds)
+{
+ if (!IsEmpty(fds))
+ {
+ HashSet^ sockets = gcnew HashSet(fds);
+
+ fds->Clear();
+
+ for each(Udt::Socket^ socket in sockets)
+ {
+ UDTSOCKET socketHandle = socket->_socket;
+ if (UD_ISSET(socketHandle, set))
+ {
+ fds->Add(socket);
+ }
+ }
+ }
+}
+
+void Udt::Socket::Select(
+ System::Collections::Generic::ICollection^ checkSockets,
+ System::Collections::Generic::ICollection^ readSockets,
+ System::Collections::Generic::ICollection^ writeSockets,
+ System::Collections::Generic::ICollection^ errorSockets,
+ System::TimeSpan timeout)
+{
+ if (checkSockets == nullptr)
+ throw gcnew ArgumentNullException("checkSockets");
+
+ if (readSockets == nullptr && writeSockets == nullptr && errorSockets == nullptr)
+ throw gcnew ArgumentException("At least one of readSockets, writeSockets, or errorSockets is required");
+
+ if (timeout != Udt::Socket::InfiniteTimeout && timeout < System::TimeSpan::Zero)
+ throw gcnew ArgumentOutOfRangeException("timeout", timeout, "Value must be infinite (-1 ticks) or greater than or equal to 0.");
+
+ // Setup native function parameters
+ std::vector fds;
+ Dictionary^ socketMap = gcnew Dictionary();
+
+ for each (Udt::Socket^ socket in checkSockets)
+ {
+ if (socket == nullptr)
+ throw gcnew ArgumentException("Value can not contain null reference.", "checkSockets");
+
+ UDTSOCKET socketHandle = socket->_socket;
+
+ if (!socketMap->ContainsKey(socketHandle))
+ {
+ socketMap->Add(socketHandle, socket);
+ fds.push_back(socketHandle);
+ }
+ }
+
+ std::vector readFds;
+ std::vector* readFdsPtr = readSockets == nullptr ? NULL : &readFds;
+ std::vector writeFds;
+ std::vector* writeFdsPtr = writeSockets == nullptr ? NULL : &writeFds;
+ std::vector exceptFds;
+ std::vector* exceptFdsPtr = errorSockets == nullptr ? NULL : &exceptFds;
+
+ int64_t msTimeOut = Int64::MaxValue;
+
+ if (timeout != Udt::Socket::InfiniteTimeout)
+ msTimeOut = (int64_t)timeout.TotalMilliseconds;
+
+ // Call native function
+ if (UDT::ERROR == UDT::selectEx(fds, readFdsPtr, writeFdsPtr, exceptFdsPtr, msTimeOut))
+ {
+ throw Udt::SocketException::GetLastError("Error in socket selectEx.");
+ }
+
+ // Add the sockets to the provided socket collections
+ FillSocketList(readFdsPtr, socketMap, readSockets);
+ FillSocketList(writeFdsPtr, socketMap, writeSockets);
+ FillSocketList(exceptFdsPtr, socketMap, errorSockets);
+}
+
+void Udt::Socket::Select(
+ System::Collections::Generic::ICollection^ checkRead,
+ System::Collections::Generic::ICollection^ checkWrite,
+ System::Collections::Generic::ICollection^ checkError,
+ System::TimeSpan timeout)
+{
+ if (IsEmpty(checkRead) && IsEmpty(checkWrite) && IsEmpty(checkError))
+ {
+ throw gcnew ArgumentException("At least one of checkRead, checkWrite, or checkError is required");
+ }
+
+ if (timeout != Udt::Socket::InfiniteTimeout && timeout < System::TimeSpan::Zero)
+ {
+ throw gcnew ArgumentOutOfRangeException("timeout", timeout, "Value must be infinite (-1 ticks) or greater than or equal to 0.");
+ }
+
+ timeval tv;
+
+ if (timeout == Udt::Socket::InfiniteTimeout)
+ {
+ tv.tv_sec = Int32::MaxValue;
+ tv.tv_usec = 0;
+ }
+ else
+ {
+ __int64 timeoutTicks = timeout.Ticks;
+ tv.tv_sec = (long)(timeoutTicks / TimeSpan::TicksPerSecond);
+ tv.tv_usec = (timeoutTicks % TimeSpan::TicksPerSecond) / 10;
+ }
+
+ std::auto_ptr readFds(CreateUDSet("checkRead", checkRead));
+ std::auto_ptr writeFds(CreateUDSet("checkWrite", checkWrite));
+ std::auto_ptr exceptFds(CreateUDSet("checkError", checkError));
+
+ if (UDT::ERROR == UDT::select(0, readFds.get(), writeFds.get(), exceptFds.get(), &tv))
+ {
+ throw Udt::SocketException::GetLastError("Error in socket select.");
+ }
+
+ Filter(readFds.get(), checkRead);
+ Filter(writeFds.get(), checkWrite);
+ Filter(exceptFds.get(), checkError);
+}
+
+void Udt::Socket::Connect(System::Net::IPEndPoint^ endPoint)
+{
+ if (endPoint == nullptr)
+ throw gcnew ArgumentNullException("endPoint");
+
+ Connect(endPoint->Address, endPoint->Port);
+}
+
+int Udt::Socket::Receive(cli::array^ buffer)
+{
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ return Receive(buffer, 0, buffer->Length);
+}
+
+int Udt::Socket::Receive(cli::array^ buffer, int offset, int size)
+{
+ AssertNotDisposed();
+
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ if (offset < 0)
+ throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+
+ if (size < 0)
+ throw gcnew ArgumentOutOfRangeException("size", size, "Value must be greater than or equal to 0.");
+
+ if ((offset + size) > buffer->Length)
+ throw gcnew ArgumentException("Buffer is smaller than specified segment (count + size).", "buffer");
+
+ cli::pin_ptr buffer_pin = &buffer[0];
+ unsigned char* buffer_pin_ptr = &buffer_pin[offset];
+
+ int received = UDT::recv(_socket, (char*)buffer_pin_ptr, size, 0);
+
+ if (UDT::ERROR == received)
+ {
+ throw Udt::SocketException::GetLastError("Error receiving data.");
+ }
+
+ return received;
+}
+
+int Udt::Socket::Send(cli::array^ buffer)
+{
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ return Send(buffer, 0, buffer->Length);
+}
+
+int Udt::Socket::Send(cli::array^ buffer, int offset, int size)
+{
+ AssertNotDisposed();
+
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ if (offset < 0)
+ throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+
+ if (size < 0)
+ throw gcnew ArgumentOutOfRangeException("size", size, "Value must be greater than or equal to 0.");
+
+ if ((offset + size) > buffer->Length)
+ throw gcnew ArgumentException("Buffer is smaller than specified segment (count + size).", "buffer");
+
+ cli::pin_ptr buffer_pin = &buffer[0];
+ char* buffer_pin_ptr = (char*)&buffer_pin[offset];
+ int sent = 0;
+
+ if (_blockingSend) {
+ // Socket is blocking, but may not send the entire buffer in one send call.
+ // Loop until the entire buffer is sent or an error occurs.
+
+ do {
+ int send_result = UDT::send(_socket, buffer_pin_ptr + sent, size - sent, 0);
+
+ if (UDT::ERROR == send_result)
+ {
+ throw Udt::SocketException::GetLastError("Error sending data.");
+ }
+
+ sent += send_result;
+ } while (sent < size);
+ } else {
+ sent = UDT::send(_socket, buffer_pin_ptr, size, 0);
+
+ if (UDT::ERROR == sent)
+ {
+ if (UDT::getlasterror().getErrorCode() == UDT::ERRORINFO::EASYNCSND)
+ {
+ // Socket is non-blocking and send queue is full
+ sent = 0;
+ }
+ else
+ {
+ throw Udt::SocketException::GetLastError("Error sending data.");
+ }
+ }
+ }
+
+ return sent;
+}
+
+__int64 Udt::Socket::SendFile(System::String^ fileName)
+{
+ return SendFile(fileName, 0, -1);
+}
+
+__int64 Udt::Socket::SendFile(System::String^ fileName, __int64 offset)
+{
+ return SendFile(fileName, offset, -1);
+}
+
+__int64 Udt::Socket::SendFile(System::String^ fileName, __int64 offset, __int64 count)
+{
+ AssertNotDisposed();
+
+ if (fileName == nullptr) throw gcnew ArgumentNullException("fileName");
+ if (offset < 0) throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+ if (count < -1) throw gcnew ArgumentOutOfRangeException("count", count, "Value must be greater than or equal to -1.");
+
+ cli::pin_ptr file_name_pin = PtrToStringChars(fileName);
+ const wchar_t* file_name_ptr = file_name_pin;
+
+ // In VC10, fstream tellg has a bug. Should be fixed in VC11.
+ // http://connect.microsoft.com/VisualStudio/feedback/details/627639/std-fstream-use-32-bit-int-as-pos-type-even-on-x64-platform
+ //std::fstream ifs(file_name_ptr, std::ios::in | std::ios::binary);
+
+ //if (count < 0)
+ //{
+ // ifs.seekg(0, std::ios::end);
+ // count = ifs.tellg() - offset;
+ //}
+
+ FILE* streamPtr = _wfsopen(file_name_ptr, L"rbN", _SH_DENYRW); // ifs will close handle
+ if (streamPtr == NULL) StdFileStream::CheckLastError(file_name_ptr);
+ std::fstream ifs(streamPtr);
+
+ if (count < 0)
+ {
+ _fseeki64(streamPtr, 0, SEEK_END);
+ count = _ftelli64(streamPtr) - offset;
+ if (count < 0) throw gcnew ArgumentOutOfRangeException("offset", offset, "Value is greater than the length of the file.");
+ }
+
+ int64_t sent = UDT::sendfile(_socket, ifs, offset, count);
+
+ if (UDT::ERROR == sent)
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error sending file ", fileName));
+ }
+
+ return sent;
+}
+
+__int64 Udt::Socket::SendFile(StdFileStream^ file)
+{
+ return SendFile(file, -1);
+}
+
+__int64 Udt::Socket::SendFile(StdFileStream^ file, __int64 count)
+{
+ AssertNotDisposed();
+
+ if (file == nullptr) throw gcnew ArgumentNullException("file");
+ if (!file->CanRead) throw gcnew ArgumentException("Stream does not support reading.", "file");
+
+ __int64 pos = file->Position;
+
+ if (count < 0)
+ {
+ count = file->Length - pos;
+ }
+
+ int64_t sent = UDT::sendfile(_socket, file->LoadStdStream(), pos, count);
+
+ if (UDT::ERROR == sent)
+ {
+ throw Udt::SocketException::GetLastError("Error sending file.");
+ }
+
+ return sent;
+}
+
+__int64 Udt::Socket::ReceiveFile(System::String^ fileName, __int64 length)
+{
+ AssertNotDisposed();
+
+ if (fileName == nullptr) throw gcnew ArgumentNullException("fileName");
+ if (length < 0) throw gcnew ArgumentOutOfRangeException("length", length, "Value must be greater than or equal to 0.");
+
+ cli::pin_ptr file_name_pin = PtrToStringChars(fileName);
+ const wchar_t* file_name_ptr = file_name_pin;
+ std::fstream ofs(file_name_ptr, std::ios::out | std::ios::binary | std::ios::trunc);
+
+ int64_t offset = 0;
+ int64_t received = UDT::recvfile(_socket, ofs, offset, length);
+
+ if (received == UDT::ERROR)
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error receiving file ", fileName));
+ }
+
+ return received;
+}
+
+__int64 Udt::Socket::ReceiveFile(StdFileStream^ file, __int64 length)
+{
+ AssertNotDisposed();
+
+ if (file == nullptr) throw gcnew ArgumentNullException("file");
+ if (!file->CanWrite) throw gcnew ArgumentException("Stream does not support writing.", "file");
+ if (length < 0) throw gcnew ArgumentOutOfRangeException("length", length, "Value must be greater than or equal to 0.");
+
+ __int64 offset = file->Position;
+ int64_t received = UDT::recvfile(_socket, file->LoadStdStream(), offset, length);
+
+ if (received == UDT::ERROR)
+ {
+ throw Udt::SocketException::GetLastError("Error receiving file.");
+ }
+
+ return received;
+}
+
+TraceInfo^ Udt::Socket::GetPerformanceInfo()
+{
+ return GetPerformanceInfo(true);
+}
+
+TraceInfo^ Udt::Socket::GetPerformanceInfo(bool clear)
+{
+ AssertNotDisposed();
+
+ UDT::TRACEINFO trace_info;
+
+ if (UDT::ERROR == UDT::perfmon(_socket, &trace_info, clear))
+ {
+ throw Udt::SocketException::GetLastError("Error getting socket performance information.");
+ }
+
+ return gcnew TraceInfo(trace_info);
+}
+
+System::Net::Sockets::AddressFamily Udt::Socket::AddressFamily::get(void)
+{
+ return _addressFamily;
+}
+
+System::Net::Sockets::SocketType Udt::Socket::SocketType::get(void)
+{
+ return _socketType;
+}
+
+System::Net::IPEndPoint^ Udt::Socket::LocalEndPoint::get(void)
+{
+ AssertNotDisposed();
+
+ sockaddr_storage local_addr;
+ int local_addr_len = sizeof(local_addr);
+
+ if (UDT::ERROR == UDT::getsockname(_socket, (sockaddr*)&local_addr, &local_addr_len))
+ {
+ throw Udt::SocketException::GetLastError("Error getting local end point.");
+ }
+
+ return ToEndPoint(&local_addr);
+}
+
+System::Net::IPEndPoint^ Udt::Socket::RemoteEndPoint::get(void)
+{
+ AssertNotDisposed();
+
+ sockaddr_storage remote_addr;
+ int remote_addr_len = sizeof(remote_addr);
+
+ if (UDT::ERROR == UDT::getpeername(_socket, (sockaddr*)&remote_addr, &remote_addr_len))
+ {
+ throw Udt::SocketException::GetLastError("Error getting remote end point.");
+ }
+
+ return ToEndPoint(&remote_addr);
+}
+
+int Udt::Socket::SendMessage(cli::array^ buffer)
+{
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ return SendMessage(buffer, 0, buffer->Length);
+}
+
+int Udt::Socket::SendMessage(cli::array^ buffer, int offset, int size)
+{
+ AssertNotDisposed();
+
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ if (offset < 0)
+ throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+
+ if (size < 0)
+ throw gcnew ArgumentOutOfRangeException("size", size, "Value must be greater than or equal to 0.");
+
+ if ((offset + size) > buffer->Length)
+ throw gcnew ArgumentException("Buffer is smaller than specified segment (count + size).", "buffer");
+
+ return UdtSendMessage(_socket, buffer, offset, size);
+}
+
+int Udt::Socket::SendMessage(Message^ message)
+{
+ AssertNotDisposed();
+
+ if (message == nullptr)
+ throw gcnew ArgumentNullException("message");
+
+ ArraySegment buffer = message->Buffer;
+ int ttl = (int)message->TimeToLive.TotalMilliseconds;
+ return UdtSendMessage(_socket, buffer.Array, buffer.Offset, buffer.Count, ttl, message->InOrder);
+}
+
+int Udt::Socket::ReceiveMessage(cli::array^ buffer)
+{
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ return ReceiveMessage(buffer, 0, buffer->Length);
+}
+
+int Udt::Socket::ReceiveMessage(cli::array^ buffer, int offset, int size)
+{
+ AssertNotDisposed();
+
+ if (buffer == nullptr)
+ throw gcnew ArgumentNullException("buffer");
+
+ if (offset < 0)
+ throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+
+ if (size < 0)
+ throw gcnew ArgumentOutOfRangeException("size", size, "Value must be greater than or equal to 0.");
+
+ if ((offset + size) > buffer->Length)
+ throw gcnew ArgumentException("Buffer is smaller than specified segment (count + size).", "buffer");
+
+ cli::pin_ptr buffer_pin = &buffer[0];
+ unsigned char* buffer_ptr = &buffer_pin[offset];
+
+ int result = UDT::recvmsg(_socket, (char*)buffer_ptr, size);
+
+ if (UDT::ERROR == result)
+ {
+ throw Udt::SocketException::GetLastError("Error receiving message.");
+ }
+
+ return result;
+}
+
+void Udt::Socket::SetSocketOptionInt32(Udt::SocketOptionName name, int value)
+{
+ AssertNotDisposed();
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, sizeof(int)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error setting socket option ", name.ToString(), " to ", (Object^)value, "."));
+ }
+}
+
+void Udt::Socket::SetSocketOptionInt64(Udt::SocketOptionName name, __int64 value)
+{
+ AssertNotDisposed();
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, sizeof(__int64)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error setting socket option ", name.ToString(), " to ", (Object^)value, "."));
+ }
+}
+
+void Udt::Socket::SetSocketOptionBoolean(Udt::SocketOptionName name, bool value)
+{
+ AssertNotDisposed();
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, sizeof(bool)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error setting socket option ", name.ToString(), " to ", (Object^)value, "."));
+ }
+
+ if (name == Udt::SocketOptionName::BlockingSend)
+ {
+ _blockingSend = value;
+ }
+}
+
+void Udt::Socket::SetSocketOption(Udt::SocketOptionName name, int value)
+{
+ switch (name)
+ {
+ case Udt::SocketOptionName::BlockingReceive:
+ case Udt::SocketOptionName::BlockingSend:
+ case Udt::SocketOptionName::Rendezvous:
+ case Udt::SocketOptionName::ReuseAddress:
+ SetSocketOptionBoolean(name, value != 0);
+ break;
+
+ case Udt::SocketOptionName::MaxPacketSize:
+ case Udt::SocketOptionName::MaxWindowSize:
+ case Udt::SocketOptionName::SendBuffer:
+ case Udt::SocketOptionName::ReceiveBuffer:
+ case Udt::SocketOptionName::UdpReceiveBuffer:
+ case Udt::SocketOptionName::UdpSendBuffer:
+ case Udt::SocketOptionName::SendTimeout:
+ case Udt::SocketOptionName::ReceiveTimeout:
+ SetSocketOptionInt32(name, value);
+ break;
+
+ case Udt::SocketOptionName::MaxBandwidth:
+ SetSocketOptionInt64(name, (long)value);
+ break;
+
+ case Udt::SocketOptionName::SendData:
+ case Udt::SocketOptionName::ReceiveData:
+ case Udt::SocketOptionName::Events:
+ case Udt::SocketOptionName::State:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " is read only"), "name");
+
+ case Udt::SocketOptionName::Linger:
+ case Udt::SocketOptionName::CongestionControl:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " can not be set to Int32 value"), "value");
+
+ default:
+ throw gcnew ArgumentException("Unhandled socket option name.", "name");
+ }
+}
+
+void Udt::Socket::SetSocketOption(Udt::SocketOptionName name, __int64 value)
+{
+ switch (name)
+ {
+ case Udt::SocketOptionName::BlockingReceive:
+ case Udt::SocketOptionName::BlockingSend:
+ case Udt::SocketOptionName::Rendezvous:
+ case Udt::SocketOptionName::ReuseAddress:
+ SetSocketOptionBoolean(name, value != 0);
+ break;
+
+ case Udt::SocketOptionName::MaxPacketSize:
+ case Udt::SocketOptionName::MaxWindowSize:
+ case Udt::SocketOptionName::SendBuffer:
+ case Udt::SocketOptionName::ReceiveBuffer:
+ case Udt::SocketOptionName::UdpReceiveBuffer:
+ case Udt::SocketOptionName::UdpSendBuffer:
+ case Udt::SocketOptionName::SendTimeout:
+ case Udt::SocketOptionName::ReceiveTimeout:
+ SetSocketOptionInt32(name, (int)value);
+ break;
+
+ case Udt::SocketOptionName::MaxBandwidth:
+ SetSocketOptionInt64(name, value);
+ break;
+
+ case Udt::SocketOptionName::SendData:
+ case Udt::SocketOptionName::ReceiveData:
+ case Udt::SocketOptionName::Events:
+ case Udt::SocketOptionName::State:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " is read only"), "name");
+
+ case Udt::SocketOptionName::Linger:
+ case Udt::SocketOptionName::CongestionControl:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " can not be set to Int64 value"), "value");
+
+ default:
+ throw gcnew ArgumentException("Unhandled socket option name.", "name");
+ }
+}
+
+void Udt::Socket::SetSocketOption(Udt::SocketOptionName name, bool value)
+{
+ switch (name)
+ {
+ case Udt::SocketOptionName::BlockingReceive:
+ case Udt::SocketOptionName::BlockingSend:
+ case Udt::SocketOptionName::Rendezvous:
+ case Udt::SocketOptionName::ReuseAddress:
+ SetSocketOptionBoolean(name, value);
+ break;
+
+ case Udt::SocketOptionName::MaxPacketSize:
+ case Udt::SocketOptionName::MaxWindowSize:
+ case Udt::SocketOptionName::SendBuffer:
+ case Udt::SocketOptionName::ReceiveBuffer:
+ case Udt::SocketOptionName::UdpReceiveBuffer:
+ case Udt::SocketOptionName::UdpSendBuffer:
+ case Udt::SocketOptionName::SendTimeout:
+ case Udt::SocketOptionName::ReceiveTimeout:
+ SetSocketOptionInt32(name, value ? 1 : 0);
+ break;
+
+ case Udt::SocketOptionName::MaxBandwidth:
+ SetSocketOptionInt64(name, value ? 1L : 0L);
+ break;
+
+ case Udt::SocketOptionName::SendData:
+ case Udt::SocketOptionName::ReceiveData:
+ case Udt::SocketOptionName::Events:
+ case Udt::SocketOptionName::State:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " is read only"), "name");
+
+ case Udt::SocketOptionName::Linger:
+ case Udt::SocketOptionName::CongestionControl:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " can not be set to Boolean value"), "value");
+
+ default:
+ throw gcnew ArgumentException("Unhandled socket option name.", "name");
+ }
+}
+
+void Udt::Socket::SetSocketOption(Udt::SocketOptionName name, System::Object^ value)
+{
+ if (name == Udt::SocketOptionName::Linger)
+ {
+ if (value == nullptr)
+ throw gcnew ArgumentNullException("value");
+
+ if (System::Net::Sockets::LingerOption::typeid->IsAssignableFrom(value->GetType()))
+ {
+ System::Net::Sockets::LingerOption^ lingerOpt = (System::Net::Sockets::LingerOption^)value;
+
+ linger lingerValue;
+ lingerValue.l_onoff = lingerOpt->Enabled ? 1 : 0;
+ lingerValue.l_linger = lingerOpt->LingerTime;
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &lingerValue, sizeof(linger)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error setting socket option ", name.ToString(), " to ", value->ToString(), "."));
+ }
+ }
+ else
+ {
+ throw gcnew ArgumentException("Linger socket option value must be of type System.Net.Sockets.LingerOption", "value");
+ }
+ }
+ else if (name == Udt::SocketOptionName::CongestionControl)
+ {
+ if (value != _congestionControl)
+ {
+ if (value == nullptr)
+ {
+ CCCFactory factory;
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &factory, sizeof(CCCVirtualFactory)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error clearing socket option ", name.ToString(), "."));
+ }
+
+ _congestionControl = nullptr;
+ }
+ else if (ICongestionControlFactory::typeid->IsAssignableFrom(value->GetType()))
+ {
+ ICongestionControlFactory^ ccValue = (ICongestionControlFactory^)value;
+ CCCWrapperFactory factory(ccValue);
+
+ if (UDT::ERROR == UDT::setsockopt(_socket, 0, (UDT::SOCKOPT)name, &factory, sizeof(CCCWrapperFactory)))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error setting socket option ", name.ToString(), " to ", value->ToString(), "."));
+ }
+
+ _congestionControl = ccValue;
+ }
+ else
+ {
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " can not be set to ", value->GetType()->Name, " value"), "value");
+ }
+ }
+ }
+ else
+ {
+ if (value == nullptr)
+ throw gcnew ArgumentNullException("value");
+
+ switch (name)
+ {
+ case Udt::SocketOptionName::BlockingReceive:
+ case Udt::SocketOptionName::BlockingSend:
+ case Udt::SocketOptionName::Rendezvous:
+ case Udt::SocketOptionName::ReuseAddress:
+ SetSocketOptionBoolean(name, System::Convert::ToBoolean(value, CultureInfo::InvariantCulture));
+ break;
+
+ case Udt::SocketOptionName::MaxPacketSize:
+ case Udt::SocketOptionName::MaxWindowSize:
+ case Udt::SocketOptionName::SendBuffer:
+ case Udt::SocketOptionName::ReceiveBuffer:
+ case Udt::SocketOptionName::UdpReceiveBuffer:
+ case Udt::SocketOptionName::UdpSendBuffer:
+ case Udt::SocketOptionName::SendTimeout:
+ case Udt::SocketOptionName::ReceiveTimeout:
+ SetSocketOptionInt32(name, System::Convert::ToInt32(value, CultureInfo::InvariantCulture));
+ break;
+
+ case Udt::SocketOptionName::MaxBandwidth:
+ SetSocketOptionInt64(name, System::Convert::ToInt64(value, CultureInfo::InvariantCulture));
+ break;
+
+ case Udt::SocketOptionName::SendData:
+ case Udt::SocketOptionName::ReceiveData:
+ case Udt::SocketOptionName::Events:
+ case Udt::SocketOptionName::State:
+ throw gcnew ArgumentException(System::String::Concat("Socket option ", name, " is read only"), "name");
+
+ default:
+ throw gcnew ArgumentException("Unhandled socket option name.", "name");
+ }
+ }
+}
+
+System::Object^ Udt::Socket::GetSocketOption(Udt::SocketOptionName name)
+{
+ switch (name)
+ {
+ case Udt::SocketOptionName::BlockingReceive:
+ case Udt::SocketOptionName::BlockingSend:
+ case Udt::SocketOptionName::Rendezvous:
+ case Udt::SocketOptionName::ReuseAddress:
+ return GetSocketOptionBoolean(name);
+
+ case Udt::SocketOptionName::MaxPacketSize:
+ case Udt::SocketOptionName::MaxWindowSize:
+ case Udt::SocketOptionName::SendBuffer:
+ case Udt::SocketOptionName::ReceiveBuffer:
+ case Udt::SocketOptionName::UdpReceiveBuffer:
+ case Udt::SocketOptionName::UdpSendBuffer:
+ case Udt::SocketOptionName::SendTimeout:
+ case Udt::SocketOptionName::ReceiveTimeout:
+ case Udt::SocketOptionName::SendData:
+ case Udt::SocketOptionName::ReceiveData:
+ return GetSocketOptionInt32(name);
+
+ case Udt::SocketOptionName::Events:
+ return this->Events;
+
+ case Udt::SocketOptionName::State:
+ return this->State;
+
+ case Udt::SocketOptionName::MaxBandwidth:
+ return GetSocketOptionInt64(name);
+
+ case Udt::SocketOptionName::Linger:
+ {
+ linger value;
+ int valueLen = sizeof(linger);
+
+ if (UDT::ERROR == UDT::getsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, &valueLen))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error getting socket option ", name.ToString(), "."));
+ }
+
+ return gcnew System::Net::Sockets::LingerOption(value.l_onoff != 0, value.l_linger);
+ }
+
+ case Udt::SocketOptionName::CongestionControl:
+ return _congestionControl;
+
+ default:
+ throw gcnew ArgumentException("Unhandled socket option name.", "name");
+ }
+}
+
+int Udt::Socket::GetSocketOptionInt32(Udt::SocketOptionName name)
+{
+ AssertNotDisposed();
+
+ int value;
+ int valueLen = sizeof(int);
+
+ if (UDT::ERROR == UDT::getsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, &valueLen))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error getting socket option ", name.ToString(), "."));
+ }
+
+ return value;
+}
+
+__int64 Udt::Socket::GetSocketOptionInt64(Udt::SocketOptionName name)
+{
+ AssertNotDisposed();
+
+ __int64 value;
+ int valueLen = sizeof(__int64);
+
+ if (UDT::ERROR == UDT::getsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, &valueLen))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error getting socket option ", name.ToString(), "."));
+ }
+
+ return value;
+}
+
+bool Udt::Socket::GetSocketOptionBoolean(Udt::SocketOptionName name)
+{
+ AssertNotDisposed();
+
+ bool value;
+ int valueLen = sizeof(bool);
+
+ if (UDT::ERROR == UDT::getsockopt(_socket, 0, (UDT::SOCKOPT)name, &value, &valueLen))
+ {
+ throw Udt::SocketException::GetLastError(String::Concat("Error getting socket option ", name.ToString(), "."));
+ }
+
+ return value;
+}
diff --git a/UdtProtocol/Socket.h b/UdtProtocol/Socket.h
new file mode 100644
index 0000000..2c11a27
--- /dev/null
+++ b/UdtProtocol/Socket.h
@@ -0,0 +1,679 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "Message.h"
+#include "TraceInfo.h"
+#include "SocketOptionName.h"
+#include "SocketEvents.h"
+#include "SocketState.h"
+#include "SocketException.h"
+#include "StdFileStream.h"
+#include
+
+namespace Udt
+{
+ interface class ICongestionControlFactory;
+
+ ///
+ /// Interface to a UDT socket.
+ ///
+ public ref class Socket
+ {
+ private:
+ UDTSOCKET _socket;
+ bool _isDisposed;
+ System::Net::Sockets::AddressFamily _addressFamily;
+ System::Net::Sockets::SocketType _socketType;
+ ICongestionControlFactory^ _congestionControl;
+ bool _blockingSend;
+
+ void AssertNotDisposed(void)
+ {
+ if (_isDisposed)
+ throw gcnew System::ObjectDisposedException(this->ToString());
+ }
+
+ Socket(UDTSOCKET socket, System::Net::Sockets::AddressFamily family, System::Net::Sockets::SocketType type, ICongestionControlFactory^ congestionControl);
+
+ static Socket(void)
+ {
+ if (UDT::ERROR == UDT::startup())
+ throw SocketException::GetLastError("Error in UDT startup");
+
+ System::AppDomain::CurrentDomain->DomainUnload += gcnew System::EventHandler(DomainUnloaded);
+ }
+
+ static void DomainUnloaded(System::Object^ source, System::EventArgs^ args)
+ {
+ if (UDT::ERROR == UDT::cleanup())
+ throw SocketException::GetLastError("Error in UDT cleanup");
+ }
+
+ int GetSocketOptionInt32(SocketOptionName name);
+ __int64 GetSocketOptionInt64(SocketOptionName name);
+ bool GetSocketOptionBoolean(SocketOptionName name);
+
+ void SetSocketOptionInt32(SocketOptionName name, int value);
+ void SetSocketOptionInt64(SocketOptionName name, __int64 value);
+ void SetSocketOptionBoolean(SocketOptionName name, bool value);
+
+ static UDT::UDSET* CreateUDSet(System::String^ paramName, System::Collections::Generic::ICollection^ fds);
+ static void FillSocketList(const std::vector* list, System::Collections::Generic::Dictionary^ sockets, System::Collections::Generic::ICollection^ fds);
+ static void Filter(UDT::UDSET* set, System::Collections::Generic::ICollection^ fds);
+
+ internal:
+
+ property UDTSOCKET Handle
+ {
+ UDTSOCKET get(void) { return _socket; }
+ }
+
+ public:
+
+ ///
+ /// Timeout value that indicates infinite.
+ ///
+ static initonly System::TimeSpan InfiniteTimeout = System::TimeSpan(-1L);
+
+ ///
+ /// Initialize a new instance using the specified address family and
+ /// socket type.
+ ///
+ /// Address family.
+ /// Socket type.
+ ///
+ /// is not either InterNetwork or InterNetworkV6
+ /// - or -
+ /// is not either Dgram or Stream
+ ///
+ /// If an error occurs creating the socket.
+ Socket(System::Net::Sockets::AddressFamily family, System::Net::Sockets::SocketType type);
+
+ ///
+ /// Closes the socket.
+ ///
+ ~Socket(void);
+
+ ///
+ /// Close the socket and release any associated resources.
+ ///
+ void Close(void);
+
+ ///
+ /// Associate the socket with a local end point.
+ ///
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// If the type of is not compatible with the
+ /// AddressFamily passed to the Socket(AddressFamily,SocketType)
+ /// constructor.
+ ///
+ ///
+ /// If is less than
+ /// or greater than .
+ ///
+ ///
+ /// If an error occurs binding the socket (i.e. the socket is already bound, etc).
+ ///
+ void Bind(System::Net::IPAddress^ address, int port);
+
+ ///
+ /// Associate the socket with a local end point.
+ ///
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// If the type of address in is not compatible with the
+ /// AddressFamily passed to the Socket(AddressFamily,SocketType)
+ /// constructor.
+ ///
+ ///
+ /// If an error occurs binding the socket (i.e. the socket is already bound, etc).
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1702:CompoundWordsShouldBeCasedCorrectly",
+ Justification = "EndPoint is the casing used in IPEndPoint")]
+ void Bind(System::Net::IPEndPoint^ endPoint);
+
+ ///
+ /// Bind directly to an existing UDP socket.
+ ///
+ ///
+ ///
+ /// This is useful for firewall traversing in certain situations:
+ ///
+ /// -
+ /// A UDP socket is created and its address is learned from a name server,
+ /// there is no need to close the UDP socket and open a UDT socket on the
+ /// same address again
+ ///
+ /// -
+ /// For certain firewalls, especially some on local system, the port mapping
+ /// may be changed or the "hole" may be closed when a UDP socket is closed
+ /// and reopened, thus it is necessary to use the UDP socket directly in UDT.
+ ///
+ ///
+ ///
+ ///
+ /// Use this form of bind with caution, as it violates certain programming
+ /// rules regarding code robustness. Once is
+ /// passed to UDT, it MUST NOT be touched again. DO NOT use this unless
+ /// you clearly understand how the related systems work.
+ ///
+ ///
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// is not
+ /// Udp for
+ ///
+ ///
+ /// If an error occurs binding the socket (i.e. the socket is already bound, etc).
+ ///
+ void Bind(System::Net::Sockets::Socket^ udpSocket);
+
+ ///
+ /// Places the socket in a listening state.
+ ///
+ ///
+ /// If is less than 1.
+ ///
+ /// If an error occurs.
+ void Listen(int backlog);
+
+ ///
+ /// Creates a for a newly created connection.
+ ///
+ ///
+ /// Accept synchronously extracts the first pending connection
+ /// request from the connection request queue of the listening socket,
+ /// and then creates and returns a new .
+ ///
+ /// If an error occurs.
+ Socket^ Accept();
+
+ ///
+ /// Establishes a connection to a remote host.
+ ///
+ /// Name of the host to connect to.
+ /// Port to connect to.
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// If is less than
+ /// or greater than .
+ ///
+ /// If an error occurs.
+ void Connect(System::String^ host, int port);
+
+ ///
+ /// Establishes a connection to a remote host.
+ ///
+ /// Address of the host to connect to.
+ /// Port to connect to.
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// If is less than
+ /// or greater than .
+ ///
+ /// If an error occurs.
+ void Connect(System::Net::IPAddress^ address, int port);
+
+ ///
+ /// Establishes a connection to a remote host.
+ ///
+ /// Addresses of the host to connect to.
+ /// Port to connect to.
+ ///
+ /// If is a null reference
+ ///
+ ///
+ /// If is empty
+ ///
+ ///
+ /// If is less than
+ /// or greater than .
+ ///
+ /// If an error occurs.
+ void Connect(cli::array^ addresses, int port);
+
+ ///
+ /// Establishes a connection to a remote host.
+ ///
+ /// Remote end point to connect to.
+ ///
+ /// If is a null reference
+ ///
+ /// If an error occurs.
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1702:CompoundWordsShouldBeCasedCorrectly",
+ Justification = "EndPoint is the casing used in IPEndPoint")]
+ void Connect(System::Net::IPEndPoint^ endPoint);
+
+ ///
+ /// Determines the status of one or more sockets.
+ ///
+ ///
+ /// Note that, currently, is ignored in UDT4.
+ ///
+ /// Socket instances to check for readability.
+ /// Socket instances to check for writeability.
+ /// Socket instances to check for errors.
+ /// Timeout value or .
+ ///
+ /// is a null reference or empty
+ /// - and -
+ /// is a null reference or empty
+ /// - and -
+ /// is a null reference or empty
+ ///
+ ///
+ /// If , , or
+ /// contains a null reference.
+ ///
+ ///
+ /// If is not and
+ /// is less than 0.
+ ///
+ /// If an error occurs.
+ static void Select(
+ System::Collections::Generic::ICollection^ checkRead,
+ System::Collections::Generic::ICollection^ checkWrite,
+ System::Collections::Generic::ICollection^ checkError,
+ System::TimeSpan timeout);
+
+ ///
+ /// Determines the status of one or more sockets.
+ ///
+ /// Sockets to check the status of.
+ /// Sockets that are ready for receive.
+ /// Socket that are ready to write.
+ /// Sockets that are closed or with a broken connection.
+ /// Timeout value or .
+ ///
+ /// If is a null reference.
+ ///
+ ///
+ /// If contains a null reference.
+ ///
+ ///
+ /// , , and are null references.
+ ///
+ ///
+ /// If is not and
+ /// is less than 0.
+ ///
+ /// If an error occurs.
+ static void Select(
+ System::Collections::Generic::ICollection^ checkSockets,
+ System::Collections::Generic::ICollection^ readSockets,
+ System::Collections::Generic::ICollection^ writeSockets,
+ System::Collections::Generic::ICollection^ errorSockets,
+ System::TimeSpan timeout);
+
+ int Receive(cli::array^ buffer);
+ int Receive(cli::array^ buffer, int offset, int size);
+
+ ///
+ /// Send the specified bytes.
+ ///
+ ///
+ /// If the socket is in blocking mode, the call will block until the
+ /// entire buffer is sent. In non-blocking mode, the call may return
+ /// a value less than the length of the buffer (even zero) if the socket
+ /// send queue limit has been reached. See .
+ ///
+ /// Bytes to send.
+ /// The total number of bytes sent.
+ /// If is null.
+ /// If an error occurs.
+ int Send(cli::array^ buffer);
+
+ ///
+ /// Send the specified bytes.
+ ///
+ ///
+ /// If the socket is in blocking mode, the call will block until the
+ /// entire buffer is sent. In non-blocking mode, the call may return
+ /// a value less than the length of the buffer (even zero) if the socket
+ /// send queue limit has been reached. See .
+ ///
+ /// Bytes to send.
+ /// Offset into to start sending.
+ /// Number of bytes to send.
+ /// The total number of bytes sent.
+ /// If is null.
+ /// If or is less than zero.
+ /// If is greater than the length of the minus the .
+ /// If an error occurs.
+ int Send(cli::array^ buffer, int offset, int size);
+
+ ///
+ /// Send the contents of a file on this socket.
+ ///
+ ///
+ /// Does not send a file size.
+ ///
+ /// Name of the local file to send.
+ /// The total number of bytes sent.
+ /// If is null.
+ /// If an error occurs accessing the socket or the file.
+ __int64 SendFile(System::String^ fileName);
+
+ ///
+ /// Send the contents of a file on this socket.
+ ///
+ ///
+ /// Does not send a file size.
+ ///
+ /// Name of the local file to send.
+ /// Offset in the file to start sending.
+ /// The total number of bytes sent.
+ /// If is null.
+ /// If is less than 0.
+ /// If an error occurs accessing the socket or the file.
+ __int64 SendFile(System::String^ fileName, __int64 offset);
+
+ ///
+ /// Send the contents of a file on this socket.
+ ///
+ ///
+ /// Does not send a file size.
+ ///
+ /// Name of the local file to send.
+ /// Offset in the file to start sending.
+ /// Number of bytes to send or -1 to send until the end of the file is reached.
+ /// The total number of bytes sent.
+ /// If is null.
+ /// If is less than 0 or is less than -1.
+ /// If an error occurs accessing the socket or the file.
+ __int64 SendFile(System::String^ fileName, __int64 offset, __int64 count);
+
+ __int64 SendFile(StdFileStream^ file);
+ __int64 SendFile(StdFileStream^ file, __int64 count);
+
+ ///
+ /// Receive data on this socket and store it in a local file.
+ ///
+ /// Name of the local file to write the data to.
+ /// Number of bytes to read from the socket into
+ /// The total number of bytes received.
+ /// If an error occurs accessing the socket or the file.
+ __int64 ReceiveFile(System::String^ fileName, __int64 length);
+
+ __int64 ReceiveFile(StdFileStream^ file, __int64 length);
+
+ int SendMessage(cli::array^ buffer);
+ int SendMessage(cli::array^ buffer, int offset, int size);
+ int SendMessage(Message^ message);
+
+ int ReceiveMessage(cli::array^ buffer);
+ int ReceiveMessage(cli::array^ buffer, int offset, int size);
+
+ ///
+ /// Retrieve internal protocol parameters and performance trace.
+ ///
+ ///
+ /// Same as GetPerformanceInfo(true).
+ ///
+ /// UDT socket performance trace information.
+ TraceInfo^ GetPerformanceInfo();
+
+ ///
+ /// Retrieve internal protocol parameters and performance trace.
+ ///
+ /// True to clear local trace information and counts.
+ /// UDT socket performance trace information.
+ TraceInfo^ GetPerformanceInfo(bool clear);
+
+ void SetSocketOption(SocketOptionName name, int value);
+ void SetSocketOption(SocketOptionName name, __int64 value);
+ void SetSocketOption(SocketOptionName name, bool value);
+ void SetSocketOption(SocketOptionName name, System::Object^ value);
+
+ System::Object^ GetSocketOption(SocketOptionName name);
+
+ ///
+ /// Gets the local end point.
+ ///
+ ///
+ /// The local end point that the socket is using for communications.
+ ///
+ /// If an error occurs accessing the socket.
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1702:CompoundWordsShouldBeCasedCorrectly",
+ Justification = "EndPoint is the casing used in IPEndPoint")]
+ property System::Net::IPEndPoint^ LocalEndPoint
+ {
+ System::Net::IPEndPoint^ get(void);
+ }
+
+ ///
+ /// Gets the address family of the socket.
+ ///
+ property System::Net::Sockets::AddressFamily AddressFamily
+ {
+ System::Net::Sockets::AddressFamily get(void);
+ }
+
+ ///
+ /// Gets the type of the socket.
+ ///
+ property System::Net::Sockets::SocketType SocketType
+ {
+ System::Net::Sockets::SocketType get(void);
+ }
+
+ ///
+ /// Gets the remote end point.
+ ///
+ ///
+ /// The remote end point that the socket is using for communications.
+ ///
+ /// If an error occurs accessing the socket.
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1702:CompoundWordsShouldBeCasedCorrectly",
+ Justification = "EndPoint is the casing used in IPEndPoint")]
+ property System::Net::IPEndPoint^ RemoteEndPoint
+ {
+ System::Net::IPEndPoint^ get(void);
+ }
+
+ property int SendBufferSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::SendBuffer); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::SendBuffer, value); }
+ }
+
+ property int UdpSendBufferSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::UdpSendBuffer); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::UdpSendBuffer, value); }
+ }
+
+ property int SendTimeout
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::SendTimeout); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::SendTimeout, value); }
+ }
+
+ property bool BlockingSend
+ {
+ bool get(void) { return _blockingSend; }
+ void set(bool value) { SetSocketOptionBoolean(Udt::SocketOptionName::BlockingSend, value); }
+ }
+
+ property int ReceiveBufferSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::ReceiveBuffer); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::ReceiveBuffer, value); }
+ }
+
+ property int UdpReceiveBufferSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::UdpReceiveBuffer); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::UdpReceiveBuffer, value); }
+ }
+
+ property int ReceiveTimeout
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::ReceiveTimeout); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::ReceiveTimeout, value); }
+ }
+
+ property bool BlockingReceive
+ {
+ bool get(void) { return GetSocketOptionBoolean(Udt::SocketOptionName::BlockingReceive); }
+ void set(bool value) { SetSocketOptionBoolean(Udt::SocketOptionName::BlockingReceive, value); }
+ }
+
+ property bool Rendezvous
+ {
+ bool get(void) { return GetSocketOptionBoolean(Udt::SocketOptionName::Rendezvous); }
+ void set(bool value) { SetSocketOptionBoolean(Udt::SocketOptionName::Rendezvous, value); }
+ }
+
+ property bool ReuseAddress
+ {
+ bool get(void) { return GetSocketOptionBoolean(Udt::SocketOptionName::ReuseAddress); }
+ void set(bool value) { SetSocketOptionBoolean(Udt::SocketOptionName::ReuseAddress, value); }
+ }
+
+ property __int64 MaxBandwidth
+ {
+ __int64 get(void) { return GetSocketOptionInt64(Udt::SocketOptionName::MaxBandwidth); }
+ void set(__int64 value) { SetSocketOptionInt64(Udt::SocketOptionName::MaxBandwidth, value); }
+ }
+
+ property System::Net::Sockets::LingerOption^ LingerState
+ {
+ System::Net::Sockets::LingerOption^ get(void)
+ {
+ return (System::Net::Sockets::LingerOption^)GetSocketOption(Udt::SocketOptionName::Linger);
+ }
+
+ void set(System::Net::Sockets::LingerOption^ value)
+ {
+ SetSocketOption(Udt::SocketOptionName::Linger, value);
+ }
+ }
+
+ property int MaxPacketSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::MaxPacketSize); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::MaxPacketSize, value); }
+ }
+
+ property int MaxWindowSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::MaxWindowSize); }
+ void set(int value) { SetSocketOptionInt32(Udt::SocketOptionName::MaxWindowSize, value); }
+ }
+
+ property int SendDataSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::SendData); }
+ }
+
+ property int ReceiveDataSize
+ {
+ int get(void) { return GetSocketOptionInt32(Udt::SocketOptionName::ReceiveData); }
+ }
+
+ property Udt::SocketEvents Events
+ {
+ Udt::SocketEvents get(void) { return (Udt::SocketEvents)GetSocketOptionInt32(Udt::SocketOptionName::Events); }
+ }
+
+ property Udt::SocketState State
+ {
+ Udt::SocketState get(void)
+ {
+ if (_isDisposed)
+ {
+ return Udt::SocketState::Closed;
+ }
+
+ Udt::SocketState state = (Udt::SocketState)GetSocketOptionInt32(Udt::SocketOptionName::State);
+
+ if ((int)state == NONEXIST)
+ {
+ state = Udt::SocketState::Closed;
+ }
+
+ return state;
+ }
+ }
+
+ ///
+ /// Get or set the custom congestion control algorithm for this socket
+ /// or null to use the default.
+ ///
+ ///
+ /// The custom congestion control algorithm will be passed to any
+ /// sockets accepted by this socket.
+ ///
+ property ICongestionControlFactory^ CongestionControl
+ {
+ ICongestionControlFactory^ get(void)
+ {
+ return (ICongestionControlFactory^)GetSocketOption(Udt::SocketOptionName::CongestionControl);
+ }
+
+ void set(ICongestionControlFactory^ value)
+ {
+ SetSocketOption(Udt::SocketOptionName::CongestionControl, value);
+ }
+ }
+
+ ///
+ /// Get true or false if this socket has been closed.
+ ///
+ property bool IsDisposed
+ {
+ bool get(void) { return _isDisposed; }
+ }
+ };
+}
diff --git a/UdtProtocol/SocketError.h b/UdtProtocol/SocketError.h
new file mode 100644
index 0000000..937431e
--- /dev/null
+++ b/UdtProtocol/SocketError.h
@@ -0,0 +1,253 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// UDT socket error codes.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Design",
+ "CA1027:MarkEnumsWithFlags",
+ Justification = "This is a set of discrete values, not a set of flags.")]
+ public enum class SocketError
+ {
+ ///
+ /// Unspecified socket error.
+ ///
+ /// -1
+ Error = -1,
+
+ ///
+ /// The operation succeeded.
+ ///
+ /// 0
+ Success = 0,
+
+ ///
+ /// Connection setup failure.
+ ///
+ /// 1000
+ ConnectionSetup = 1000,
+
+ ///
+ /// Server does not exist.
+ ///
+ /// 1001
+ NoServer = 1001,
+
+ ///
+ /// Connection request was rejected by server.
+ ///
+ /// 1002
+ ConnectionRejected = 1002,
+
+ ///
+ /// Could not create/configure UDP socket.
+ ///
+ /// 1003
+ SocketFail = 1003,
+
+ ///
+ /// Connection request was aborted due to security reasons.
+ ///
+ /// 1004
+ SecurityFail = 1004,
+
+ ///
+ /// Connection failure.
+ ///
+ /// 2000
+ ConnectionFail = 2000,
+
+ ///
+ /// Connection was broken.
+ ///
+ /// 2001
+ ConnectionLost = 2001,
+
+ ///
+ /// Connection does not exist.
+ ///
+ /// 2002
+ NoConnection = 2002,
+
+ ///
+ /// System resource failure.
+ ///
+ /// 3000
+ Resource = 3000,
+
+ ///
+ /// Could not create new thread.
+ ///
+ /// 3001
+ Thread = 3001,
+
+ ///
+ /// No memory space.
+ ///
+ /// 3002
+ NoBuffer = 3002,
+
+ ///
+ /// File access error.
+ ///
+ /// 4000
+ File = 4000,
+
+ ///
+ /// Invalid read offset.
+ ///
+ /// 4001
+ InvalidReadOffset = 4001,
+
+ ///
+ /// No read permission.
+ ///
+ /// 4002
+ ReadPermission = 4002,
+
+ ///
+ /// Invalid write offset.
+ ///
+ /// 4003
+ InvalidWriteOffset = 4003,
+
+ ///
+ /// No write permission.
+ ///
+ /// 4004
+ WritePermission = 4004,
+
+ ///
+ /// Invalid operation.
+ ///
+ /// 5000
+ InvalidOperation = 5000,
+
+ ///
+ /// Cannot execute the operation on a bound socket.
+ ///
+ /// 5001
+ BoundSocket = 5001,
+
+ ///
+ /// Cannot execute the operation on a connected socket.
+ ///
+ /// 5002
+ ConnectedSocket = 5002,
+
+ ///
+ /// Bad parameters.
+ ///
+ /// 5003
+ InvalidParameter = 5003,
+
+ ///
+ /// Invalid UDT socket.
+ ///
+ /// 5004
+ InvalidSocket = 5004,
+
+ ///
+ /// Cannot listen on unbound socket.
+ ///
+ /// 5005
+ UnboundSocket = 5005,
+
+ ///
+ /// Socket is not in listening state (accept).
+ ///
+ /// 5006
+ NotListening = 5006,
+
+ ///
+ /// Rendezvous connection process does not allow listen and accept call.
+ ///
+ /// 5007
+ RendezvousNoServer = 5007,
+
+ ///
+ /// Rendezvous connection setup is enabled, but bind has not been called
+ /// before connect.
+ ///
+ /// 5008
+ RendezvousUnbound = 5008,
+
+ ///
+ /// Operation not supported in SOCK_STREAM mode.
+ ///
+ /// 5009
+ OperationNotSupportedForStream = 5009,
+
+ ///
+ /// Operation not supported in SOCK_DGRAM mode.
+ ///
+ /// 5010
+ OperationNotSupportedForDGram = 5010,
+
+ ///
+ /// Another socket is already listening on the same UDP port.
+ ///
+ /// 5011
+ SocketInUse = 5011,
+
+ ///
+ /// Message is too large to be hold in the sending buffer.
+ ///
+ /// 5012
+ MessageTooBig = 5012,
+
+ ///
+ /// Non-blocking call failure.
+ ///
+ /// 6000
+ NonBlockCallFail = 6000,
+
+ ///
+ /// No buffer available for sending.
+ ///
+ /// 6001
+ NoSendBuffer = 6001,
+
+ ///
+ /// No data available for read.
+ ///
+ /// 6002
+ NoDataAvailable = 6002,
+ };
+}
diff --git a/UdtProtocol/SocketEvents.h b/UdtProtocol/SocketEvents.h
new file mode 100644
index 0000000..d14852e
--- /dev/null
+++ b/UdtProtocol/SocketEvents.h
@@ -0,0 +1,65 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// Events available on the socket.
+ ///
+ [System::Flags]
+ public enum class SocketEvents
+ {
+ ///
+ /// No status flags.
+ ///
+ None = 0,
+
+ ///
+ /// Socket has an error.
+ ///
+ Error = UDT_EPOLL_ERR,
+
+ ///
+ /// There is data pending to read.
+ ///
+ Input = UDT_EPOLL_IN,
+
+ ///
+ /// There is data pending to send.
+ ///
+ Output = UDT_EPOLL_OUT,
+ };
+}
\ No newline at end of file
diff --git a/UdtProtocol/SocketException.cpp b/UdtProtocol/SocketException.cpp
new file mode 100644
index 0000000..5a81a27
--- /dev/null
+++ b/UdtProtocol/SocketException.cpp
@@ -0,0 +1,83 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "SocketException.h"
+
+#include
+
+using namespace System;
+using namespace Udt;
+
+SocketException::SocketException(System::Runtime::Serialization::SerializationInfo^ info, System::Runtime::Serialization::StreamingContext context)
+ : System::Exception(info, context)
+{
+ _socketErrorCode = (Udt::SocketError)info->GetInt32("ErrorCode");
+}
+
+SocketException::SocketException(void)
+{
+ _socketErrorCode = Udt::SocketError::Error;
+}
+
+SocketException::SocketException(System::String^ message)
+ : System::Exception(message)
+{
+ _socketErrorCode = Udt::SocketError::Error;
+}
+
+SocketException::SocketException(System::String^ message, System::Exception^ inner)
+ : System::Exception(message, inner)
+{
+ _socketErrorCode = Udt::SocketError::Error;
+}
+
+SocketException::SocketException(System::String^ message, Udt::SocketError errorCode)
+ : System::Exception(message)
+{
+ _socketErrorCode = errorCode;
+}
+
+SocketException^ SocketException::GetLastError(String^ message)
+{
+ UDT::ERRORINFO& lastError = UDT::getlasterror();
+ int errorCode = lastError.getErrorCode();
+ String^ udtMessage = (gcnew String(lastError.getErrorMessage()))->TrimEnd();
+ String^ exMessage;
+
+ if (String::IsNullOrEmpty(message))
+ exMessage = String::Concat(udtMessage, Environment::NewLine, "UDT Error Code: ", (Object^)errorCode);
+ else
+ exMessage = String::Concat(message, Environment::NewLine, udtMessage, Environment::NewLine, "UDT Error Code: ", (Object^)errorCode);
+
+ return gcnew SocketException(exMessage, (Udt::SocketError)errorCode);
+}
diff --git a/UdtProtocol/SocketException.h b/UdtProtocol/SocketException.h
new file mode 100644
index 0000000..d59f046
--- /dev/null
+++ b/UdtProtocol/SocketException.h
@@ -0,0 +1,71 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include "SocketError.h"
+
+namespace Udt
+{
+ [System::Serializable]
+ public ref class SocketException : System::Exception
+ {
+ private:
+ Udt::SocketError _socketErrorCode;
+
+ internal:
+ static SocketException^ GetLastError(System::String^ message);
+
+ protected:
+ SocketException(System::Runtime::Serialization::SerializationInfo^ info, System::Runtime::Serialization::StreamingContext context);
+
+ public:
+ SocketException(void);
+ SocketException(System::String^ message);
+ SocketException(System::String^ message, System::Exception^ inner);
+ SocketException(System::String^ message, Udt::SocketError errorCode);
+
+ [System::Security::Permissions::SecurityPermission(
+ System::Security::Permissions::SecurityAction::LinkDemand,
+ Flags = System::Security::Permissions::SecurityPermissionFlag::SerializationFormatter)]
+ virtual void GetObjectData(System::Runtime::Serialization::SerializationInfo^ info, System::Runtime::Serialization::StreamingContext context) override
+ {
+ this->System::Exception::GetObjectData(info, context);
+ info->AddValue("ErrorCode", _socketErrorCode);
+ }
+
+ property Udt::SocketError SocketErrorCode
+ {
+ Udt::SocketError get() { return _socketErrorCode; }
+ }
+ };
+}
diff --git a/UdtProtocol/SocketOptionName.h b/UdtProtocol/SocketOptionName.h
new file mode 100644
index 0000000..6697f41
--- /dev/null
+++ b/UdtProtocol/SocketOptionName.h
@@ -0,0 +1,143 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// Socket configuration option names.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Design",
+ "CA1027:MarkEnumsWithFlags",
+ Justification = "This is a set of discrete values, not a set of flags.")]
+ public enum class SocketOptionName
+ {
+ ///
+ /// The maximum transfer unit.
+ ///
+ MaxPacketSize = UDT_MSS,
+
+ ///
+ /// If sending is blocking.
+ ///
+ BlockingSend = UDT_SNDSYN,
+
+ ///
+ /// If receiving is blocking.
+ ///
+ BlockingReceive = UDT_RCVSYN,
+
+ ///
+ /// Flight flag size (window size).
+ ///
+ MaxWindowSize = UDT_FC,
+
+ ///
+ /// Maximum buffer in sending queue.
+ ///
+ SendBuffer = UDT_SNDBUF,
+
+ ///
+ /// UDT receiving buffer size.
+ ///
+ ReceiveBuffer = UDT_RCVBUF,
+
+ ///
+ /// UDP sending buffer size.
+ ///
+ UdpSendBuffer = UDP_SNDBUF,
+
+ ///
+ /// UDP receiving buffer size.
+ ///
+ UdpReceiveBuffer = UDP_RCVBUF,
+
+ ///
+ /// Rendezvous connection mode.
+ ///
+ Rendezvous = UDT_RENDEZVOUS,
+
+ ///
+ /// Send timeout.
+ ///
+ SendTimeout = UDT_SNDTIMEO,
+
+ ///
+ /// Receive timeout.
+ ///
+ ReceiveTimeout = UDT_RCVTIMEO,
+
+ ///
+ /// Reuse an existing port or create a new one.
+ ///
+ ReuseAddress = UDT_REUSEADDR,
+
+ ///
+ /// Maximum bandwidth (bytes per second) that the connection can use.
+ ///
+ MaxBandwidth = UDT_MAXBW,
+
+ ///
+ /// Waiting for unsent data when closing.
+ ///
+ Linger = UDT_LINGER,
+
+ ///
+ /// Custom congestion control algorithm.
+ ///
+ CongestionControl = UDT_CC,
+
+ ///
+ /// Size of data in the sending buffer (read only).
+ ///
+ SendData = UDT_SNDDATA,
+
+ ///
+ /// Size of data available for receiving (read only).
+ ///
+ ReceiveData = UDT_RCVDATA,
+
+ ///
+ /// Events available on the socket (read only).
+ ///
+ Events = UDT_EVENT,
+
+ ///
+ /// Socket state (read only).
+ ///
+ State = UDT_STATE,
+ };
+}
diff --git a/UdtProtocol/SocketPoller.cpp b/UdtProtocol/SocketPoller.cpp
new file mode 100644
index 0000000..c8b9c25
--- /dev/null
+++ b/UdtProtocol/SocketPoller.cpp
@@ -0,0 +1,172 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "SocketPoller.h"
+
+#include "Socket.h"
+#include "SocketException.h"
+
+#include
+
+using namespace System;
+using namespace System::Collections::Generic;
+using namespace System::Collections::ObjectModel;
+using namespace Udt;
+
+SocketPoller::SocketPoller(void)
+{
+ _epollId = UDT::epoll_create();
+
+ if (_epollId < 0)
+ throw Udt::SocketException::GetLastError("Error creating epoll id.");
+
+ _pollSockets = gcnew Dictionary();
+ _writeSockets = _readSockets = (ICollection^)EmptySocketList;
+}
+
+SocketPoller::~SocketPoller(void)
+{
+ if (_epollId >= 0)
+ {
+ UDT::epoll_release(_epollId);
+ _epollId = -1;
+ }
+}
+
+void SocketPoller::AssertNotDisposed()
+{
+ if (_epollId < 0) throw gcnew ObjectDisposedException(this->ToString());
+}
+
+void SocketPoller::AddSocket(Udt::Socket^ socket)
+{
+ if (socket == nullptr) throw gcnew ArgumentNullException("socket");
+
+ AssertNotDisposed();
+
+ if (UDT::epoll_add_usock(_epollId, socket->Handle) < 0)
+ {
+ throw Udt::SocketException::GetLastError("Error adding UDT socket to epoll.");
+ }
+
+ _pollSockets[socket->Handle] = socket;
+}
+
+void SocketPoller::RemoveSocket(Udt::Socket^ socket)
+{
+ if (socket == nullptr) throw gcnew ArgumentNullException("socket");
+
+ AssertNotDisposed();
+
+ if (UDT::epoll_remove_usock(_epollId, socket->Handle) < 0)
+ throw Udt::SocketException::GetLastError("Error removing UDT socket from epoll.");
+
+ _pollSockets->Remove(socket->Handle);
+}
+
+void SocketPoller::Wait()
+{
+ Wait(Udt::Socket::InfiniteTimeout);
+}
+
+bool SocketPoller::Wait(System::TimeSpan timeout)
+{
+ AssertNotDisposed();
+
+ if (_pollSockets->Count == 0) throw gcnew InvalidOperationException("No sockets have been added to the poller.");
+
+ _writeSockets = _readSockets = (ICollection^)EmptySocketList;
+
+ std::set readSockets;
+ std::set writeSockets;
+
+ int result = UDT::epoll_wait(_epollId, &readSockets, &writeSockets, (int64_t)timeout.TotalMilliseconds);
+
+ if (result < 0) {
+ if (UDT::getlasterror().getErrorCode() == CUDTException::ETIMEOUT) {
+ return false;
+ }
+
+ throw Udt::SocketException::GetLastError("Error waiting for socket epoll.");
+ }
+
+ if (result == 0)
+ return false;
+
+ if (readSockets.size() > 0)
+ {
+ List^ socketList = GetSockets(readSockets);
+
+ if (socketList->Count > 0)
+ {
+ _readSockets = gcnew ReadOnlyCollection(socketList);
+ }
+ }
+
+ if (writeSockets.size() > 0)
+ {
+ List^ socketList = GetSockets(writeSockets);
+
+ if (socketList->Count > 0)
+ {
+ _writeSockets = gcnew ReadOnlyCollection(socketList);
+ }
+ }
+
+ return true;
+}
+
+List^ SocketPoller::GetSockets(std::set& handles)
+{
+ List^ list = gcnew List((int)handles.size());
+
+ for (std::set::iterator handleIter = handles.begin(); handleIter != handles.end(); ++handleIter)
+ {
+ Udt::Socket^ socket;
+
+ if (_pollSockets->TryGetValue(*handleIter, socket))
+ list->Add(socket);
+ }
+
+ return list;
+}
+
+ICollection^ SocketPoller::ReadSockets::get(void)
+{
+ return _readSockets;
+}
+
+ICollection^ SocketPoller::WriteSockets::get(void)
+{
+ return _writeSockets;
+}
diff --git a/UdtProtocol/SocketPoller.h b/UdtProtocol/SocketPoller.h
new file mode 100644
index 0000000..6c3eaf6
--- /dev/null
+++ b/UdtProtocol/SocketPoller.h
@@ -0,0 +1,138 @@
+#pragma once
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ref class Socket;
+ ref class SocketException;
+
+ ///
+ /// Used to poll IO events from multiple sockets.
+ ///
+ public ref class SocketPoller
+ {
+ private:
+ int _epollId;
+ System::Collections::Generic::Dictionary^ _pollSockets;
+ System::Collections::Generic::ICollection^ _readSockets;
+ System::Collections::Generic::ICollection^ _writeSockets;
+
+ static cli::array^ EmptySocketList = gcnew cli::array(0);
+
+ void AssertNotDisposed();
+ System::Collections::Generic::List^ GetSockets(std::set& handles);
+
+ public:
+
+ ///
+ /// Initialize a new instance.
+ ///
+ SocketPoller(void);
+
+ virtual ~SocketPoller(void);
+
+ ///
+ /// Add a socket to the poller.
+ ///
+ ///
+ /// If the has already been added to the poller,
+ /// it will be ignored if added again.
+ ///
+ /// Socket to add.
+ /// If is null.
+ /// If an error occurs adding the socket.
+ /// If the object has been disposed.
+ void AddSocket(Udt::Socket^ socket);
+
+ ///
+ /// Remove a socket from the poller.
+ ///
+ /// Socket to remove.
+ /// If is null.
+ /// If an error occurs removing the socket.
+ /// If the object has been disposed.
+ void RemoveSocket(Udt::Socket^ socket);
+
+ ///
+ /// Wait indefinitely for a socket event to occur.
+ ///
+ /// If an error occurs waiting.
+ /// If no sockets have been added to the poller.
+ /// If the object has been disposed.
+ void Wait();
+
+ ///
+ /// Wait for a socket event to occur.
+ ///
+ ///
+ /// Use and to get
+ /// the sockets an event occurred on.
+ ///
+ /// Maximum amount of time to wait for an event to occur or -1 milliseconds to wait indefinitely.
+ /// True if an event occurred before the timeout expired.
+ /// If an error occurs waiting.
+ /// If no sockets have been added to the poller.
+ /// If the object has been disposed.
+ bool Wait(System::TimeSpan timeout);
+
+ ///
+ /// Sockets that are ready to read or empty for none.
+ /// By default the collection is empty.
+ ///
+ ///
+ /// The collection is read-only. A new collection instance is
+ /// created each time is called.
+ ///
+ property System::Collections::Generic::ICollection^ ReadSockets
+ {
+ System::Collections::Generic::ICollection^ get(void);
+ }
+
+ ///
+ /// Sockets that are ready to write or broken or empty for none.
+ /// By default the collection is empty.
+ ///
+ ///
+ /// The collection is read-only. A new collection instance is
+ /// created each time is called.
+ ///
+ property System::Collections::Generic::ICollection^ WriteSockets
+ {
+ System::Collections::Generic::ICollection^ get(void);
+ }
+ };
+}
diff --git a/UdtProtocol/SocketState.h b/UdtProtocol/SocketState.h
new file mode 100644
index 0000000..12df2c3
--- /dev/null
+++ b/UdtProtocol/SocketState.h
@@ -0,0 +1,89 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// States the UDT socket can be in.
+ ///
+ public enum class SocketState
+ {
+ ///
+ /// Invalid socket state. A socket will never be in this state.
+ ///
+ Invalid = 0,
+
+ ///
+ /// Socket is in initialized state.
+ ///
+ Initial = INIT,
+
+ ///
+ /// Socket is open.
+ ///
+ Open = OPENED,
+
+ ///
+ /// Socket is listening.
+ ///
+ Listening = LISTENING,
+
+ ///
+ /// Socket is establishing the connection.
+ ///
+ Connecting = CONNECTING,
+
+ ///
+ /// Socket is connected.
+ ///
+ Connected = CONNECTED,
+
+ ///
+ /// Socket is broken.
+ ///
+ Broken = BROKEN,
+
+ ///
+ /// Socket is closing.
+ ///
+ Closing = CLOSING,
+
+ ///
+ /// Socket is closed.
+ ///
+ Closed = CLOSED,
+ };
+}
\ No newline at end of file
diff --git a/UdtProtocol/StdFileStream.cpp b/UdtProtocol/StdFileStream.cpp
new file mode 100644
index 0000000..bbec560
--- /dev/null
+++ b/UdtProtocol/StdFileStream.cpp
@@ -0,0 +1,588 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "StdFileStream.h"
+
+#include
+#include
+#include
+#include
+
+using namespace Udt;
+using namespace System;
+using namespace System::Runtime::InteropServices;
+using namespace System::IO;
+using namespace System::Security::AccessControl;
+using namespace Microsoft::Win32::SafeHandles;
+
+StdFileStream::StdFileStream(String^ path, FileMode mode)
+{
+ Init(path, mode, mode == FileMode::Append ? FileAccess::Write : FileAccess::ReadWrite, FileShare::None);
+}
+
+StdFileStream::StdFileStream(String^ path, FileMode mode, FileAccess access)
+{
+ Init(path, mode, access, FileShare::None);
+}
+
+StdFileStream::StdFileStream(String^ path, FileMode mode, FileAccess access, FileShare share)
+{
+ Init(path, mode, access, share);
+}
+
+void StdFileStream::AssertNotDisposed()
+{
+ if (_stdStream == NULL) throw gcnew ObjectDisposedException(this->ToString());
+}
+
+void StdFileStream::Init(String^ path, FileMode mode, FileAccess access, FileShare share)
+{
+ if (path == nullptr) throw gcnew ArgumentNullException("path");
+ if (path->Length == 0) throw gcnew ArgumentException("Value can not be empty.", "path");
+
+ _canRead = false;
+ _canWrite = false;
+ _canSeek = false;
+
+ int shareFlag;
+ pin_ptr pathPin = PtrToStringChars(path);
+
+ switch (share)
+ {
+ case FileShare::Read:
+ shareFlag = _SH_DENYWR;
+ break;
+
+ case FileShare::Write:
+ shareFlag = _SH_DENYRD;
+ break;
+
+ case FileShare::ReadWrite:
+ shareFlag = _SH_DENYNO;
+ break;
+
+ case FileShare::None:
+ shareFlag = _SH_DENYRW;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("share", share, "Share mode is not supported.");
+ }
+
+ switch (mode)
+ {
+ case FileMode::CreateNew:
+ _streamPtr = InitCreateNew(pathPin, access, shareFlag);
+ break;
+
+ case FileMode::Create:
+ _streamPtr = InitCreate(pathPin, access, shareFlag);
+ break;
+
+ case FileMode::Open:
+ _streamPtr = InitOpen(pathPin, access, shareFlag);
+ break;
+
+ case FileMode::OpenOrCreate:
+ _streamPtr = InitOpenOrCreate(pathPin, access, shareFlag);
+ break;
+
+ case FileMode::Truncate:
+ _streamPtr = InitTruncate(pathPin, access, shareFlag);
+ break;
+
+ case FileMode::Append:
+ _streamPtr = InitAppend(pathPin, access, shareFlag);
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("mode", mode, "File mode is not supported.");
+ }
+
+ _stdStream = new std::fstream(_streamPtr);
+ _stdStream->exceptions(std::ios::failbit);
+}
+
+StdFileStream::~StdFileStream(void)
+{
+ _canRead = false;
+ _canWrite = false;
+ _canSeek = false;
+
+ if (_stdStream != NULL)
+ {
+ _stdStream->close();
+ delete _stdStream;
+ _stdStream = NULL;
+ _streamPtr = NULL; // Handle is closed by _stdStream
+ }
+}
+
+void StdFileStream::CheckLastError(const wchar_t* path)
+{
+ if (errno == ENOENT)
+ {
+ throw gcnew FileNotFoundException("File not found.", gcnew String(path));
+ }
+ else if (errno == EINVAL)
+ {
+ throw gcnew ArgumentException(String::Format("Invalid path value.{0}Value: {1}", Environment::NewLine, gcnew String(path)), "path");
+ }
+ else
+ {
+ char buffer[1024];
+ strerror_s(buffer, 1024, errno);
+ throw gcnew IOException(gcnew String(buffer));
+ }
+}
+
+void StdFileStream::CheckFileNotExists(const wchar_t* path, int shareFlag)
+{
+ struct _stat statInfo;
+
+ // Throw an error if anything other than file not found occurs
+
+ if (_wstat(path, &statInfo) == 0)
+ {
+ throw gcnew IOException("File already exists");
+ }
+ else if (errno != ENOENT)
+ {
+ char buffer[1024];
+ strerror_s(buffer, 1024, errno);
+ throw gcnew IOException(gcnew String(buffer));
+ }
+}
+
+FILE* StdFileStream::InitCreateNew(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ // There is a race condition here in that the first operation is to
+ // check if the file exists before attempting to open for reading.
+ // It is possible for another process to create the file between these
+ // two operations. Risk is small; not sure how to handle that scenario, though.
+
+ switch (access)
+ {
+ case FileAccess::ReadWrite:
+ CheckFileNotExists(path, shareFlag);
+
+ // w+: write+read (truncate file if exists)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"wbN+", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = true;
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ case FileAccess::Write:
+ CheckFileNotExists(path, shareFlag);
+
+ // w: write only (truncate file if exists)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"wbN", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = false;
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.Create");
+ }
+
+ return streamPtr;
+}
+
+FILE* StdFileStream::InitCreate(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ switch (access)
+ {
+ case FileAccess::ReadWrite:
+ // w+: write+read (truncate file if exists)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"wbN+", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = true;
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ case FileAccess::Write:
+ // w: write only (truncate file if exists)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"wbN", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = false;
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.Create");
+ }
+
+ return streamPtr;
+}
+
+FILE* StdFileStream::InitOpen(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ switch (access)
+ {
+ case FileAccess::ReadWrite:
+ case FileAccess::Write:
+ // r+: read+write (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"rbN+", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = (access == FileAccess::ReadWrite);
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ case FileAccess::Read:
+ // r: read only (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"rbN", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = true;
+ _canWrite = false;
+ _canSeek = true;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.Open");
+ }
+
+ return streamPtr;
+}
+
+FILE* StdFileStream::InitOpenOrCreate(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ switch (access)
+ {
+ case FileAccess::ReadWrite:
+ case FileAccess::Write:
+ // r+: read+write (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"rbN+", shareFlag);
+
+ if (streamPtr == NULL)
+ {
+ if (errno == ENOENT) streamPtr = _wfsopen(path, L"wbN+", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+ }
+
+ _canRead = (access == FileAccess::ReadWrite);
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ case FileAccess::Read:
+ // r: read only (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"rbN", shareFlag);
+
+ if (streamPtr == NULL)
+ {
+ if (errno == ENOENT) streamPtr = _wfsopen(path, L"wbN", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+ }
+
+ _canRead = true;
+ _canWrite = false;
+ _canSeek = true;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.OpenOrCreate");
+ }
+
+ return streamPtr;
+}
+
+FILE* StdFileStream::InitTruncate(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ switch (access)
+ {
+ case FileAccess::ReadWrite:
+ case FileAccess::Write:
+ // r+: read+write (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"rbN+", shareFlag);
+
+ if (streamPtr == NULL)
+ CheckLastError(path);
+
+ if (_chsize(_fileno(streamPtr), 0) != 0)
+ {
+ fclose(streamPtr);
+ CheckLastError(path);
+ }
+
+ _canRead = (access == FileAccess::ReadWrite);
+ _canWrite = true;
+ _canSeek = true;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.Truncate");
+ }
+
+ return streamPtr;
+}
+
+FILE* StdFileStream::InitAppend(const wchar_t* path, FileAccess access, int shareFlag)
+{
+ FILE* streamPtr;
+
+ switch (access)
+ {
+ case FileAccess::Write:
+ // a: append only (error file if does not exist)
+ // b: binary
+ // N: not inherited
+ streamPtr = _wfsopen(path, L"abN", shareFlag);
+ if (streamPtr == NULL) CheckLastError(path);
+
+ _canRead = false;
+ _canWrite = true;
+ _canSeek = false;
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("access", access, "Invalid value in combination with FileMode.Append");
+ }
+
+ return streamPtr;
+}
+
+std::fstream& StdFileStream::LoadStdStream(void)
+{
+ AssertNotDisposed();
+ return *_stdStream;
+}
+
+void StdFileStream::Flush(void)
+{
+ AssertNotDisposed();
+ if (CanWrite) _stdStream->flush();
+}
+
+bool StdFileStream::CanRead::get(void)
+{
+ return _canRead;
+}
+
+bool StdFileStream::CanSeek::get(void)
+{
+ return _canSeek;
+}
+
+bool StdFileStream::CanWrite::get(void)
+{
+ return _canWrite;
+}
+
+__int64 StdFileStream::Length::get(void)
+{
+ AssertNotDisposed();
+
+ try
+ {
+ __int64 currentPos = _ftelli64(_streamPtr);
+ _fseeki64(_streamPtr, 0, SEEK_END);
+ __int64 length = _ftelli64(_streamPtr);
+ _fseeki64(_streamPtr, currentPos, SEEK_SET);
+
+ return length;
+ }
+ catch (const std::exception& ex)
+ {
+ throw gcnew IOException(gcnew String(ex.what()));
+ }
+}
+
+__int64 StdFileStream::Position::get(void)
+{
+ AssertNotDisposed();
+
+ try
+ {
+ return _ftelli64(_streamPtr);
+ }
+ catch (const std::exception& ex)
+ {
+ throw gcnew IOException(gcnew String(ex.what()));
+ }
+}
+
+void StdFileStream::Position::set(__int64 value)
+{
+ AssertNotDisposed();
+
+ // The documentation for FileMode::Append states that attempting to seek
+ // results in IOException while attempting to read results in NotSupportedException
+ if (!CanSeek) throw gcnew IOException("Stream does not support seeking.");
+
+ try
+ {
+ if (_fseeki64(_streamPtr, value, SEEK_SET))
+ throw gcnew IOException("Seek failed");
+ }
+ catch (const std::exception& ex)
+ {
+ throw gcnew IOException(gcnew String(ex.what()));
+ }
+}
+
+void StdFileStream::SetLength(__int64 value)
+{
+ throw gcnew NotImplementedException();
+}
+
+__int64 StdFileStream::Seek(__int64 offset, SeekOrigin origin)
+{
+ AssertNotDisposed();
+
+ // The documentation for FileMode::Append states that attempting to seek
+ // results in IOException while attempting to read results in NotSupportedException
+ if (!CanSeek) throw gcnew IOException("Stream does not support seeking.");
+
+ try
+ {
+ switch (origin)
+ {
+ case SeekOrigin::Begin:
+ if (_fseeki64(_streamPtr, offset, SEEK_SET))
+ throw gcnew IOException("Seek failed");
+ break;
+
+ case SeekOrigin::End:
+ if (_fseeki64(_streamPtr, offset, SEEK_END))
+ throw gcnew IOException("Seek failed");
+ break;
+
+ case SeekOrigin::Current:
+ if (_fseeki64(_streamPtr, offset, SEEK_CUR))
+ throw gcnew IOException("Seek failed");
+ break;
+
+ default:
+ throw gcnew ArgumentOutOfRangeException("origin", origin, "Unsupported value.");
+ }
+ }
+ catch (const std::exception& ex)
+ {
+ throw gcnew IOException(gcnew String(ex.what()));
+ }
+
+ return Position;
+}
+
+int StdFileStream::Read(cli::array^ buffer, int offset, int count)
+{
+ if (buffer == nullptr) throw gcnew ArgumentNullException("buffer");
+ if (offset < 0) throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+ if (count < 0) throw gcnew ArgumentOutOfRangeException("count", count, "Value must be greater than or equal to 0.");
+ if (buffer->Length - offset < count) throw gcnew ArgumentException("Invalid array offset/count.");
+
+ AssertNotDisposed();
+
+ if (!CanRead) throw gcnew NotSupportedException("Stream does not support reading.");
+
+ if (_stdStream->eof()) return 0;
+
+ pin_ptr bufferPin = &buffer[0];
+ unsigned char* bufferPtr = bufferPin;
+
+ try
+ {
+ _stdStream->read((char*)bufferPtr + offset, count);
+ }
+ catch (const std::exception& ex)
+ {
+ if (_stdStream->bad()) throw gcnew IOException(gcnew String(ex.what()));
+ }
+
+ return (int)_stdStream->gcount();
+}
+
+void StdFileStream::Write(cli::array^ buffer, int offset, int count)
+{
+ if (buffer == nullptr) throw gcnew ArgumentNullException("buffer");
+ if (offset < 0) throw gcnew ArgumentOutOfRangeException("offset", offset, "Value must be greater than or equal to 0.");
+ if (count < 0) throw gcnew ArgumentOutOfRangeException("count", count, "Value must be greater than or equal to 0.");
+ if (buffer->Length - offset < count) throw gcnew ArgumentException("Invalid array offset/count.");
+
+ AssertNotDisposed();
+
+ if (!CanWrite) throw gcnew NotSupportedException("Stream does not support writing.");
+
+ pin_ptr bufferPin = &buffer[0];
+ unsigned char* bufferPtr = bufferPin;
+
+ try
+ {
+ _stdStream->write((char*)bufferPtr + offset, count);
+ }
+ catch (const std::exception& ex)
+ {
+ throw gcnew IOException(gcnew String(ex.what()));
+ }
+}
diff --git a/UdtProtocol/StdFileStream.h b/UdtProtocol/StdFileStream.h
new file mode 100644
index 0000000..bb79e7c
--- /dev/null
+++ b/UdtProtocol/StdFileStream.h
@@ -0,0 +1,173 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+#include
+
+namespace Udt
+{
+ ///
+ /// Interface to a UDT socket.
+ ///
+ public ref class StdFileStream : public System::IO::Stream
+ {
+ private:
+
+ bool _canRead;
+ bool _canWrite;
+ bool _canSeek;
+ std::fstream* _stdStream;
+
+ // In VC10, fstream tellg has a bug. Should be fixed in VC11.
+ // So, we retain the FILE handle to perform seek/tell operations.
+ // http://connect.microsoft.com/VisualStudio/feedback/details/627639/std-fstream-use-32-bit-int-as-pos-type-even-on-x64-platform
+ FILE* _streamPtr;
+
+ static void CheckFileNotExists(const wchar_t* path, int shareFlag);
+
+ void Init(System::String^ path, System::IO::FileMode mode, System::IO::FileAccess access, System::IO::FileShare share);
+ FILE* InitCreateNew(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+ FILE* InitCreate(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+ FILE* InitOpen(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+ FILE* InitOpenOrCreate(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+ FILE* InitTruncate(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+ FILE* InitAppend(const wchar_t* path, System::IO::FileAccess access, int shareFlag);
+
+ void AssertNotDisposed();
+
+ internal:
+
+ static void CheckLastError(const wchar_t* path);
+ std::fstream& LoadStdStream(void);
+
+ public:
+
+ /// Initializes a new instance of the class with the specified path and creation mode.
+ /// A relative or absolute path for the file that the current FileStream object will encapsulate.
+ /// A constant that determines how to open or create the file.
+ ///
+ /// is an empty string (""), contains only white space, or contains one or more invalid characters. -or- refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in an NTFS environment.
+ ///
+ /// refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in a non-NTFS environment.
+ ///
+ /// is null.
+ /// The caller does not have the required permission.
+ /// The file cannot be found, such as when is FileMode.Truncate or FileMode.Open, and the file specified by does not exist. The file must already exist in these modes.
+ /// An I/O error, such as specifying FileMode.CreateNew when the file specified by already exists, occurred.-or-The stream has been closed.
+ /// The specified path is invalid, such as being on an unmapped drive.
+ /// The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.
+ ///
+ /// contains an invalid value.
+ StdFileStream(System::String^ path, System::IO::FileMode mode);
+
+ /// Initializes a new instance of the class with the specified path, creation mode, and read/write permission.
+ /// A relative or absolute path for the file that the current FileStream object will encapsulate.
+ /// A constant that determines how to open or create the file.
+ /// A constant that determines how the file can be accessed by the FileStream object. This gets the and properties of the FileStream object. is true if specifies a disk file.
+ ///
+ /// is null.
+ ///
+ /// is an empty string (""), contains only white space, or contains one or more invalid characters. -or- refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in an NTFS environment.
+ ///
+ /// refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in a non-NTFS environment.
+ ///
+ /// is an empty string (""), contains only white space, or contains one or more invalid characters.
+ /// The file cannot be found, such as when is FileMode.Truncate or FileMode.Open, and the file specified by does not exist. The file must already exist in these modes.
+ /// An I/O error, such as specifying FileMode.CreateNew when the file specified by already exists, occurred. -or-The stream has been closed.
+ /// The caller does not have the required permission.
+ /// The specified path is invalid, such as being on an unmapped drive.
+ /// The requested is not permitted by the operating system for the specified , such as when is Write or ReadWrite and the file or directory is set for read-only access.
+ /// The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.
+ ///
+ /// contains an invalid value.
+ StdFileStream(System::String^ path, System::IO::FileMode mode, System::IO::FileAccess access);
+
+ /// Initializes a new instance of the class with the specified path, creation mode, read/write permission, and sharing permission.
+ /// A relative or absolute path for the file that the current FileStream object will encapsulate.
+ /// A constant that determines how to open or create the file.
+ /// A constant that determines how the file can be accessed by the FileStream object. This gets the and properties of the FileStream object. is true if specifies a disk file.
+ /// A constant that determines how the file will be shared by processes.
+ ///
+ /// is null.
+ ///
+ /// is an empty string (""), contains only white space, or contains one or more invalid characters. -or- refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in an NTFS environment.
+ ///
+ /// refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in a non-NTFS environment.
+ ///
+ /// is an empty string (""), contains only white space, or contains one or more invalid characters.
+ /// The file cannot be found, such as when is FileMode.Truncate or FileMode.Open, and the file specified by does not exist. The file must already exist in these modes.
+ /// An I/O error, such as specifying FileMode.CreateNew when the file specified by already exists, occurred. -or-The system is running Windows 98 or Windows 98 Second Edition and is set to FileShare.Delete.-or-The stream has been closed.
+ /// The caller does not have the required permission.
+ /// The specified path is invalid, such as being on an unmapped drive.
+ /// The requested is not permitted by the operating system for the specified , such as when is Write or ReadWrite and the file or directory is set for read-only access.
+ /// The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.
+ ///
+ /// contains an invalid value.
+ /// - or -
+ /// contains FileShare::Inheritable or FileShare::Delete
+ ///
+ StdFileStream(System::String^ path, System::IO::FileMode mode, System::IO::FileAccess access, System::IO::FileShare share);
+
+ virtual ~StdFileStream(void);
+
+ virtual property bool CanRead {
+ bool get(void) override;
+ }
+
+ virtual property bool CanSeek {
+ bool get(void) override;
+ }
+
+ virtual property bool CanWrite {
+ bool get(void) override;
+ }
+
+ virtual property __int64 Length {
+ __int64 get(void) override;
+ }
+
+ virtual property __int64 Position {
+ __int64 get(void) override;
+ void set(__int64 value) override;
+ }
+
+ virtual void Flush(void) override;
+
+ virtual void SetLength(__int64 value) override;
+ virtual __int64 Seek(__int64 offset, System::IO::SeekOrigin origin) override;
+
+ virtual int Read(cli::array^ buffer, int offset, int count) override;
+ virtual void Write(cli::array^ buffer, int offset, int count) override;
+ };
+}
diff --git a/UdtProtocol/Stdafx.cpp b/UdtProtocol/Stdafx.cpp
new file mode 100644
index 0000000..a27cecc
--- /dev/null
+++ b/UdtProtocol/Stdafx.cpp
@@ -0,0 +1,20 @@
+// stdafx.cpp : source file that includes just the standard includes
+// UdtProtocol.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+System::TimeSpan FromMicroseconds(__int64 us)
+{
+ return System::TimeSpan(us * 10);
+}
+
+System::TimeSpan FromMilliseconds(__int64 ms)
+{
+ return System::TimeSpan(ms * 10000);
+}
+
+__int64 ToMicroseconds(System::TimeSpan value)
+{
+ return value.Ticks / 10;
+}
diff --git a/UdtProtocol/Stdafx.h b/UdtProtocol/Stdafx.h
new file mode 100644
index 0000000..4a0450f
--- /dev/null
+++ b/UdtProtocol/Stdafx.h
@@ -0,0 +1,14 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+System::TimeSpan FromMicroseconds(__int64 us);
+System::TimeSpan FromMilliseconds(__int64 ms);
+
+__int64 ToMicroseconds(System::TimeSpan value);
diff --git a/UdtProtocol/TotalTraceInfo.cpp b/UdtProtocol/TotalTraceInfo.cpp
new file mode 100644
index 0000000..b7e2279
--- /dev/null
+++ b/UdtProtocol/TotalTraceInfo.cpp
@@ -0,0 +1,56 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "TotalTraceInfo.h"
+
+using namespace Udt;
+using namespace System;
+
+TotalTraceInfo::TotalTraceInfo(const UDT::TRACEINFO& copy)
+{
+ this->SocketCreated = FromMilliseconds(copy.msTimeStamp);
+ this->PacketsSent = copy.pktSentTotal;
+ this->PacketsReceived = copy.pktRecvTotal;
+ this->SendPacketsLost = copy.pktSndLossTotal;
+ this->ReceivePacketsLost = copy.pktRcvLossTotal;
+ this->PacketsRetransmitted = copy.pktRetransTotal;
+ this->AcksSent = copy.pktSentACKTotal;
+ this->AcksReceived = copy.pktRecvACKTotal;
+ this->NaksSent = copy.pktSentNAKTotal;
+ this->NaksReceived = copy.pktRecvNAKTotal;
+ this->SendDuration = FromMicroseconds(copy.usSndDurationTotal);
+}
+
+TotalTraceInfo::TotalTraceInfo(void)
+{
+}
diff --git a/UdtProtocol/TotalTraceInfo.h b/UdtProtocol/TotalTraceInfo.h
new file mode 100644
index 0000000..0f9016d
--- /dev/null
+++ b/UdtProtocol/TotalTraceInfo.h
@@ -0,0 +1,124 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+
+namespace Udt
+{
+ ///
+ /// Performance trace information aggregated since the socket was created.
+ ///
+ public ref class TotalTraceInfo
+ {
+ internal:
+ TotalTraceInfo(const UDT::TRACEINFO& copy);
+
+ public:
+ ///
+ /// Initialize a new instance with default values.
+ ///
+ TotalTraceInfo(void);
+
+ ///
+ /// Time elapsed since the UDT socket is created.
+ ///
+ property System::TimeSpan SocketCreated;
+
+ ///
+ /// Total number of sent packets, including retransmissions.
+ ///
+ property __int64 PacketsSent;
+
+ ///
+ /// Total number of received packets.
+ ///
+ property __int64 PacketsReceived;
+
+ ///
+ /// Total number of lost packets, measured in the sending side.
+ ///
+ property int SendPacketsLost;
+
+ ///
+ /// Total number of lost packets, measured in the receiving side.
+ ///
+ property int ReceivePacketsLost;
+
+ ///
+ /// Total number of retransmitted packets, measured in the sending side.
+ ///
+ property int PacketsRetransmitted;
+
+ ///
+ /// Total number of sent ACK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ property int AcksSent;
+
+ ///
+ /// Total number of received ACK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "ACK is the accepted abbreviation for acknowledgement in this context.")]
+ property int AcksReceived;
+
+ ///
+ /// Total number of sent NAK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "NAK is the accepted abbreviation for negative acknowledgement in this context.")]
+ property int NaksSent;
+
+ ///
+ /// Total number of received NAK packets.
+ ///
+ [System::Diagnostics::CodeAnalysis::SuppressMessageAttribute(
+ "Microsoft.Naming",
+ "CA1704:IdentifiersShouldBeSpelledCorrectly",
+ Justification = "NAK is the accepted abbreviation for negative acknowledgement in this context.")]
+ property int NaksReceived;
+
+ ///
+ /// Total time duration when UDT is sending data (idle time exclusive).
+ ///
+ property System::TimeSpan SendDuration;
+ };
+}
diff --git a/UdtProtocol/TraceInfo.cpp b/UdtProtocol/TraceInfo.cpp
new file mode 100644
index 0000000..6e285f3
--- /dev/null
+++ b/UdtProtocol/TraceInfo.cpp
@@ -0,0 +1,51 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#include "StdAfx.h"
+#include "TraceInfo.h"
+
+using namespace Udt;
+using namespace System;
+
+TraceInfo::TraceInfo(const UDT::TRACEINFO& copy)
+{
+ _total = gcnew TotalTraceInfo(copy);
+ _local = gcnew LocalTraceInfo(copy);
+ _probe = gcnew ProbeTraceInfo(copy);
+}
+
+TraceInfo::TraceInfo(void)
+{
+ _total = gcnew TotalTraceInfo();
+ _local = gcnew LocalTraceInfo();
+ _probe = gcnew ProbeTraceInfo();
+}
diff --git a/UdtProtocol/TraceInfo.h b/UdtProtocol/TraceInfo.h
new file mode 100644
index 0000000..baee682
--- /dev/null
+++ b/UdtProtocol/TraceInfo.h
@@ -0,0 +1,85 @@
+/*****************************************************************
+ *
+ * BSD LICENCE (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Copyright (c) 2010, Cory Thomas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************/
+
+#pragma once
+
+#include
+#include "TotalTraceInfo.h"
+#include "LocalTraceInfo.h"
+#include "ProbeTraceInfo.h"
+
+namespace Udt
+{
+ ///
+ /// UDT socket performance trace information.
+ ///
+ public ref class TraceInfo
+ {
+ private:
+ [System::Diagnostics::DebuggerBrowsable(System::Diagnostics::DebuggerBrowsableState::Never)]
+ Udt::TotalTraceInfo^ _total;
+
+ [System::Diagnostics::DebuggerBrowsable(System::Diagnostics::DebuggerBrowsableState::Never)]
+ Udt::LocalTraceInfo^ _local;
+
+ [System::Diagnostics::DebuggerBrowsable(System::Diagnostics::DebuggerBrowsableState::Never)]
+ Udt::ProbeTraceInfo^ _probe;
+
+ internal:
+ TraceInfo(const UDT::TRACEINFO& copy);
+
+ public:
+ ///
+ /// Initialize a new instance with default values.
+ ///
+ TraceInfo(void);
+
+ ///
+ /// Aggregate values since the UDT socket is created.
+ ///
+ property Udt::TotalTraceInfo^ Total { Udt::TotalTraceInfo^ get(void) { return _total; } }
+
+ ///
+ /// Local values since the last time they are recorded.
+ ///
+ ///
+ /// The local attributes are reset when true is passed to
+ /// Udt.Socket.GetPerformanceInfo(bool).
+ ///
+ property Udt::LocalTraceInfo^ Local { Udt::LocalTraceInfo^ get(void) { return _local; } }
+
+ ///
+ /// Instant values at the time they are observed.
+ ///
+ property Udt::ProbeTraceInfo^ Probe { Udt::ProbeTraceInfo^ get(void) { return _probe; } }
+ };
+}
diff --git a/UdtProtocol/UdtProtocol.rc b/UdtProtocol/UdtProtocol.rc
new file mode 100644
index 0000000..64fc6a5
--- /dev/null
+++ b/UdtProtocol/UdtProtocol.rc
@@ -0,0 +1,99 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,10,0,0
+ PRODUCTVERSION 0,10,0,0
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "UDT.Net wrapper library"
+ VALUE "FileVersion", "0.10.0.0"
+ VALUE "InternalName", "UdtProtocol"
+ VALUE "LegalCopyright", "Copyright (C) 2011"
+ VALUE "OriginalFilename", "UdtProtocol.dll"
+ VALUE "ProductName", "UDT.Net wrapper library"
+ VALUE "ProductVersion", "0.10.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/UdtProtocol/UdtProtocol.vcxproj b/UdtProtocol/UdtProtocol.vcxproj
new file mode 100644
index 0000000..72ac20d
--- /dev/null
+++ b/UdtProtocol/UdtProtocol.vcxproj
@@ -0,0 +1,331 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release - Signed
+ Win32
+
+
+ Release - Signed
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ..\udt4
+
+
+ {CFA7453B-8B9B-4112-AF04-F72C3D431100}
+ Udt
+ ManagedCProj
+ 10.0.17134.0
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+ true
+ v141
+
+
+ DynamicLibrary
+ Unicode
+ true
+ true
+ v141
+
+
+ DynamicLibrary
+ Unicode
+ true
+ true
+ v141
+
+
+ DynamicLibrary
+ Unicode
+ true
+ true
+ v141
+
+
+ DynamicLibrary
+ Unicode
+ true
+ v141
+
+
+ DynamicLibrary
+ Unicode
+ true
+ v141
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ true
+ true
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)bin\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ $(ProjectDir)obj\$(Configuration)\$(Platform)\
+ false
+ false
+ false
+ false
+ $(ProjectDir)UdtProtocol.snk
+ $(ProjectDir)UdtProtocol.snk
+
+
+
+ Disabled
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebugDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+ true
+ MachineX86
+
+
+
+
+
+
+ Disabled
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebugDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+ true
+
+
+
+
+
+
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+ MachineX86
+
+
+
+
+
+
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+ MachineX86
+
+
+
+
+
+
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+
+
+
+
+
+
+ $(UdtHome)\src;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Use
+ true
+ Level3
+ ProgramDatabase
+
+
+ udt.lib;ws2_32.lib
+ $(UdtHome)\src;%(AdditionalLibraryDirectories)
+ true
+
+
+
+
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UdtProtocol/UdtProtocol.vcxproj.filters b/UdtProtocol/UdtProtocol.vcxproj.filters
new file mode 100644
index 0000000..d442ccc
--- /dev/null
+++ b/UdtProtocol/UdtProtocol.vcxproj.filters
@@ -0,0 +1,197 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/UdtProtocol/resource.h b/UdtProtocol/resource.h
new file mode 100644
index 0000000..6d976a0
--- /dev/null
+++ b/UdtProtocol/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by UdtProtocol.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/lib/UdtProtocol.dll b/lib/UdtProtocol.dll
new file mode 100644
index 0000000..8214b34
Binary files /dev/null and b/lib/UdtProtocol.dll differ
diff --git a/lib/msvcp100.dll b/lib/msvcp100.dll
new file mode 100644
index 0000000..8502dfa
Binary files /dev/null and b/lib/msvcp100.dll differ
diff --git a/lib/msvcr100.dll b/lib/msvcr100.dll
new file mode 100644
index 0000000..3e82b1a
Binary files /dev/null and b/lib/msvcr100.dll differ
diff --git a/udt4/src/Makefile b/udt4/src/Makefile
new file mode 100644
index 0000000..bc1e049
--- /dev/null
+++ b/udt4/src/Makefile
@@ -0,0 +1,58 @@
+C++ = g++
+
+ifndef os
+ os = LINUX
+endif
+
+ifndef arch
+ arch = IA32
+endif
+
+CCFLAGS = -fPIC -Wall -Wextra -D$(os) -finline-functions -O3 -fno-strict-aliasing -fvisibility=hidden
+
+ifeq ($(arch), IA32)
+ CCFLAGS += -DIA32
+endif
+
+ifeq ($(arch), POWERPC)
+ CCFLAGS += -mcpu=powerpc
+endif
+
+ifeq ($(arch), SPARC)
+ CCFLAGS += -DSPARC
+endif
+
+ifeq ($(arch), IA64)
+ CCFLAGS += -DIA64
+endif
+
+ifeq ($(arch), AMD64)
+ CCFLAGS += -DAMD64
+endif
+
+OBJS = api.o buffer.o cache.o ccc.o channel.o common.o core.o epoll.o list.o md5.o packet.o queue.o window.o
+DIR = $(shell pwd)
+
+all: libudt.so libudt.a udt
+
+%.o: %.cpp %.h udt.h
+ $(C++) $(CCFLAGS) $< -c
+
+libudt.so: $(OBJS)
+ifneq ($(os), OSX)
+ $(C++) -shared -o $@ $^
+else
+ $(C++) -dynamiclib -o libudt.dylib -lstdc++ -lpthread -lm $^
+endif
+
+libudt.a: $(OBJS)
+ ar -rcs $@ $^
+
+udt:
+ cp udt.h udt
+
+clean:
+ rm -f *.o *.so *.dylib *.a udt
+
+install:
+ export LD_LIBRARY_PATH=$(DIR):$$LD_LIBRARY_PATH
diff --git a/udt4/src/api.cpp b/udt4/src/api.cpp
new file mode 100644
index 0000000..e444218
--- /dev/null
+++ b/udt4/src/api.cpp
@@ -0,0 +1,2392 @@
+/*****************************************************************************
+Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the
+ above copyright notice, this list of conditions
+ and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the University of Illinois
+ nor the names of its contributors may be used to
+ endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+/*****************************************************************************
+written by
+ Yunhong Gu, last updated 07/09/2011
+*****************************************************************************/
+
+#ifdef WIN32
+ #include
+ #include
+ #ifdef LEGACY_WIN32
+ #include
+ #endif
+#else
+ #include
+#endif
+#include
+#include "api.h"
+#include "core.h"
+
+using namespace std;
+
+CUDTSocket::CUDTSocket():
+m_Status(INIT),
+m_TimeStamp(0),
+m_iIPversion(0),
+m_pSelfAddr(NULL),
+m_pPeerAddr(NULL),
+m_SocketID(0),
+m_ListenSocket(0),
+m_PeerID(0),
+m_iISN(0),
+m_pUDT(NULL),
+m_pQueuedSockets(NULL),
+m_pAcceptSockets(NULL),
+m_AcceptCond(),
+m_AcceptLock(),
+m_uiBackLog(0),
+m_iMuxID(-1)
+{
+ #ifndef WIN32
+ pthread_mutex_init(&m_AcceptLock, NULL);
+ pthread_cond_init(&m_AcceptCond, NULL);
+ pthread_mutex_init(&m_ControlLock, NULL);
+ #else
+ m_AcceptLock = CreateMutex(NULL, false, NULL);
+ m_AcceptCond = CreateEvent(NULL, false, false, NULL);
+ m_ControlLock = CreateMutex(NULL, false, NULL);
+ #endif
+}
+
+CUDTSocket::~CUDTSocket()
+{
+ if (AF_INET == m_iIPversion)
+ {
+ delete (sockaddr_in*)m_pSelfAddr;
+ delete (sockaddr_in*)m_pPeerAddr;
+ }
+ else
+ {
+ delete (sockaddr_in6*)m_pSelfAddr;
+ delete (sockaddr_in6*)m_pPeerAddr;
+ }
+
+ delete m_pUDT;
+ m_pUDT = NULL;
+
+ delete m_pQueuedSockets;
+ delete m_pAcceptSockets;
+
+ #ifndef WIN32
+ pthread_mutex_destroy(&m_AcceptLock);
+ pthread_cond_destroy(&m_AcceptCond);
+ pthread_mutex_destroy(&m_ControlLock);
+ #else
+ CloseHandle(m_AcceptLock);
+ CloseHandle(m_AcceptCond);
+ CloseHandle(m_ControlLock);
+ #endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+CUDTUnited::CUDTUnited():
+m_Sockets(),
+m_ControlLock(),
+m_IDLock(),
+m_SocketID(0),
+m_TLSError(),
+m_mMultiplexer(),
+m_MultiplexerLock(),
+m_pCache(NULL),
+m_bClosing(false),
+m_GCStopLock(),
+m_GCStopCond(),
+m_InitLock(),
+m_iInstanceCount(0),
+m_bGCStatus(false),
+m_GCThread(),
+m_ClosedSockets()
+{
+ // Socket ID MUST start from a random value
+ srand((unsigned int)CTimer::getTime());
+ m_SocketID = 1 + (int)((1 << 30) * (double(rand()) / RAND_MAX));
+
+ #ifndef WIN32
+ pthread_mutex_init(&m_ControlLock, NULL);
+ pthread_mutex_init(&m_IDLock, NULL);
+ pthread_mutex_init(&m_InitLock, NULL);
+ #else
+ m_ControlLock = CreateMutex(NULL, false, NULL);
+ m_IDLock = CreateMutex(NULL, false, NULL);
+ m_InitLock = CreateMutex(NULL, false, NULL);
+ #endif
+
+ #ifndef WIN32
+ pthread_key_create(&m_TLSError, TLSDestroy);
+ #else
+ m_TLSError = TlsAlloc();
+ m_TLSLock = CreateMutex(NULL, false, NULL);
+ #endif
+
+ m_pCache = new CCache;
+}
+
+CUDTUnited::~CUDTUnited()
+{
+ #ifndef WIN32
+ pthread_mutex_destroy(&m_ControlLock);
+ pthread_mutex_destroy(&m_IDLock);
+ pthread_mutex_destroy(&m_InitLock);
+ #else
+ CloseHandle(m_ControlLock);
+ CloseHandle(m_IDLock);
+ CloseHandle(m_InitLock);
+ #endif
+
+ #ifndef WIN32
+ pthread_key_delete(m_TLSError);
+ #else
+ TlsFree(m_TLSError);
+ CloseHandle(m_TLSLock);
+ #endif
+
+ delete m_pCache;
+}
+
+int CUDTUnited::startup()
+{
+ CGuard gcinit(m_InitLock);
+
+ if (m_iInstanceCount++ > 0)
+ return 0;
+
+ // Global initialization code
+ #ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ wVersionRequested = MAKEWORD(2, 2);
+
+ if (0 != WSAStartup(wVersionRequested, &wsaData))
+ throw CUDTException(1, 0, WSAGetLastError());
+ #endif
+
+ //init CTimer::EventLock
+
+ if (m_bGCStatus)
+ return true;
+
+ m_bClosing = false;
+ #ifndef WIN32
+ pthread_mutex_init(&m_GCStopLock, NULL);
+ pthread_cond_init(&m_GCStopCond, NULL);
+ pthread_create(&m_GCThread, NULL, garbageCollect, this);
+ #else
+ m_GCStopLock = CreateMutex(NULL, false, NULL);
+ m_GCStopCond = CreateEvent(NULL, false, false, NULL);
+ DWORD ThreadID;
+ m_GCThread = CreateThread(NULL, 0, garbageCollect, this, 0, &ThreadID);
+ #endif
+
+ m_bGCStatus = true;
+
+ return 0;
+}
+
+int CUDTUnited::cleanup()
+{
+ CGuard gcinit(m_InitLock);
+
+ if (--m_iInstanceCount > 0)
+ return 0;
+
+ //destroy CTimer::EventLock
+
+ if (!m_bGCStatus)
+ return 0;
+
+ m_bClosing = true;
+ #ifndef WIN32
+ pthread_cond_signal(&m_GCStopCond);
+ pthread_join(m_GCThread, NULL);
+ pthread_mutex_destroy(&m_GCStopLock);
+ pthread_cond_destroy(&m_GCStopCond);
+ #else
+ SetEvent(m_GCStopCond);
+ WaitForSingleObject(m_GCThread, INFINITE);
+ CloseHandle(m_GCThread);
+ CloseHandle(m_GCStopLock);
+ CloseHandle(m_GCStopCond);
+ #endif
+
+ m_bGCStatus = false;
+
+ // Global destruction code
+ #ifdef WIN32
+ WSACleanup();
+ #endif
+
+ return 0;
+}
+
+UDTSOCKET CUDTUnited::newSocket(int af, int type)
+{
+ if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
+ throw CUDTException(5, 3, 0);
+
+ CUDTSocket* ns = NULL;
+
+ try
+ {
+ ns = new CUDTSocket;
+ ns->m_pUDT = new CUDT;
+ if (AF_INET == af)
+ {
+ ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in);
+ ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0;
+ }
+ else
+ {
+ ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6);
+ ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0;
+ }
+ }
+ catch (...)
+ {
+ delete ns;
+ throw CUDTException(3, 2, 0);
+ }
+
+ CGuard::enterCS(m_IDLock);
+ ns->m_SocketID = -- m_SocketID;
+ CGuard::leaveCS(m_IDLock);
+
+ ns->m_Status = INIT;
+ ns->m_ListenSocket = 0;
+ ns->m_pUDT->m_SocketID = ns->m_SocketID;
+ ns->m_pUDT->m_iSockType = (SOCK_STREAM == type) ? UDT_STREAM : UDT_DGRAM;
+ ns->m_pUDT->m_iIPversion = ns->m_iIPversion = af;
+ ns->m_pUDT->m_pCache = m_pCache;
+
+ // protect the m_Sockets structure.
+ CGuard::enterCS(m_ControlLock);
+ try
+ {
+ m_Sockets[ns->m_SocketID] = ns;
+ }
+ catch (...)
+ {
+ //failure and rollback
+ CGuard::leaveCS(m_ControlLock);
+ delete ns;
+ ns = NULL;
+ }
+ CGuard::leaveCS(m_ControlLock);
+
+ if (NULL == ns)
+ throw CUDTException(3, 2, 0);
+
+ return ns->m_SocketID;
+}
+
+int CUDTUnited::newConnection(const UDTSOCKET listen, const sockaddr* peer, CHandShake* hs)
+{
+ CUDTSocket* ns = NULL;
+ CUDTSocket* ls = locate(listen);
+
+ if (NULL == ls)
+ return -1;
+
+ // if this connection has already been processed
+ if (NULL != (ns = locate(peer, hs->m_iID, hs->m_iISN)))
+ {
+ if (ns->m_pUDT->m_bBroken)
+ {
+ // last connection from the "peer" address has been broken
+ ns->m_Status = CLOSED;
+ ns->m_TimeStamp = CTimer::getTime();
+
+ CGuard::enterCS(ls->m_AcceptLock);
+ ls->m_pQueuedSockets->erase(ns->m_SocketID);
+ ls->m_pAcceptSockets->erase(ns->m_SocketID);
+ CGuard::leaveCS(ls->m_AcceptLock);
+ }
+ else
+ {
+ // connection already exist, this is a repeated connection request
+ // respond with existing HS information
+
+ hs->m_iISN = ns->m_pUDT->m_iISN;
+ hs->m_iMSS = ns->m_pUDT->m_iMSS;
+ hs->m_iFlightFlagSize = ns->m_pUDT->m_iFlightFlagSize;
+ hs->m_iReqType = -1;
+ hs->m_iID = ns->m_SocketID;
+
+ return 0;
+
+ //except for this situation a new connection should be started
+ }
+ }
+
+ // exceeding backlog, refuse the connection request
+ if (ls->m_pQueuedSockets->size() >= ls->m_uiBackLog)
+ return -1;
+
+ try
+ {
+ ns = new CUDTSocket;
+ ns->m_pUDT = new CUDT(*(ls->m_pUDT));
+ if (AF_INET == ls->m_iIPversion)
+ {
+ ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in);
+ ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0;
+ ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in);
+ memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in));
+ }
+ else
+ {
+ ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6);
+ ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0;
+ ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in6);
+ memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in6));
+ }
+ }
+ catch (...)
+ {
+ delete ns;
+ return -1;
+ }
+
+ CGuard::enterCS(m_IDLock);
+ ns->m_SocketID = -- m_SocketID;
+ CGuard::leaveCS(m_IDLock);
+
+ ns->m_ListenSocket = listen;
+ ns->m_iIPversion = ls->m_iIPversion;
+ ns->m_pUDT->m_SocketID = ns->m_SocketID;
+ ns->m_PeerID = hs->m_iID;
+ ns->m_iISN = hs->m_iISN;
+
+ int error = 0;
+
+ try
+ {
+ // bind to the same addr of listening socket
+ ns->m_pUDT->open();
+ updateMux(ns, ls);
+ ns->m_pUDT->connect(peer, hs);
+ }
+ catch (...)
+ {
+ error = 1;
+ goto ERR_ROLLBACK;
+ }
+
+ ns->m_Status = CONNECTED;
+
+ // copy address information of local node
+ ns->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(ns->m_pSelfAddr);
+ CIPAddress::pton(ns->m_pSelfAddr, ns->m_pUDT->m_piSelfIP, ns->m_iIPversion);
+
+ // protect the m_Sockets structure.
+ CGuard::enterCS(m_ControlLock);
+ try
+ {
+ m_Sockets[ns->m_SocketID] = ns;
+ m_PeerRec[(ns->m_PeerID << 30) + ns->m_iISN].insert(ns->m_SocketID);
+ }
+ catch (...)
+ {
+ error = 2;
+ }
+ CGuard::leaveCS(m_ControlLock);
+
+ CGuard::enterCS(ls->m_AcceptLock);
+ try
+ {
+ ls->m_pQueuedSockets->insert(ns->m_SocketID);
+ }
+ catch (...)
+ {
+ error = 3;
+ }
+ CGuard::leaveCS(ls->m_AcceptLock);
+
+ // acknowledge users waiting for new connections on the listening socket
+ m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, true);
+
+ CTimer::triggerEvent();
+
+ ERR_ROLLBACK:
+ if (error > 0)
+ {
+ ns->m_pUDT->close();
+ ns->m_Status = CLOSED;
+ ns->m_TimeStamp = CTimer::getTime();
+
+ return -1;
+ }
+
+ // wake up a waiting accept() call
+ #ifndef WIN32
+ pthread_mutex_lock(&(ls->m_AcceptLock));
+ pthread_cond_signal(&(ls->m_AcceptCond));
+ pthread_mutex_unlock(&(ls->m_AcceptLock));
+ #else
+ SetEvent(ls->m_AcceptCond);
+ #endif
+
+ return 1;
+}
+
+CUDT* CUDTUnited::lookup(const UDTSOCKET u)
+{
+ // protects the m_Sockets structure
+ CGuard cg(m_ControlLock);
+
+ map::iterator i = m_Sockets.find(u);
+
+ if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED))
+ throw CUDTException(5, 4, 0);
+
+ return i->second->m_pUDT;
+}
+
+UDTSTATUS CUDTUnited::getStatus(const UDTSOCKET u)
+{
+ // protects the m_Sockets structure
+ CGuard cg(m_ControlLock);
+
+ map::iterator i = m_Sockets.find(u);
+
+ if (i == m_Sockets.end())
+ {
+ if (m_ClosedSockets.find(u) != m_ClosedSockets.end())
+ return CLOSED;
+
+ return NONEXIST;
+ }
+
+ if (i->second->m_pUDT->m_bBroken)
+ return BROKEN;
+
+ return i->second->m_Status;
+}
+
+int CUDTUnited::bind(const UDTSOCKET u, const sockaddr* name, int namelen)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ CGuard cg(s->m_ControlLock);
+
+ // cannot bind a socket more than once
+ if (INIT != s->m_Status)
+ throw CUDTException(5, 0, 0);
+
+ // check the size of SOCKADDR structure
+ if (AF_INET == s->m_iIPversion)
+ {
+ if (namelen != sizeof(sockaddr_in))
+ throw CUDTException(5, 3, 0);
+ }
+ else
+ {
+ if (namelen != sizeof(sockaddr_in6))
+ throw CUDTException(5, 3, 0);
+ }
+
+ s->m_pUDT->open();
+ updateMux(s, name);
+ s->m_Status = OPENED;
+
+ // copy address information of local node
+ s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr);
+
+ return 0;
+}
+
+int CUDTUnited::bind(UDTSOCKET u, UDPSOCKET udpsock)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ CGuard cg(s->m_ControlLock);
+
+ // cannot bind a socket more than once
+ if (INIT != s->m_Status)
+ throw CUDTException(5, 0, 0);
+
+ sockaddr_in name4;
+ sockaddr_in6 name6;
+ sockaddr* name;
+ socklen_t namelen;
+
+ if (AF_INET == s->m_iIPversion)
+ {
+ namelen = sizeof(sockaddr_in);
+ name = (sockaddr*)&name4;
+ }
+ else
+ {
+ namelen = sizeof(sockaddr_in6);
+ name = (sockaddr*)&name6;
+ }
+
+ if (-1 == ::getsockname(udpsock, name, &namelen))
+ throw CUDTException(5, 3);
+
+ s->m_pUDT->open();
+ updateMux(s, name, &udpsock);
+ s->m_Status = OPENED;
+
+ // copy address information of local node
+ s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr);
+
+ return 0;
+}
+
+int CUDTUnited::listen(const UDTSOCKET u, int backlog)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ CGuard cg(s->m_ControlLock);
+
+ // do nothing if the socket is already listening
+ if (LISTENING == s->m_Status)
+ return 0;
+
+ // a socket can listen only if is in OPENED status
+ if (OPENED != s->m_Status)
+ throw CUDTException(5, 5, 0);
+
+ // listen is not supported in rendezvous connection setup
+ if (s->m_pUDT->m_bRendezvous)
+ throw CUDTException(5, 7, 0);
+
+ if (backlog <= 0)
+ throw CUDTException(5, 3, 0);
+
+ s->m_uiBackLog = backlog;
+
+ try
+ {
+ s->m_pQueuedSockets = new set;
+ s->m_pAcceptSockets = new set;
+ }
+ catch (...)
+ {
+ delete s->m_pQueuedSockets;
+ delete s->m_pAcceptSockets;
+ throw CUDTException(3, 2, 0);
+ }
+
+ s->m_pUDT->listen();
+
+ s->m_Status = LISTENING;
+
+ return 0;
+}
+
+UDTSOCKET CUDTUnited::accept(const UDTSOCKET listen, sockaddr* addr, int* addrlen)
+{
+ if ((NULL != addr) && (NULL == addrlen))
+ throw CUDTException(5, 3, 0);
+
+ CUDTSocket* ls = locate(listen);
+
+ if (ls == NULL)
+ throw CUDTException(5, 4, 0);
+
+ // the "listen" socket must be in LISTENING status
+ if (LISTENING != ls->m_Status)
+ throw CUDTException(5, 6, 0);
+
+ // no "accept" in rendezvous connection setup
+ if (ls->m_pUDT->m_bRendezvous)
+ throw CUDTException(5, 7, 0);
+
+ UDTSOCKET u = CUDT::INVALID_SOCK;
+ bool accepted = false;
+
+ // !!only one conection can be set up each time!!
+ #ifndef WIN32
+ while (!accepted)
+ {
+ pthread_mutex_lock(&(ls->m_AcceptLock));
+
+ if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken)
+ {
+ // This socket has been closed.
+ accepted = true;
+ }
+ else if (ls->m_pQueuedSockets->size() > 0)
+ {
+ u = *(ls->m_pQueuedSockets->begin());
+ ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u);
+ ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin());
+ accepted = true;
+ }
+ else if (!ls->m_pUDT->m_bSynRecving)
+ {
+ accepted = true;
+ }
+
+ if (!accepted && (LISTENING == ls->m_Status))
+ pthread_cond_wait(&(ls->m_AcceptCond), &(ls->m_AcceptLock));
+
+ if (ls->m_pQueuedSockets->empty())
+ m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, false);
+
+ pthread_mutex_unlock(&(ls->m_AcceptLock));
+ }
+ #else
+ while (!accepted)
+ {
+ WaitForSingleObject(ls->m_AcceptLock, INFINITE);
+
+ if (ls->m_pQueuedSockets->size() > 0)
+ {
+ u = *(ls->m_pQueuedSockets->begin());
+ ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u);
+ ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin());
+
+ accepted = true;
+ }
+ else if (!ls->m_pUDT->m_bSynRecving)
+ accepted = true;
+
+ ReleaseMutex(ls->m_AcceptLock);
+
+ if (!accepted & (LISTENING == ls->m_Status))
+ WaitForSingleObject(ls->m_AcceptCond, INFINITE);
+
+ if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken)
+ {
+ // Send signal to other threads that are waiting to accept.
+ SetEvent(ls->m_AcceptCond);
+ accepted = true;
+ }
+
+ if (ls->m_pQueuedSockets->empty())
+ m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, false);
+ }
+ #endif
+
+ if (u == CUDT::INVALID_SOCK)
+ {
+ // non-blocking receiving, no connection available
+ if (!ls->m_pUDT->m_bSynRecving)
+ throw CUDTException(6, 2, 0);
+
+ // listening socket is closed
+ throw CUDTException(5, 6, 0);
+ }
+
+ if ((addr != NULL) && (addrlen != NULL))
+ {
+ if (AF_INET == locate(u)->m_iIPversion)
+ *addrlen = sizeof(sockaddr_in);
+ else
+ *addrlen = sizeof(sockaddr_in6);
+
+ // copy address information of peer node
+ memcpy(addr, locate(u)->m_pPeerAddr, *addrlen);
+ }
+
+ return u;
+}
+
+int CUDTUnited::connect(const UDTSOCKET u, const sockaddr* name, int namelen)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ CGuard cg(s->m_ControlLock);
+
+ // check the size of SOCKADDR structure
+ if (AF_INET == s->m_iIPversion)
+ {
+ if (namelen != sizeof(sockaddr_in))
+ throw CUDTException(5, 3, 0);
+ }
+ else
+ {
+ if (namelen != sizeof(sockaddr_in6))
+ throw CUDTException(5, 3, 0);
+ }
+
+ // a socket can "connect" only if it is in INIT or OPENED status
+ if (INIT == s->m_Status)
+ {
+ if (!s->m_pUDT->m_bRendezvous)
+ {
+ s->m_pUDT->open();
+ updateMux(s);
+ s->m_Status = OPENED;
+ }
+ else
+ throw CUDTException(5, 8, 0);
+ }
+ else if (OPENED != s->m_Status)
+ throw CUDTException(5, 2, 0);
+
+ // connect_complete() may be called before connect() returns.
+ // So we need to update the status before connect() is called,
+ // otherwise the status may be overwritten with wrong value (CONNECTED vs. CONNECTING).
+ s->m_Status = CONNECTING;
+ try
+ {
+ s->m_pUDT->connect(name);
+ }
+ catch (CUDTException e)
+ {
+ s->m_Status = OPENED;
+ throw e;
+ }
+
+ // record peer address
+ delete s->m_pPeerAddr;
+ if (AF_INET == s->m_iIPversion)
+ {
+ s->m_pPeerAddr = (sockaddr*)(new sockaddr_in);
+ memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in));
+ }
+ else
+ {
+ s->m_pPeerAddr = (sockaddr*)(new sockaddr_in6);
+ memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in6));
+ }
+
+ return 0;
+}
+
+void CUDTUnited::connect_complete(const UDTSOCKET u)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ // copy address information of local node
+ // the local port must be correctly assigned BEFORE CUDT::connect(),
+ // otherwise if connect() fails, the multiplexer cannot be located by garbage collection and will cause leak
+ s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr);
+ CIPAddress::pton(s->m_pSelfAddr, s->m_pUDT->m_piSelfIP, s->m_iIPversion);
+
+ s->m_Status = CONNECTED;
+}
+
+int CUDTUnited::close(const UDTSOCKET u)
+{
+ CUDTSocket* s = locate(u);
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ CGuard socket_cg(s->m_ControlLock);
+
+ if (s->m_Status == LISTENING)
+ {
+ if (s->m_pUDT->m_bBroken)
+ return 0;
+
+ s->m_TimeStamp = CTimer::getTime();
+ s->m_pUDT->m_bBroken = true;
+
+ // broadcast all "accept" waiting
+ #ifndef WIN32
+ pthread_mutex_lock(&(s->m_AcceptLock));
+ pthread_cond_broadcast(&(s->m_AcceptCond));
+ pthread_mutex_unlock(&(s->m_AcceptLock));
+ #else
+ SetEvent(s->m_AcceptCond);
+ #endif
+
+ return 0;
+ }
+
+ s->m_pUDT->close();
+
+ // synchronize with garbage collection.
+ CGuard manager_cg(m_ControlLock);
+
+ // since "s" is located before m_ControlLock, locate it again in case it became invalid
+ map::iterator i = m_Sockets.find(u);
+ if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED))
+ return 0;
+ s = i->second;
+
+ s->m_Status = CLOSED;
+
+ // a socket will not be immediated removed when it is closed
+ // in order to prevent other methods from accessing invalid address
+ // a timer is started and the socket will be removed after approximately 1 second
+ s->m_TimeStamp = CTimer::getTime();
+
+ m_Sockets.erase(s->m_SocketID);
+ m_ClosedSockets.insert(pair(s->m_SocketID, s));
+
+ CTimer::triggerEvent();
+
+ return 0;
+}
+
+int CUDTUnited::getpeername(const UDTSOCKET u, sockaddr* name, int* namelen)
+{
+ if (CONNECTED != getStatus(u))
+ throw CUDTException(2, 2, 0);
+
+ CUDTSocket* s = locate(u);
+
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ if (!s->m_pUDT->m_bConnected || s->m_pUDT->m_bBroken)
+ throw CUDTException(2, 2, 0);
+
+ if (AF_INET == s->m_iIPversion)
+ *namelen = sizeof(sockaddr_in);
+ else
+ *namelen = sizeof(sockaddr_in6);
+
+ // copy address information of peer node
+ memcpy(name, s->m_pPeerAddr, *namelen);
+
+ return 0;
+}
+
+int CUDTUnited::getsockname(const UDTSOCKET u, sockaddr* name, int* namelen)
+{
+ CUDTSocket* s = locate(u);
+
+ if (NULL == s)
+ throw CUDTException(5, 4, 0);
+
+ if (s->m_pUDT->m_bBroken)
+ throw CUDTException(5, 4, 0);
+
+ if (INIT == s->m_Status)
+ throw CUDTException(2, 2, 0);
+
+ if (AF_INET == s->m_iIPversion)
+ *namelen = sizeof(sockaddr_in);
+ else
+ *namelen = sizeof(sockaddr_in6);
+
+ // copy address information of local node
+ memcpy(name, s->m_pSelfAddr, *namelen);
+
+ return 0;
+}
+
+int CUDTUnited::select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout)
+{
+ uint64_t entertime = CTimer::getTime();
+
+ uint64_t to;
+ if (NULL == timeout)
+ to = 0xFFFFFFFFFFFFFFFFULL;
+ else
+ to = timeout->tv_sec * 1000000 + timeout->tv_usec;
+
+ // initialize results
+ int count = 0;
+ set rs, ws, es;
+
+ // retrieve related UDT sockets
+ vector