diff --git a/.gitignore b/.gitignore index 5ebd21a..8224dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -32,20 +32,69 @@ local.properties ################# ## Visual Studio ################# - ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # 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/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# 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 + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c +*_i.h *.ilk *.meta *.obj @@ -59,29 +108,80 @@ local.properties *.tli *.tlh *.tmp +*.tmp_proj +*.log *.vspscc +*.vssscc .builds -*.dotCover +*.pidb +*.svclog +*.scc -## TODO: If you have NuGet Package Restore enabled, uncomment this -#packages/ +# 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 + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState # ReSharper is a .NET coding add-in -_ReSharper* +_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 + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ # Installshield output folder -[Ee]xpress +[Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ @@ -94,26 +194,166 @@ DocProject/Help/Html2 DocProject/Help/html # Click-Once directory -publish +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: 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 +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable 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 +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ # Others -[Bb]in -[Oo]bj -sql -TestResults -*.Cache -ClientBin -stylecop.* +ClientBin/ ~$* +*~ *.dbmdl -Generated_Code #added for RIA/Silverlight projects +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# 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 +*.ndf + +# 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 +node_modules/ + +# TypeScript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# 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 + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog ############ diff --git a/Lidgren.Network.sln b/Lidgren.Network.sln index 71d1822..9d7e1c1 100644 --- a/Lidgren.Network.sln +++ b/Lidgren.Network.sln @@ -1,6 +1,6 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network", "Lidgren.Network\Lidgren.Network.csproj", "{49BA1C69-6104-41AC-A5D8-B54FA9F696E8}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{6691874A-1766-4A08-A72A-B1132FAB8E58}" diff --git a/Lidgren.Network/Lidgren.Network.csproj b/Lidgren.Network/Lidgren.Network.csproj index 7ab1b31..76527dd 100644 --- a/Lidgren.Network/Lidgren.Network.csproj +++ b/Lidgren.Network/Lidgren.Network.csproj @@ -1,16 +1,15 @@  - + Debug AnyCPU 8.0.30703 - 2.0 {49BA1C69-6104-41AC-A5D8-B54FA9F696E8} Library Properties Lidgren.Network Lidgren.Network - v4.5.1 + v4.6 512 publish\ true @@ -42,10 +41,11 @@ false - pdbonly + + true bin\Release\ - TRACE + TRACE;__CONSTRAINED__ prompt 4 AllRules.ruleset diff --git a/Lidgren.Network/NetBuffer.Read.cs b/Lidgren.Network/NetBuffer.Read.cs index a49b385..a093490 100644 --- a/Lidgren.Network/NetBuffer.Read.cs +++ b/Lidgren.Network/NetBuffer.Read.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Reflection; using System.Net; +using System.Threading; #if !__NOIPENDPOINT__ using NetEndPoint = System.Net.IPEndPoint; @@ -16,6 +17,8 @@ namespace Lidgren.Network public partial class NetBuffer { private const string c_readOverflowError = "Trying to read past the buffer size - likely caused by mismatching Write/Reads, different size or order."; + private const int c_bufferSize = 64; // Min 8 to hold anything but strings. Increase it if readed strings usally don't fit inside the buffer + private static object s_buffer; /// /// Reads a boolean value (stored as a single bit) written using Write(bool) @@ -352,8 +355,11 @@ namespace Lidgren.Network return retval; } - byte[] bytes = ReadBytes(4); - return BitConverter.ToSingle(bytes, 0); + byte[] bytes = (byte[]) Interlocked.Exchange(ref s_buffer, null) ?? new byte[c_bufferSize]; + ReadBytes(bytes, 0, 4); + float res = BitConverter.ToSingle(bytes, 0); + s_buffer = bytes; + return res; } /// @@ -374,8 +380,10 @@ namespace Lidgren.Network return true; } - byte[] bytes = ReadBytes(4); + byte[] bytes = (byte[]) Interlocked.Exchange(ref s_buffer, null) ?? new byte[c_bufferSize]; + ReadBytes(bytes, 0, 4); result = BitConverter.ToSingle(bytes, 0); + s_buffer = bytes; return true; } @@ -394,8 +402,11 @@ namespace Lidgren.Network return retval; } - byte[] bytes = ReadBytes(8); - return BitConverter.ToDouble(bytes, 0); + byte[] bytes = (byte[]) Interlocked.Exchange(ref s_buffer, null) ?? new byte[c_bufferSize]; + ReadBytes(bytes, 0, 8); + double res = BitConverter.ToDouble(bytes, 0); + s_buffer = bytes; + return res; } // @@ -593,8 +604,16 @@ namespace Lidgren.Network return retval; } - byte[] bytes = ReadBytes(byteLen); - return System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length); + if (byteLen <= c_bufferSize) { + byte[] buffer = (byte[]) Interlocked.Exchange(ref s_buffer, null) ?? new byte[c_bufferSize]; + ReadBytes(buffer, 0, byteLen); + string retval = Encoding.UTF8.GetString(buffer, 0, byteLen); + s_buffer = buffer; + return retval; + } else { + byte[] bytes = ReadBytes(byteLen); + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + } } /// diff --git a/Lidgren.Network/NetPeer.Internal.cs b/Lidgren.Network/NetPeer.Internal.cs index 303059e..fc378cd 100644 --- a/Lidgren.Network/NetPeer.Internal.cs +++ b/Lidgren.Network/NetPeer.Internal.cs @@ -4,12 +4,12 @@ using System.Threading; using System.Diagnostics; using System.Security.Cryptography; using System.Net.Sockets; -using System.Collections.Generic; - +using System.Collections.Generic; + #if !__NOIPENDPOINT__ -using NetEndPoint = System.Net.IPEndPoint; +using NetEndPoint = System.Net.IPEndPoint; #endif - + namespace Lidgren.Network { public partial class NetPeer @@ -39,13 +39,13 @@ namespace Lidgren.Network internal bool m_executeFlushSendQueue; private AutoResetEvent m_messageReceivedEvent; - private List> m_receiveCallbacks; - + private List> m_receiveCallbacks; + /// /// Gets the socket, if Start() has been called /// - public Socket Socket { get { return m_socket; } } - + public Socket Socket { get { return m_socket; } } + /// /// Call this to register a callback for when a new message arrives /// @@ -58,18 +58,18 @@ namespace Lidgren.Network if (m_receiveCallbacks == null) m_receiveCallbacks = new List>(); m_receiveCallbacks.Add(new NetTuple(syncContext, callback)); - } - + } + /// /// Call this to unregister a callback, but remember to do it in the same synchronization context! /// public void UnregisterReceivedCallback(SendOrPostCallback callback) { if (m_receiveCallbacks == null) - return; - - // remove all callbacks regardless of sync context - m_receiveCallbacks.RemoveAll(tuple => tuple.Item2.Equals(callback)); + return; + + // remove all callbacks regardless of sync context + m_receiveCallbacks.RemoveAll(tuple => tuple.Item2.Equals(callback)); if (m_receiveCallbacks.Count < 1) m_receiveCallbacks = null; @@ -112,7 +112,7 @@ namespace Lidgren.Network if (now - m_lastSocketBind < 1.0) { LogDebug("Suppressed socket rebind; last bound " + (now - m_lastSocketBind) + " seconds ago"); - return; // only allow rebind once every second + return; // only allow rebind once every second } m_lastSocketBind = now; @@ -127,17 +127,28 @@ namespace Lidgren.Network m_socket.Blocking = false; var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); - m_socket.Bind(ep); - + m_socket.Bind(ep); + + // try catch only works on linux not osx try - { - const uint IOC_IN = 0x80000000; - const uint IOC_VENDOR = 0x18000000; - uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; - m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); + { + // this is not supported in mono / mac or linux yet. + if(Environment.OSVersion.Platform != PlatformID.Unix) + { + const uint IOC_IN = 0x80000000; + const uint IOC_VENDOR = 0x18000000; + uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; + m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); + } + else + { + LogDebug("Platform doesn't support SIO_UDP_CONNRESET"); + } } - catch + catch (System.Exception e) { + LogDebug("Platform doesn't support SIO_UDP_CONNRESET"); + // this will be thrown on linux but not mac if it doesn't exist. // ignore; SIO_UDP_CONNRESET not supported on this platform } diff --git a/Lidgren.Network/NetServer.cs b/Lidgren.Network/NetServer.cs index e6ebf62..99a198f 100644 --- a/Lidgren.Network/NetServer.cs +++ b/Lidgren.Network/NetServer.cs @@ -24,7 +24,8 @@ namespace Lidgren.Network /// How to deliver the message public void SendToAll(NetOutgoingMessage msg, NetDeliveryMethod method) { - var all = this.Connections; + // Modifying m_connections will modify the list of the connections of the NetPeer. Do only reads here + var all = m_connections; if (all.Count <= 0) { if (msg.m_isSent == false) Recycle(msg); @@ -43,7 +44,8 @@ namespace Lidgren.Network /// Which sequence channel to use for the message public void SendToAll(NetOutgoingMessage msg, NetConnection except, NetDeliveryMethod method, int sequenceChannel) { - var all = this.Connections; + // Modifying m_connections will modify the list of the connections of the NetPeer. Do only reads here + var all = m_connections; if (all.Count <= 0) { if (msg.m_isSent == false) Recycle(msg); diff --git a/README.md b/README.md index 4cb32d9..1d67c76 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ -# lidgren-network-gen3 ![](https://travis-ci.org/lidgren/lidgren-network-gen3.svg) -Lidgren.Network is a networking library for .net framework which uses a single udp socket to deliver a simple API for connecting a client to a server, reading and sending messages. +# Lidgren.Network ![](https://api.travis-ci.org/RevoluPowered/lidgren-network-gen3.svg?branch=master) +Lidgren.Network is a networking library for .net framework which uses a single UDP socket to deliver a simple API for connecting a client to a server, reading and sending messages. +This has been updated for use with Unity3D, the normal repository doesn't work with OSX without crashing, so the patches applied here fix that. +I'll be working on some performance improvements too, feel free to send PRs for other bugs fixed as the other repo has been abandoned. + +To use this in Unity3D just enable the experimental .NET framework. + +This makes it work on Windows, OSX and Linux. \ No newline at end of file diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index b1ed00e..8e3e4ca 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -1,16 +1,15 @@  - + Debug x86 8.0.30703 - 2.0 {6691874A-1766-4A08-A72A-B1132FAB8E58} Exe Properties UnitTests UnitTests - v4.5.1 + v4.6 512 diff --git a/UnitTests/app.config b/UnitTests/app.config index d35fbee..92ed828 100644 --- a/UnitTests/app.config +++ b/UnitTests/app.config @@ -1,3 +1,3 @@ - +