├── .gitignore
├── .gitmodules
├── ENet.ndoc
├── ENetCS
├── ENetCS.csproj
├── ENetException.cs
├── Event.cs
├── EventType.cs
├── Host.cs
├── Library.cs
├── Native
│ ├── ENetApi.cs
│ ├── ENetApiAny.cs
│ └── Structs.cs
├── Packet.IList.cs
├── Packet.UserData.cs
├── Packet.cs
├── PacketFlags.cs
├── Peer.cs
├── PeerState.cs
└── Properties
│ └── AssemblyInfo.cs
├── ENetDLL
├── ENetDLL.vcxproj
└── ENetDLL.vcxproj.filters
├── ENetDemo
├── ENetDemo.csproj
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── ENetUnityDemo
├── .gitignore
├── Assets
│ ├── Plugins
│ │ ├── ENetCS.dll
│ │ ├── x86
│ │ │ └── ENet.dll
│ │ └── x86_64
│ │ │ └── ENet.dll
│ ├── Scenes
│ │ └── Demo.unity
│ └── Scripts
│ │ └── Demo.cs
├── ProjectSettings
│ ├── AudioManager.asset
│ ├── ClusterInputManager.asset
│ ├── DynamicsManager.asset
│ ├── EditorBuildSettings.asset
│ ├── EditorSettings.asset
│ ├── GraphicsSettings.asset
│ ├── InputManager.asset
│ ├── NavMeshAreas.asset
│ ├── NetworkManager.asset
│ ├── Physics2DSettings.asset
│ ├── ProjectSettings.asset
│ ├── ProjectVersion.txt
│ ├── QualitySettings.asset
│ ├── TagManager.asset
│ ├── TimeManager.asset
│ └── UnityConnectSettings.asset
└── UnityPackageManager
│ └── manifest.json
├── LICENSE
├── License.txt
├── README.md
└── enet-cs.sln
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | build/
16 | bld/
17 | [Bb]in/
18 | [Oo]bj/
19 |
20 | # Roslyn cache directories
21 | *.ide/
22 |
23 | # MSTest test Results
24 | [Tt]est[Rr]esult*/
25 | [Bb]uild[Ll]og.*
26 |
27 | #NUNIT
28 | *.VisualState.xml
29 | TestResult.xml
30 |
31 | # Build Results of an ATL Project
32 | [Dd]ebugPS/
33 | [Rr]eleasePS/
34 | dlldata.c
35 |
36 | *_i.c
37 | *_p.c
38 | *_i.h
39 | *.ilk
40 | *.meta
41 | *.obj
42 | *.pch
43 | *.pdb
44 | *.pgc
45 | *.pgd
46 | *.rsp
47 | *.sbr
48 | *.tlb
49 | *.tli
50 | *.tlh
51 | *.tmp
52 | *.tmp_proj
53 | *.log
54 | *.vspscc
55 | *.vssscc
56 | .builds
57 | *.pidb
58 | *.svclog
59 | *.scc
60 |
61 | # Chutzpah Test files
62 | _Chutzpah*
63 |
64 | # Visual C++ cache files
65 | ipch/
66 | *.aps
67 | *.ncb
68 | *.opensdf
69 | *.sdf
70 | *.cachefile
71 |
72 | # Visual Studio profiler
73 | *.psess
74 | *.vsp
75 | *.vspx
76 |
77 | # TFS 2012 Local Workspace
78 | $tf/
79 |
80 | # Guidance Automation Toolkit
81 | *.gpState
82 |
83 | # ReSharper is a .NET coding add-in
84 | _ReSharper*/
85 | *.[Rr]e[Ss]harper
86 | *.DotSettings.user
87 |
88 | # JustCode is a .NET coding addin-in
89 | .JustCode
90 |
91 | # TeamCity is a build add-in
92 | _TeamCity*
93 |
94 | # DotCover is a Code Coverage Tool
95 | *.dotCover
96 |
97 | # NCrunch
98 | _NCrunch_*
99 | .*crunch*.local.xml
100 |
101 | # MightyMoose
102 | *.mm.*
103 | AutoTest.Net/
104 |
105 | # Web workbench (sass)
106 | .sass-cache/
107 |
108 | # Installshield output folder
109 | [Ee]xpress/
110 |
111 | # DocProject is a documentation generator add-in
112 | DocProject/buildhelp/
113 | DocProject/Help/*.HxT
114 | DocProject/Help/*.HxC
115 | DocProject/Help/*.hhc
116 | DocProject/Help/*.hhk
117 | DocProject/Help/*.hhp
118 | DocProject/Help/Html2
119 | DocProject/Help/html
120 |
121 | # Click-Once directory
122 | publish/
123 |
124 | # Publish Web Output
125 | *.[Pp]ublish.xml
126 | *.azurePubxml
127 | # TODO: Comment the next line if you want to checkin your web deploy settings
128 | # but database connection strings (with potential passwords) will be unencrypted
129 | *.pubxml
130 | *.publishproj
131 |
132 | # NuGet Packages
133 | *.nupkg
134 | # The packages folder can be ignored because of Package Restore
135 | **/packages/*
136 | # except build/, which is used as an MSBuild target.
137 | !**/packages/build/
138 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
139 | #!**/packages/repositories.config
140 |
141 | # Windows Azure Build Output
142 | csx/
143 | *.build.csdef
144 |
145 | # Windows Store app package directory
146 | AppPackages/
147 |
148 | # Others
149 | sql/
150 | *.Cache
151 | ClientBin/
152 | [Ss]tyle[Cc]op.*
153 | ~$*
154 | *~
155 | *.dbmdl
156 | *.dbproj.schemaview
157 | *.pfx
158 | *.publishsettings
159 | node_modules/
160 |
161 | # RIA/Silverlight projects
162 | Generated_Code/
163 |
164 | # Backup & report files from converting an old project file
165 | # to a newer Visual Studio version. Backup files are not needed,
166 | # because we have git ;-)
167 | _UpgradeReport_Files/
168 | Backup*/
169 | UpgradeLog*.XML
170 | UpgradeLog*.htm
171 |
172 | # SQL Server files
173 | *.mdf
174 | *.ldf
175 |
176 | # Business Intelligence projects
177 | *.rdl.data
178 | *.bim.layout
179 | *.bim_*.settings
180 |
181 | # Microsoft Fakes
182 | FakesAssemblies/
183 |
184 | # =========================
185 | # Operating System Files
186 | # =========================
187 |
188 | # OSX
189 | # =========================
190 |
191 | .DS_Store
192 | .AppleDouble
193 | .LSOverride
194 |
195 | # Thumbnails
196 | ._*
197 |
198 | # Files that might appear on external disk
199 | .Spotlight-V100
200 | .Trashes
201 |
202 | # Directories potentially created on remote AFP share
203 | .AppleDB
204 | .AppleDesktop
205 | Network Trash Folder
206 | Temporary Items
207 | .apdisk
208 |
209 | # Windows
210 | # =========================
211 |
212 | # Windows image file caches
213 | Thumbs.db
214 | ehthumbs.db
215 |
216 | # Folder config file
217 | Desktop.ini
218 |
219 | # Recycle Bin used on file shares
220 | $RECYCLE.BIN/
221 |
222 | # Windows Installer files
223 | *.cab
224 | *.msi
225 | *.msm
226 | *.msp
227 |
228 | # Windows shortcuts
229 | *.lnk
230 |
231 | # Visual Studio 2015 cache/options directory
232 | .vs/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ENet"]
2 | path = ENet
3 | url = https://github.com/lsalzman/enet
4 |
--------------------------------------------------------------------------------
/ENet.ndoc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ENet is a UDP-based networking library for transmitting packets reliably and unreliably, sequenced and unsequenced, and with multiple channels per connection.
7 |
8 | In a game, for example, you can send chat and status updates reliably and positions unreliably, and in the event of packet loss the two will not interfere nor will there be lag on future position updates. Were you to use TCP, on the other hand, a "lag burst" would occur affecting all data, ending only on reception of the lost packet's retry.
9 | Access to the native C API is also available.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ENetCS/ENetCS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {D3AFF7FA-96F6-42B8-B03C-E508DC80EC3A}
9 | Library
10 | Properties
11 | ENetCS
12 | ENetCS
13 | v2.0
14 | 512
15 |
16 |
17 |
18 |
19 | 3.5
20 |
21 |
22 |
23 | true
24 | bin\Debug\
25 | DEBUG;TRACE
26 | true
27 | ..\bin\ENetCS.xml
28 | full
29 | AnyCPU
30 | prompt
31 | MinimumRecommendedRules.ruleset
32 |
33 |
34 | bin\Release\
35 | TRACE
36 | true
37 | ..\bin\ENetCS.xml
38 | true
39 | pdbonly
40 | AnyCPU
41 | prompt
42 | MinimumRecommendedRules.ruleset
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
72 |
--------------------------------------------------------------------------------
/ENetCS/ENetException.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2012 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using System;
21 | using System.Runtime.Serialization;
22 |
23 | namespace ENet
24 | {
25 | ///
26 | /// This exception is thrown when ENet has an error.
27 | ///
28 | [Serializable]
29 | public class ENetException : Exception
30 | {
31 | ///
32 | /// Initializes an ENetException.
33 | ///
34 | public ENetException()
35 | : base("ENet error.")
36 | {
37 |
38 | }
39 |
40 | ///
41 | /// Initializes an ENetException with a given message.
42 | ///
43 | /// The error message.
44 | public ENetException(string message)
45 | : base(message)
46 | {
47 |
48 | }
49 |
50 | ///
51 | /// Initializes an ENetException with the given message and a reference to an inner exception.
52 | ///
53 | /// The error message.
54 | /// The inner exception.
55 | public ENetException(string message, Exception innerException)
56 | : base(message, innerException)
57 | {
58 |
59 | }
60 |
61 | ///
62 | /// Initializes an ENetException for serialization.
63 | ///
64 | /// The serialized data.
65 | /// The context for the serialization.
66 | protected ENetException(SerializationInfo info, StreamingContext context)
67 | : base(info, context)
68 | {
69 |
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/ENetCS/Event.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2012 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using ENet.Native;
21 |
22 | namespace ENet
23 | {
24 | ///
25 | /// Represents an event from the method.
26 | ///
27 | public unsafe struct Event
28 | {
29 | ENetEvent _event;
30 |
31 | ///
32 | /// Initializes an event based on a native C event.
33 | ///
34 | /// The native C event.
35 | public Event(ENetEvent @event)
36 | {
37 | this = new Event() { NativeData = @event };
38 | }
39 |
40 | ///
41 | /// Gets the channel ID.
42 | ///
43 | public byte ChannelID
44 | {
45 | get { return NativeData.channelID; }
46 | }
47 |
48 | ///
49 | /// Gets the data associated with the event.
50 | ///
51 | public int Data
52 | {
53 | get { return (int)NativeData.data; }
54 | }
55 |
56 | ///
57 | /// Gets or sets the native C event.
58 | ///
59 | public ENetEvent NativeData
60 | {
61 | get { return _event; }
62 | set { _event = value; }
63 | }
64 |
65 | ///
66 | /// Gets the packet associated with the event.
67 | ///
68 | public Packet Packet
69 | {
70 | get { return new Packet(NativeData.packet); }
71 | }
72 |
73 | ///
74 | /// Gets the peer associated with the event.
75 | ///
76 | public Peer Peer
77 | {
78 | get { return new Peer(NativeData.peer); }
79 | }
80 |
81 | ///
82 | /// Gets the event type.
83 | ///
84 | public EventType Type
85 | {
86 | get { return NativeData.type; }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/ENetCS/EventType.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | namespace ENet
21 | {
22 | ///
23 | /// Specifies types of events that can occur.
24 | ///
25 | public enum EventType
26 | {
27 | ///
28 | /// Nothing happened.
29 | ///
30 | None = 0,
31 |
32 | ///
33 | /// A peer has connected.
34 | ///
35 | Connect = 1,
36 |
37 | ///
38 | /// A peer has disconnected.
39 | ///
40 | Disconnect = 2,
41 |
42 | ///
43 | /// A packet has been received.
44 | ///
45 | Receive = 3
46 | }
47 | }
--------------------------------------------------------------------------------
/ENetCS/Host.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2012 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using System;
21 | using System.Net;
22 | using System.Net.Sockets;
23 | using ENet.Native;
24 |
25 | namespace ENet
26 | {
27 | ///
28 | /// Acts as either client or peer-to-peer/server.
29 | ///
30 | public unsafe struct Host : IDisposable, IEquatable
31 | {
32 | ENetHost* _host;
33 |
34 | ///
35 | /// Initializes a host based on a native C host.
36 | ///
37 | /// The native C peer.
38 | public Host(ENetHost* host)
39 | {
40 | this = new Host() { NativeData = host };
41 | }
42 |
43 | public override bool Equals(object obj)
44 | {
45 | return obj is Host && Equals((Host)obj);
46 | }
47 |
48 | public bool Equals(Host other)
49 | {
50 | return NativeData == other.NativeData;
51 | }
52 |
53 | public override int GetHashCode()
54 | {
55 | return (int)(long)NativeData; // ENet types are malloc'ed. They do not move.
56 | }
57 |
58 | static void CheckBandwidthLimit(int incomingBandwidth, int outgoingBandwidth)
59 | {
60 | if (incomingBandwidth < 0) { throw new ArgumentOutOfRangeException("incomingBandwidth"); }
61 | if (outgoingBandwidth < 0) { throw new ArgumentOutOfRangeException("outgoingBandwidth"); }
62 | }
63 |
64 | static void CheckChannelLimit(int channelLimit)
65 | {
66 | if (channelLimit < 0 || channelLimit > ENetApi.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
67 | { throw new ArgumentOutOfRangeException("channelLimit"); }
68 | }
69 |
70 | void CheckInitialized()
71 | {
72 | if (NativeData == null) { throw new InvalidOperationException("Not initialized."); }
73 | }
74 |
75 | ///
76 | /// Initialize a host that will not accept connections.
77 | ///
78 | ///
79 | /// The maximum number of peers for this host.
80 | /// If you are only connecting to one server, set this to 1.
81 | ///
82 | ///
83 | /// is less than 0 or greater than 4095.
84 | ///
85 | /// The host is already initialized.
86 | /// Failed to initialize the host.
87 | public void InitializeClient(int peerLimit)
88 | {
89 | Initialize(null, peerLimit);
90 | }
91 |
92 | ///
93 | /// Initialize a host that will accept connections on any IP address.
94 | ///
95 | /// The port to listen on.
96 | /// The maximum number of peers for this host.
97 | ///
98 | /// is less than 0 or greater than 65535, and/or
99 | /// is less than 0 or greater than 4095.
100 | ///
101 | /// The host is already initialized.
102 | /// Failed to initialize the host.
103 | public void InitializeServer(int port, int peerLimit)
104 | {
105 | Initialize(new IPEndPoint(IPAddress.Any, port), peerLimit);
106 | }
107 |
108 | ///
109 | /// Initialize a host that will accept connections on a particular address, or not accept connections.
110 | ///
111 | /// The address to listen on, or null to not accept connections.
112 | /// The maximum number of peers for this host.
113 | /// The maximum number of channels, or 0 to use the maximum possible (255).
114 | /// The maximum incoming rate of transfer, or 0 for no limit.
115 | /// The maximum outgoing rate of transfer, or 0 for no limit.
116 | ///
117 | /// is less than 0 or greater than 4095,
118 | /// is less than 0 or greater than 255,
119 | /// is less than 0, and/or
120 | /// is less than 0.
121 | ///
122 | /// The host is already initialized.
123 | /// Failed to initialize the host.
124 | public void Initialize(IPEndPoint address, int peerLimit,
125 | int channelLimit = 0, int incomingBandwidth = 0, int outgoingBandwidth = 0)
126 | {
127 | if (NativeData != null) { throw new InvalidOperationException("Already initialized."); }
128 | if (peerLimit < 0 || peerLimit > ENetApi.ENET_PROTOCOL_MAXIMUM_PEER_ID)
129 | { throw new ArgumentOutOfRangeException("peerLimit"); }
130 | CheckChannelLimit(channelLimit);
131 | CheckBandwidthLimit(incomingBandwidth, outgoingBandwidth);
132 |
133 | if (address != null)
134 | {
135 | ENetAddress nativeAddress = (ENetAddress)address;
136 | NativeData = ENetApi.enet_host_create(ref nativeAddress, (IntPtr)peerLimit,
137 | (IntPtr)channelLimit, (uint)incomingBandwidth, (uint)outgoingBandwidth);
138 | }
139 | else
140 | {
141 | NativeData = ENetApi.enet_host_create(null, (IntPtr)peerLimit,
142 | (IntPtr)channelLimit, (uint)incomingBandwidth, (uint)outgoingBandwidth);
143 | }
144 | if (NativeData == null) { throw new ENetException("Host creation call failed."); }
145 | }
146 |
147 | ///
148 | /// Destroys the host.
149 | ///
150 | public void Dispose()
151 | {
152 | if (NativeData != null)
153 | {
154 | ENetApi.enet_host_destroy(NativeData);
155 | NativeData = null;
156 | }
157 | }
158 |
159 | ///
160 | /// Broadcast a packet to all peers.
161 | ///
162 | /// The ID of the channel
163 | /// The packet to send.
164 | /// ENet takes ownership of the packet. Do not call methods on it afterwards.
165 | /// The host is not initialized.
166 | public void Broadcast(byte channelID, ref Packet packet)
167 | {
168 | CheckInitialized(); packet.CheckInitialized();
169 |
170 | bool clear = packet.ReferenceCount == 0;
171 | ENetApi.enet_host_broadcast(NativeData, channelID, packet.NativeData);
172 | if (clear) { packet.NativeData = null; } // Broadcast may automatically free in this case.
173 | }
174 |
175 | ///
176 | /// Enables compression using the range encoder.
177 | ///
178 | /// The host is not initialized.
179 | /// Failed to create range encoder. This is likely due to low memory.
180 | public void CompressWithRangeEncoder()
181 | {
182 | CheckInitialized();
183 | int ret = ENetApi.enet_host_compress_with_range_encoder(NativeData);
184 | if (ret < 0) { throw new ENetException("Failed to create range encoder."); }
185 | }
186 |
187 | ///
188 | /// Disables compression.
189 | ///
190 | /// The host is not initialized.
191 | public void DoNotCompress()
192 | {
193 | CheckInitialized();
194 | ENetApi.enet_host_compress(NativeData, null);
195 | }
196 |
197 | ///
198 | /// Checks for queued events.
199 | ///
200 | /// The dequeued event.
201 | /// True if an event was dequeued, otherwise false.
202 | /// The host is not initialized.
203 | /// An error occured while checking events.
204 | public bool CheckEvents(out Event @event)
205 | {
206 | CheckInitialized(); ENetEvent nativeEvent;
207 | int ret = ENetApi.enet_host_check_events(NativeData, out nativeEvent);
208 | if (ret < 0) { throw new ENetException("Error while checking for events."); }
209 | if (ret == 0) { @event = new Event(); return false; }
210 | @event = new Event(nativeEvent); return true;
211 | }
212 |
213 | ///
214 | /// Connects to a remote computer at the given host and port.
215 | ///
216 | /// The IP address or host name to connect to.
217 | /// The port to connect to.
218 | /// Data to send along with the connect packet.
219 | /// The maximum number of channels, or 0 to use the maximum possible (255).
220 | ///
221 | /// The new peer. This method does not block: the connection will be established
222 | /// when you receive a event.
223 | ///
224 | /// is null.
225 | /// is invalid.
226 | ///
227 | /// is too long,
228 | /// is less than 0 or greater than 65535, and/or
229 | /// is less than 0 or greater than 255.
230 | ///
231 | /// The host is not initialized.
232 | /// Host name lookup failed, or no IPv4 hosts were available.
233 | /// An error occured.
234 | public Peer Connect(string hostName, int port, int data, int channelLimit = 0)
235 | {
236 | IPAddress[] addresses = Dns.GetHostAddresses(hostName);
237 | foreach (IPAddress address in addresses)
238 | {
239 | if (address.AddressFamily == AddressFamily.InterNetwork)
240 | {
241 | return Connect(new IPEndPoint(address, port), data, channelLimit);
242 | }
243 | }
244 | throw new SocketException();
245 | }
246 |
247 | ///
248 | /// Connects to a remote computer at the given address.
249 | ///
250 | /// The address to connect to.
251 | /// Data to send along with the connect packet.
252 | /// The maximum number of channels, or 0 to use the maximum possible (255).
253 | ///
254 | /// The new peer. This method does not block: the connection will be established
255 | /// when you receive a event.
256 | ///
257 | /// is null.
258 | /// is not IPv4.
259 | ///
260 | /// 's port is less than 0 or greater than 65535, and/or
261 | /// is less than 0 or greater than 255.
262 | ///
263 | /// The host is not initialized.
264 | /// An error occured.
265 | public Peer Connect(IPEndPoint address, int data, int channelLimit = 0)
266 | {
267 | CheckInitialized(); ENetAddress nativeAddress = (ENetAddress)address;
268 | CheckChannelLimit(channelLimit);
269 |
270 | // For consistency with Connect() and SetChannelLimit(),
271 | if (channelLimit == 0) { channelLimit = (int)ENetApi.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; }
272 |
273 | Peer peer = new Peer(ENetApi.enet_host_connect(NativeData, ref nativeAddress, (IntPtr)channelLimit, (uint)data));
274 | if (peer.NativeData == null) { throw new ENetException("Host connect failed."); }
275 | return peer;
276 | }
277 |
278 | ///
279 | /// Sends queued packets immediately. Normally they are sent when you call .
280 | ///
281 | /// The host is not initialized.
282 | public void Flush()
283 | {
284 | CheckInitialized();
285 | ENetApi.enet_host_flush(NativeData);
286 | }
287 |
288 | ///
289 | /// Sends queued outgoing packets, receives incoming packets, and handles connection events.
290 | ///
291 | /// Timeout in milliseconds to wait for an event. For polling, use 0.
292 | /// The event.
293 | /// True if an event occured, otherwise false.
294 | /// is negative.
295 | /// The host is not initialized.
296 | /// An error occured.
297 | public bool Service(int timeout, out Event @event)
298 | {
299 | if (timeout < 0) { throw new ArgumentOutOfRangeException("timeout"); }
300 | CheckInitialized(); ENetEvent nativeEvent = new ENetEvent();
301 |
302 | // As of 1.3.6, ENet is not signal safe, and Mono uses signals for garbage collection.
303 | //
304 | // So, there's really nothing better we can do than retry. Luckily the cases that return -1
305 | // are cases that return immediately or this could cause lockups.
306 | //
307 | // The entire situation is still very dicey with MonoDevelop.
308 | // A proper fix really has to be done in the ENet native library.
309 | // If you want to eliminate this entirely and don't care about these spurious
310 | // failures of enet_host_service, try/catch the ENetException and just ignore it.
311 | // That's essentially what I am doing here, except with an upper limit so real errors
312 | // can get through...
313 | int ret = -1;
314 | for (int nretries = 0; nretries < 1000 && ret == -1; nretries++)
315 | {
316 | ret = ENetApi.enet_host_service(NativeData, out nativeEvent, (uint)timeout);
317 | }
318 |
319 | if (ret < 0) { throw new ENetException(string.Format("Service failed (native data {0}).", (IntPtr)NativeData)); }
320 | if (ret == 0) { @event = new Event(); return false; }
321 | @event = new Event(nativeEvent); return true;
322 | }
323 |
324 | ///
325 | /// Set the bandwidth limit.
326 | ///
327 | /// The maximum incoming rate of transfer, or 0 for no limit.
328 | /// The maximum outgoing rate of transfer, or 0 for no limit.
329 | ///
330 | /// is less than 0, and/or
331 | /// is less than 0.
332 | ///
333 | /// The host is not initialized.
334 | public void SetBandwidthLimit(int incomingBandwidth, int outgoingBandwidth)
335 | {
336 | CheckInitialized(); CheckBandwidthLimit(incomingBandwidth, outgoingBandwidth);
337 | ENetApi.enet_host_bandwidth_limit(NativeData, (uint)incomingBandwidth, (uint)outgoingBandwidth);
338 | }
339 |
340 | ///
341 | /// Set the channel limit.
342 | ///
343 | /// The maximum number of channels, or 0 to use the maximum possible (255).
344 | /// The host is not initialized.
345 | public void SetChannelLimit(int channelLimit)
346 | {
347 | CheckChannelLimit(channelLimit); CheckInitialized();
348 | ENetApi.enet_host_channel_limit(NativeData, (IntPtr)channelLimit);
349 | }
350 |
351 | ///
352 | /// Gets or sets the native C host.
353 | ///
354 | public ENetHost* NativeData
355 | {
356 | get { return _host; }
357 | set { _host = value; }
358 | }
359 |
360 | ///
361 | /// Returns true if the host is initialized.
362 | ///
363 | public bool IsInitialized
364 | {
365 | get { return NativeData != null; }
366 | }
367 |
368 | public static bool operator ==(Host host1, Host host2)
369 | {
370 | return host1.Equals(host2);
371 | }
372 |
373 | public static bool operator !=(Host host1, Host host2)
374 | {
375 | return !host1.Equals(host2);
376 | }
377 | }
378 | }
379 |
--------------------------------------------------------------------------------
/ENetCS/Library.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2013 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using System;
21 | using ENet.Native;
22 |
23 | namespace ENet
24 | {
25 | ///
26 | /// Provides initialization, deinitialization, and time-keeping methods.
27 | ///
28 | public unsafe static class Library
29 | {
30 | ///
31 | /// Throws an exception if the ENet native library cannot be loaded.
32 | /// ENet is now automatically initialized, so it is no longer strictly
33 | /// necessary to call this function.
34 | ///
35 | /// The native library cannot be loaded.
36 | public static void Initialize()
37 | {
38 | ENetApi.enet_time_get();
39 | }
40 |
41 | ///
42 | /// This method is retained for backwards compatibility. It does nothing.
43 | ///
44 | public static void Deinitialize()
45 | {
46 |
47 | }
48 |
49 | ///
50 | /// Gets or set the time in milliseconds.
51 | ///
52 | public static int Time
53 | {
54 | get { return (int)ENetApi.enet_time_get(); }
55 | set { ENetApi.enet_time_set((uint)value); }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ENetCS/Native/ENetApi.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2013 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | #pragma warning disable 1591
21 |
22 | using System;
23 |
24 | namespace ENet.Native
25 | {
26 | public unsafe abstract class ENetApi
27 | {
28 | public const uint ENET_HOST_ANY = 0;
29 | public const uint ENET_HOST_BROADCAST = 0xffffffff;
30 | public const uint ENET_PEER_PACKET_THROTTLE_SCALE = 32;
31 | public const uint ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2;
32 | public const uint ENET_PEER_PACKET_THROTTLE_DECELERATION = 2;
33 | public const uint ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000;
34 | public const uint ENET_PEER_PING_INTERVAL = 500;
35 | public const uint ENET_PEER_TIMEOUT_LIMIT = 32;
36 | public const uint ENET_PEER_TIMEOUT_MINIMUM = 5000;
37 | public const uint ENET_PEER_TIMEOUT_MAXIMUM = 30000;
38 | public const uint ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 0x01;
39 | public const uint ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 0xff;
40 | public const uint ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024;
41 | public const uint ENET_PROTOCOL_MAXIMUM_PACKET_SIZE = 1024 * 1024 * 1024;
42 | public const uint ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xfff;
43 | const uint ENET_VERSION = (1 << 16) | (3 << 8) | (6 << 0);
44 |
45 | #region Platform Detection
46 | internal static ENetApi _platform;
47 | internal static object _platformLock = new object();
48 |
49 | internal ENetApi()
50 | {
51 |
52 | }
53 |
54 | internal static ENetApi Platform
55 | {
56 | get
57 | {
58 | if (_platform == null)
59 | {
60 | lock (_platformLock)
61 | {
62 | if (_platform == null)
63 | {
64 | foreach (ENetApi platform in new ENetApi[]
65 | {
66 | new ENetApiAny(),
67 | })
68 | {
69 | try
70 | {
71 | ENetCallbacks inits = new ENetCallbacks();
72 | if (platform.initialize_with_callbacks(ENET_VERSION, ref inits) >= 0)
73 | {
74 | _platform = platform; return platform;
75 | }
76 | }
77 | catch (BadImageFormatException)
78 | {
79 | continue;
80 | }
81 | catch (DllNotFoundException)
82 | {
83 | continue;
84 | }
85 | catch (EntryPointNotFoundException)
86 | {
87 | continue;
88 | }
89 | }
90 |
91 | throw new ENetException
92 | ("The ENet native library failed to initialize." +
93 | " Make sure ENetX86.dll and ENetX64.dll are in the program directory, and that" +
94 | " you are running on a x86 or x64-based computer." +
95 | " If you are running on Linux, make sure the libenet.so.1 is in your path." +
96 | " On Ubuntu Linux, install the libenet1a package (1.3.3 or newer) if you haven't already." +
97 | " If you are running on MacOS, make sure libenet.dylib is in your path or program directory.");
98 | }
99 |
100 | return _platform;
101 | }
102 | }
103 |
104 | return _platform;
105 | }
106 | }
107 | #endregion
108 |
109 | #region Address Functions
110 | public static int enet_address_set_host(ref ENetAddress address, byte* hostName)
111 | {
112 | return Platform.address_set_host(ref address, hostName);
113 | }
114 |
115 | public static int enet_address_set_host(ref ENetAddress address, byte[] hostName)
116 | {
117 | return Platform.address_set_host(ref address, hostName);
118 | }
119 |
120 | public static int enet_address_get_host(ref ENetAddress address, byte* hostName, IntPtr nameLength)
121 | {
122 | return Platform.address_get_host(ref address, hostName, nameLength);
123 | }
124 |
125 | public static int enet_address_get_host(ref ENetAddress address, byte[] hostName, IntPtr nameLength)
126 | {
127 | return Platform.address_get_host(ref address, hostName, nameLength);
128 | }
129 |
130 | public static int enet_address_get_host_ip(ref ENetAddress address, byte* hostIP, IntPtr ipLength)
131 | {
132 | return Platform.address_get_host_ip(ref address, hostIP, ipLength);
133 | }
134 |
135 | public static int enet_address_get_host_ip(ref ENetAddress address, byte[] hostIP, IntPtr ipLength)
136 | {
137 | return Platform.address_get_host_ip(ref address, hostIP, ipLength);
138 | }
139 |
140 | public abstract int address_set_host(ref ENetAddress address, byte* hostName);
141 |
142 | public abstract int address_set_host(ref ENetAddress address, byte[] hostName);
143 |
144 | public abstract int address_get_host(ref ENetAddress address, byte* hostName, IntPtr nameLength);
145 |
146 | public abstract int address_get_host(ref ENetAddress address, byte[] hostName, IntPtr nameLength);
147 |
148 | public abstract int address_get_host_ip(ref ENetAddress address, byte* hostIP, IntPtr ipLength);
149 |
150 | public abstract int address_get_host_ip(ref ENetAddress address, byte[] hostIP, IntPtr ipLength);
151 | #endregion
152 |
153 | #region Global Functions
154 | public abstract int initialize_with_callbacks(uint version, ref ENetCallbacks inits);
155 | #endregion
156 |
157 | #region Host Functions
158 | public static void enet_host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth)
159 | {
160 | Platform.host_bandwidth_limit(host, incomingBandwidth, outgoingBandwidth);
161 | }
162 |
163 | public static void enet_host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet)
164 | {
165 | Platform.host_broadcast(host, channelID, packet);
166 | }
167 |
168 | public static void enet_host_channel_limit(ENetHost* host, IntPtr channelLimit)
169 | {
170 | Platform.host_channel_limit(host, channelLimit);
171 | }
172 |
173 | public static int enet_host_check_events(ENetHost* host, out ENetEvent @event)
174 | {
175 | return Platform.host_check_events(host, out @event);
176 | }
177 |
178 | public static ENetPeer* enet_host_connect(ENetHost* host, ref ENetAddress address, IntPtr channelCount, uint data)
179 | {
180 | return Platform.host_connect(host, ref address, channelCount, data);
181 | }
182 |
183 | public static void enet_host_compress(ENetHost* host, ENetCompressor* compressor)
184 | {
185 | Platform.host_compress(host, compressor);
186 | }
187 |
188 | public static int enet_host_compress_with_range_encoder(ENetHost* host)
189 | {
190 | return Platform.host_compress_with_range_encoder(host);
191 | }
192 |
193 | public static ENetHost* enet_host_create(ENetAddress* address,
194 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth)
195 | {
196 | return Platform.host_create(address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth);
197 | }
198 |
199 | public static ENetHost* enet_host_create(ref ENetAddress address,
200 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth)
201 | {
202 | return Platform.host_create(ref address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth);
203 | }
204 |
205 | public static void enet_host_destroy(ENetHost* host)
206 | {
207 | Platform.host_destroy(host);
208 | }
209 |
210 | public static void enet_host_flush(ENetHost* host)
211 | {
212 | Platform.host_flush(host);
213 | }
214 |
215 | public static int enet_host_service(ENetHost* host, ENetEvent* @event, uint timeout)
216 | {
217 | return Platform.host_service(host, @event, timeout);
218 | }
219 |
220 | public static int enet_host_service(ENetHost* host, out ENetEvent @event, uint timeout)
221 | {
222 | return Platform.host_service(host, out @event, timeout);
223 | }
224 |
225 | public abstract void host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth);
226 |
227 | public abstract void host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet);
228 |
229 | public abstract void host_channel_limit(ENetHost* host, IntPtr channelLimit);
230 |
231 | public abstract int host_check_events(ENetHost* host, out ENetEvent @event);
232 |
233 | public abstract ENetPeer* host_connect(ENetHost* host, ref ENetAddress address, IntPtr channelCount, uint data);
234 |
235 | public abstract void host_compress(ENetHost* host, ENetCompressor* compressor);
236 |
237 | public abstract int host_compress_with_range_encoder(ENetHost* host);
238 |
239 | public abstract ENetHost* host_create(ENetAddress* address,
240 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth);
241 |
242 | public abstract ENetHost* host_create(ref ENetAddress address,
243 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth);
244 |
245 | public abstract void host_destroy(ENetHost* host);
246 |
247 | public abstract void host_flush(ENetHost* host);
248 |
249 | public abstract int host_service(ENetHost* host, ENetEvent* @event, uint timeout);
250 |
251 | public abstract int host_service(ENetHost* host, out ENetEvent @event, uint timeout);
252 | #endregion
253 |
254 | #region Miscellaneous Functions
255 | public static uint enet_time_get()
256 | {
257 | return Platform.time_get();
258 | }
259 |
260 | public static void enet_time_set(uint newTimeBase)
261 | {
262 | Platform.time_set(newTimeBase);
263 | }
264 |
265 | public abstract uint time_get();
266 |
267 | public abstract void time_set(uint newTimeBase);
268 | #endregion
269 |
270 | #region Packet Functions
271 | public static ENetPacket* enet_packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags)
272 | {
273 | return Platform.packet_create(data, dataLength, flags);
274 | }
275 |
276 | public static void enet_packet_destroy(ENetPacket* packet)
277 | {
278 | Platform.packet_destroy(packet);
279 | }
280 |
281 | public static int enet_packet_resize(ENetPacket* packet, IntPtr dataLength)
282 | {
283 | return Platform.packet_resize(packet, dataLength);
284 | }
285 |
286 | public abstract ENetPacket* packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags);
287 |
288 | public abstract void packet_destroy(ENetPacket* packet);
289 |
290 | public abstract int packet_resize(ENetPacket* packet, IntPtr dataLength);
291 | #endregion
292 |
293 | #region Peer Functions
294 | public static void enet_peer_disconnect(ENetPeer* peer, uint data)
295 | {
296 | Platform.peer_disconnect(peer, data);
297 | }
298 |
299 | public static void enet_peer_disconnect_now(ENetPeer* peer, uint data)
300 | {
301 | Platform.peer_disconnect_now(peer, data);
302 | }
303 |
304 | public static void enet_peer_disconnect_later(ENetPeer* peer, uint data)
305 | {
306 | Platform.peer_disconnect_later(peer, data);
307 | }
308 |
309 | public static void enet_peer_ping(ENetPeer* peer)
310 | {
311 | Platform.peer_ping(peer);
312 | }
313 |
314 | public static void enet_peer_ping_interval(ENetPeer* peer, uint pingInterval)
315 | {
316 | Platform.peer_ping_interval(peer, pingInterval);
317 | }
318 |
319 | public static ENetPacket* enet_peer_receive(ENetPeer* peer, out byte channelID)
320 | {
321 | return Platform.peer_receive(peer, out channelID);
322 | }
323 |
324 | public static void enet_peer_reset(ENetPeer* peer)
325 | {
326 | Platform.peer_reset(peer);
327 | }
328 |
329 | public static int enet_peer_send(ENetPeer* peer, byte channelID, ENetPacket* packet)
330 | {
331 | return Platform.peer_send(peer, channelID, packet);
332 | }
333 |
334 | public static void enet_peer_throttle_configure(ENetPeer* peer, uint interval, uint acceleration, uint deceleration)
335 | {
336 | Platform.peer_throttle_configure(peer, interval, acceleration, deceleration);
337 | }
338 |
339 | public static void enet_peer_timeout(ENetPeer* peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum)
340 | {
341 | Platform.peer_timeout(peer, timeoutLimit, timeoutMinimum, timeoutMaximum);
342 | }
343 |
344 | public abstract void peer_disconnect(ENetPeer* peer, uint data);
345 |
346 | public abstract void peer_disconnect_now(ENetPeer* peer, uint data);
347 |
348 | public abstract void peer_disconnect_later(ENetPeer* peer, uint data);
349 |
350 | public abstract void peer_ping(ENetPeer* peer);
351 |
352 | public abstract void peer_ping_interval(ENetPeer* peer, uint pingInterval);
353 |
354 | public abstract ENetPacket* peer_receive(ENetPeer* peer, out byte channelID);
355 |
356 | public abstract void peer_reset(ENetPeer* peer);
357 |
358 | public abstract int peer_send(ENetPeer* peer, byte channelID, ENetPacket* packet);
359 |
360 | public abstract void peer_throttle_configure(ENetPeer* peer, uint interval, uint acceleration, uint deceleration);
361 |
362 | public abstract void peer_timeout(ENetPeer* peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum);
363 | #endregion
364 |
365 | #region C# Utility
366 | public static bool memcmp(byte[] s1, byte[] s2)
367 | {
368 | if (s1 == null || s2 == null) { throw new ArgumentNullException(); }
369 | if (s1.Length != s2.Length) { return false; }
370 |
371 | for (int i = 0; i < s1.Length; i++) { if (s1[i] != s2[i]) { return false; } }
372 | return true;
373 | }
374 |
375 | public static int strlen(byte[] s)
376 | {
377 | if (s == null) { throw new ArgumentNullException(); }
378 |
379 | int i;
380 | for (i = 0; i < s.Length && s[i] != 0; i++) ;
381 | return i;
382 | }
383 | #endregion
384 | }
385 | }
386 |
--------------------------------------------------------------------------------
/ENetCS/Native/ENetApiAny.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2013 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | #pragma warning disable 1591
21 |
22 | using System;
23 | using System.Runtime.InteropServices;
24 |
25 | namespace ENet.Native
26 | {
27 | unsafe sealed class ENetApiAny : ENetApi
28 | {
29 | const string LIB = "ENet";
30 |
31 | #region Address Functions
32 | public override int address_set_host(ref ENetAddress address, byte* hostName)
33 | {
34 | return native_address_set_host(ref address, hostName);
35 | }
36 |
37 | public override int address_set_host(ref ENetAddress address, byte[] hostName)
38 | {
39 | return native_address_set_host(ref address, hostName);
40 | }
41 |
42 | public override int address_get_host(ref ENetAddress address, byte* hostName, IntPtr nameLength)
43 | {
44 | return native_address_get_host(ref address, hostName, nameLength);
45 | }
46 |
47 | public override int address_get_host(ref ENetAddress address, byte[] hostName, IntPtr nameLength)
48 | {
49 | return native_address_get_host(ref address, hostName, nameLength);
50 | }
51 |
52 | public override int address_get_host_ip(ref ENetAddress address, byte* hostIP, IntPtr ipLength)
53 | {
54 | return native_address_get_host_ip(ref address, hostIP, ipLength);
55 | }
56 |
57 | public override int address_get_host_ip(ref ENetAddress address, byte[] hostIP, IntPtr ipLength)
58 | {
59 | return native_address_get_host_ip(ref address, hostIP, ipLength);
60 | }
61 |
62 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_set_host")]
63 | static extern int native_address_set_host(ref ENetAddress address, byte* hostName);
64 |
65 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_set_host")]
66 | static extern int native_address_set_host(ref ENetAddress address, byte[] hostName);
67 |
68 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_get_host")]
69 | static extern int native_address_get_host(ref ENetAddress address, byte* hostName, IntPtr nameLength);
70 |
71 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_get_host")]
72 | static extern int native_address_get_host(ref ENetAddress address, byte[] hostName, IntPtr nameLength);
73 |
74 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_get_host_ip")]
75 | static extern int native_address_get_host_ip(ref ENetAddress address, byte* hostIP, IntPtr ipLength);
76 |
77 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_address_get_host_ip")]
78 | static extern int native_address_get_host_ip(ref ENetAddress address, byte[] hostIP, IntPtr ipLength);
79 | #endregion
80 |
81 | #region Global Functions
82 | public override int initialize_with_callbacks(uint version, ref ENetCallbacks inits)
83 | {
84 | return native_initialize_with_callbacks(version, ref inits);
85 | }
86 |
87 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_initialize_with_callbacks")]
88 | static extern int native_initialize_with_callbacks(uint version, ref ENetCallbacks inits);
89 | #endregion
90 |
91 | #region Host Functions
92 | public override void host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth)
93 | {
94 | native_host_bandwidth_limit(host, incomingBandwidth, outgoingBandwidth);
95 | }
96 |
97 | public override void host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet)
98 | {
99 | native_host_broadcast(host, channelID, packet);
100 | }
101 |
102 | public override void host_channel_limit(ENetHost* host, IntPtr channelLimit)
103 | {
104 | native_host_channel_limit(host, channelLimit);
105 | }
106 |
107 | public override int host_check_events(ENetHost* host, out ENetEvent @event)
108 | {
109 | return native_host_check_events(host, out @event);
110 | }
111 |
112 | public override void host_compress(ENetHost* host, ENetCompressor* compressor)
113 | {
114 | native_host_compress(host, compressor);
115 | }
116 |
117 | public override int host_compress_with_range_encoder(ENetHost* host)
118 | {
119 | return native_host_compress_with_range_encoder(host);
120 | }
121 |
122 | public override ENetPeer* host_connect(ENetHost* host, ref ENetAddress address, IntPtr channelCount, uint data)
123 | {
124 | return native_host_connect(host, ref address, channelCount, data);
125 | }
126 |
127 | public override ENetHost* host_create(ENetAddress* address,
128 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth)
129 | {
130 | return native_host_create(address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth);
131 | }
132 |
133 | public override ENetHost* host_create(ref ENetAddress address,
134 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth)
135 | {
136 | return native_host_create(ref address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth);
137 | }
138 |
139 | public override void host_destroy(ENetHost* host)
140 | {
141 | native_host_destroy(host);
142 | }
143 |
144 | public override void host_flush(ENetHost* host)
145 | {
146 | native_host_flush(host);
147 | }
148 |
149 | public override int host_service(ENetHost* host, ENetEvent* @event, uint timeout)
150 | {
151 | return native_host_service(host, @event, timeout);
152 | }
153 |
154 | public override int host_service(ENetHost* host, out ENetEvent @event, uint timeout)
155 | {
156 | return native_host_service(host, out @event, timeout);
157 | }
158 |
159 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_bandwidth_limit")]
160 | static extern void native_host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth);
161 |
162 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_broadcast")]
163 | static extern void native_host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet);
164 |
165 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_channel_limit")]
166 | static extern void native_host_channel_limit(ENetHost* host, IntPtr channelLimit);
167 |
168 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_check_events")]
169 | static extern int native_host_check_events(ENetHost* host, out ENetEvent @event);
170 |
171 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_compress")]
172 | static extern void native_host_compress(ENetHost* host, ENetCompressor* compressor);
173 |
174 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_compress_with_range_encoder")]
175 | static extern int native_host_compress_with_range_encoder(ENetHost* host);
176 |
177 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_connect")]
178 | static extern ENetPeer* native_host_connect(ENetHost* host, ref ENetAddress address, IntPtr channelCount, uint data);
179 |
180 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_create")]
181 | static extern ENetHost* native_host_create(ENetAddress* address,
182 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth);
183 |
184 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_create")]
185 | static extern ENetHost* native_host_create(ref ENetAddress address,
186 | IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth);
187 |
188 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_destroy")]
189 | static extern void native_host_destroy(ENetHost* host);
190 |
191 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_flush")]
192 | static extern void native_host_flush(ENetHost* host);
193 |
194 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_service")]
195 | static extern int native_host_service(ENetHost* host, ENetEvent* @event, uint timeout);
196 |
197 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_host_service")]
198 | static extern int native_host_service(ENetHost* host, out ENetEvent @event, uint timeout);
199 | #endregion
200 |
201 | #region Miscellaneous Functions
202 | public override uint time_get()
203 | {
204 | return native_time_get();
205 | }
206 |
207 | public override void time_set(uint newTimeBase)
208 | {
209 | native_time_set(newTimeBase);
210 | }
211 |
212 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_time_get")]
213 | static extern uint native_time_get();
214 |
215 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_time_set")]
216 | static extern void native_time_set(uint newTimeBase);
217 | #endregion
218 |
219 | #region Packet Functions
220 | public override ENetPacket* packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags)
221 | {
222 | return native_packet_create(data, dataLength, flags);
223 | }
224 |
225 | public override void packet_destroy(ENetPacket* packet)
226 | {
227 | native_packet_destroy(packet);
228 | }
229 |
230 | public override int packet_resize(ENetPacket* packet, IntPtr dataLength)
231 | {
232 | return native_packet_resize(packet, dataLength);
233 | }
234 |
235 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_packet_create")]
236 | static extern ENetPacket* native_packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags);
237 |
238 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_packet_destroy")]
239 | static extern void native_packet_destroy(ENetPacket* packet);
240 |
241 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_packet_resize")]
242 | static extern int native_packet_resize(ENetPacket* packet, IntPtr dataLength);
243 | #endregion
244 |
245 | #region Peer Functions
246 | public override void peer_disconnect(ENetPeer* peer, uint data)
247 | {
248 | native_peer_disconnect(peer, data);
249 | }
250 |
251 | public override void peer_disconnect_now(ENetPeer* peer, uint data)
252 | {
253 | native_peer_disconnect_now(peer, data);
254 | }
255 |
256 | public override void peer_disconnect_later(ENetPeer* peer, uint data)
257 | {
258 | native_peer_disconnect_later(peer, data);
259 | }
260 |
261 | public override void peer_ping(ENetPeer* peer)
262 | {
263 | native_peer_ping(peer);
264 | }
265 |
266 | public override void peer_ping_interval(ENetPeer* peer, uint pingInterval)
267 | {
268 | native_peer_ping_interval(peer, pingInterval);
269 | }
270 |
271 | public override ENetPacket* peer_receive(ENetPeer* peer, out byte channelID)
272 | {
273 | return native_peer_receive(peer, out channelID);
274 | }
275 |
276 | public override void peer_reset(ENetPeer* peer)
277 | {
278 | native_peer_reset(peer);
279 | }
280 |
281 | public override int peer_send(ENetPeer* peer, byte channelID, ENetPacket* packet)
282 | {
283 | return native_peer_send(peer, channelID, packet);
284 | }
285 |
286 | public override void peer_throttle_configure(ENetPeer* peer, uint interval, uint acceleration, uint deceleration)
287 | {
288 | native_peer_throttle_configure(peer, interval, acceleration, deceleration);
289 | }
290 |
291 | public override void peer_timeout(ENetPeer* peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum)
292 | {
293 | native_peer_timeout(peer, timeoutLimit, timeoutMinimum, timeoutMaximum);
294 | }
295 |
296 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_disconnect")]
297 | static extern void native_peer_disconnect(ENetPeer* peer, uint data);
298 |
299 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_disconnect_now")]
300 | static extern void native_peer_disconnect_now(ENetPeer* peer, uint data);
301 |
302 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_disconnect_later")]
303 | static extern void native_peer_disconnect_later(ENetPeer* peer, uint data);
304 |
305 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_ping")]
306 | static extern void native_peer_ping(ENetPeer* peer);
307 |
308 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_ping_interval")]
309 | static extern void native_peer_ping_interval(ENetPeer* peer, uint pingInterval);
310 |
311 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_receive")]
312 | static extern ENetPacket* native_peer_receive(ENetPeer* peer, out byte channelID);
313 |
314 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_reset")]
315 | static extern void native_peer_reset(ENetPeer* peer);
316 |
317 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_send")]
318 | static extern int native_peer_send(ENetPeer* peer, byte channelID, ENetPacket* packet);
319 |
320 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_throttle_configure")]
321 | static extern void native_peer_throttle_configure(ENetPeer* peer, uint interval, uint acceleration, uint deceleration);
322 |
323 | [DllImport(LIB, CallingConvention = CallingConvention.Cdecl, EntryPoint = "enet_peer_timeout")]
324 | static extern void native_peer_timeout(ENetPeer* peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum);
325 | #endregion
326 | }
327 | }
328 |
--------------------------------------------------------------------------------
/ENetCS/Native/Structs.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2011-2012 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | #pragma warning disable 1591
21 |
22 | using System;
23 | using System.Net;
24 | using System.Net.Sockets;
25 | using System.Runtime.InteropServices;
26 |
27 | namespace ENet.Native
28 | {
29 | [StructLayout(LayoutKind.Sequential)]
30 | public struct ENetAddress
31 | {
32 | public uint host;
33 | public ushort port;
34 |
35 | /// The address is null.
36 | /// The address is not IPv4.
37 | /// The port is less than 0 or greater than 65535.
38 | public static explicit operator ENetAddress(IPEndPoint endPoint)
39 | {
40 | if (endPoint == null) { throw new ArgumentNullException(); }
41 | if (endPoint.AddressFamily != AddressFamily.InterNetwork) { throw new ArgumentException(); }
42 | if (endPoint.Port < 0 || endPoint.Port > 65535) { throw new ArgumentOutOfRangeException(); }
43 |
44 | return new ENetAddress()
45 | {
46 | host = endPoint.Address == IPAddress.Any ? 0 : BitConverter.ToUInt32(endPoint.Address.GetAddressBytes(), 0),
47 | port = (ushort)endPoint.Port
48 | };
49 | }
50 |
51 | public static implicit operator IPEndPoint(ENetAddress address)
52 | {
53 | return new IPEndPoint(address.host, address.port);
54 | }
55 | }
56 |
57 | [StructLayout(LayoutKind.Sequential)]
58 | public struct ENetCallbacks
59 | {
60 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
61 | public delegate IntPtr malloc_cb(IntPtr size);
62 |
63 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
64 | public delegate void free_cb(IntPtr memory);
65 |
66 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
67 | public delegate void no_memory_cb();
68 |
69 | public IntPtr malloc, free, no_memory;
70 | }
71 |
72 | [StructLayout(LayoutKind.Sequential)]
73 | public struct ENetCompressor
74 | {
75 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
76 | public delegate IntPtr compress_cb(IntPtr context, IntPtr inBuffers, IntPtr inBufferCount, IntPtr inLimit, IntPtr outData, IntPtr outLimit);
77 |
78 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
79 | public delegate IntPtr decompress_cb(IntPtr context, IntPtr inData, IntPtr inLimit, IntPtr outData, IntPtr outLimit);
80 |
81 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
82 | public delegate void destroy_cb(IntPtr context);
83 |
84 | public IntPtr context;
85 | public IntPtr compress, decompress, destroy;
86 | }
87 |
88 | [StructLayout(LayoutKind.Sequential)]
89 | public unsafe struct ENetEvent
90 | {
91 | public EventType type;
92 | public ENetPeer* peer;
93 | public byte channelID;
94 | public uint data;
95 | public ENetPacket* packet;
96 | }
97 |
98 | [StructLayout(LayoutKind.Sequential)]
99 | public struct ENetHost
100 | {
101 |
102 | }
103 |
104 | [StructLayout(LayoutKind.Sequential)]
105 | public unsafe struct ENetListNode
106 | {
107 | public ENetListNode* next, previous;
108 | }
109 |
110 | [StructLayout(LayoutKind.Sequential)]
111 | public unsafe struct ENetPacket
112 | {
113 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
114 | public delegate void freeCallback_cb(ENetPacket* packet);
115 |
116 | public IntPtr referenceCount;
117 | public PacketFlags flags;
118 | public IntPtr data;
119 | public IntPtr dataLength;
120 | public IntPtr freeCallback;
121 | }
122 |
123 | [StructLayout(LayoutKind.Sequential)]
124 | public unsafe struct ENetPeer
125 | {
126 | public ENetListNode dispatchList;
127 | public ENetHost* host;
128 | public ushort outgoingPeerID;
129 | public ushort incomingPeerID;
130 | public uint connectID;
131 | public byte outgoingSessionID;
132 | public byte incomingSessionID;
133 |
134 | uint addressHost; // https://bugzilla.xamarin.com/show_bug.cgi?id=11899
135 | ushort addressPort;
136 | public ENetAddress address
137 | {
138 | get { return new ENetAddress() { host = addressHost, port = addressPort }; }
139 | set { addressHost = value.host; addressPort = value.port; }
140 | }
141 |
142 | public IntPtr data;
143 | public PeerState state;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/ENetCS/Packet.IList.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2013 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using System;
21 | using System.Collections;
22 | using System.Collections.Generic;
23 | using System.Runtime.InteropServices;
24 |
25 | namespace ENet
26 | {
27 | partial struct Packet : IList
28 | {
29 | ///
30 | /// Adds a byte to the end of the packet.
31 | ///
32 | /// The value of the byte.
33 | /// The packet is not initialized.
34 | ///
35 | /// Packet resizing behavior is less than optimal. So, in performance-critical applications, it's
36 | /// presently a good idea to initialize the packet with a final byte array instead of using this method.
37 | ///
38 | public void Add(byte value)
39 | {
40 | Insert(Length, value);
41 | }
42 |
43 | ///
44 | /// Sets the packet length to zero.
45 | ///
46 | /// The packet is not initialized.
47 | public void Clear()
48 | {
49 | Resize(0);
50 | }
51 |
52 | ///
53 | /// Checks if the packet contains a particular byte.
54 | ///
55 | /// The value to look for.
56 | /// True if the packet contains the byte.
57 | /// The packet is not initialized.
58 | public bool Contains(byte value)
59 | {
60 | return IndexOf(value) != -1;
61 | }
62 |
63 | ///
64 | /// Copies part of the packet data into an array.
65 | ///
66 | /// The array to copy into.
67 | /// The target array index at which to begin copying.
68 | /// is null.
69 | /// is out of range.
70 | /// The packet is not initialized.
71 | public void CopyTo(byte[] array, int arrayIndex)
72 | {
73 | CopyTo(array, arrayIndex, Length, 0);
74 | }
75 |
76 | ///
77 | /// Returns an enumerator that iterates through the bytes of the packet.
78 | ///
79 | /// An enumerator.
80 | /// The packet is not initialized.
81 | public IEnumerator GetEnumerator()
82 | {
83 | CheckInitialized();
84 |
85 | for (int i = 0; i < Length; i++)
86 | {
87 | yield return this[i];
88 | }
89 | }
90 |
91 | IEnumerator IEnumerable.GetEnumerator()
92 | {
93 | return GetEnumerator();
94 | }
95 |
96 | ///
97 | /// Checks if the packet contains a particular byte, and if so, returns the index.
98 | ///
99 | /// The value to look for.
100 | /// The index of the byte, or -1.
101 | /// The packet is not initialized.
102 | public int IndexOf(byte value)
103 | {
104 | for (int i = 0; i < Length; i++)
105 | {
106 | if (this[i] == value) { return i; }
107 | }
108 |
109 | return -1;
110 | }
111 |
112 | ///
113 | /// Inserts a byte in the packet.
114 | ///
115 | /// The index to insert at.
116 | /// The value of the byte.
117 | /// is out of range.
118 | /// The packet is not initialized.
119 | ///
120 | /// Packet resizing behavior is less than optimal. So, in performance-critical applications, it's
121 | /// presently a good idea to initialize the packet with a final byte array instead of using this method.
122 | ///
123 | public void Insert(int index, byte value)
124 | {
125 | if (index < 0 || index > Length) { throw new ArgumentOutOfRangeException("index"); }
126 |
127 | Resize(checked(Length + 1));
128 | for (int i = Length - 1; i > index; i--)
129 | {
130 | this[i] = this[i - 1];
131 | }
132 | this[index] = value;
133 | }
134 |
135 | ///
136 | /// Removes the first byte in the packet with the specified value.
137 | ///
138 | /// The value of the byte to remove.
139 | /// True if a byte was found and removed.
140 | /// The packet is not initialized.
141 | public bool Remove(byte value)
142 | {
143 | int index = IndexOf(value);
144 | if (index == -1) { return false; }
145 | RemoveAt(index); return true;
146 | }
147 |
148 | ///
149 | /// Removes the byte at the specified index from the packet.
150 | ///
151 | /// The index of the byte to remove.
152 | /// is out of range.
153 | /// The packet is not initialized.
154 | public void RemoveAt(int index)
155 | {
156 | if (index < 0 || index >= Length) { throw new ArgumentOutOfRangeException("index"); }
157 |
158 | for (int i = index; i < Length - 1; i++)
159 | {
160 | this[i] = this[i + 1];
161 | }
162 | Resize(Length - 1);
163 | }
164 |
165 | ///
166 | /// Gets or sets the byte at the specified index.
167 | ///
168 | /// The index of the byte.
169 | /// The byte value.
170 | /// is out of range.
171 | /// The packet is not initialized.
172 | public byte this[int index]
173 | {
174 | get
175 | {
176 | if (index < 0 || index >= Length) { throw new ArgumentOutOfRangeException("index"); }
177 | return Marshal.ReadByte(Data, index);
178 | }
179 |
180 | set
181 | {
182 | if (index < 0 || index >= Length) { throw new ArgumentOutOfRangeException("index"); }
183 | Marshal.WriteByte(Data, index, value);
184 | }
185 | }
186 |
187 | int ICollection.Count
188 | {
189 | get { return Length; }
190 | }
191 |
192 | bool ICollection.IsReadOnly
193 | {
194 | get { return false; }
195 | }
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/ENetCS/Packet.UserData.cs:
--------------------------------------------------------------------------------
1 | #region License
2 | /*
3 | ENet for C#
4 | Copyright (c) 2013 James F. Bellinger
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | */
18 | #endregion
19 |
20 | using System;
21 | using System.Collections.Generic;
22 | using System.Runtime.InteropServices;
23 | using System.Threading;
24 |
25 | namespace ENet
26 | {
27 | ///
28 | /// Called when ENet is finished with a packet and it is about to be freed from memory.
29 | ///
30 | /// The packet.
31 | public delegate void PacketFreeCallback(Packet packet);
32 |
33 | unsafe partial struct Packet
34 | {
35 | static Native.ENetPacket.freeCallback_cb _freeCallbackDelegate;
36 | static IntPtr _freeCallbackFunctionPointer;
37 | static object _freeCallbackKey;
38 | static Dictionary> _userData;
39 | static object _userDataDefaultKey;
40 |
41 | static void InitializeUserData()
42 | {
43 | _freeCallbackDelegate = FreeCallbackHandler;
44 | _freeCallbackFunctionPointer = Marshal.GetFunctionPointerForDelegate(_freeCallbackDelegate);
45 | _freeCallbackKey = new object();
46 | _userData = new Dictionary>();
47 | _userDataDefaultKey = new object();
48 | }
49 |
50 | static void FreeCallbackHandler(Native.ENetPacket* native)
51 | {
52 | Packet packet = new Packet(native);
53 |
54 | lock (_userData)
55 | {
56 | try
57 | {
58 | PacketFreeCallback callback = (PacketFreeCallback)packet.GetUserData(_freeCallbackKey);
59 |
60 | if (callback != null)
61 | {
62 | try
63 | {
64 | Monitor.Exit(_userData);
65 | callback(packet);
66 | }
67 | finally
68 | {
69 | Monitor.Enter(_userData);
70 | }
71 | }
72 | }
73 | finally
74 | {
75 | _userData.Remove(packet);
76 | }
77 | }
78 | }
79 |
80 | ///
81 | /// Occurs when ENet is finished with a packet and it is about to be freed from memory.
82 | ///
83 | public event PacketFreeCallback Freed
84 | {
85 | add
86 | {
87 | lock (_userData)
88 | {
89 | SetUserData(_freeCallbackKey, (PacketFreeCallback)GetUserData(_freeCallbackKey) + value);
90 | }
91 | }
92 |
93 | remove
94 | {
95 | lock (_userData)
96 | {
97 | SetUserData(_freeCallbackKey, (PacketFreeCallback)GetUserData(_freeCallbackKey) - value);
98 | }
99 | }
100 | }
101 |
102 | ///
103 | /// Gets the user data associated with this packet.
104 | ///
105 | ///
106 | public object GetUserData()
107 | {
108 | return GetUserData(null);
109 | }
110 |
111 | ///
112 | /// Gets the user data associated with this packet and a particular key.
113 | ///
114 | /// The key to use.
115 | /// The user data.
116 | public object GetUserData(object key)
117 | {
118 | if (key == null) { key = _userDataDefaultKey; }
119 |
120 | lock (_userData)
121 | {
122 | Dictionary