diff --git a/Assets/NSM2/INetworkPacketHandler.cs b/Assets/NSM2/INetworkPacketHandler.cs
index fa0ff30..de7c8a0 100644
--- a/Assets/NSM2/INetworkPacketHandler.cs
+++ b/Assets/NSM2/INetworkPacketHandler.cs
@@ -1,16 +1,30 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-using ByteDance.NAPI;
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using System;
using System.IO;
@@ -37,7 +51,7 @@ public interface INetworkPacketHandler
///
/// The user data(such as pb buffer)
/// The pdu wrapped with c++ obstream*) for Encode output
- void EncodePDU(int cmd, NativeDataView ud, IntPtr ob);
+ void EncodePDU(int cmd, Span ud, IntPtr ob);
///
/// 处理应用层协议单元(协议头+PB数据)
@@ -45,7 +59,7 @@ public interface INetworkPacketHandler
/// The pointer of first byte of whole PDU
/// The length of PDU
///
- (int, NativeDataView,Stream) DecodePDU(IntPtr d, int len);
+ (int, Stream) DecodePDU(IntPtr d, int len, out Span msg);
///
/// 处理网络事件
@@ -54,6 +68,6 @@ public interface INetworkPacketHandler
/// 消息码
/// 消息
/// 信道
- void HandleEvent(NetworkEvent ev, int cmd, NativeDataView ud, int channel);
+ void HandleEvent(NetworkEvent ev, int cmd, Span ud, int channel);
}
}
diff --git a/Assets/NSM2/NetworkServiceManager.cs b/Assets/NSM2/NetworkServiceManager.cs
index df70f45..9da57f5 100644
--- a/Assets/NSM2/NetworkServiceManager.cs
+++ b/Assets/NSM2/NetworkServiceManager.cs
@@ -1,19 +1,34 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using System;
using System.Collections.Generic;
using UnityEngine;
using AOT;
-using ByteDance.NAPI;
using System.IO;
namespace NSM2
@@ -215,10 +230,10 @@ void BroadcastEventToListeners(NetworkEventType eventType, int ec, int channel =
}
}
- unsafe public void SendSerializedMsg(int cmd, NativeDataView ud, int channel = 0)
+ unsafe public void SendSerializedMsg(int cmd, Span ud, int channel = 0)
{
// The whole packet is sizeof(body) + sizeof(header), so no memory realloc
- IntPtr pdu = YASIO_NI.yasio_ob_new(ud.len + _packeter.GetHeaderSize());
+ IntPtr pdu = YASIO_NI.yasio_ob_new(ud.Length + _packeter.GetHeaderSize());
_packeter.EncodePDU(cmd, ud, pdu);
if (channel < _sessions.Length)
@@ -246,15 +261,16 @@ unsafe public void SendSerializedMsg(int cmd, NativeDataView ud, int channel = 0
/// 向远端发送数据
///
///
- public void SendRaw(NativeDataView data, int channel)
+ public unsafe void SendRaw(Span data, int channel)
{
if (channel < _sessions.Length)
{
IntPtr sid = _sessions[channel];
if (sid != IntPtr.Zero)
{
-
- YASIO_NI.yasio_write(_service, sid, data.ptr, data.len);
+ fixed (void* p = data) {
+ YASIO_NI.yasio_write(_service, sid, (IntPtr)p, data.Length);
+ }
}
else
{
@@ -270,10 +286,7 @@ public void SendRaw(NativeDataView data, int channel)
public unsafe void SendRaw(byte[] data, int channel)
{
- fixed (byte* p = data)
- {
- SendRaw(new NativeDataView((IntPtr)p, data.Length), channel);
- }
+ SendRaw(new Span(data), channel);
}
///
@@ -312,34 +325,35 @@ static void HandleNativeConsolePrint(int level, string msg)
///
/// The stack address of shared_ptr
[MonoPInvokeCallback(typeof(YASIO_NI.YNIEventDelegate))]
- static void HandleNativeNetworkIoEvent(ref YASIO_NI.EventData data)
+ static void HandleNativeNetworkIoEvent(ref YASIO_NI.IOEvent ev)
{
var nsm = NetworkServiceManager.Instance;
- Debug.LogFormat("The channel connect_id={0}, bytes_transferred={1}", YASIO_NI.yasio_connect_id(nsm._service, data.channel),
- YASIO_NI.yasio_bytes_transferred(nsm._service, data.channel));
- switch ((YASIO_NI.YEnums)data.kind)
+ Debug.LogFormat("The channel connect_id={0}, bytes_transferred={1}", YASIO_NI.yasio_connect_id(nsm._service, ev.channel),
+ YASIO_NI.yasio_bytes_transferred(nsm._service, ev.channel));
+ switch ((YASIO_NI.YEnums)ev.kind)
{
case YASIO_NI.YEnums.YEK_ON_PACKET:
- (int cmd, NativeDataView ud, Stream hold) = nsm._packeter.DecodePDU(YASIO_NI.yasio_unwrap_ptr(data.packet, 0), YASIO_NI.yasio_unwrap_len(data.packet, 0));
- nsm._packeter.HandleEvent(NetworkEvent.PACKET, cmd, ud, data.channel);
+ Span ud;
+ (int cmd, Stream hold) = nsm._packeter.DecodePDU(YASIO_NI.yasio_unwrap_ptr(ev.data.msg, 0), YASIO_NI.yasio_unwrap_len(ev.data.msg, 0), out ud);
+ nsm._packeter.HandleEvent(NetworkEvent.PACKET, cmd, ud, ev.channel);
hold?.Dispose();
break;
case YASIO_NI.YEnums.YEK_ON_OPEN:
- if (data.status == 0)
+ if (ev.data.error == 0)
{
- nsm.UpdateSession(data.channel, data.session);
- nsm.BroadcastEventToListeners(NetworkEventType.CONNECT_SUCCESS, 0, data.channel);
- nsm._packeter.HandleEvent(NetworkEvent.CONNECT_SUCCESS, -1, NativeDataView.NullValue, data.channel);
+ nsm.UpdateSession(ev.channel, ev.thandle);
+ nsm.BroadcastEventToListeners(NetworkEventType.CONNECT_SUCCESS, 0, ev.channel);
+ nsm._packeter.HandleEvent(NetworkEvent.CONNECT_SUCCESS, -1, Span.Empty, ev.channel);
}
else
{
- nsm.BroadcastEventToListeners(NetworkEventType.CONNECT_FAILED, data.status, data.channel);
- nsm._packeter.HandleEvent(NetworkEvent.CONNECT_FAILED, -1, NativeDataView.NullValue, data.channel);
+ nsm.BroadcastEventToListeners(NetworkEventType.CONNECT_FAILED, ev.data.error, ev.channel);
+ nsm._packeter.HandleEvent(NetworkEvent.CONNECT_FAILED, -1, Span.Empty, ev.channel);
}
break;
case YASIO_NI.YEnums.YEK_ON_CLOSE:
- nsm.BroadcastEventToListeners(NetworkEventType.CONNECTION_LOST, data.status, data.channel);
- nsm._packeter.HandleEvent(NetworkEvent.CONNECTION_LOST, -1, NativeDataView.NullValue, data.channel);
+ nsm.BroadcastEventToListeners(NetworkEventType.CONNECTION_LOST, ev.data.error, ev.channel);
+ nsm._packeter.HandleEvent(NetworkEvent.CONNECTION_LOST, -1, Span.Empty, ev.channel);
break;
}
}
diff --git a/Assets/NSM2/Singleton.cs b/Assets/NSM2/Singleton.cs
index 8e57a10..2a7fc2b 100644
--- a/Assets/NSM2/Singleton.cs
+++ b/Assets/NSM2/Singleton.cs
@@ -1,14 +1,30 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using System;
using UnityEngine;
diff --git a/Assets/NSM2/YASIO_NI.cs b/Assets/NSM2/YASIO_NI.cs
index 60764c0..c1e1d0c 100644
--- a/Assets/NSM2/YASIO_NI.cs
+++ b/Assets/NSM2/YASIO_NI.cs
@@ -1,16 +1,32 @@
-//
-// Copyright (c) Bytedance Inc 2021-2022. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-/* Match with yasio-4.0.x+ */
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/* Match with yasio-5.0.x+ */
using System;
using System.Runtime.InteropServices;
@@ -23,21 +39,28 @@ public class YASIO_NI
#else
public const string LIBNAME = "yasio";
#endif
- // match with yasio/binding/yasio_ni.cpp: struct yasio_event_data
+ // match with yasio/binding/yasio_ni.cpp: struct yasio_io_event
[StructLayout(LayoutKind.Sequential)]
- public unsafe struct EventData
+ public unsafe struct IOEvent
{
public int kind;
- public int status;
public int channel;
- public IntPtr session; // transport
- public IntPtr packet;
- public IntPtr user; // the user data
+ public IntPtr thandle;
- public static readonly int cbSize = sizeof(EventData);
+ [StructLayout(LayoutKind.Explicit)]
+ public unsafe struct EventData
+ {
+ [FieldOffset(0)] public IntPtr msg;
+ [FieldOffset(0)] public int error;
+ }
+
+ public EventData data;
+ public void* user;
+
+ public static readonly int cbSize = sizeof(IOEvent);
}
- public delegate void YNIEventDelegate(ref EventData eventData);
+ public delegate void YNIEventDelegate(ref IOEvent eventData);
public delegate int YNIResolvDelegate(string host, IntPtr sbuf);
public delegate void YNIPrintDelegate(int level, string msg);
diff --git a/Assets/Plugins/x86_64/yasio.dll b/Assets/Plugins/x86_64/yasio.dll
index f1889ec..7699dfa 100644
Binary files a/Assets/Plugins/x86_64/yasio.dll and b/Assets/Plugins/x86_64/yasio.dll differ
diff --git a/Assets/Scripts/AppProtocol.cs b/Assets/Scripts/AppProtocol.cs
index 340279d..0fac028 100644
--- a/Assets/Scripts/AppProtocol.cs
+++ b/Assets/Scripts/AppProtocol.cs
@@ -1,15 +1,30 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-using ByteDance.NAPI;
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using System;
using System.IO;
using System.Net;
@@ -29,73 +44,90 @@ public class AppProtocol
public const short CMD_LOGIN_REQ = 2021;
public const int CMD_LOGIN_RESP = 2022;
- public interface Message
+ public abstract class Message
{
- void print();
- unsafe (NativeDataView, Stream) encode();
- unsafe void decode(NativeDataView ud);
+ public virtual void print() { }
+ public virtual Span encode() { return null; }
+ public virtual unsafe void decode(Span ud) { }
+
+ protected BinaryWriter m_writer = null;
+
+ public BinaryWriter writer() {
+ if (m_writer != null) m_writer.Dispose();
+ return new BinaryWriter(new MemoryStream());
+ }
+
+ public void Dispose()
+ {
+ if(m_writer != null) m_writer.Dispose();
+ m_writer = null;
+ }
}
+
public class LoginReq : Message
{
public int uid = 0;
- public void print()
+ public override void print()
{
UnityEngine.Debug.LogFormat("---> LoginReq: \r\n uid={0}", uid);
}
- public unsafe (NativeDataView, Stream) encode()
+ public override unsafe Span encode()
{
- MemoryStream ms = new MemoryStream();
- var writer = new BinaryWriter(ms);
- writer.Write(IPAddress.HostToNetworkOrder(uid));
+ var w = writer();
+
+ w.Write(IPAddress.HostToNetworkOrder(uid));
+
+ var ms = (MemoryStream)w.BaseStream;
var buf = ms.GetBuffer();
- fixed (byte* data = buf)
- {
- return (new NativeDataView((IntPtr)data, (int)ms.Length), ms);
- }
+ return new Span(buf, 0, (int)ms.Length);
}
- public unsafe void decode(NativeDataView ud)
+ public override unsafe void decode(Span ud)
{
- using (UnmanagedMemoryStream ums = new UnmanagedMemoryStream((byte*)ud.ptr, ud.len))
+ fixed(byte* ptr = ud)
{
- BinaryReader reader = new BinaryReader(ums);
- uid = IPAddress.NetworkToHostOrder(reader.ReadInt32());
- reader.Dispose();
+ using (UnmanagedMemoryStream ums = new UnmanagedMemoryStream(ptr, ud.Length))
+ {
+ BinaryReader reader = new BinaryReader(ums);
+ uid = IPAddress.NetworkToHostOrder(reader.ReadInt32());
+ reader.Dispose();
+ }
}
}
}
- public class LoginResp
+ public class LoginResp : Message
{
- public void print()
+ public override void print()
{
UnityEngine.Debug.LogFormat("---> LoginResp: \r\n uid={0}, status={1}", uid, status);
}
- public unsafe (NativeDataView, Stream) encode()
+ public override unsafe Span encode()
{
- MemoryStream ms = new MemoryStream();
-
- var writer = new BinaryWriter(ms);
- writer.Write(IPAddress.HostToNetworkOrder(uid));
- writer.Write(IPAddress.HostToNetworkOrder(status));
+ var w = writer();
+
+ w.Write(IPAddress.HostToNetworkOrder(uid));
+ w.Write(IPAddress.HostToNetworkOrder(status));
+
+ var ms = (MemoryStream)w.BaseStream;
var buf = ms.GetBuffer();
- fixed (byte* data = buf)
- {
- return (new NativeDataView((IntPtr)data, (int)ms.Length), ms);
- }
+ return new Span(buf, 0, (int)ms.Length);
}
- public unsafe void decode(NativeDataView ud)
+ public override unsafe void decode(Span ud)
{
- using (UnmanagedMemoryStream ums = new UnmanagedMemoryStream((byte*)ud.ptr, ud.len))
+ fixed (byte* ptr = ud)
{
- BinaryReader reader = new BinaryReader(ums);
- uid = IPAddress.NetworkToHostOrder(reader.ReadInt32());
- status = IPAddress.NetworkToHostOrder(reader.ReadInt32());
- reader.Dispose();
+ using (UnmanagedMemoryStream ums = new UnmanagedMemoryStream(ptr, ud.Length))
+ {
+ BinaryReader reader = new BinaryReader(ums);
+ uid = IPAddress.NetworkToHostOrder(reader.ReadInt32());
+ status = IPAddress.NetworkToHostOrder(reader.ReadInt32());
+ reader.Dispose();
+ }
}
}
public int uid;
diff --git a/Assets/Scripts/SampleNetworkPacketHandler.cs b/Assets/Scripts/SampleNetworkPacketHandler.cs
index 7da5b5b..cb92647 100644
--- a/Assets/Scripts/SampleNetworkPacketHandler.cs
+++ b/Assets/Scripts/SampleNetworkPacketHandler.cs
@@ -1,15 +1,30 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-using ByteDance.NAPI;
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using System;
using System.IO;
using System.Net;
@@ -49,15 +64,18 @@ public int GetHeaderSize()
return PROTO_HEADER_SIZE;
}
- unsafe public void EncodePDU(int cmd, NativeDataView ud, IntPtr ob)
+ unsafe public void EncodePDU(int cmd, Span ud, IntPtr ob)
{
YASIO_NI.yasio_ob_write_short(ob, (short)cmd);
- YASIO_NI.yasio_ob_write_int(ob, ud.len); // packet size
+ YASIO_NI.yasio_ob_write_int(ob, ud.Length); // packet size
YASIO_NI.yasio_ob_write_int(ob, VERIFIED_MAGIC_NUM); // magic number
- YASIO_NI.yasio_ob_write_bytes(ob, ud.ptr, ud.len); // ud
+ fixed (void* bytes = ud)
+ {
+ YASIO_NI.yasio_ob_write_bytes(ob, (IntPtr)bytes, ud.Length); // ud
+ }
}
- unsafe public (int, NativeDataView, Stream) DecodePDU(IntPtr bytes, int len)
+ unsafe public (int, Stream) DecodePDU(IntPtr bytes, int len, out Span msg)
{
Stream dataStream = new UnmanagedMemoryStream((byte*)bytes, len);
try
@@ -77,15 +95,13 @@ unsafe public (int, NativeDataView, Stream) DecodePDU(IntPtr bytes, int len)
if (DUMP_RECV_HEX)
{
int bodyLen = len - PROTO_HEADER_SIZE; // the udLen===bodyLen
- string wholeHexs = YASIO_NI.DumpHex(bytes, len);
- UnityEngine.Debug.LogFormat("cmd={0}, udLen/bodyLen={1}/{2}, wholeHexs: {3}\n", cmd, udLen, bodyLen, wholeHexs);
- string bodyHexs = YASIO_NI.DumpHex(bytes + PROTO_HEADER_SIZE, bodyLen);
- UnityEngine.Debug.LogFormat("cmd={0}, bodyHexs: {1}\n", cmd, bodyHexs);
+ UnityEngine.Debug.LogFormat("cmd={0}, udLen/bodyLen={1}/{2}, msg: {3}\n", cmd, udLen, bodyLen, YASIO_NI.DumpHex(bytes, len));
+ UnityEngine.Debug.LogFormat("cmd={0}, payload: {1}\n", cmd, YASIO_NI.DumpHex(bytes + PROTO_HEADER_SIZE, bodyLen));
}
#endif
- NativeDataView ud = new NativeDataView { ptr = bytes + PROTO_HEADER_SIZE, len = len - PROTO_HEADER_SIZE };
+ msg = new Span((bytes + PROTO_HEADER_SIZE).ToPointer(), len - PROTO_HEADER_SIZE);
- return (cmd, ud, dataStream);
+ return (cmd, dataStream);
}
else
{
@@ -98,7 +114,8 @@ unsafe public (int, NativeDataView, Stream) DecodePDU(IntPtr bytes, int len)
dataStream?.Dispose();
}
- return (-1, NativeDataView.NullValue, null);
+ msg = Span.Empty;
+ return (-1, null);
}
///
@@ -108,7 +125,7 @@ unsafe public (int, NativeDataView, Stream) DecodePDU(IntPtr bytes, int len)
///
///
///
- public void HandleEvent(NetworkEvent ev, int cmd, NativeDataView ud, int channel)
+ public void HandleEvent(NetworkEvent ev, int cmd, Span ud, int channel)
{
UnityEngine.Debug.LogFormat("SampleNetworkPacketHandler.HandleEvent, event={0}, cmd={1}, channel={2}", ev, cmd, channel);
if(cmd == AppProtocol.CMD_LOGIN_REQ)
@@ -121,9 +138,8 @@ public void HandleEvent(NetworkEvent ev, int cmd, NativeDataView ud, int channel
var reply = new AppProtocol.LoginResp();
reply.uid = msg.uid;
reply.status = 200; // 200 表示success
- (NativeDataView udReply, Stream hold) = reply.encode();
+ Span udReply = reply.encode();
NetworkServiceManager.Instance.SendSerializedMsg(AppProtocol.CMD_LOGIN_RESP, udReply, AppProtocol.SERVER_CHANNEL);
- hold.Dispose();
}
else if(cmd == AppProtocol.CMD_LOGIN_RESP)
{ // SampelScene应该是 channel:0 收到
diff --git a/Assets/Scripts/SampleScene.cs b/Assets/Scripts/SampleScene.cs
index 7328dcc..c949093 100644
--- a/Assets/Scripts/SampleScene.cs
+++ b/Assets/Scripts/SampleScene.cs
@@ -1,14 +1,30 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
using UnityEngine;
using NSM2;
using System;
@@ -56,11 +72,11 @@ unsafe public void OnConnectSuccess(int channel = 0)
// 模拟登录协议
var loginReq = new AppProtocol.LoginReq();
loginReq.uid = 1219;
- (var ud, var ms) = loginReq.encode();
+ Span ud = loginReq.encode();
nsm.SendSerializedMsg(AppProtocol.CMD_LOGIN_REQ, ud, AppProtocol.CLIENT_CHANNEL);
- ms.Dispose();
+ loginReq.Dispose();
}
else if(channel == AppProtocol.SERVER_CHANNEL)
{
diff --git a/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef b/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef
deleted file mode 100644
index 5c4f5f5..0000000
--- a/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "ByteDance.NAPI",
- "references": [],
- "includePlatforms": [],
- "excludePlatforms": [],
- "allowUnsafeCode": true,
- "overrideReferences": false,
- "precompiledReferences": [],
- "autoReferenced": true,
- "defineConstraints": [],
- "versionDefines": [],
- "noEngineReferences": true
-}
\ No newline at end of file
diff --git a/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef.meta b/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef.meta
deleted file mode 100644
index 7aae9e9..0000000
--- a/LocalPackages/com.bytedance.napi/ByteDance.NAPI.asmdef.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 5d7149410a8a1a34097bd36a18dbf316
-AssemblyDefinitionImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LocalPackages/com.bytedance.napi/NativeDataTypes.cs b/LocalPackages/com.bytedance.napi/NativeDataTypes.cs
deleted file mode 100644
index d645fdc..0000000
--- a/LocalPackages/com.bytedance.napi/NativeDataTypes.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright (c) Bytedance Inc 2021. All right reserved.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-using System;
-
-namespace ByteDance.NAPI
-{
- ///
- /// Could use as Natvie CStr or byte array
- ///
- public struct NativeDataView
- {
- public IntPtr ptr;
- public int len;
-
- public NativeDataView(IntPtr p, int l)
- {
- ptr = p;
- len = l;
- }
-
- public void Set(IntPtr p, int l)
- {
- ptr = p;
- len = l;
- }
-
- public bool IsNull()
- {
- return ptr == IntPtr.Zero;
- }
-
- public void SetNull()
- {
- ptr = IntPtr.Zero;
- len = 0;
- }
-
- public bool IsEmpty()
- {
- return ptr == IntPtr.Zero || len == 0;
- }
-
- public static readonly NativeDataView NullValue = new NativeDataView(IntPtr.Zero, 0);
- }
-
- ///
- /// Could use as any natvie UDT* view, not char*
- /// Such as Lua TString*
- ///
- public struct NativeUDTView
- {
- public NativeUDTView(IntPtr p)
- {
- ptr = p;
- }
-
- public bool IsNull()
- {
- return ptr == IntPtr.Zero;
- }
-
- public void Set(IntPtr p)
- {
- ptr = p;
- }
-
- public IntPtr ptr; // the lua vm TString*
-
- public static readonly NativeUDTView NullValue = new NativeUDTView(IntPtr.Zero);
- }
-}
diff --git a/LocalPackages/com.bytedance.napi/NativeDataTypes.cs.meta b/LocalPackages/com.bytedance.napi/NativeDataTypes.cs.meta
deleted file mode 100644
index 23d885a..0000000
--- a/LocalPackages/com.bytedance.napi/NativeDataTypes.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 8501494195697ce4e85aae685c4b05dc
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LocalPackages/com.bytedance.napi/README.md b/LocalPackages/com.bytedance.napi/README.md
deleted file mode 100644
index 6741e21..0000000
--- a/LocalPackages/com.bytedance.napi/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# ByteDance.NAPI
-
-方便和Native数据指针交互的通用数据结构
\ No newline at end of file
diff --git a/LocalPackages/com.bytedance.napi/README.md.meta b/LocalPackages/com.bytedance.napi/README.md.meta
deleted file mode 100644
index c7d5a42..0000000
--- a/LocalPackages/com.bytedance.napi/README.md.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 5695b22997f20b5499ba6bfcd9dfe3e5
-TextScriptImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LocalPackages/com.bytedance.napi/package.json b/LocalPackages/com.bytedance.napi/package.json
deleted file mode 100644
index 2187672..0000000
--- a/LocalPackages/com.bytedance.napi/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "com.bytedance.napi",
- "displayName": "ByteDance NAPI",
- "version": "1.0.0",
- "unity": "2019.2",
- "keywords": ["ByteDance", "NAPI"],
- "description": "ByteDance Native API for interop.",
- "dependencies": {
- }
-}
\ No newline at end of file
diff --git a/LocalPackages/com.bytedance.napi/package.json.meta b/LocalPackages/com.bytedance.napi/package.json.meta
deleted file mode 100644
index 109d96c..0000000
--- a/LocalPackages/com.bytedance.napi/package.json.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 4952efaa7b7e1e3478648467e1ea647c
-PackageManifestImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/NativeLibs/yasio/1k/fetch.cmake b/NativeLibs/yasio/1k/fetch.cmake
new file mode 100644
index 0000000..391bb53
--- /dev/null
+++ b/NativeLibs/yasio/1k/fetch.cmake
@@ -0,0 +1,76 @@
+#
+# the 1k fetch functions
+# require predefine variable:
+# _1kfetch_cache_dir
+# _1kfetch_manifest
+#
+
+### 1kdist url
+find_program(PWSH_COMMAND NAMES pwsh powershell NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH)
+
+function(_1kfetch_init)
+ execute_process(COMMAND ${PWSH_COMMAND} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/fetchurl.ps1
+ -name "1kdist"
+ -cfg ${_1kfetch_manifest}
+ OUTPUT_VARIABLE _1kdist_url
+ )
+ string(REPLACE "#" ";" _1kdist_url ${_1kdist_url})
+ list(GET _1kdist_url 0 _1kdist_base_url)
+ list(GET _1kdist_url 1 _1kdist_ver)
+ set(_1kdist_base_url "${_1kdist_base_url}/v${_1kdist_ver}" PARENT_SCOPE)
+ set(_1kdist_ver ${_1kdist_ver} PARENT_SCOPE)
+endfunction()
+
+# fetch prebuilt from 1kdist
+# param package_name
+function(_1kfetch_dist package_name)
+ set(_prebuilt_root ${CMAKE_CURRENT_LIST_DIR}/_d)
+ if(NOT IS_DIRECTORY ${_prebuilt_root})
+ set (package_store "${_1kfetch_cache_dir}/1kdist/v${_1kdist_ver}/${package_name}.zip")
+ if (NOT EXISTS ${package_store})
+ set (package_url "${_1kdist_base_url}/${package_name}.zip")
+ message(AUTHOR_WARNING "Downloading ${package_url}")
+ file(DOWNLOAD ${package_url} ${package_store} STATUS _status LOG _logs SHOW_PROGRESS)
+ list(GET _status 0 status_code)
+ list(GET _status 1 status_string)
+ if(NOT status_code EQUAL 0)
+ message(FATAL_ERROR "Download ${package_url} fail, ${status_string}, logs: ${_logs}")
+ endif()
+ endif()
+ file(ARCHIVE_EXTRACT INPUT ${package_store} DESTINATION ${CMAKE_CURRENT_LIST_DIR}/)
+ file(RENAME ${CMAKE_CURRENT_LIST_DIR}/${package_name} ${_prebuilt_root})
+ endif()
+
+ # set platform specific path, PLATFORM_NAME provided by user: win32,winrt,mac,ios,android,tvos,watchos,linux
+ set(_prebuilt_lib_dir "${_prebuilt_root}/lib/${PLATFORM_NAME}")
+ if(ANDROID OR WIN32)
+ set(_prebuilt_lib_dir "${_prebuilt_lib_dir}/${ARCH_ALIAS}")
+ endif()
+ set(${package_name}_INC_DIR ${_prebuilt_root}/include PARENT_SCOPE)
+ set(${package_name}_LIB_DIR ${_prebuilt_lib_dir} PARENT_SCOPE)
+endfunction()
+
+# params: name, url
+function(_1kfetch name)
+ set(_pkg_store "${_1kfetch_cache_dir}/${name}")
+ execute_process(COMMAND ${PWSH_COMMAND} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/fetch.ps1
+ -name "${name}"
+ -dest "${_pkg_store}"
+ -cfg ${_1kfetch_manifest}
+ RESULT_VARIABLE _errorcode
+ )
+ if (_errorcode)
+ message(FATAL_ERROR "aborted")
+ endif()
+ set(${name}_SOURCE_DIR ${_pkg_store} PARENT_SCOPE)
+endfunction()
+
+function(_1klink src dest)
+ file(TO_NATIVE_PATH "${src}" _srcDir)
+ file(TO_NATIVE_PATH "${dest}" _dstDir)
+ execute_process(COMMAND ${PWSH_COMMAND} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/fsync.ps1 -s "${_srcDir}" -d "${_dstDir}" -l 1)
+endfunction()
+
+if(PWSH_COMMAND)
+ _1kfetch_init()
+endif()
diff --git a/NativeLibs/yasio/1k/fetchurl.ps1 b/NativeLibs/yasio/1k/fetchurl.ps1
new file mode 100644
index 0000000..4a3d857
--- /dev/null
+++ b/NativeLibs/yasio/1k/fetchurl.ps1
@@ -0,0 +1,13 @@
+param(
+ $name,
+ $cfg
+)
+
+$mirror = if (!(Test-Path (Join-Path $PSScriptRoot '.gitee') -PathType Leaf)) {'github'} else {'gitee'}
+$url_base = @{'github' = 'https://github.com/'; 'gitee' = 'https://gitee.com/' }[$mirror]
+
+$manifest_map = ConvertFrom-Json (Get-Content $cfg -raw)
+$ver = $manifest_map.versions.PSObject.Properties[$name].Value
+$url_path = $manifest_map.mirrors.PSObject.Properties[$mirror].Value.PSObject.Properties[$name].Value
+
+Write-Host "$url_base$url_path#$ver" -NoNewline
\ No newline at end of file
diff --git a/NativeLibs/yasio/1k/platform.cmake b/NativeLibs/yasio/1k/platform.cmake
new file mode 100644
index 0000000..b51f824
--- /dev/null
+++ b/NativeLibs/yasio/1k/platform.cmake
@@ -0,0 +1,76 @@
+#Please use them everywhere
+#WINDOWS = Windows Desktop
+#ANDROID = Android
+#IOS = iOS
+#MACOSX = MacOS X
+#LINUX = Linux
+
+#############################
+# cmake commands:
+# win32: cmake -B build -A x64
+# winrt: cmake -B build -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0"
+#
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(WINDOWS TRUE)
+ if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
+ set(WIN32 TRUE)
+ set(ARCH_ALIAS "x86")
+ elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "arm64")
+ set(WIN64 TRUE)
+ set(ARCH_ALIAS "arm64")
+ else()
+ set(WIN64 TRUE)
+ set(ARCH_ALIAS "x64")
+ endif()
+ set(PLATFORM_NAME win32)
+ if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
+ set(WINRT TRUE CACHE BOOL "" FORCE)
+ set(PLATFORM_NAME winrt)
+ endif()
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
+ set(PLATFORM_NAME android)
+ set(ARCH_ALIAS ${ANDROID_ABI})
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(LINUX TRUE)
+ set(PLATFORM_NAME linux)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
+ set(WASM TRUE)
+ set(EMSCRIPTEN TRUE)
+ set(PLATFORM_NAME wasm)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(APPLE TRUE)
+ set(MACOSX TRUE)
+ set(PLATFORM_NAME mac)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "iOS")
+ set(APPLE TRUE)
+ set(IOS TRUE)
+ set(PLATFORM_NAME ios)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "tvOS")
+ set(APPLE TRUE)
+ set(IOS TRUE)
+ set(TVOS TRUE)
+ set(PLATFORM_NAME tvos)
+else()
+ message(AUTHOR_WARNING "Unsupported platform to use prebuilt libs")
+ return()
+endif()
+
+if (NOT DEFINED WIN32)
+ set(WIN32 FALSE)
+endif()
+
+# generators that are capable of organizing into a hierarchy of folders
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+# simplify generator condition, please use them everywhere
+if(CMAKE_GENERATOR STREQUAL Xcode)
+ set(XCODE TRUE)
+elseif(CMAKE_GENERATOR MATCHES Visual)
+ set(VS TRUE)
+endif()
+
+function(_1k_deprecated_32bit project_name release_ver)
+ if(("${ARCH_ALIAS}" STREQUAL "x86") OR ("${ARCH_ALIAS}" MATCHES "armeabi-v7a"))
+ message(WARNING "Building 32-bit[${ARCH_ALIAS}] ${project_name} is deprecated, and will be removed in next release ${release_ver}")
+ endif()
+endfunction()
diff --git a/NativeLibs/yasio/kcp/ikcp.c b/NativeLibs/yasio/3rdparty/kcp/ikcp.c
similarity index 96%
rename from NativeLibs/yasio/kcp/ikcp.c
rename to NativeLibs/yasio/3rdparty/kcp/ikcp.c
index 8070a78..6e14bc9 100644
--- a/NativeLibs/yasio/kcp/ikcp.c
+++ b/NativeLibs/yasio/3rdparty/kcp/ikcp.c
@@ -1,1306 +1,1306 @@
-//=====================================================================
-//
-// KCP - A Better ARQ Protocol Implementation
-// skywind3000 (at) gmail.com, 2010-2011
-//
-// Features:
-// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
-// + Maximum RTT reduce three times vs tcp.
-// + Lightweight, distributed as a single source file.
-//
-//=====================================================================
-#include "ikcp.h"
-
-#include
-#include
-#include
-#include
-#include
-
-
-
-//=====================================================================
-// KCP BASIC
-//=====================================================================
-const IUINT32 IKCP_RTO_NDL = 30; // no delay min rto
-const IUINT32 IKCP_RTO_MIN = 100; // normal min rto
-const IUINT32 IKCP_RTO_DEF = 200;
-const IUINT32 IKCP_RTO_MAX = 60000;
-const IUINT32 IKCP_CMD_PUSH = 81; // cmd: push data
-const IUINT32 IKCP_CMD_ACK = 82; // cmd: ack
-const IUINT32 IKCP_CMD_WASK = 83; // cmd: window probe (ask)
-const IUINT32 IKCP_CMD_WINS = 84; // cmd: window size (tell)
-const IUINT32 IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK
-const IUINT32 IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS
-const IUINT32 IKCP_WND_SND = 32;
-const IUINT32 IKCP_WND_RCV = 128; // must >= max fragment size
-const IUINT32 IKCP_MTU_DEF = 1400;
-const IUINT32 IKCP_ACK_FAST = 3;
-const IUINT32 IKCP_INTERVAL = 100;
-const IUINT32 IKCP_OVERHEAD = 24;
-const IUINT32 IKCP_DEADLINK = 20;
-const IUINT32 IKCP_THRESH_INIT = 2;
-const IUINT32 IKCP_THRESH_MIN = 2;
-const IUINT32 IKCP_PROBE_INIT = 7000; // 7 secs to probe window size
-const IUINT32 IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window
-const IUINT32 IKCP_FASTACK_LIMIT = 5; // max times to trigger fastack
-
-
-//---------------------------------------------------------------------
-// encode / decode
-//---------------------------------------------------------------------
-
-/* encode 8 bits unsigned int */
-static inline char *ikcp_encode8u(char *p, unsigned char c)
-{
- *(unsigned char*)p++ = c;
- return p;
-}
-
-/* decode 8 bits unsigned int */
-static inline const char *ikcp_decode8u(const char *p, unsigned char *c)
-{
- *c = *(unsigned char*)p++;
- return p;
-}
-
-/* encode 16 bits unsigned int (lsb) */
-static inline char *ikcp_encode16u(char *p, unsigned short w)
-{
-#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
- *(unsigned char*)(p + 0) = (w & 255);
- *(unsigned char*)(p + 1) = (w >> 8);
-#else
- memcpy(p, &w, 2);
-#endif
- p += 2;
- return p;
-}
-
-/* decode 16 bits unsigned int (lsb) */
-static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
-{
-#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
- *w = *(const unsigned char*)(p + 1);
- *w = *(const unsigned char*)(p + 0) + (*w << 8);
-#else
- memcpy(w, p, 2);
-#endif
- p += 2;
- return p;
-}
-
-/* encode 32 bits unsigned int (lsb) */
-static inline char *ikcp_encode32u(char *p, IUINT32 l)
-{
-#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
- *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff);
- *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff);
- *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff);
- *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff);
-#else
- memcpy(p, &l, 4);
-#endif
- p += 4;
- return p;
-}
-
-/* decode 32 bits unsigned int (lsb) */
-static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
-{
-#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
- *l = *(const unsigned char*)(p + 3);
- *l = *(const unsigned char*)(p + 2) + (*l << 8);
- *l = *(const unsigned char*)(p + 1) + (*l << 8);
- *l = *(const unsigned char*)(p + 0) + (*l << 8);
-#else
- memcpy(l, p, 4);
-#endif
- p += 4;
- return p;
-}
-
-static inline IUINT32 _imin_(IUINT32 a, IUINT32 b) {
- return a <= b ? a : b;
-}
-
-static inline IUINT32 _imax_(IUINT32 a, IUINT32 b) {
- return a >= b ? a : b;
-}
-
-static inline IUINT32 _ibound_(IUINT32 lower, IUINT32 middle, IUINT32 upper)
-{
- return _imin_(_imax_(lower, middle), upper);
-}
-
-static inline long _itimediff(IUINT32 later, IUINT32 earlier)
-{
- return ((IINT32)(later - earlier));
-}
-
-//---------------------------------------------------------------------
-// manage segment
-//---------------------------------------------------------------------
-typedef struct IKCPSEG IKCPSEG;
-
-static void* (*ikcp_malloc_hook)(size_t) = NULL;
-static void (*ikcp_free_hook)(void *) = NULL;
-
-// internal malloc
-static void* ikcp_malloc(size_t size) {
- if (ikcp_malloc_hook)
- return ikcp_malloc_hook(size);
- return malloc(size);
-}
-
-// internal free
-static void ikcp_free(void *ptr) {
- if (ikcp_free_hook) {
- ikcp_free_hook(ptr);
- } else {
- free(ptr);
- }
-}
-
-// redefine allocator
-void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*))
-{
- ikcp_malloc_hook = new_malloc;
- ikcp_free_hook = new_free;
-}
-
-// allocate a new kcp segment
-static IKCPSEG* ikcp_segment_new(ikcpcb *kcp, int size)
-{
- return (IKCPSEG*)ikcp_malloc(sizeof(IKCPSEG) + size);
-}
-
-// delete a segment
-static void ikcp_segment_delete(ikcpcb *kcp, IKCPSEG *seg)
-{
- ikcp_free(seg);
-}
-
-// write log
-void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...)
-{
- char buffer[1024];
- va_list argptr;
- if ((mask & kcp->logmask) == 0 || kcp->writelog == 0) return;
- va_start(argptr, fmt);
- vsprintf(buffer, fmt, argptr);
- va_end(argptr);
- kcp->writelog(buffer, kcp, kcp->user);
-}
-
-// check log mask
-static int ikcp_canlog(const ikcpcb *kcp, int mask)
-{
- if ((mask & kcp->logmask) == 0 || kcp->writelog == NULL) return 0;
- return 1;
-}
-
-// output segment
-static int ikcp_output(ikcpcb *kcp, const void *data, int size)
-{
- assert(kcp);
- assert(kcp->output);
- if (ikcp_canlog(kcp, IKCP_LOG_OUTPUT)) {
- ikcp_log(kcp, IKCP_LOG_OUTPUT, "[RO] %ld bytes", (long)size);
- }
- if (size == 0) return 0;
- return kcp->output((const char*)data, size, kcp, kcp->user);
-}
-
-// output queue
-void ikcp_qprint(const char *name, const struct IQUEUEHEAD *head)
-{
-#if 0
- const struct IQUEUEHEAD *p;
- printf("<%s>: [", name);
- for (p = head->next; p != head; p = p->next) {
- const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node);
- printf("(%lu %d)", (unsigned long)seg->sn, (int)(seg->ts % 10000));
- if (p->next != head) printf(",");
- }
- printf("]\n");
-#endif
-}
-
-
-//---------------------------------------------------------------------
-// create a new kcpcb
-//---------------------------------------------------------------------
-ikcpcb* ikcp_create(IUINT32 conv, void *user)
-{
- ikcpcb *kcp = (ikcpcb*)ikcp_malloc(sizeof(struct IKCPCB));
- if (kcp == NULL) return NULL;
- kcp->conv = conv;
- kcp->user = user;
- kcp->snd_una = 0;
- kcp->snd_nxt = 0;
- kcp->rcv_nxt = 0;
- kcp->ts_recent = 0;
- kcp->ts_lastack = 0;
- kcp->ts_probe = 0;
- kcp->probe_wait = 0;
- kcp->snd_wnd = IKCP_WND_SND;
- kcp->rcv_wnd = IKCP_WND_RCV;
- kcp->rmt_wnd = IKCP_WND_RCV;
- kcp->cwnd = 0;
- kcp->incr = 0;
- kcp->probe = 0;
- kcp->mtu = IKCP_MTU_DEF;
- kcp->mss = kcp->mtu - IKCP_OVERHEAD;
- kcp->stream = 0;
-
- kcp->buffer = (char*)ikcp_malloc((kcp->mtu + IKCP_OVERHEAD) * 3);
- if (kcp->buffer == NULL) {
- ikcp_free(kcp);
- return NULL;
- }
-
- iqueue_init(&kcp->snd_queue);
- iqueue_init(&kcp->rcv_queue);
- iqueue_init(&kcp->snd_buf);
- iqueue_init(&kcp->rcv_buf);
- kcp->nrcv_buf = 0;
- kcp->nsnd_buf = 0;
- kcp->nrcv_que = 0;
- kcp->nsnd_que = 0;
- kcp->state = 0;
- kcp->acklist = NULL;
- kcp->ackblock = 0;
- kcp->ackcount = 0;
- kcp->rx_srtt = 0;
- kcp->rx_rttval = 0;
- kcp->rx_rto = IKCP_RTO_DEF;
- kcp->rx_minrto = IKCP_RTO_MIN;
- kcp->current = 0;
- kcp->interval = IKCP_INTERVAL;
- kcp->ts_flush = IKCP_INTERVAL;
- kcp->nodelay = 0;
- kcp->updated = 0;
- kcp->logmask = 0;
- kcp->ssthresh = IKCP_THRESH_INIT;
- kcp->fastresend = 0;
- kcp->fastlimit = IKCP_FASTACK_LIMIT;
- kcp->nocwnd = 0;
- kcp->xmit = 0;
- kcp->dead_link = IKCP_DEADLINK;
- kcp->output = NULL;
- kcp->writelog = NULL;
-
- return kcp;
-}
-
-
-//---------------------------------------------------------------------
-// release a new kcpcb
-//---------------------------------------------------------------------
-void ikcp_release(ikcpcb *kcp)
-{
- assert(kcp);
- if (kcp) {
- IKCPSEG *seg;
- while (!iqueue_is_empty(&kcp->snd_buf)) {
- seg = iqueue_entry(kcp->snd_buf.next, IKCPSEG, node);
- iqueue_del(&seg->node);
- ikcp_segment_delete(kcp, seg);
- }
- while (!iqueue_is_empty(&kcp->rcv_buf)) {
- seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
- iqueue_del(&seg->node);
- ikcp_segment_delete(kcp, seg);
- }
- while (!iqueue_is_empty(&kcp->snd_queue)) {
- seg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);
- iqueue_del(&seg->node);
- ikcp_segment_delete(kcp, seg);
- }
- while (!iqueue_is_empty(&kcp->rcv_queue)) {
- seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node);
- iqueue_del(&seg->node);
- ikcp_segment_delete(kcp, seg);
- }
- if (kcp->buffer) {
- ikcp_free(kcp->buffer);
- }
- if (kcp->acklist) {
- ikcp_free(kcp->acklist);
- }
-
- kcp->nrcv_buf = 0;
- kcp->nsnd_buf = 0;
- kcp->nrcv_que = 0;
- kcp->nsnd_que = 0;
- kcp->ackcount = 0;
- kcp->buffer = NULL;
- kcp->acklist = NULL;
- ikcp_free(kcp);
- }
-}
-
-
-//---------------------------------------------------------------------
-// set output callback, which will be invoked by kcp
-//---------------------------------------------------------------------
-void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
- ikcpcb *kcp, void *user))
-{
- kcp->output = output;
-}
-
-
-//---------------------------------------------------------------------
-// user/upper level recv: returns size, returns below zero for EAGAIN
-//---------------------------------------------------------------------
-int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
-{
- struct IQUEUEHEAD *p;
- int ispeek = (len < 0)? 1 : 0;
- int peeksize;
- int recover = 0;
- IKCPSEG *seg;
- assert(kcp);
-
- if (iqueue_is_empty(&kcp->rcv_queue))
- return -1;
-
- if (len < 0) len = -len;
-
- peeksize = ikcp_peeksize(kcp);
-
- if (peeksize < 0)
- return -2;
-
- if (peeksize > len)
- return -3;
-
- if (kcp->nrcv_que >= kcp->rcv_wnd)
- recover = 1;
-
- // merge fragment
- for (len = 0, p = kcp->rcv_queue.next; p != &kcp->rcv_queue; ) {
- int fragment;
- seg = iqueue_entry(p, IKCPSEG, node);
- p = p->next;
-
- if (buffer) {
- memcpy(buffer, seg->data, seg->len);
- buffer += seg->len;
- }
-
- len += seg->len;
- fragment = seg->frg;
-
- if (ikcp_canlog(kcp, IKCP_LOG_RECV)) {
- ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", (unsigned long)seg->sn);
- }
-
- if (ispeek == 0) {
- iqueue_del(&seg->node);
- ikcp_segment_delete(kcp, seg);
- kcp->nrcv_que--;
- }
-
- if (fragment == 0)
- break;
- }
-
- assert(len == peeksize);
-
- // move available data from rcv_buf -> rcv_queue
- while (! iqueue_is_empty(&kcp->rcv_buf)) {
- seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
- if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
- iqueue_del(&seg->node);
- kcp->nrcv_buf--;
- iqueue_add_tail(&seg->node, &kcp->rcv_queue);
- kcp->nrcv_que++;
- kcp->rcv_nxt++;
- } else {
- break;
- }
- }
-
- // fast recover
- if (kcp->nrcv_que < kcp->rcv_wnd && recover) {
- // ready to send back IKCP_CMD_WINS in ikcp_flush
- // tell remote my window size
- kcp->probe |= IKCP_ASK_TELL;
- }
-
- return len;
-}
-
-
-//---------------------------------------------------------------------
-// peek data size
-//---------------------------------------------------------------------
-int ikcp_peeksize(const ikcpcb *kcp)
-{
- struct IQUEUEHEAD *p;
- IKCPSEG *seg;
- int length = 0;
-
- assert(kcp);
-
- if (iqueue_is_empty(&kcp->rcv_queue)) return -1;
-
- seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node);
- if (seg->frg == 0) return seg->len;
-
- if (kcp->nrcv_que < seg->frg + 1) return -1;
-
- for (p = kcp->rcv_queue.next; p != &kcp->rcv_queue; p = p->next) {
- seg = iqueue_entry(p, IKCPSEG, node);
- length += seg->len;
- if (seg->frg == 0) break;
- }
-
- return length;
-}
-
-
-//---------------------------------------------------------------------
-// user/upper level send, returns below zero for error
-//---------------------------------------------------------------------
-int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
-{
- IKCPSEG *seg;
- int count, i;
- int sent = 0;
-
- assert(kcp->mss > 0);
- if (len < 0) return -1;
-
- // append to previous segment in streaming mode (if possible)
- if (kcp->stream != 0) {
- if (!iqueue_is_empty(&kcp->snd_queue)) {
- IKCPSEG *old = iqueue_entry(kcp->snd_queue.prev, IKCPSEG, node);
- if (old->len < kcp->mss) {
- int capacity = kcp->mss - old->len;
- int extend = (len < capacity)? len : capacity;
- seg = ikcp_segment_new(kcp, old->len + extend);
- assert(seg);
- if (seg == NULL) {
- return -2;
- }
- iqueue_add_tail(&seg->node, &kcp->snd_queue);
- memcpy(seg->data, old->data, old->len);
- if (buffer) {
- memcpy(seg->data + old->len, buffer, extend);
- buffer += extend;
- }
- seg->len = old->len + extend;
- seg->frg = 0;
- len -= extend;
- iqueue_del_init(&old->node);
- ikcp_segment_delete(kcp, old);
- sent = extend;
- }
- }
- if (len <= 0) {
- return sent;
- }
- }
-
- if (len <= (int)kcp->mss) count = 1;
- else count = (len + kcp->mss - 1) / kcp->mss;
-
- if (count >= (int)IKCP_WND_RCV) {
- if (kcp->stream != 0 && sent > 0)
- return sent;
- return -2;
- }
-
- if (count == 0) count = 1;
-
- // fragment
- for (i = 0; i < count; i++) {
- int size = len > (int)kcp->mss ? (int)kcp->mss : len;
- seg = ikcp_segment_new(kcp, size);
- assert(seg);
- if (seg == NULL) {
- return -2;
- }
- if (buffer && len > 0) {
- memcpy(seg->data, buffer, size);
- }
- seg->len = size;
- seg->frg = (kcp->stream == 0)? (count - i - 1) : 0;
- iqueue_init(&seg->node);
- iqueue_add_tail(&seg->node, &kcp->snd_queue);
- kcp->nsnd_que++;
- if (buffer) {
- buffer += size;
- }
- len -= size;
- sent += size;
- }
-
- return sent;
-}
-
-
-//---------------------------------------------------------------------
-// parse ack
-//---------------------------------------------------------------------
-static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt)
-{
- IINT32 rto = 0;
- if (kcp->rx_srtt == 0) {
- kcp->rx_srtt = rtt;
- kcp->rx_rttval = rtt / 2;
- } else {
- long delta = rtt - kcp->rx_srtt;
- if (delta < 0) delta = -delta;
- kcp->rx_rttval = (3 * kcp->rx_rttval + delta) / 4;
- kcp->rx_srtt = (7 * kcp->rx_srtt + rtt) / 8;
- if (kcp->rx_srtt < 1) kcp->rx_srtt = 1;
- }
- rto = kcp->rx_srtt + _imax_(kcp->interval, 4 * kcp->rx_rttval);
- kcp->rx_rto = _ibound_(kcp->rx_minrto, rto, IKCP_RTO_MAX);
-}
-
-static void ikcp_shrink_buf(ikcpcb *kcp)
-{
- struct IQUEUEHEAD *p = kcp->snd_buf.next;
- if (p != &kcp->snd_buf) {
- IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
- kcp->snd_una = seg->sn;
- } else {
- kcp->snd_una = kcp->snd_nxt;
- }
-}
-
-static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn)
-{
- struct IQUEUEHEAD *p, *next;
-
- if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0)
- return;
-
- for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
- IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
- next = p->next;
- if (sn == seg->sn) {
- iqueue_del(p);
- ikcp_segment_delete(kcp, seg);
- kcp->nsnd_buf--;
- break;
- }
- if (_itimediff(sn, seg->sn) < 0) {
- break;
- }
- }
-}
-
-static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
-{
- struct IQUEUEHEAD *p, *next;
- for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
- IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
- next = p->next;
- if (_itimediff(una, seg->sn) > 0) {
- iqueue_del(p);
- ikcp_segment_delete(kcp, seg);
- kcp->nsnd_buf--;
- } else {
- break;
- }
- }
-}
-
-static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
-{
- struct IQUEUEHEAD *p, *next;
-
- if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0)
- return;
-
- for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
- IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
- next = p->next;
- if (_itimediff(sn, seg->sn) < 0) {
- break;
- }
- else if (sn != seg->sn) {
- #ifndef IKCP_FASTACK_CONSERVE
- seg->fastack++;
- #else
- if (_itimediff(ts, seg->ts) >= 0)
- seg->fastack++;
- #endif
- }
- }
-}
-
-
-//---------------------------------------------------------------------
-// ack append
-//---------------------------------------------------------------------
-static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
-{
- IUINT32 newsize = kcp->ackcount + 1;
- IUINT32 *ptr;
-
- if (newsize > kcp->ackblock) {
- IUINT32 *acklist;
- IUINT32 newblock;
-
- for (newblock = 8; newblock < newsize; newblock <<= 1);
- acklist = (IUINT32*)ikcp_malloc(newblock * sizeof(IUINT32) * 2);
-
- if (acklist == NULL) {
- assert(acklist != NULL);
- abort();
- }
-
- if (kcp->acklist != NULL) {
- IUINT32 x;
- for (x = 0; x < kcp->ackcount; x++) {
- acklist[x * 2 + 0] = kcp->acklist[x * 2 + 0];
- acklist[x * 2 + 1] = kcp->acklist[x * 2 + 1];
- }
- ikcp_free(kcp->acklist);
- }
-
- kcp->acklist = acklist;
- kcp->ackblock = newblock;
- }
-
- ptr = &kcp->acklist[kcp->ackcount * 2];
- ptr[0] = sn;
- ptr[1] = ts;
- kcp->ackcount++;
-}
-
-static void ikcp_ack_get(const ikcpcb *kcp, int p, IUINT32 *sn, IUINT32 *ts)
-{
- if (sn) sn[0] = kcp->acklist[p * 2 + 0];
- if (ts) ts[0] = kcp->acklist[p * 2 + 1];
-}
-
-
-//---------------------------------------------------------------------
-// parse data
-//---------------------------------------------------------------------
-void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg)
-{
- struct IQUEUEHEAD *p, *prev;
- IUINT32 sn = newseg->sn;
- int repeat = 0;
-
- if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) >= 0 ||
- _itimediff(sn, kcp->rcv_nxt) < 0) {
- ikcp_segment_delete(kcp, newseg);
- return;
- }
-
- for (p = kcp->rcv_buf.prev; p != &kcp->rcv_buf; p = prev) {
- IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
- prev = p->prev;
- if (seg->sn == sn) {
- repeat = 1;
- break;
- }
- if (_itimediff(sn, seg->sn) > 0) {
- break;
- }
- }
-
- if (repeat == 0) {
- iqueue_init(&newseg->node);
- iqueue_add(&newseg->node, p);
- kcp->nrcv_buf++;
- } else {
- ikcp_segment_delete(kcp, newseg);
- }
-
-#if 0
- ikcp_qprint("rcvbuf", &kcp->rcv_buf);
- printf("rcv_nxt=%lu\n", kcp->rcv_nxt);
-#endif
-
- // move available data from rcv_buf -> rcv_queue
- while (! iqueue_is_empty(&kcp->rcv_buf)) {
- IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
- if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
- iqueue_del(&seg->node);
- kcp->nrcv_buf--;
- iqueue_add_tail(&seg->node, &kcp->rcv_queue);
- kcp->nrcv_que++;
- kcp->rcv_nxt++;
- } else {
- break;
- }
- }
-
-#if 0
- ikcp_qprint("queue", &kcp->rcv_queue);
- printf("rcv_nxt=%lu\n", kcp->rcv_nxt);
-#endif
-
-#if 1
-// printf("snd(buf=%d, queue=%d)\n", kcp->nsnd_buf, kcp->nsnd_que);
-// printf("rcv(buf=%d, queue=%d)\n", kcp->nrcv_buf, kcp->nrcv_que);
-#endif
-}
-
-
-//---------------------------------------------------------------------
-// input data
-//---------------------------------------------------------------------
-int ikcp_input(ikcpcb *kcp, const char *data, long size)
-{
- IUINT32 prev_una = kcp->snd_una;
- IUINT32 maxack = 0, latest_ts = 0;
- int flag = 0;
-
- if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
- ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", (int)size);
- }
-
- if (data == NULL || (int)size < (int)IKCP_OVERHEAD) return -1;
-
- while (1) {
- IUINT32 ts, sn, len, una, conv;
- IUINT16 wnd;
- IUINT8 cmd, frg;
- IKCPSEG *seg;
-
- if (size < (int)IKCP_OVERHEAD) break;
-
- data = ikcp_decode32u(data, &conv);
- if (conv != kcp->conv) return -1;
-
- data = ikcp_decode8u(data, &cmd);
- data = ikcp_decode8u(data, &frg);
- data = ikcp_decode16u(data, &wnd);
- data = ikcp_decode32u(data, &ts);
- data = ikcp_decode32u(data, &sn);
- data = ikcp_decode32u(data, &una);
- data = ikcp_decode32u(data, &len);
-
- size -= IKCP_OVERHEAD;
-
- if ((long)size < (long)len || (int)len < 0) return -2;
-
- if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
- cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS)
- return -3;
-
- kcp->rmt_wnd = wnd;
- ikcp_parse_una(kcp, una);
- ikcp_shrink_buf(kcp);
-
- if (cmd == IKCP_CMD_ACK) {
- if (_itimediff(kcp->current, ts) >= 0) {
- ikcp_update_ack(kcp, _itimediff(kcp->current, ts));
- }
- ikcp_parse_ack(kcp, sn);
- ikcp_shrink_buf(kcp);
- if (flag == 0) {
- flag = 1;
- maxack = sn;
- latest_ts = ts;
- } else {
- if (_itimediff(sn, maxack) > 0) {
- #ifndef IKCP_FASTACK_CONSERVE
- maxack = sn;
- latest_ts = ts;
- #else
- if (_itimediff(ts, latest_ts) > 0) {
- maxack = sn;
- latest_ts = ts;
- }
- #endif
- }
- }
- if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) {
- ikcp_log(kcp, IKCP_LOG_IN_ACK,
- "input ack: sn=%lu rtt=%ld rto=%ld", (unsigned long)sn,
- (long)_itimediff(kcp->current, ts),
- (long)kcp->rx_rto);
- }
- }
- else if (cmd == IKCP_CMD_PUSH) {
- if (ikcp_canlog(kcp, IKCP_LOG_IN_DATA)) {
- ikcp_log(kcp, IKCP_LOG_IN_DATA,
- "input psh: sn=%lu ts=%lu", (unsigned long)sn, (unsigned long)ts);
- }
- if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) < 0) {
- ikcp_ack_push(kcp, sn, ts);
- if (_itimediff(sn, kcp->rcv_nxt) >= 0) {
- seg = ikcp_segment_new(kcp, len);
- seg->conv = conv;
- seg->cmd = cmd;
- seg->frg = frg;
- seg->wnd = wnd;
- seg->ts = ts;
- seg->sn = sn;
- seg->una = una;
- seg->len = len;
-
- if (len > 0) {
- memcpy(seg->data, data, len);
- }
-
- ikcp_parse_data(kcp, seg);
- }
- }
- }
- else if (cmd == IKCP_CMD_WASK) {
- // ready to send back IKCP_CMD_WINS in ikcp_flush
- // tell remote my window size
- kcp->probe |= IKCP_ASK_TELL;
- if (ikcp_canlog(kcp, IKCP_LOG_IN_PROBE)) {
- ikcp_log(kcp, IKCP_LOG_IN_PROBE, "input probe");
- }
- }
- else if (cmd == IKCP_CMD_WINS) {
- // do nothing
- if (ikcp_canlog(kcp, IKCP_LOG_IN_WINS)) {
- ikcp_log(kcp, IKCP_LOG_IN_WINS,
- "input wins: %lu", (unsigned long)(wnd));
- }
- }
- else {
- return -3;
- }
-
- data += len;
- size -= len;
- }
-
- if (flag != 0) {
- ikcp_parse_fastack(kcp, maxack, latest_ts);
- }
-
- if (_itimediff(kcp->snd_una, prev_una) > 0) {
- if (kcp->cwnd < kcp->rmt_wnd) {
- IUINT32 mss = kcp->mss;
- if (kcp->cwnd < kcp->ssthresh) {
- kcp->cwnd++;
- kcp->incr += mss;
- } else {
- if (kcp->incr < mss) kcp->incr = mss;
- kcp->incr += (mss * mss) / kcp->incr + (mss / 16);
- if ((kcp->cwnd + 1) * mss <= kcp->incr) {
- #if 1
- kcp->cwnd = (kcp->incr + mss - 1) / ((mss > 0)? mss : 1);
- #else
- kcp->cwnd++;
- #endif
- }
- }
- if (kcp->cwnd > kcp->rmt_wnd) {
- kcp->cwnd = kcp->rmt_wnd;
- kcp->incr = kcp->rmt_wnd * mss;
- }
- }
- }
-
- return 0;
-}
-
-
-//---------------------------------------------------------------------
-// ikcp_encode_seg
-//---------------------------------------------------------------------
-static char *ikcp_encode_seg(char *ptr, const IKCPSEG *seg)
-{
- ptr = ikcp_encode32u(ptr, seg->conv);
- ptr = ikcp_encode8u(ptr, (IUINT8)seg->cmd);
- ptr = ikcp_encode8u(ptr, (IUINT8)seg->frg);
- ptr = ikcp_encode16u(ptr, (IUINT16)seg->wnd);
- ptr = ikcp_encode32u(ptr, seg->ts);
- ptr = ikcp_encode32u(ptr, seg->sn);
- ptr = ikcp_encode32u(ptr, seg->una);
- ptr = ikcp_encode32u(ptr, seg->len);
- return ptr;
-}
-
-static int ikcp_wnd_unused(const ikcpcb *kcp)
-{
- if (kcp->nrcv_que < kcp->rcv_wnd) {
- return kcp->rcv_wnd - kcp->nrcv_que;
- }
- return 0;
-}
-
-
-//---------------------------------------------------------------------
-// ikcp_flush
-//---------------------------------------------------------------------
-void ikcp_flush(ikcpcb *kcp)
-{
- IUINT32 current = kcp->current;
- char *buffer = kcp->buffer;
- char *ptr = buffer;
- int count, size, i;
- IUINT32 resent, cwnd;
- IUINT32 rtomin;
- struct IQUEUEHEAD *p;
- int change = 0;
- int lost = 0;
- IKCPSEG seg;
-
- // 'ikcp_update' haven't been called.
- if (kcp->updated == 0) return;
-
- seg.conv = kcp->conv;
- seg.cmd = IKCP_CMD_ACK;
- seg.frg = 0;
- seg.wnd = ikcp_wnd_unused(kcp);
- seg.una = kcp->rcv_nxt;
- seg.len = 0;
- seg.sn = 0;
- seg.ts = 0;
-
- // flush acknowledges
- count = kcp->ackcount;
- for (i = 0; i < count; i++) {
- size = (int)(ptr - buffer);
- if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
- ikcp_output(kcp, buffer, size);
- ptr = buffer;
- }
- ikcp_ack_get(kcp, i, &seg.sn, &seg.ts);
- ptr = ikcp_encode_seg(ptr, &seg);
- }
-
- kcp->ackcount = 0;
-
- // probe window size (if remote window size equals zero)
- if (kcp->rmt_wnd == 0) {
- if (kcp->probe_wait == 0) {
- kcp->probe_wait = IKCP_PROBE_INIT;
- kcp->ts_probe = kcp->current + kcp->probe_wait;
- }
- else {
- if (_itimediff(kcp->current, kcp->ts_probe) >= 0) {
- if (kcp->probe_wait < IKCP_PROBE_INIT)
- kcp->probe_wait = IKCP_PROBE_INIT;
- kcp->probe_wait += kcp->probe_wait / 2;
- if (kcp->probe_wait > IKCP_PROBE_LIMIT)
- kcp->probe_wait = IKCP_PROBE_LIMIT;
- kcp->ts_probe = kcp->current + kcp->probe_wait;
- kcp->probe |= IKCP_ASK_SEND;
- }
- }
- } else {
- kcp->ts_probe = 0;
- kcp->probe_wait = 0;
- }
-
- // flush window probing commands
- if (kcp->probe & IKCP_ASK_SEND) {
- seg.cmd = IKCP_CMD_WASK;
- size = (int)(ptr - buffer);
- if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
- ikcp_output(kcp, buffer, size);
- ptr = buffer;
- }
- ptr = ikcp_encode_seg(ptr, &seg);
- }
-
- // flush window probing commands
- if (kcp->probe & IKCP_ASK_TELL) {
- seg.cmd = IKCP_CMD_WINS;
- size = (int)(ptr - buffer);
- if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
- ikcp_output(kcp, buffer, size);
- ptr = buffer;
- }
- ptr = ikcp_encode_seg(ptr, &seg);
- }
-
- kcp->probe = 0;
-
- // calculate window size
- cwnd = _imin_(kcp->snd_wnd, kcp->rmt_wnd);
- if (kcp->nocwnd == 0) cwnd = _imin_(kcp->cwnd, cwnd);
-
- // move data from snd_queue to snd_buf
- while (_itimediff(kcp->snd_nxt, kcp->snd_una + cwnd) < 0) {
- IKCPSEG *newseg;
- if (iqueue_is_empty(&kcp->snd_queue)) break;
-
- newseg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);
-
- iqueue_del(&newseg->node);
- iqueue_add_tail(&newseg->node, &kcp->snd_buf);
- kcp->nsnd_que--;
- kcp->nsnd_buf++;
-
- newseg->conv = kcp->conv;
- newseg->cmd = IKCP_CMD_PUSH;
- newseg->wnd = seg.wnd;
- newseg->ts = current;
- newseg->sn = kcp->snd_nxt++;
- newseg->una = kcp->rcv_nxt;
- newseg->resendts = current;
- newseg->rto = kcp->rx_rto;
- newseg->fastack = 0;
- newseg->xmit = 0;
- }
-
- // calculate resent
- resent = (kcp->fastresend > 0)? (IUINT32)kcp->fastresend : 0xffffffff;
- rtomin = (kcp->nodelay == 0)? (kcp->rx_rto >> 3) : 0;
-
- // flush data segments
- for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) {
- IKCPSEG *segment = iqueue_entry(p, IKCPSEG, node);
- int needsend = 0;
- if (segment->xmit == 0) {
- needsend = 1;
- segment->xmit++;
- segment->rto = kcp->rx_rto;
- segment->resendts = current + segment->rto + rtomin;
- }
- else if (_itimediff(current, segment->resendts) >= 0) {
- needsend = 1;
- segment->xmit++;
- kcp->xmit++;
- if (kcp->nodelay == 0) {
- segment->rto += _imax_(segment->rto, (IUINT32)kcp->rx_rto);
- } else {
- IINT32 step = (kcp->nodelay < 2)?
- ((IINT32)(segment->rto)) : kcp->rx_rto;
- segment->rto += step / 2;
- }
- segment->resendts = current + segment->rto;
- lost = 1;
- }
- else if (segment->fastack >= resent) {
- if ((int)segment->xmit <= kcp->fastlimit ||
- kcp->fastlimit <= 0) {
- needsend = 1;
- segment->xmit++;
- segment->fastack = 0;
- segment->resendts = current + segment->rto;
- change++;
- }
- }
-
- if (needsend) {
- int need;
- segment->ts = current;
- segment->wnd = seg.wnd;
- segment->una = kcp->rcv_nxt;
-
- size = (int)(ptr - buffer);
- need = IKCP_OVERHEAD + segment->len;
-
- if (size + need > (int)kcp->mtu) {
- ikcp_output(kcp, buffer, size);
- ptr = buffer;
- }
-
- ptr = ikcp_encode_seg(ptr, segment);
-
- if (segment->len > 0) {
- memcpy(ptr, segment->data, segment->len);
- ptr += segment->len;
- }
-
- if (segment->xmit >= kcp->dead_link) {
- kcp->state = (IUINT32)-1;
- }
- }
- }
-
- // flash remain segments
- size = (int)(ptr - buffer);
- if (size > 0) {
- ikcp_output(kcp, buffer, size);
- }
-
- // update ssthresh
- if (change) {
- IUINT32 inflight = kcp->snd_nxt - kcp->snd_una;
- kcp->ssthresh = inflight / 2;
- if (kcp->ssthresh < IKCP_THRESH_MIN)
- kcp->ssthresh = IKCP_THRESH_MIN;
- kcp->cwnd = kcp->ssthresh + resent;
- kcp->incr = kcp->cwnd * kcp->mss;
- }
-
- if (lost) {
- kcp->ssthresh = cwnd / 2;
- if (kcp->ssthresh < IKCP_THRESH_MIN)
- kcp->ssthresh = IKCP_THRESH_MIN;
- kcp->cwnd = 1;
- kcp->incr = kcp->mss;
- }
-
- if (kcp->cwnd < 1) {
- kcp->cwnd = 1;
- kcp->incr = kcp->mss;
- }
-}
-
-
-//---------------------------------------------------------------------
-// update state (call it repeatedly, every 10ms-100ms), or you can ask
-// ikcp_check when to call it again (without ikcp_input/_send calling).
-// 'current' - current timestamp in millisec.
-//---------------------------------------------------------------------
-void ikcp_update(ikcpcb *kcp, IUINT32 current)
-{
- IINT32 slap;
-
- kcp->current = current;
-
- if (kcp->updated == 0) {
- kcp->updated = 1;
- kcp->ts_flush = kcp->current;
- }
-
- slap = _itimediff(kcp->current, kcp->ts_flush);
-
- if (slap >= 10000 || slap < -10000) {
- kcp->ts_flush = kcp->current;
- slap = 0;
- }
-
- if (slap >= 0) {
- kcp->ts_flush += kcp->interval;
- if (_itimediff(kcp->current, kcp->ts_flush) >= 0) {
- kcp->ts_flush = kcp->current + kcp->interval;
- }
- ikcp_flush(kcp);
- }
-}
-
-
-//---------------------------------------------------------------------
-// Determine when should you invoke ikcp_update:
-// returns when you should invoke ikcp_update in millisec, if there
-// is no ikcp_input/_send calling. you can call ikcp_update in that
-// time, instead of call update repeatly.
-// Important to reduce unnacessary ikcp_update invoking. use it to
-// schedule ikcp_update (eg. implementing an epoll-like mechanism,
-// or optimize ikcp_update when handling massive kcp connections)
-//---------------------------------------------------------------------
-IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current)
-{
- IUINT32 ts_flush = kcp->ts_flush;
- IINT32 tm_flush = 0x7fffffff;
- IINT32 tm_packet = 0x7fffffff;
- IUINT32 minimal = 0;
- struct IQUEUEHEAD *p;
-
- if (kcp->updated == 0) {
- return current;
- }
-
- if (_itimediff(current, ts_flush) >= 10000 ||
- _itimediff(current, ts_flush) < -10000) {
- ts_flush = current;
- }
-
- if (_itimediff(current, ts_flush) >= 0) {
- return current;
- }
-
- tm_flush = _itimediff(ts_flush, current);
-
- for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) {
- const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node);
- IINT32 diff = _itimediff(seg->resendts, current);
- if (diff <= 0) {
- return current;
- }
- if (diff < tm_packet) tm_packet = diff;
- }
-
- minimal = (IUINT32)(tm_packet < tm_flush ? tm_packet : tm_flush);
- if (minimal >= kcp->interval) minimal = kcp->interval;
-
- return current + minimal;
-}
-
-
-
-int ikcp_setmtu(ikcpcb *kcp, int mtu)
-{
- char *buffer;
- if (mtu < 50 || mtu < (int)IKCP_OVERHEAD)
- return -1;
- buffer = (char*)ikcp_malloc((mtu + IKCP_OVERHEAD) * 3);
- if (buffer == NULL)
- return -2;
- kcp->mtu = mtu;
- kcp->mss = kcp->mtu - IKCP_OVERHEAD;
- ikcp_free(kcp->buffer);
- kcp->buffer = buffer;
- return 0;
-}
-
-int ikcp_interval(ikcpcb *kcp, int interval)
-{
- if (interval > 5000) interval = 5000;
- else if (interval < 10) interval = 10;
- kcp->interval = interval;
- return 0;
-}
-
-int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
-{
- if (nodelay >= 0) {
- kcp->nodelay = nodelay;
- if (nodelay) {
- kcp->rx_minrto = IKCP_RTO_NDL;
- }
- else {
- kcp->rx_minrto = IKCP_RTO_MIN;
- }
- }
- if (interval >= 0) {
- if (interval > 5000) interval = 5000;
- else if (interval < 10) interval = 10;
- kcp->interval = interval;
- }
- if (resend >= 0) {
- kcp->fastresend = resend;
- }
- if (nc >= 0) {
- kcp->nocwnd = nc;
- }
- return 0;
-}
-
-
-int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd)
-{
- if (kcp) {
- if (sndwnd > 0) {
- kcp->snd_wnd = sndwnd;
- }
- if (rcvwnd > 0) { // must >= max fragment size
- kcp->rcv_wnd = _imax_(rcvwnd, IKCP_WND_RCV);
- }
- }
- return 0;
-}
-
-int ikcp_waitsnd(const ikcpcb *kcp)
-{
- return kcp->nsnd_buf + kcp->nsnd_que;
-}
-
-
-// read conv
-IUINT32 ikcp_getconv(const void *ptr)
-{
- IUINT32 conv;
- ikcp_decode32u((const char*)ptr, &conv);
- return conv;
-}
-
-
+//=====================================================================
+//
+// KCP - A Better ARQ Protocol Implementation
+// skywind3000 (at) gmail.com, 2010-2011
+//
+// Features:
+// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
+// + Maximum RTT reduce three times vs tcp.
+// + Lightweight, distributed as a single source file.
+//
+//=====================================================================
+#include "ikcp.h"
+
+#include
+#include
+#include
+#include
+#include
+
+
+
+//=====================================================================
+// KCP BASIC
+//=====================================================================
+const IUINT32 IKCP_RTO_NDL = 30; // no delay min rto
+const IUINT32 IKCP_RTO_MIN = 100; // normal min rto
+const IUINT32 IKCP_RTO_DEF = 200;
+const IUINT32 IKCP_RTO_MAX = 60000;
+const IUINT32 IKCP_CMD_PUSH = 81; // cmd: push data
+const IUINT32 IKCP_CMD_ACK = 82; // cmd: ack
+const IUINT32 IKCP_CMD_WASK = 83; // cmd: window probe (ask)
+const IUINT32 IKCP_CMD_WINS = 84; // cmd: window size (tell)
+const IUINT32 IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK
+const IUINT32 IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS
+const IUINT32 IKCP_WND_SND = 32;
+const IUINT32 IKCP_WND_RCV = 128; // must >= max fragment size
+const IUINT32 IKCP_MTU_DEF = 1400;
+const IUINT32 IKCP_ACK_FAST = 3;
+const IUINT32 IKCP_INTERVAL = 100;
+const IUINT32 IKCP_OVERHEAD = 24;
+const IUINT32 IKCP_DEADLINK = 20;
+const IUINT32 IKCP_THRESH_INIT = 2;
+const IUINT32 IKCP_THRESH_MIN = 2;
+const IUINT32 IKCP_PROBE_INIT = 7000; // 7 secs to probe window size
+const IUINT32 IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window
+const IUINT32 IKCP_FASTACK_LIMIT = 5; // max times to trigger fastack
+
+
+//---------------------------------------------------------------------
+// encode / decode
+//---------------------------------------------------------------------
+
+/* encode 8 bits unsigned int */
+static inline char *ikcp_encode8u(char *p, unsigned char c)
+{
+ *(unsigned char*)p++ = c;
+ return p;
+}
+
+/* decode 8 bits unsigned int */
+static inline const char *ikcp_decode8u(const char *p, unsigned char *c)
+{
+ *c = *(unsigned char*)p++;
+ return p;
+}
+
+/* encode 16 bits unsigned int (lsb) */
+static inline char *ikcp_encode16u(char *p, unsigned short w)
+{
+#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
+ *(unsigned char*)(p + 0) = (w & 255);
+ *(unsigned char*)(p + 1) = (w >> 8);
+#else
+ memcpy(p, &w, 2);
+#endif
+ p += 2;
+ return p;
+}
+
+/* decode 16 bits unsigned int (lsb) */
+static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
+{
+#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
+ *w = *(const unsigned char*)(p + 1);
+ *w = *(const unsigned char*)(p + 0) + (*w << 8);
+#else
+ memcpy(w, p, 2);
+#endif
+ p += 2;
+ return p;
+}
+
+/* encode 32 bits unsigned int (lsb) */
+static inline char *ikcp_encode32u(char *p, IUINT32 l)
+{
+#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
+ *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff);
+ *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff);
+ *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff);
+ *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff);
+#else
+ memcpy(p, &l, 4);
+#endif
+ p += 4;
+ return p;
+}
+
+/* decode 32 bits unsigned int (lsb) */
+static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
+{
+#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
+ *l = *(const unsigned char*)(p + 3);
+ *l = *(const unsigned char*)(p + 2) + (*l << 8);
+ *l = *(const unsigned char*)(p + 1) + (*l << 8);
+ *l = *(const unsigned char*)(p + 0) + (*l << 8);
+#else
+ memcpy(l, p, 4);
+#endif
+ p += 4;
+ return p;
+}
+
+static inline IUINT32 _imin_(IUINT32 a, IUINT32 b) {
+ return a <= b ? a : b;
+}
+
+static inline IUINT32 _imax_(IUINT32 a, IUINT32 b) {
+ return a >= b ? a : b;
+}
+
+static inline IUINT32 _ibound_(IUINT32 lower, IUINT32 middle, IUINT32 upper)
+{
+ return _imin_(_imax_(lower, middle), upper);
+}
+
+static inline long _itimediff(IUINT32 later, IUINT32 earlier)
+{
+ return ((IINT32)(later - earlier));
+}
+
+//---------------------------------------------------------------------
+// manage segment
+//---------------------------------------------------------------------
+typedef struct IKCPSEG IKCPSEG;
+
+static void* (*ikcp_malloc_hook)(size_t) = NULL;
+static void (*ikcp_free_hook)(void *) = NULL;
+
+// internal malloc
+static void* ikcp_malloc(size_t size) {
+ if (ikcp_malloc_hook)
+ return ikcp_malloc_hook(size);
+ return malloc(size);
+}
+
+// internal free
+static void ikcp_free(void *ptr) {
+ if (ikcp_free_hook) {
+ ikcp_free_hook(ptr);
+ } else {
+ free(ptr);
+ }
+}
+
+// redefine allocator
+void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*))
+{
+ ikcp_malloc_hook = new_malloc;
+ ikcp_free_hook = new_free;
+}
+
+// allocate a new kcp segment
+static IKCPSEG* ikcp_segment_new(ikcpcb *kcp, int size)
+{
+ return (IKCPSEG*)ikcp_malloc(sizeof(IKCPSEG) + size);
+}
+
+// delete a segment
+static void ikcp_segment_delete(ikcpcb *kcp, IKCPSEG *seg)
+{
+ ikcp_free(seg);
+}
+
+// write log
+void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...)
+{
+ char buffer[1024];
+ va_list argptr;
+ if ((mask & kcp->logmask) == 0 || kcp->writelog == 0) return;
+ va_start(argptr, fmt);
+ vsprintf(buffer, fmt, argptr);
+ va_end(argptr);
+ kcp->writelog(buffer, kcp, kcp->user);
+}
+
+// check log mask
+static int ikcp_canlog(const ikcpcb *kcp, int mask)
+{
+ if ((mask & kcp->logmask) == 0 || kcp->writelog == NULL) return 0;
+ return 1;
+}
+
+// output segment
+static int ikcp_output(ikcpcb *kcp, const void *data, int size)
+{
+ assert(kcp);
+ assert(kcp->output);
+ if (ikcp_canlog(kcp, IKCP_LOG_OUTPUT)) {
+ ikcp_log(kcp, IKCP_LOG_OUTPUT, "[RO] %ld bytes", (long)size);
+ }
+ if (size == 0) return 0;
+ return kcp->output((const char*)data, size, kcp, kcp->user);
+}
+
+// output queue
+void ikcp_qprint(const char *name, const struct IQUEUEHEAD *head)
+{
+#if 0
+ const struct IQUEUEHEAD *p;
+ printf("<%s>: [", name);
+ for (p = head->next; p != head; p = p->next) {
+ const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node);
+ printf("(%lu %d)", (unsigned long)seg->sn, (int)(seg->ts % 10000));
+ if (p->next != head) printf(",");
+ }
+ printf("]\n");
+#endif
+}
+
+
+//---------------------------------------------------------------------
+// create a new kcpcb
+//---------------------------------------------------------------------
+ikcpcb* ikcp_create(IUINT32 conv, void *user)
+{
+ ikcpcb *kcp = (ikcpcb*)ikcp_malloc(sizeof(struct IKCPCB));
+ if (kcp == NULL) return NULL;
+ kcp->conv = conv;
+ kcp->user = user;
+ kcp->snd_una = 0;
+ kcp->snd_nxt = 0;
+ kcp->rcv_nxt = 0;
+ kcp->ts_recent = 0;
+ kcp->ts_lastack = 0;
+ kcp->ts_probe = 0;
+ kcp->probe_wait = 0;
+ kcp->snd_wnd = IKCP_WND_SND;
+ kcp->rcv_wnd = IKCP_WND_RCV;
+ kcp->rmt_wnd = IKCP_WND_RCV;
+ kcp->cwnd = 0;
+ kcp->incr = 0;
+ kcp->probe = 0;
+ kcp->mtu = IKCP_MTU_DEF;
+ kcp->mss = kcp->mtu - IKCP_OVERHEAD;
+ kcp->stream = 0;
+
+ kcp->buffer = (char*)ikcp_malloc((kcp->mtu + IKCP_OVERHEAD) * 3);
+ if (kcp->buffer == NULL) {
+ ikcp_free(kcp);
+ return NULL;
+ }
+
+ iqueue_init(&kcp->snd_queue);
+ iqueue_init(&kcp->rcv_queue);
+ iqueue_init(&kcp->snd_buf);
+ iqueue_init(&kcp->rcv_buf);
+ kcp->nrcv_buf = 0;
+ kcp->nsnd_buf = 0;
+ kcp->nrcv_que = 0;
+ kcp->nsnd_que = 0;
+ kcp->state = 0;
+ kcp->acklist = NULL;
+ kcp->ackblock = 0;
+ kcp->ackcount = 0;
+ kcp->rx_srtt = 0;
+ kcp->rx_rttval = 0;
+ kcp->rx_rto = IKCP_RTO_DEF;
+ kcp->rx_minrto = IKCP_RTO_MIN;
+ kcp->current = 0;
+ kcp->interval = IKCP_INTERVAL;
+ kcp->ts_flush = IKCP_INTERVAL;
+ kcp->nodelay = 0;
+ kcp->updated = 0;
+ kcp->logmask = 0;
+ kcp->ssthresh = IKCP_THRESH_INIT;
+ kcp->fastresend = 0;
+ kcp->fastlimit = IKCP_FASTACK_LIMIT;
+ kcp->nocwnd = 0;
+ kcp->xmit = 0;
+ kcp->dead_link = IKCP_DEADLINK;
+ kcp->output = NULL;
+ kcp->writelog = NULL;
+
+ return kcp;
+}
+
+
+//---------------------------------------------------------------------
+// release a new kcpcb
+//---------------------------------------------------------------------
+void ikcp_release(ikcpcb *kcp)
+{
+ assert(kcp);
+ if (kcp) {
+ IKCPSEG *seg;
+ while (!iqueue_is_empty(&kcp->snd_buf)) {
+ seg = iqueue_entry(kcp->snd_buf.next, IKCPSEG, node);
+ iqueue_del(&seg->node);
+ ikcp_segment_delete(kcp, seg);
+ }
+ while (!iqueue_is_empty(&kcp->rcv_buf)) {
+ seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
+ iqueue_del(&seg->node);
+ ikcp_segment_delete(kcp, seg);
+ }
+ while (!iqueue_is_empty(&kcp->snd_queue)) {
+ seg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);
+ iqueue_del(&seg->node);
+ ikcp_segment_delete(kcp, seg);
+ }
+ while (!iqueue_is_empty(&kcp->rcv_queue)) {
+ seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node);
+ iqueue_del(&seg->node);
+ ikcp_segment_delete(kcp, seg);
+ }
+ if (kcp->buffer) {
+ ikcp_free(kcp->buffer);
+ }
+ if (kcp->acklist) {
+ ikcp_free(kcp->acklist);
+ }
+
+ kcp->nrcv_buf = 0;
+ kcp->nsnd_buf = 0;
+ kcp->nrcv_que = 0;
+ kcp->nsnd_que = 0;
+ kcp->ackcount = 0;
+ kcp->buffer = NULL;
+ kcp->acklist = NULL;
+ ikcp_free(kcp);
+ }
+}
+
+
+//---------------------------------------------------------------------
+// set output callback, which will be invoked by kcp
+//---------------------------------------------------------------------
+void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
+ ikcpcb *kcp, void *user))
+{
+ kcp->output = output;
+}
+
+
+//---------------------------------------------------------------------
+// user/upper level recv: returns size, returns below zero for EAGAIN
+//---------------------------------------------------------------------
+int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
+{
+ struct IQUEUEHEAD *p;
+ int ispeek = (len < 0)? 1 : 0;
+ int peeksize;
+ int recover = 0;
+ IKCPSEG *seg;
+ assert(kcp);
+
+ if (iqueue_is_empty(&kcp->rcv_queue))
+ return -1;
+
+ if (len < 0) len = -len;
+
+ peeksize = ikcp_peeksize(kcp);
+
+ if (peeksize < 0)
+ return -2;
+
+ if (peeksize > len)
+ return -3;
+
+ if (kcp->nrcv_que >= kcp->rcv_wnd)
+ recover = 1;
+
+ // merge fragment
+ for (len = 0, p = kcp->rcv_queue.next; p != &kcp->rcv_queue; ) {
+ int fragment;
+ seg = iqueue_entry(p, IKCPSEG, node);
+ p = p->next;
+
+ if (buffer) {
+ memcpy(buffer, seg->data, seg->len);
+ buffer += seg->len;
+ }
+
+ len += seg->len;
+ fragment = seg->frg;
+
+ if (ikcp_canlog(kcp, IKCP_LOG_RECV)) {
+ ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", (unsigned long)seg->sn);
+ }
+
+ if (ispeek == 0) {
+ iqueue_del(&seg->node);
+ ikcp_segment_delete(kcp, seg);
+ kcp->nrcv_que--;
+ }
+
+ if (fragment == 0)
+ break;
+ }
+
+ assert(len == peeksize);
+
+ // move available data from rcv_buf -> rcv_queue
+ while (! iqueue_is_empty(&kcp->rcv_buf)) {
+ seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
+ if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
+ iqueue_del(&seg->node);
+ kcp->nrcv_buf--;
+ iqueue_add_tail(&seg->node, &kcp->rcv_queue);
+ kcp->nrcv_que++;
+ kcp->rcv_nxt++;
+ } else {
+ break;
+ }
+ }
+
+ // fast recover
+ if (kcp->nrcv_que < kcp->rcv_wnd && recover) {
+ // ready to send back IKCP_CMD_WINS in ikcp_flush
+ // tell remote my window size
+ kcp->probe |= IKCP_ASK_TELL;
+ }
+
+ return len;
+}
+
+
+//---------------------------------------------------------------------
+// peek data size
+//---------------------------------------------------------------------
+int ikcp_peeksize(const ikcpcb *kcp)
+{
+ struct IQUEUEHEAD *p;
+ IKCPSEG *seg;
+ int length = 0;
+
+ assert(kcp);
+
+ if (iqueue_is_empty(&kcp->rcv_queue)) return -1;
+
+ seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node);
+ if (seg->frg == 0) return seg->len;
+
+ if (kcp->nrcv_que < seg->frg + 1) return -1;
+
+ for (p = kcp->rcv_queue.next; p != &kcp->rcv_queue; p = p->next) {
+ seg = iqueue_entry(p, IKCPSEG, node);
+ length += seg->len;
+ if (seg->frg == 0) break;
+ }
+
+ return length;
+}
+
+
+//---------------------------------------------------------------------
+// user/upper level send, returns below zero for error
+//---------------------------------------------------------------------
+int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
+{
+ IKCPSEG *seg;
+ int count, i;
+ int sent = 0;
+
+ assert(kcp->mss > 0);
+ if (len < 0) return -1;
+
+ // append to previous segment in streaming mode (if possible)
+ if (kcp->stream != 0) {
+ if (!iqueue_is_empty(&kcp->snd_queue)) {
+ IKCPSEG *old = iqueue_entry(kcp->snd_queue.prev, IKCPSEG, node);
+ if (old->len < kcp->mss) {
+ int capacity = kcp->mss - old->len;
+ int extend = (len < capacity)? len : capacity;
+ seg = ikcp_segment_new(kcp, old->len + extend);
+ assert(seg);
+ if (seg == NULL) {
+ return -2;
+ }
+ iqueue_add_tail(&seg->node, &kcp->snd_queue);
+ memcpy(seg->data, old->data, old->len);
+ if (buffer) {
+ memcpy(seg->data + old->len, buffer, extend);
+ buffer += extend;
+ }
+ seg->len = old->len + extend;
+ seg->frg = 0;
+ len -= extend;
+ iqueue_del_init(&old->node);
+ ikcp_segment_delete(kcp, old);
+ sent = extend;
+ }
+ }
+ if (len <= 0) {
+ return sent;
+ }
+ }
+
+ if (len <= (int)kcp->mss) count = 1;
+ else count = (len + kcp->mss - 1) / kcp->mss;
+
+ if (count >= (int)IKCP_WND_RCV) {
+ if (kcp->stream != 0 && sent > 0)
+ return sent;
+ return -2;
+ }
+
+ if (count == 0) count = 1;
+
+ // fragment
+ for (i = 0; i < count; i++) {
+ int size = len > (int)kcp->mss ? (int)kcp->mss : len;
+ seg = ikcp_segment_new(kcp, size);
+ assert(seg);
+ if (seg == NULL) {
+ return -2;
+ }
+ if (buffer && len > 0) {
+ memcpy(seg->data, buffer, size);
+ }
+ seg->len = size;
+ seg->frg = (kcp->stream == 0)? (count - i - 1) : 0;
+ iqueue_init(&seg->node);
+ iqueue_add_tail(&seg->node, &kcp->snd_queue);
+ kcp->nsnd_que++;
+ if (buffer) {
+ buffer += size;
+ }
+ len -= size;
+ sent += size;
+ }
+
+ return sent;
+}
+
+
+//---------------------------------------------------------------------
+// parse ack
+//---------------------------------------------------------------------
+static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt)
+{
+ IINT32 rto = 0;
+ if (kcp->rx_srtt == 0) {
+ kcp->rx_srtt = rtt;
+ kcp->rx_rttval = rtt / 2;
+ } else {
+ long delta = rtt - kcp->rx_srtt;
+ if (delta < 0) delta = -delta;
+ kcp->rx_rttval = (3 * kcp->rx_rttval + delta) / 4;
+ kcp->rx_srtt = (7 * kcp->rx_srtt + rtt) / 8;
+ if (kcp->rx_srtt < 1) kcp->rx_srtt = 1;
+ }
+ rto = kcp->rx_srtt + _imax_(kcp->interval, 4 * kcp->rx_rttval);
+ kcp->rx_rto = _ibound_(kcp->rx_minrto, rto, IKCP_RTO_MAX);
+}
+
+static void ikcp_shrink_buf(ikcpcb *kcp)
+{
+ struct IQUEUEHEAD *p = kcp->snd_buf.next;
+ if (p != &kcp->snd_buf) {
+ IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
+ kcp->snd_una = seg->sn;
+ } else {
+ kcp->snd_una = kcp->snd_nxt;
+ }
+}
+
+static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn)
+{
+ struct IQUEUEHEAD *p, *next;
+
+ if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0)
+ return;
+
+ for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
+ IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
+ next = p->next;
+ if (sn == seg->sn) {
+ iqueue_del(p);
+ ikcp_segment_delete(kcp, seg);
+ kcp->nsnd_buf--;
+ break;
+ }
+ if (_itimediff(sn, seg->sn) < 0) {
+ break;
+ }
+ }
+}
+
+static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
+{
+ struct IQUEUEHEAD *p, *next;
+ for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
+ IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
+ next = p->next;
+ if (_itimediff(una, seg->sn) > 0) {
+ iqueue_del(p);
+ ikcp_segment_delete(kcp, seg);
+ kcp->nsnd_buf--;
+ } else {
+ break;
+ }
+ }
+}
+
+static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
+{
+ struct IQUEUEHEAD *p, *next;
+
+ if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0)
+ return;
+
+ for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
+ IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
+ next = p->next;
+ if (_itimediff(sn, seg->sn) < 0) {
+ break;
+ }
+ else if (sn != seg->sn) {
+ #ifndef IKCP_FASTACK_CONSERVE
+ seg->fastack++;
+ #else
+ if (_itimediff(ts, seg->ts) >= 0)
+ seg->fastack++;
+ #endif
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------
+// ack append
+//---------------------------------------------------------------------
+static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
+{
+ IUINT32 newsize = kcp->ackcount + 1;
+ IUINT32 *ptr;
+
+ if (newsize > kcp->ackblock) {
+ IUINT32 *acklist;
+ IUINT32 newblock;
+
+ for (newblock = 8; newblock < newsize; newblock <<= 1);
+ acklist = (IUINT32*)ikcp_malloc(newblock * sizeof(IUINT32) * 2);
+
+ if (acklist == NULL) {
+ assert(acklist != NULL);
+ abort();
+ }
+
+ if (kcp->acklist != NULL) {
+ IUINT32 x;
+ for (x = 0; x < kcp->ackcount; x++) {
+ acklist[x * 2 + 0] = kcp->acklist[x * 2 + 0];
+ acklist[x * 2 + 1] = kcp->acklist[x * 2 + 1];
+ }
+ ikcp_free(kcp->acklist);
+ }
+
+ kcp->acklist = acklist;
+ kcp->ackblock = newblock;
+ }
+
+ ptr = &kcp->acklist[kcp->ackcount * 2];
+ ptr[0] = sn;
+ ptr[1] = ts;
+ kcp->ackcount++;
+}
+
+static void ikcp_ack_get(const ikcpcb *kcp, int p, IUINT32 *sn, IUINT32 *ts)
+{
+ if (sn) sn[0] = kcp->acklist[p * 2 + 0];
+ if (ts) ts[0] = kcp->acklist[p * 2 + 1];
+}
+
+
+//---------------------------------------------------------------------
+// parse data
+//---------------------------------------------------------------------
+void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg)
+{
+ struct IQUEUEHEAD *p, *prev;
+ IUINT32 sn = newseg->sn;
+ int repeat = 0;
+
+ if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) >= 0 ||
+ _itimediff(sn, kcp->rcv_nxt) < 0) {
+ ikcp_segment_delete(kcp, newseg);
+ return;
+ }
+
+ for (p = kcp->rcv_buf.prev; p != &kcp->rcv_buf; p = prev) {
+ IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
+ prev = p->prev;
+ if (seg->sn == sn) {
+ repeat = 1;
+ break;
+ }
+ if (_itimediff(sn, seg->sn) > 0) {
+ break;
+ }
+ }
+
+ if (repeat == 0) {
+ iqueue_init(&newseg->node);
+ iqueue_add(&newseg->node, p);
+ kcp->nrcv_buf++;
+ } else {
+ ikcp_segment_delete(kcp, newseg);
+ }
+
+#if 0
+ ikcp_qprint("rcvbuf", &kcp->rcv_buf);
+ printf("rcv_nxt=%lu\n", kcp->rcv_nxt);
+#endif
+
+ // move available data from rcv_buf -> rcv_queue
+ while (! iqueue_is_empty(&kcp->rcv_buf)) {
+ IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
+ if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
+ iqueue_del(&seg->node);
+ kcp->nrcv_buf--;
+ iqueue_add_tail(&seg->node, &kcp->rcv_queue);
+ kcp->nrcv_que++;
+ kcp->rcv_nxt++;
+ } else {
+ break;
+ }
+ }
+
+#if 0
+ ikcp_qprint("queue", &kcp->rcv_queue);
+ printf("rcv_nxt=%lu\n", kcp->rcv_nxt);
+#endif
+
+#if 1
+// printf("snd(buf=%d, queue=%d)\n", kcp->nsnd_buf, kcp->nsnd_que);
+// printf("rcv(buf=%d, queue=%d)\n", kcp->nrcv_buf, kcp->nrcv_que);
+#endif
+}
+
+
+//---------------------------------------------------------------------
+// input data
+//---------------------------------------------------------------------
+int ikcp_input(ikcpcb *kcp, const char *data, long size)
+{
+ IUINT32 prev_una = kcp->snd_una;
+ IUINT32 maxack = 0, latest_ts = 0;
+ int flag = 0;
+
+ if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
+ ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", (int)size);
+ }
+
+ if (data == NULL || (int)size < (int)IKCP_OVERHEAD) return -1;
+
+ while (1) {
+ IUINT32 ts, sn, len, una, conv;
+ IUINT16 wnd;
+ IUINT8 cmd, frg;
+ IKCPSEG *seg;
+
+ if (size < (int)IKCP_OVERHEAD) break;
+
+ data = ikcp_decode32u(data, &conv);
+ if (conv != kcp->conv) return -1;
+
+ data = ikcp_decode8u(data, &cmd);
+ data = ikcp_decode8u(data, &frg);
+ data = ikcp_decode16u(data, &wnd);
+ data = ikcp_decode32u(data, &ts);
+ data = ikcp_decode32u(data, &sn);
+ data = ikcp_decode32u(data, &una);
+ data = ikcp_decode32u(data, &len);
+
+ size -= IKCP_OVERHEAD;
+
+ if ((long)size < (long)len || (int)len < 0) return -2;
+
+ if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
+ cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS)
+ return -3;
+
+ kcp->rmt_wnd = wnd;
+ ikcp_parse_una(kcp, una);
+ ikcp_shrink_buf(kcp);
+
+ if (cmd == IKCP_CMD_ACK) {
+ if (_itimediff(kcp->current, ts) >= 0) {
+ ikcp_update_ack(kcp, _itimediff(kcp->current, ts));
+ }
+ ikcp_parse_ack(kcp, sn);
+ ikcp_shrink_buf(kcp);
+ if (flag == 0) {
+ flag = 1;
+ maxack = sn;
+ latest_ts = ts;
+ } else {
+ if (_itimediff(sn, maxack) > 0) {
+ #ifndef IKCP_FASTACK_CONSERVE
+ maxack = sn;
+ latest_ts = ts;
+ #else
+ if (_itimediff(ts, latest_ts) > 0) {
+ maxack = sn;
+ latest_ts = ts;
+ }
+ #endif
+ }
+ }
+ if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) {
+ ikcp_log(kcp, IKCP_LOG_IN_ACK,
+ "input ack: sn=%lu rtt=%ld rto=%ld", (unsigned long)sn,
+ (long)_itimediff(kcp->current, ts),
+ (long)kcp->rx_rto);
+ }
+ }
+ else if (cmd == IKCP_CMD_PUSH) {
+ if (ikcp_canlog(kcp, IKCP_LOG_IN_DATA)) {
+ ikcp_log(kcp, IKCP_LOG_IN_DATA,
+ "input psh: sn=%lu ts=%lu", (unsigned long)sn, (unsigned long)ts);
+ }
+ if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) < 0) {
+ ikcp_ack_push(kcp, sn, ts);
+ if (_itimediff(sn, kcp->rcv_nxt) >= 0) {
+ seg = ikcp_segment_new(kcp, len);
+ seg->conv = conv;
+ seg->cmd = cmd;
+ seg->frg = frg;
+ seg->wnd = wnd;
+ seg->ts = ts;
+ seg->sn = sn;
+ seg->una = una;
+ seg->len = len;
+
+ if (len > 0) {
+ memcpy(seg->data, data, len);
+ }
+
+ ikcp_parse_data(kcp, seg);
+ }
+ }
+ }
+ else if (cmd == IKCP_CMD_WASK) {
+ // ready to send back IKCP_CMD_WINS in ikcp_flush
+ // tell remote my window size
+ kcp->probe |= IKCP_ASK_TELL;
+ if (ikcp_canlog(kcp, IKCP_LOG_IN_PROBE)) {
+ ikcp_log(kcp, IKCP_LOG_IN_PROBE, "input probe");
+ }
+ }
+ else if (cmd == IKCP_CMD_WINS) {
+ // do nothing
+ if (ikcp_canlog(kcp, IKCP_LOG_IN_WINS)) {
+ ikcp_log(kcp, IKCP_LOG_IN_WINS,
+ "input wins: %lu", (unsigned long)(wnd));
+ }
+ }
+ else {
+ return -3;
+ }
+
+ data += len;
+ size -= len;
+ }
+
+ if (flag != 0) {
+ ikcp_parse_fastack(kcp, maxack, latest_ts);
+ }
+
+ if (_itimediff(kcp->snd_una, prev_una) > 0) {
+ if (kcp->cwnd < kcp->rmt_wnd) {
+ IUINT32 mss = kcp->mss;
+ if (kcp->cwnd < kcp->ssthresh) {
+ kcp->cwnd++;
+ kcp->incr += mss;
+ } else {
+ if (kcp->incr < mss) kcp->incr = mss;
+ kcp->incr += (mss * mss) / kcp->incr + (mss / 16);
+ if ((kcp->cwnd + 1) * mss <= kcp->incr) {
+ #if 1
+ kcp->cwnd = (kcp->incr + mss - 1) / ((mss > 0)? mss : 1);
+ #else
+ kcp->cwnd++;
+ #endif
+ }
+ }
+ if (kcp->cwnd > kcp->rmt_wnd) {
+ kcp->cwnd = kcp->rmt_wnd;
+ kcp->incr = kcp->rmt_wnd * mss;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------
+// ikcp_encode_seg
+//---------------------------------------------------------------------
+static char *ikcp_encode_seg(char *ptr, const IKCPSEG *seg)
+{
+ ptr = ikcp_encode32u(ptr, seg->conv);
+ ptr = ikcp_encode8u(ptr, (IUINT8)seg->cmd);
+ ptr = ikcp_encode8u(ptr, (IUINT8)seg->frg);
+ ptr = ikcp_encode16u(ptr, (IUINT16)seg->wnd);
+ ptr = ikcp_encode32u(ptr, seg->ts);
+ ptr = ikcp_encode32u(ptr, seg->sn);
+ ptr = ikcp_encode32u(ptr, seg->una);
+ ptr = ikcp_encode32u(ptr, seg->len);
+ return ptr;
+}
+
+static int ikcp_wnd_unused(const ikcpcb *kcp)
+{
+ if (kcp->nrcv_que < kcp->rcv_wnd) {
+ return kcp->rcv_wnd - kcp->nrcv_que;
+ }
+ return 0;
+}
+
+
+//---------------------------------------------------------------------
+// ikcp_flush
+//---------------------------------------------------------------------
+void ikcp_flush(ikcpcb *kcp)
+{
+ IUINT32 current = kcp->current;
+ char *buffer = kcp->buffer;
+ char *ptr = buffer;
+ int count, size, i;
+ IUINT32 resent, cwnd;
+ IUINT32 rtomin;
+ struct IQUEUEHEAD *p;
+ int change = 0;
+ int lost = 0;
+ IKCPSEG seg;
+
+ // 'ikcp_update' haven't been called.
+ if (kcp->updated == 0) return;
+
+ seg.conv = kcp->conv;
+ seg.cmd = IKCP_CMD_ACK;
+ seg.frg = 0;
+ seg.wnd = ikcp_wnd_unused(kcp);
+ seg.una = kcp->rcv_nxt;
+ seg.len = 0;
+ seg.sn = 0;
+ seg.ts = 0;
+
+ // flush acknowledges
+ count = kcp->ackcount;
+ for (i = 0; i < count; i++) {
+ size = (int)(ptr - buffer);
+ if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
+ ikcp_output(kcp, buffer, size);
+ ptr = buffer;
+ }
+ ikcp_ack_get(kcp, i, &seg.sn, &seg.ts);
+ ptr = ikcp_encode_seg(ptr, &seg);
+ }
+
+ kcp->ackcount = 0;
+
+ // probe window size (if remote window size equals zero)
+ if (kcp->rmt_wnd == 0) {
+ if (kcp->probe_wait == 0) {
+ kcp->probe_wait = IKCP_PROBE_INIT;
+ kcp->ts_probe = kcp->current + kcp->probe_wait;
+ }
+ else {
+ if (_itimediff(kcp->current, kcp->ts_probe) >= 0) {
+ if (kcp->probe_wait < IKCP_PROBE_INIT)
+ kcp->probe_wait = IKCP_PROBE_INIT;
+ kcp->probe_wait += kcp->probe_wait / 2;
+ if (kcp->probe_wait > IKCP_PROBE_LIMIT)
+ kcp->probe_wait = IKCP_PROBE_LIMIT;
+ kcp->ts_probe = kcp->current + kcp->probe_wait;
+ kcp->probe |= IKCP_ASK_SEND;
+ }
+ }
+ } else {
+ kcp->ts_probe = 0;
+ kcp->probe_wait = 0;
+ }
+
+ // flush window probing commands
+ if (kcp->probe & IKCP_ASK_SEND) {
+ seg.cmd = IKCP_CMD_WASK;
+ size = (int)(ptr - buffer);
+ if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
+ ikcp_output(kcp, buffer, size);
+ ptr = buffer;
+ }
+ ptr = ikcp_encode_seg(ptr, &seg);
+ }
+
+ // flush window probing commands
+ if (kcp->probe & IKCP_ASK_TELL) {
+ seg.cmd = IKCP_CMD_WINS;
+ size = (int)(ptr - buffer);
+ if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
+ ikcp_output(kcp, buffer, size);
+ ptr = buffer;
+ }
+ ptr = ikcp_encode_seg(ptr, &seg);
+ }
+
+ kcp->probe = 0;
+
+ // calculate window size
+ cwnd = _imin_(kcp->snd_wnd, kcp->rmt_wnd);
+ if (kcp->nocwnd == 0) cwnd = _imin_(kcp->cwnd, cwnd);
+
+ // move data from snd_queue to snd_buf
+ while (_itimediff(kcp->snd_nxt, kcp->snd_una + cwnd) < 0) {
+ IKCPSEG *newseg;
+ if (iqueue_is_empty(&kcp->snd_queue)) break;
+
+ newseg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);
+
+ iqueue_del(&newseg->node);
+ iqueue_add_tail(&newseg->node, &kcp->snd_buf);
+ kcp->nsnd_que--;
+ kcp->nsnd_buf++;
+
+ newseg->conv = kcp->conv;
+ newseg->cmd = IKCP_CMD_PUSH;
+ newseg->wnd = seg.wnd;
+ newseg->ts = current;
+ newseg->sn = kcp->snd_nxt++;
+ newseg->una = kcp->rcv_nxt;
+ newseg->resendts = current;
+ newseg->rto = kcp->rx_rto;
+ newseg->fastack = 0;
+ newseg->xmit = 0;
+ }
+
+ // calculate resent
+ resent = (kcp->fastresend > 0)? (IUINT32)kcp->fastresend : 0xffffffff;
+ rtomin = (kcp->nodelay == 0)? (kcp->rx_rto >> 3) : 0;
+
+ // flush data segments
+ for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) {
+ IKCPSEG *segment = iqueue_entry(p, IKCPSEG, node);
+ int needsend = 0;
+ if (segment->xmit == 0) {
+ needsend = 1;
+ segment->xmit++;
+ segment->rto = kcp->rx_rto;
+ segment->resendts = current + segment->rto + rtomin;
+ }
+ else if (_itimediff(current, segment->resendts) >= 0) {
+ needsend = 1;
+ segment->xmit++;
+ kcp->xmit++;
+ if (kcp->nodelay == 0) {
+ segment->rto += _imax_(segment->rto, (IUINT32)kcp->rx_rto);
+ } else {
+ IINT32 step = (kcp->nodelay < 2)?
+ ((IINT32)(segment->rto)) : kcp->rx_rto;
+ segment->rto += step / 2;
+ }
+ segment->resendts = current + segment->rto;
+ lost = 1;
+ }
+ else if (segment->fastack >= resent) {
+ if ((int)segment->xmit <= kcp->fastlimit ||
+ kcp->fastlimit <= 0) {
+ needsend = 1;
+ segment->xmit++;
+ segment->fastack = 0;
+ segment->resendts = current + segment->rto;
+ change++;
+ }
+ }
+
+ if (needsend) {
+ int need;
+ segment->ts = current;
+ segment->wnd = seg.wnd;
+ segment->una = kcp->rcv_nxt;
+
+ size = (int)(ptr - buffer);
+ need = IKCP_OVERHEAD + segment->len;
+
+ if (size + need > (int)kcp->mtu) {
+ ikcp_output(kcp, buffer, size);
+ ptr = buffer;
+ }
+
+ ptr = ikcp_encode_seg(ptr, segment);
+
+ if (segment->len > 0) {
+ memcpy(ptr, segment->data, segment->len);
+ ptr += segment->len;
+ }
+
+ if (segment->xmit >= kcp->dead_link) {
+ kcp->state = (IUINT32)-1;
+ }
+ }
+ }
+
+ // flash remain segments
+ size = (int)(ptr - buffer);
+ if (size > 0) {
+ ikcp_output(kcp, buffer, size);
+ }
+
+ // update ssthresh
+ if (change) {
+ IUINT32 inflight = kcp->snd_nxt - kcp->snd_una;
+ kcp->ssthresh = inflight / 2;
+ if (kcp->ssthresh < IKCP_THRESH_MIN)
+ kcp->ssthresh = IKCP_THRESH_MIN;
+ kcp->cwnd = kcp->ssthresh + resent;
+ kcp->incr = kcp->cwnd * kcp->mss;
+ }
+
+ if (lost) {
+ kcp->ssthresh = cwnd / 2;
+ if (kcp->ssthresh < IKCP_THRESH_MIN)
+ kcp->ssthresh = IKCP_THRESH_MIN;
+ kcp->cwnd = 1;
+ kcp->incr = kcp->mss;
+ }
+
+ if (kcp->cwnd < 1) {
+ kcp->cwnd = 1;
+ kcp->incr = kcp->mss;
+ }
+}
+
+
+//---------------------------------------------------------------------
+// update state (call it repeatedly, every 10ms-100ms), or you can ask
+// ikcp_check when to call it again (without ikcp_input/_send calling).
+// 'current' - current timestamp in millisec.
+//---------------------------------------------------------------------
+void ikcp_update(ikcpcb *kcp, IUINT32 current)
+{
+ IINT32 slap;
+
+ kcp->current = current;
+
+ if (kcp->updated == 0) {
+ kcp->updated = 1;
+ kcp->ts_flush = kcp->current;
+ }
+
+ slap = _itimediff(kcp->current, kcp->ts_flush);
+
+ if (slap >= 10000 || slap < -10000) {
+ kcp->ts_flush = kcp->current;
+ slap = 0;
+ }
+
+ if (slap >= 0) {
+ kcp->ts_flush += kcp->interval;
+ if (_itimediff(kcp->current, kcp->ts_flush) >= 0) {
+ kcp->ts_flush = kcp->current + kcp->interval;
+ }
+ ikcp_flush(kcp);
+ }
+}
+
+
+//---------------------------------------------------------------------
+// Determine when should you invoke ikcp_update:
+// returns when you should invoke ikcp_update in millisec, if there
+// is no ikcp_input/_send calling. you can call ikcp_update in that
+// time, instead of call update repeatly.
+// Important to reduce unnacessary ikcp_update invoking. use it to
+// schedule ikcp_update (eg. implementing an epoll-like mechanism,
+// or optimize ikcp_update when handling massive kcp connections)
+//---------------------------------------------------------------------
+IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current)
+{
+ IUINT32 ts_flush = kcp->ts_flush;
+ IINT32 tm_flush = 0x7fffffff;
+ IINT32 tm_packet = 0x7fffffff;
+ IUINT32 minimal = 0;
+ struct IQUEUEHEAD *p;
+
+ if (kcp->updated == 0) {
+ return current;
+ }
+
+ if (_itimediff(current, ts_flush) >= 10000 ||
+ _itimediff(current, ts_flush) < -10000) {
+ ts_flush = current;
+ }
+
+ if (_itimediff(current, ts_flush) >= 0) {
+ return current;
+ }
+
+ tm_flush = _itimediff(ts_flush, current);
+
+ for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) {
+ const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node);
+ IINT32 diff = _itimediff(seg->resendts, current);
+ if (diff <= 0) {
+ return current;
+ }
+ if (diff < tm_packet) tm_packet = diff;
+ }
+
+ minimal = (IUINT32)(tm_packet < tm_flush ? tm_packet : tm_flush);
+ if (minimal >= kcp->interval) minimal = kcp->interval;
+
+ return current + minimal;
+}
+
+
+
+int ikcp_setmtu(ikcpcb *kcp, int mtu)
+{
+ char *buffer;
+ if (mtu < 50 || mtu < (int)IKCP_OVERHEAD)
+ return -1;
+ buffer = (char*)ikcp_malloc((mtu + IKCP_OVERHEAD) * 3);
+ if (buffer == NULL)
+ return -2;
+ kcp->mtu = mtu;
+ kcp->mss = kcp->mtu - IKCP_OVERHEAD;
+ ikcp_free(kcp->buffer);
+ kcp->buffer = buffer;
+ return 0;
+}
+
+int ikcp_interval(ikcpcb *kcp, int interval)
+{
+ if (interval > 5000) interval = 5000;
+ else if (interval < 10) interval = 10;
+ kcp->interval = interval;
+ return 0;
+}
+
+int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
+{
+ if (nodelay >= 0) {
+ kcp->nodelay = nodelay;
+ if (nodelay) {
+ kcp->rx_minrto = IKCP_RTO_NDL;
+ }
+ else {
+ kcp->rx_minrto = IKCP_RTO_MIN;
+ }
+ }
+ if (interval >= 0) {
+ if (interval > 5000) interval = 5000;
+ else if (interval < 10) interval = 10;
+ kcp->interval = interval;
+ }
+ if (resend >= 0) {
+ kcp->fastresend = resend;
+ }
+ if (nc >= 0) {
+ kcp->nocwnd = nc;
+ }
+ return 0;
+}
+
+
+int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd)
+{
+ if (kcp) {
+ if (sndwnd > 0) {
+ kcp->snd_wnd = sndwnd;
+ }
+ if (rcvwnd > 0) { // must >= max fragment size
+ kcp->rcv_wnd = _imax_(rcvwnd, IKCP_WND_RCV);
+ }
+ }
+ return 0;
+}
+
+int ikcp_waitsnd(const ikcpcb *kcp)
+{
+ return kcp->nsnd_buf + kcp->nsnd_que;
+}
+
+
+// read conv
+IUINT32 ikcp_getconv(const void *ptr)
+{
+ IUINT32 conv;
+ ikcp_decode32u((const char*)ptr, &conv);
+ return conv;
+}
+
+
diff --git a/NativeLibs/yasio/kcp/ikcp.h b/NativeLibs/yasio/3rdparty/kcp/ikcp.h
similarity index 96%
rename from NativeLibs/yasio/kcp/ikcp.h
rename to NativeLibs/yasio/3rdparty/kcp/ikcp.h
index b8c337f..e525105 100644
--- a/NativeLibs/yasio/kcp/ikcp.h
+++ b/NativeLibs/yasio/3rdparty/kcp/ikcp.h
@@ -1,416 +1,416 @@
-//=====================================================================
-//
-// KCP - A Better ARQ Protocol Implementation
-// skywind3000 (at) gmail.com, 2010-2011
-//
-// Features:
-// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
-// + Maximum RTT reduce three times vs tcp.
-// + Lightweight, distributed as a single source file.
-//
-//=====================================================================
-#ifndef __IKCP_H__
-#define __IKCP_H__
-
-#include
-#include
-#include
-
-
-//=====================================================================
-// 32BIT INTEGER DEFINITION
-//=====================================================================
-#ifndef __INTEGER_32_BITS__
-#define __INTEGER_32_BITS__
-#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \
- defined(_M_AMD64)
- typedef unsigned int ISTDUINT32;
- typedef int ISTDINT32;
-#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \
- defined(__i386) || defined(_M_X86)
- typedef unsigned long ISTDUINT32;
- typedef long ISTDINT32;
-#elif defined(__MACOS__)
- typedef UInt32 ISTDUINT32;
- typedef SInt32 ISTDINT32;
-#elif defined(__APPLE__) && defined(__MACH__)
- #include
- typedef u_int32_t ISTDUINT32;
- typedef int32_t ISTDINT32;
-#elif defined(__BEOS__)
- #include
- typedef u_int32_t ISTDUINT32;
- typedef int32_t ISTDINT32;
-#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__))
- typedef unsigned __int32 ISTDUINT32;
- typedef __int32 ISTDINT32;
-#elif defined(__GNUC__)
- #include
- typedef uint32_t ISTDUINT32;
- typedef int32_t ISTDINT32;
-#else
- typedef unsigned long ISTDUINT32;
- typedef long ISTDINT32;
-#endif
-#endif
-
-
-//=====================================================================
-// Integer Definition
-//=====================================================================
-#ifndef __IINT8_DEFINED
-#define __IINT8_DEFINED
-typedef char IINT8;
-#endif
-
-#ifndef __IUINT8_DEFINED
-#define __IUINT8_DEFINED
-typedef unsigned char IUINT8;
-#endif
-
-#ifndef __IUINT16_DEFINED
-#define __IUINT16_DEFINED
-typedef unsigned short IUINT16;
-#endif
-
-#ifndef __IINT16_DEFINED
-#define __IINT16_DEFINED
-typedef short IINT16;
-#endif
-
-#ifndef __IINT32_DEFINED
-#define __IINT32_DEFINED
-typedef ISTDINT32 IINT32;
-#endif
-
-#ifndef __IUINT32_DEFINED
-#define __IUINT32_DEFINED
-typedef ISTDUINT32 IUINT32;
-#endif
-
-#ifndef __IINT64_DEFINED
-#define __IINT64_DEFINED
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef __int64 IINT64;
-#else
-typedef long long IINT64;
-#endif
-#endif
-
-#ifndef __IUINT64_DEFINED
-#define __IUINT64_DEFINED
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef unsigned __int64 IUINT64;
-#else
-typedef unsigned long long IUINT64;
-#endif
-#endif
-
-#ifndef INLINE
-#if defined(__GNUC__)
-
-#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
-#define INLINE __inline__ __attribute__((always_inline))
-#else
-#define INLINE __inline__
-#endif
-
-#elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__))
-#define INLINE __inline
-#else
-#define INLINE
-#endif
-#endif
-
-#if (!defined(__cplusplus)) && (!defined(inline))
-#define inline INLINE
-#endif
-
-
-//=====================================================================
-// QUEUE DEFINITION
-//=====================================================================
-#ifndef __IQUEUE_DEF__
-#define __IQUEUE_DEF__
-
-struct IQUEUEHEAD {
- struct IQUEUEHEAD *next, *prev;
-};
-
-typedef struct IQUEUEHEAD iqueue_head;
-
-
-//---------------------------------------------------------------------
-// queue init
-//---------------------------------------------------------------------
-#define IQUEUE_HEAD_INIT(name) { &(name), &(name) }
-#define IQUEUE_HEAD(name) \
- struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
-
-#define IQUEUE_INIT(ptr) ( \
- (ptr)->next = (ptr), (ptr)->prev = (ptr))
-
-#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-#define ICONTAINEROF(ptr, type, member) ( \
- (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )
-
-#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
-
-
-//---------------------------------------------------------------------
-// queue operation
-//---------------------------------------------------------------------
-#define IQUEUE_ADD(node, head) ( \
- (node)->prev = (head), (node)->next = (head)->next, \
- (head)->next->prev = (node), (head)->next = (node))
-
-#define IQUEUE_ADD_TAIL(node, head) ( \
- (node)->prev = (head)->prev, (node)->next = (head), \
- (head)->prev->next = (node), (head)->prev = (node))
-
-#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
-
-#define IQUEUE_DEL(entry) (\
- (entry)->next->prev = (entry)->prev, \
- (entry)->prev->next = (entry)->next, \
- (entry)->next = 0, (entry)->prev = 0)
-
-#define IQUEUE_DEL_INIT(entry) do { \
- IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0)
-
-#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
-
-#define iqueue_init IQUEUE_INIT
-#define iqueue_entry IQUEUE_ENTRY
-#define iqueue_add IQUEUE_ADD
-#define iqueue_add_tail IQUEUE_ADD_TAIL
-#define iqueue_del IQUEUE_DEL
-#define iqueue_del_init IQUEUE_DEL_INIT
-#define iqueue_is_empty IQUEUE_IS_EMPTY
-
-#define IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) \
- for ((iterator) = iqueue_entry((head)->next, TYPE, MEMBER); \
- &((iterator)->MEMBER) != (head); \
- (iterator) = iqueue_entry((iterator)->MEMBER.next, TYPE, MEMBER))
-
-#define iqueue_foreach(iterator, head, TYPE, MEMBER) \
- IQUEUE_FOREACH(iterator, head, TYPE, MEMBER)
-
-#define iqueue_foreach_entry(pos, head) \
- for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next )
-
-
-#define __iqueue_splice(list, head) do { \
- iqueue_head *first = (list)->next, *last = (list)->prev; \
- iqueue_head *at = (head)->next; \
- (first)->prev = (head), (head)->next = (first); \
- (last)->next = (at), (at)->prev = (last); } while (0)
-
-#define iqueue_splice(list, head) do { \
- if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0)
-
-#define iqueue_splice_init(list, head) do { \
- iqueue_splice(list, head); iqueue_init(list); } while (0)
-
-
-#ifdef _MSC_VER
-#pragma warning(disable:4311)
-#pragma warning(disable:4312)
-#pragma warning(disable:4996)
-#endif
-
-#endif
-
-
-//---------------------------------------------------------------------
-// BYTE ORDER & ALIGNMENT
-//---------------------------------------------------------------------
-#ifndef IWORDS_BIG_ENDIAN
- #ifdef _BIG_ENDIAN_
- #if _BIG_ENDIAN_
- #define IWORDS_BIG_ENDIAN 1
- #endif
- #endif
- #ifndef IWORDS_BIG_ENDIAN
- #if defined(__hppa__) || \
- defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
- (defined(__MIPS__) && defined(__MIPSEB__)) || \
- defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
- defined(__sparc__) || defined(__powerpc__) || \
- defined(__mc68000__) || defined(__s390x__) || defined(__s390__)
- #define IWORDS_BIG_ENDIAN 1
- #endif
- #endif
- #ifndef IWORDS_BIG_ENDIAN
- #define IWORDS_BIG_ENDIAN 0
- #endif
-#endif
-
-#ifndef IWORDS_MUST_ALIGN
- #if defined(__i386__) || defined(__i386) || defined(_i386_)
- #define IWORDS_MUST_ALIGN 0
- #elif defined(_M_IX86) || defined(_X86_) || defined(__x86_64__)
- #define IWORDS_MUST_ALIGN 0
- #elif defined(__amd64) || defined(__amd64__)
- #define IWORDS_MUST_ALIGN 0
- #else
- #define IWORDS_MUST_ALIGN 1
- #endif
-#endif
-
-
-//=====================================================================
-// SEGMENT
-//=====================================================================
-struct IKCPSEG
-{
- struct IQUEUEHEAD node;
- IUINT32 conv;
- IUINT32 cmd;
- IUINT32 frg;
- IUINT32 wnd;
- IUINT32 ts;
- IUINT32 sn;
- IUINT32 una;
- IUINT32 len;
- IUINT32 resendts;
- IUINT32 rto;
- IUINT32 fastack;
- IUINT32 xmit;
- char data[1];
-};
-
-
-//---------------------------------------------------------------------
-// IKCPCB
-//---------------------------------------------------------------------
-struct IKCPCB
-{
- IUINT32 conv, mtu, mss, state;
- IUINT32 snd_una, snd_nxt, rcv_nxt;
- IUINT32 ts_recent, ts_lastack, ssthresh;
- IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto;
- IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe;
- IUINT32 current, interval, ts_flush, xmit;
- IUINT32 nrcv_buf, nsnd_buf;
- IUINT32 nrcv_que, nsnd_que;
- IUINT32 nodelay, updated;
- IUINT32 ts_probe, probe_wait;
- IUINT32 dead_link, incr;
- struct IQUEUEHEAD snd_queue;
- struct IQUEUEHEAD rcv_queue;
- struct IQUEUEHEAD snd_buf;
- struct IQUEUEHEAD rcv_buf;
- IUINT32 *acklist;
- IUINT32 ackcount;
- IUINT32 ackblock;
- void *user;
- char *buffer;
- int fastresend;
- int fastlimit;
- int nocwnd, stream;
- int logmask;
- int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);
- void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);
-};
-
-
-typedef struct IKCPCB ikcpcb;
-
-#define IKCP_LOG_OUTPUT 1
-#define IKCP_LOG_INPUT 2
-#define IKCP_LOG_SEND 4
-#define IKCP_LOG_RECV 8
-#define IKCP_LOG_IN_DATA 16
-#define IKCP_LOG_IN_ACK 32
-#define IKCP_LOG_IN_PROBE 64
-#define IKCP_LOG_IN_WINS 128
-#define IKCP_LOG_OUT_DATA 256
-#define IKCP_LOG_OUT_ACK 512
-#define IKCP_LOG_OUT_PROBE 1024
-#define IKCP_LOG_OUT_WINS 2048
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//---------------------------------------------------------------------
-// interface
-//---------------------------------------------------------------------
-
-// create a new kcp control object, 'conv' must equal in two endpoint
-// from the same connection. 'user' will be passed to the output callback
-// output callback can be setup like this: 'kcp->output = my_udp_output'
-ikcpcb* ikcp_create(IUINT32 conv, void *user);
-
-// release kcp control object
-void ikcp_release(ikcpcb *kcp);
-
-// set output callback, which will be invoked by kcp
-void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
- ikcpcb *kcp, void *user));
-
-// user/upper level recv: returns size, returns below zero for EAGAIN
-int ikcp_recv(ikcpcb *kcp, char *buffer, int len);
-
-// user/upper level send, returns below zero for error
-int ikcp_send(ikcpcb *kcp, const char *buffer, int len);
-
-// update state (call it repeatedly, every 10ms-100ms), or you can ask
-// ikcp_check when to call it again (without ikcp_input/_send calling).
-// 'current' - current timestamp in millisec.
-void ikcp_update(ikcpcb *kcp, IUINT32 current);
-
-// Determine when should you invoke ikcp_update:
-// returns when you should invoke ikcp_update in millisec, if there
-// is no ikcp_input/_send calling. you can call ikcp_update in that
-// time, instead of call update repeatly.
-// Important to reduce unnacessary ikcp_update invoking. use it to
-// schedule ikcp_update (eg. implementing an epoll-like mechanism,
-// or optimize ikcp_update when handling massive kcp connections)
-IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current);
-
-// when you received a low level packet (eg. UDP packet), call it
-int ikcp_input(ikcpcb *kcp, const char *data, long size);
-
-// flush pending data
-void ikcp_flush(ikcpcb *kcp);
-
-// check the size of next message in the recv queue
-int ikcp_peeksize(const ikcpcb *kcp);
-
-// change MTU size, default is 1400
-int ikcp_setmtu(ikcpcb *kcp, int mtu);
-
-// set maximum window size: sndwnd=32, rcvwnd=32 by default
-int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
-
-// get how many packet is waiting to be sent
-int ikcp_waitsnd(const ikcpcb *kcp);
-
-// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
-// nodelay: 0:disable(default), 1:enable
-// interval: internal update timer interval in millisec, default is 100ms
-// resend: 0:disable fast resend(default), 1:enable fast resend
-// nc: 0:normal congestion control(default), 1:disable congestion control
-int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc);
-
-
-void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
-
-// setup allocator
-void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*));
-
-// read conv
-IUINT32 ikcp_getconv(const void *ptr);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
+//=====================================================================
+//
+// KCP - A Better ARQ Protocol Implementation
+// skywind3000 (at) gmail.com, 2010-2011
+//
+// Features:
+// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
+// + Maximum RTT reduce three times vs tcp.
+// + Lightweight, distributed as a single source file.
+//
+//=====================================================================
+#ifndef __IKCP_H__
+#define __IKCP_H__
+
+#include
+#include
+#include
+
+
+//=====================================================================
+// 32BIT INTEGER DEFINITION
+//=====================================================================
+#ifndef __INTEGER_32_BITS__
+#define __INTEGER_32_BITS__
+#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \
+ defined(_M_AMD64)
+ typedef unsigned int ISTDUINT32;
+ typedef int ISTDINT32;
+#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \
+ defined(__i386) || defined(_M_X86)
+ typedef unsigned long ISTDUINT32;
+ typedef long ISTDINT32;
+#elif defined(__MACOS__)
+ typedef UInt32 ISTDUINT32;
+ typedef SInt32 ISTDINT32;
+#elif defined(__APPLE__) && defined(__MACH__)
+ #include
+ typedef u_int32_t ISTDUINT32;
+ typedef int32_t ISTDINT32;
+#elif defined(__BEOS__)
+ #include
+ typedef u_int32_t ISTDUINT32;
+ typedef int32_t ISTDINT32;
+#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__))
+ typedef unsigned __int32 ISTDUINT32;
+ typedef __int32 ISTDINT32;
+#elif defined(__GNUC__)
+ #include
+ typedef uint32_t ISTDUINT32;
+ typedef int32_t ISTDINT32;
+#else
+ typedef unsigned long ISTDUINT32;
+ typedef long ISTDINT32;
+#endif
+#endif
+
+
+//=====================================================================
+// Integer Definition
+//=====================================================================
+#ifndef __IINT8_DEFINED
+#define __IINT8_DEFINED
+typedef char IINT8;
+#endif
+
+#ifndef __IUINT8_DEFINED
+#define __IUINT8_DEFINED
+typedef unsigned char IUINT8;
+#endif
+
+#ifndef __IUINT16_DEFINED
+#define __IUINT16_DEFINED
+typedef unsigned short IUINT16;
+#endif
+
+#ifndef __IINT16_DEFINED
+#define __IINT16_DEFINED
+typedef short IINT16;
+#endif
+
+#ifndef __IINT32_DEFINED
+#define __IINT32_DEFINED
+typedef ISTDINT32 IINT32;
+#endif
+
+#ifndef __IUINT32_DEFINED
+#define __IUINT32_DEFINED
+typedef ISTDUINT32 IUINT32;
+#endif
+
+#ifndef __IINT64_DEFINED
+#define __IINT64_DEFINED
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 IINT64;
+#else
+typedef long long IINT64;
+#endif
+#endif
+
+#ifndef __IUINT64_DEFINED
+#define __IUINT64_DEFINED
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 IUINT64;
+#else
+typedef unsigned long long IUINT64;
+#endif
+#endif
+
+#ifndef INLINE
+#if defined(__GNUC__)
+
+#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
+#define INLINE __inline__ __attribute__((always_inline))
+#else
+#define INLINE __inline__
+#endif
+
+#elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__))
+#define INLINE __inline
+#else
+#define INLINE
+#endif
+#endif
+
+#if (!defined(__cplusplus)) && (!defined(inline))
+#define inline INLINE
+#endif
+
+
+//=====================================================================
+// QUEUE DEFINITION
+//=====================================================================
+#ifndef __IQUEUE_DEF__
+#define __IQUEUE_DEF__
+
+struct IQUEUEHEAD {
+ struct IQUEUEHEAD *next, *prev;
+};
+
+typedef struct IQUEUEHEAD iqueue_head;
+
+
+//---------------------------------------------------------------------
+// queue init
+//---------------------------------------------------------------------
+#define IQUEUE_HEAD_INIT(name) { &(name), &(name) }
+#define IQUEUE_HEAD(name) \
+ struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
+
+#define IQUEUE_INIT(ptr) ( \
+ (ptr)->next = (ptr), (ptr)->prev = (ptr))
+
+#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define ICONTAINEROF(ptr, type, member) ( \
+ (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )
+
+#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
+
+
+//---------------------------------------------------------------------
+// queue operation
+//---------------------------------------------------------------------
+#define IQUEUE_ADD(node, head) ( \
+ (node)->prev = (head), (node)->next = (head)->next, \
+ (head)->next->prev = (node), (head)->next = (node))
+
+#define IQUEUE_ADD_TAIL(node, head) ( \
+ (node)->prev = (head)->prev, (node)->next = (head), \
+ (head)->prev->next = (node), (head)->prev = (node))
+
+#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
+
+#define IQUEUE_DEL(entry) (\
+ (entry)->next->prev = (entry)->prev, \
+ (entry)->prev->next = (entry)->next, \
+ (entry)->next = 0, (entry)->prev = 0)
+
+#define IQUEUE_DEL_INIT(entry) do { \
+ IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0)
+
+#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
+
+#define iqueue_init IQUEUE_INIT
+#define iqueue_entry IQUEUE_ENTRY
+#define iqueue_add IQUEUE_ADD
+#define iqueue_add_tail IQUEUE_ADD_TAIL
+#define iqueue_del IQUEUE_DEL
+#define iqueue_del_init IQUEUE_DEL_INIT
+#define iqueue_is_empty IQUEUE_IS_EMPTY
+
+#define IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) \
+ for ((iterator) = iqueue_entry((head)->next, TYPE, MEMBER); \
+ &((iterator)->MEMBER) != (head); \
+ (iterator) = iqueue_entry((iterator)->MEMBER.next, TYPE, MEMBER))
+
+#define iqueue_foreach(iterator, head, TYPE, MEMBER) \
+ IQUEUE_FOREACH(iterator, head, TYPE, MEMBER)
+
+#define iqueue_foreach_entry(pos, head) \
+ for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next )
+
+
+#define __iqueue_splice(list, head) do { \
+ iqueue_head *first = (list)->next, *last = (list)->prev; \
+ iqueue_head *at = (head)->next; \
+ (first)->prev = (head), (head)->next = (first); \
+ (last)->next = (at), (at)->prev = (last); } while (0)
+
+#define iqueue_splice(list, head) do { \
+ if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0)
+
+#define iqueue_splice_init(list, head) do { \
+ iqueue_splice(list, head); iqueue_init(list); } while (0)
+
+
+#ifdef _MSC_VER
+#pragma warning(disable:4311)
+#pragma warning(disable:4312)
+#pragma warning(disable:4996)
+#endif
+
+#endif
+
+
+//---------------------------------------------------------------------
+// BYTE ORDER & ALIGNMENT
+//---------------------------------------------------------------------
+#ifndef IWORDS_BIG_ENDIAN
+ #ifdef _BIG_ENDIAN_
+ #if _BIG_ENDIAN_
+ #define IWORDS_BIG_ENDIAN 1
+ #endif
+ #endif
+ #ifndef IWORDS_BIG_ENDIAN
+ #if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MIPSEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+ defined(__sparc__) || defined(__powerpc__) || \
+ defined(__mc68000__) || defined(__s390x__) || defined(__s390__)
+ #define IWORDS_BIG_ENDIAN 1
+ #endif
+ #endif
+ #ifndef IWORDS_BIG_ENDIAN
+ #define IWORDS_BIG_ENDIAN 0
+ #endif
+#endif
+
+#ifndef IWORDS_MUST_ALIGN
+ #if defined(__i386__) || defined(__i386) || defined(_i386_)
+ #define IWORDS_MUST_ALIGN 0
+ #elif defined(_M_IX86) || defined(_X86_) || defined(__x86_64__)
+ #define IWORDS_MUST_ALIGN 0
+ #elif defined(__amd64) || defined(__amd64__)
+ #define IWORDS_MUST_ALIGN 0
+ #else
+ #define IWORDS_MUST_ALIGN 1
+ #endif
+#endif
+
+
+//=====================================================================
+// SEGMENT
+//=====================================================================
+struct IKCPSEG
+{
+ struct IQUEUEHEAD node;
+ IUINT32 conv;
+ IUINT32 cmd;
+ IUINT32 frg;
+ IUINT32 wnd;
+ IUINT32 ts;
+ IUINT32 sn;
+ IUINT32 una;
+ IUINT32 len;
+ IUINT32 resendts;
+ IUINT32 rto;
+ IUINT32 fastack;
+ IUINT32 xmit;
+ char data[1];
+};
+
+
+//---------------------------------------------------------------------
+// IKCPCB
+//---------------------------------------------------------------------
+struct IKCPCB
+{
+ IUINT32 conv, mtu, mss, state;
+ IUINT32 snd_una, snd_nxt, rcv_nxt;
+ IUINT32 ts_recent, ts_lastack, ssthresh;
+ IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto;
+ IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe;
+ IUINT32 current, interval, ts_flush, xmit;
+ IUINT32 nrcv_buf, nsnd_buf;
+ IUINT32 nrcv_que, nsnd_que;
+ IUINT32 nodelay, updated;
+ IUINT32 ts_probe, probe_wait;
+ IUINT32 dead_link, incr;
+ struct IQUEUEHEAD snd_queue;
+ struct IQUEUEHEAD rcv_queue;
+ struct IQUEUEHEAD snd_buf;
+ struct IQUEUEHEAD rcv_buf;
+ IUINT32 *acklist;
+ IUINT32 ackcount;
+ IUINT32 ackblock;
+ void *user;
+ char *buffer;
+ int fastresend;
+ int fastlimit;
+ int nocwnd, stream;
+ int logmask;
+ int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);
+ void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);
+};
+
+
+typedef struct IKCPCB ikcpcb;
+
+#define IKCP_LOG_OUTPUT 1
+#define IKCP_LOG_INPUT 2
+#define IKCP_LOG_SEND 4
+#define IKCP_LOG_RECV 8
+#define IKCP_LOG_IN_DATA 16
+#define IKCP_LOG_IN_ACK 32
+#define IKCP_LOG_IN_PROBE 64
+#define IKCP_LOG_IN_WINS 128
+#define IKCP_LOG_OUT_DATA 256
+#define IKCP_LOG_OUT_ACK 512
+#define IKCP_LOG_OUT_PROBE 1024
+#define IKCP_LOG_OUT_WINS 2048
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//---------------------------------------------------------------------
+// interface
+//---------------------------------------------------------------------
+
+// create a new kcp control object, 'conv' must equal in two endpoint
+// from the same connection. 'user' will be passed to the output callback
+// output callback can be setup like this: 'kcp->output = my_udp_output'
+ikcpcb* ikcp_create(IUINT32 conv, void *user);
+
+// release kcp control object
+void ikcp_release(ikcpcb *kcp);
+
+// set output callback, which will be invoked by kcp
+void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
+ ikcpcb *kcp, void *user));
+
+// user/upper level recv: returns size, returns below zero for EAGAIN
+int ikcp_recv(ikcpcb *kcp, char *buffer, int len);
+
+// user/upper level send, returns below zero for error
+int ikcp_send(ikcpcb *kcp, const char *buffer, int len);
+
+// update state (call it repeatedly, every 10ms-100ms), or you can ask
+// ikcp_check when to call it again (without ikcp_input/_send calling).
+// 'current' - current timestamp in millisec.
+void ikcp_update(ikcpcb *kcp, IUINT32 current);
+
+// Determine when should you invoke ikcp_update:
+// returns when you should invoke ikcp_update in millisec, if there
+// is no ikcp_input/_send calling. you can call ikcp_update in that
+// time, instead of call update repeatly.
+// Important to reduce unnacessary ikcp_update invoking. use it to
+// schedule ikcp_update (eg. implementing an epoll-like mechanism,
+// or optimize ikcp_update when handling massive kcp connections)
+IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current);
+
+// when you received a low level packet (eg. UDP packet), call it
+int ikcp_input(ikcpcb *kcp, const char *data, long size);
+
+// flush pending data
+void ikcp_flush(ikcpcb *kcp);
+
+// check the size of next message in the recv queue
+int ikcp_peeksize(const ikcpcb *kcp);
+
+// change MTU size, default is 1400
+int ikcp_setmtu(ikcpcb *kcp, int mtu);
+
+// set maximum window size: sndwnd=32, rcvwnd=32 by default
+int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
+
+// get how many packet is waiting to be sent
+int ikcp_waitsnd(const ikcpcb *kcp);
+
+// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
+// nodelay: 0:disable(default), 1:enable
+// interval: internal update timer interval in millisec, default is 100ms
+// resend: 0:disable fast resend(default), 1:enable fast resend
+// nc: 0:normal congestion control(default), 1:disable congestion control
+int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc);
+
+
+void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
+
+// setup allocator
+void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*));
+
+// read conv
+IUINT32 ikcp_getconv(const void *ptr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/NativeLibs/yasio/CMakeLists.txt b/NativeLibs/yasio/CMakeLists.txt
index 5589b4a..4e75a3a 100644
--- a/NativeLibs/yasio/CMakeLists.txt
+++ b/NativeLibs/yasio/CMakeLists.txt
@@ -1,6 +1,6 @@
# A multi-platform support c++11 library with focus on asynchronous socket I/O for any client application.
#
-# Copyright (c) 2012-2023 HALX99.
+# Copyright (c) 2012-2024 HALX99.
#
# Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
# http://opensource.org/licenses/MIT
@@ -18,32 +18,32 @@ cmake_policy(SET CMP0048 NEW)
set(yasio_target_name yasio)
project(${yasio_target_name})
+set(_1kfetch_cache_dir "${CMAKE_CURRENT_LIST_DIR}/cache" CACHE STRING "" FORCE)
+set(_1kfetch_manifest "${CMAKE_CURRENT_LIST_DIR}/manifest.json" CACHE STRING "" FORCE)
+
+include(1k/platform.cmake)
+include(1k/fetch.cmake)
include(CMakeDependentOption)
-# specify settings for yasio-ni
-# cmake_dependent_option(YASIO_BUILD_TESTS
-# "Build the tests when we are the root project" ON
-# "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
+cmake_dependent_option(YASIO_BUILD_TESTS
+ "Build the tests when we are the root project" ON
+ "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
-# cmake_dependent_option(YASIO_BUILD_LUA_EXAMPLE
-# "Build lua example when we are the root project" ON
-# "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
-set(YASIO_SSL_BACKEND 0)
-set(YASIO_ENABLE_HALF_FLOAT OFF)
+cmake_dependent_option(YASIO_BUILD_LUA_EXAMPLE
+ "Build lua example when we are the root project" ON
+ "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
-option(YASIO_ENABLE_EXT_HTTP "Build yasio http extension" OFF)
+option(YASIO_ENABLE_EXT_HTTP "Build yasio http extension" ON)
option(YASIO_ENABLE_LUA "Build yasio with lua support" OFF)
option(YASIO_ENABLE_AXLUA "Build yasio with axmol-lua support" OFF)
-option(YAISO_ENABLE_NI "Build yasio with native interface for interop" ON)
-option(YASIO_ENABLE_KCP "Enable kcp support" ON)
+option(YASIO_ENABLE_NI "Build yasio with native interface for interop" OFF)
+option(YASIO_ENABLE_KCP "Enable kcp support" OFF)
option(YASIO_NO_DEPS "Build yasio without deps" OFF)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(YASIO_ROOT ${CMAKE_CURRENT_LIST_DIR})
-
-
message(STATUS "YASIO_ROOT=${YASIO_ROOT}")
message(STATUS "CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}")
message(STATUS "MSVC=${MSVC}, MSVC_IDE=${MSVC_IDE}")
@@ -120,11 +120,12 @@ endif()
# Auto choose ssl backend if not supplied by user
if (NOT DEFINED YASIO_SSL_BACKEND)
- # mbedtls can't compile for watchOS, and openssl prebuilt also not ready yet
- if ((CMAKE_SYSTEM_NAME STREQUAL "watchOS") OR (CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
+ if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(YASIO_SSL_BACKEND 0)
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "watchOS")
+ set(YASIO_SSL_BACKEND 2) # mbedtls
else()
- set(YASIO_SSL_BACKEND 1)
+ set(YASIO_SSL_BACKEND 1) # openssl
endif()
endif()
@@ -149,10 +150,10 @@ if (ANDROID)
endif()
endif()
-include_directories(
+set(YASIO_INC_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
- ${THIRDPART_INC}
+ "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty"
)
### no deps
@@ -170,13 +171,25 @@ endif()
if (YASIO_SSL_BACKEND EQUAL 1) # openssl
message(STATUS "Build with openssl support")
- add_subdirectory(thirdparty/openssl)
+ add_subdirectory(3rdparty/openssl)
elseif(YASIO_SSL_BACKEND EQUAL 2) # mbedtls
message(STATUS "Build with mbedtls support")
- include_directories("${PROJECT_SOURCE_DIR}/thirdparty/mbedtls/include")
set(ENABLE_PROGRAMS OFF CACHE BOOL "Build mbedtls programs" FORCE)
set(ENABLE_TESTING OFF CACHE BOOL "Build mbed TLS tests." FORCE)
- add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/mbedtls)
+ set(MBEDTLS_VER "3.4.1")
+ if(MSVC_VERSION LESS 1900)
+ message(AUTHOR_WARNING "Using mbedtls 2.28.3 for vs2013 happy")
+ set(MBEDTLS_VER "2.28.3")
+ endif()
+ include(1k/CPM.cmake)
+ CPMAddPackage(
+ NAME mbedtls
+ VERSION ${MBEDTLS_VER}
+ GITHUB_REPOSITORY "Mbed-TLS/mbedtls"
+ GIT_TAG "v${MBEDTLS_VER}"
+ OPTIONS
+ "MBEDTLS_FATAL_WARNINGS OFF"
+ )
yasio_config_target_outdir(mbedtls)
yasio_config_target_outdir(mbedcrypto)
yasio_config_target_outdir(mbedx509)
@@ -184,18 +197,23 @@ endif()
### c-ares support
if (YASIO_USE_CARES)
- add_subdirectory(thirdparty/c-ares)
+ add_subdirectory(3rdparty/c-ares)
endif()
### The yasio core library project
file(GLOB YASIO_CORE yasio/*.hpp;yasio/*.cpp;yasio/compiler/*.hpp;yasio/impl/*.hpp;)
if (YASIO_ENABLE_KCP)
- set(YASIO_CORE ${YASIO_CORE}
- ${PROJECT_SOURCE_DIR}/kcp/ikcp.c
- )
+ if (NOT kcp_SOURCE_DIR)
+ set(YASIO_CORE ${YASIO_CORE}
+ ${PROJECT_SOURCE_DIR}/3rdparty/kcp/ikcp.c
+ )
+ list(APPEND YASIO_INC_DIRS "${PROJECT_SOURCE_DIR}/3rdparty/kcp")
+ else()
+ list(APPEND THIRDPART_LIB "kcp")
+ endif()
endif()
-if (YAISO_ENABLE_NI)
+if (YASIO_ENABLE_NI)
set(YASIO_CORE ${YASIO_CORE}
yasio/bindings/yasio_ni.cpp
)
@@ -220,11 +238,11 @@ if(ANDROID AND CARES_INCLUDE_DIR)
endif()
if(WIN32 AND YASIO_ENABLE_HPERF_IO)
- set(THIRDPART_SRC thirdparty/wepoll/wepoll.c)
+ set(THIRDPART_SRC 3rdparty/wepoll/wepoll.c)
endif()
-if(YASIO_ENABLE_KCP OR YASIO_ENABLE_LUA OR YASIO_USE_CARES OR YASIO_ENABLE_HALF_FLOAT)
- include_directories("${PROJECT_SOURCE_DIR}/thirdparty")
+if(YASIO_ENABLE_KCP)
+ include_directories("${PROJECT_SOURCE_DIR}/3rdparty")
endif()
macro(source_group_by_dir proj_dir source_files)
@@ -294,7 +312,8 @@ else ( )
)
endif ( )
-target_include_directories(${yasio_target_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
+message(STATUS "YASIO_INC_DIRS=${YASIO_INC_DIRS}")
+target_include_directories(${yasio_target_name} PUBLIC ${YASIO_INC_DIRS})
if (BUILD_SHARED_LIBS)
target_compile_definitions(${yasio_target_name}
@@ -410,8 +429,8 @@ if(YASIO_ENABLE_LUA)
endif()
# link libraries for yasio_core when BUILD_SHARED_LIBS=TRUE
+yasio_link_ssl_libraries(${yasio_target_name})
if(BUILD_SHARED_LIBS)
- yasio_link_ssl_libraries(${yasio_target_name})
if(NOT WIN32 AND (NOT ANDROID))
target_link_libraries(${yasio_target_name} pthread)
endif()
@@ -448,6 +467,7 @@ macro (yasio_config_lib_options target_name)
yasio_config_pred(${target_name} YASIO_DISABLE_POLL)
yasio_config_pred(${target_name} YASIO_DISABLE_EPOLL)
yasio_config_pred(${target_name} YASIO_DISABLE_KQUEUE)
+ yasio_config_pred(${target_name} YASIO_NT_XHRES_TIMER)
yasio_config_target_outdir(${yasio_target_name})
endmacro()
@@ -478,7 +498,7 @@ if(YASIO_ENABLE_EXT_HTTP)
set (BUILD_SHARED_LIBS FALSE CACHE BOOL "" FORCE)
set (BUILD_STATIC_LIBS TRUE CACHE BOOL "" FORCE)
endif()
- add_subdirectory(thirdparty/llhttp)
+ add_subdirectory(3rdparty/llhttp)
# yasio_http
add_subdirectory(extensions/yasio_http)
@@ -492,6 +512,7 @@ if(YASIO_BUILD_TESTS)
add_subdirectory(tests/icmp)
add_subdirectory(tests/mcast)
add_subdirectory(tests/speed)
+ add_subdirectory(tests/mtu)
add_subdirectory(tests/issue166)
add_subdirectory(tests/issue178)
add_subdirectory(tests/issue201)
@@ -504,7 +525,7 @@ if(YASIO_BUILD_TESTS)
add_subdirectory(tests/echo_client)
if(YASIO_ENABLE_LUA AND YASIO_BUILD_LUA_EXAMPLE)
add_subdirectory(examples/lua)
- target_include_directories(example_lua PRIVATE thirdparty)
+ target_include_directories(example_lua PRIVATE 3rdparty)
target_compile_definitions(example_lua PRIVATE YASIO_LUA_ENABLE_GLOBAL=0)
endif()
if (NOT YASIO_NO_DEPS)
diff --git a/NativeLibs/yasio/build_android.sh b/NativeLibs/yasio/build_android.sh
index bd23f69..aea7b96 100755
--- a/NativeLibs/yasio/build_android.sh
+++ b/NativeLibs/yasio/build_android.sh
@@ -18,7 +18,7 @@ function build() {
ABI=$2
TOOLCHAIN_ANME=$3
BUILD_PATH=build.Android.${ABI}
- cmake -H. -B${BUILD_PATH} -DANDROID_ABI=${ABI} -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=${API} -DANDROID_TOOLCHAIN=clang -DANDROID_TOOLCHAIN_NAME=${TOOLCHAIN_ANME}
+ cmake -H. -B${BUILD_PATH} -DANDROID_ABI=${ABI} -DYASIO_BUILD_TESTS=OFF -DBUILD_SHARED_LIBS=ON -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=${API} -DANDROID_TOOLCHAIN=clang -DANDROID_TOOLCHAIN_NAME=${TOOLCHAIN_ANME}
cmake --build ${BUILD_PATH} --config Release
mkdir -p plugin_android/Plugins/Android/libs/${ABI}/
cp ${BUILD_PATH}/stripped/libyasio.so plugin_android/Plugins/Android/libs/${ABI}/libyasio.so
diff --git a/NativeLibs/yasio/build_ios.sh b/NativeLibs/yasio/build_ios.sh
index 37da558..fd82926 100755
--- a/NativeLibs/yasio/build_ios.sh
+++ b/NativeLibs/yasio/build_ios.sh
@@ -1,5 +1,5 @@
mkdir -p build_ios && cd build_ios
-cmake -DCMAKE_SYSTEM_NAME=iOS "-DCMAKE_OSX_ARCHITECTURES=arm64" -GXcode ../
+cmake -DCMAKE_SYSTEM_NAME=iOS "-DCMAKE_OSX_ARCHITECTURES=arm64" -GXcode ../ -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DYASIO_BUILD_TESTS=OFF
cd ..
cmake --build build_ios --config Release
mkdir -p plugin_ios/Plugins/iOS/
diff --git a/NativeLibs/yasio/build_linux.sh b/NativeLibs/yasio/build_linux.sh
index 6219064..5e6a751 100755
--- a/NativeLibs/yasio/build_linux.sh
+++ b/NativeLibs/yasio/build_linux.sh
@@ -1,4 +1,4 @@
-cmake -B build_linux64 -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+cmake -B build_linux64 -DBUILD_SHARED_LIBS=ON -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DYASIO_BUILD_TESTS=OFF
cmake --build build_linux64 --config Release
mkdir -p plugin_linux/Plugins/x86_64
diff --git a/NativeLibs/yasio/build_osx.sh b/NativeLibs/yasio/build_osx.sh
index 338fec1..8a2d75c 100755
--- a/NativeLibs/yasio/build_osx.sh
+++ b/NativeLibs/yasio/build_osx.sh
@@ -1,5 +1,5 @@
mkdir -p build_osx && cd build_osx
-cmake -GXcode ../ -DYAISO_ENABLE_NI=ON -DBUILD_SHARED_LIBS=ON
+cmake -GXcode ../ -DBUILD_SHARED_LIBS=ON -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DYASIO_BUILD_TESTS=OFF
cd ..
cmake --build build_osx --config Release
mkdir -p plugin_osx/Plugins/yasio.bundle/Contents/MacOS/
diff --git a/NativeLibs/yasio/build_uwp.bat b/NativeLibs/yasio/build_uwp.bat
index a924fee..4f8484b 100644
--- a/NativeLibs/yasio/build_uwp.bat
+++ b/NativeLibs/yasio/build_uwp.bat
@@ -1,19 +1,20 @@
-cmake -B build_uwp -A Win32 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+set cmake_options=-DBUILD_SHARED_LIBS=ON -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DYASIO_BUILD_TESTS=OFF
+cmake -B build_uwp -A Win32 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" %cmake_options%
cmake --build build_uwp --config MinSizeRel
md plugin_win\Plugins\WSA\x86
copy /Y build_uwp\MinSizeRel\yasio.dll plugin_win\Plugins\WSA\x86\
-cmake -B build_uwp64 -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+cmake -B build_uwp64 -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" %cmake_options%
cmake --build build_uwp64 --config MinSizeRel
md plugin_win\Plugins\WSA\x64
copy /Y build_uwp64\MinSizeRel\yasio.dll plugin_win\Plugins\WSA\x64\
-cmake -B build_uwp_arm -A ARM -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+cmake -B build_uwp_arm -A ARM -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" %cmake_options%
cmake --build build_uwp_arm --config MinSizeRel
md plugin_win\Plugins\WSA\ARM
copy /Y build_uwp_arm\MinSizeRel\yasio.dll plugin_win\Plugins\WSA\ARM\
-cmake -B build_uwp_arm64 -A ARM64 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+cmake -B build_uwp_arm64 -A ARM64 -DCMAKE_SYSTEM_NAME=WindowsStore "-DCMAKE_SYSTEM_VERSION=10.0" %cmake_options%
cmake --build build_uwp_arm64 --config MinSizeRel
md plugin_win\Plugins\WSA\ARM64
copy /Y build_uwp_arm64\MinSizeRel\yasio.dll plugin_win\Plugins\WSA\ARM64\
diff --git a/NativeLibs/yasio/build_win.bat b/NativeLibs/yasio/build_win.bat
index 44f612c..34f57e5 100644
--- a/NativeLibs/yasio/build_win.bat
+++ b/NativeLibs/yasio/build_win.bat
@@ -1,9 +1,12 @@
-cmake -B build_x64 -A x64 -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+set cmake_options=-DBUILD_SHARED_LIBS=ON -DYASIO_NO_DEPS=ON -DYASIO_ENABLE_NI=ON -DYASIO_ENABLE_KCP=ON -DYASIO_BUILD_TESTS=OFF
+cmake -B build_x64 -A x64 %cmake_options%
cmake --build build_x64 --config MinSizeRel
md plugin_win\Plugins\x86_64
copy /y build_x64\MinSizeRel\yasio.dll plugin_win\Plugins\x86_64\
-cmake -B build_x86 -A Win32 -DBUILD_SHARED_LIBS=ON -DYAISO_ENABLE_NI=ON
+cmake -B build_x86 -A Win32 %cmake_options%
cmake --build build_x86 --config MinSizeRel
md plugin_win\Plugins\x86
copy /y build_x86\MinSizeRel\yasio.dll plugin_win\Plugins\x86\
+
+if "%GITHUB_ACTIONS%"=="" copy /y plugin_win\Plugins\x86_64\yasio.dll ..\..\Assets\Plugins\x86_64\
diff --git a/NativeLibs/yasio/kcp/LICENSE b/NativeLibs/yasio/kcp/LICENSE
deleted file mode 100644
index 4f9f28f..0000000
--- a/NativeLibs/yasio/kcp/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 Lin Wei (skywind3000 at gmail.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/NativeLibs/yasio/kcp/README.md b/NativeLibs/yasio/kcp/README.md
deleted file mode 100644
index d44e52c..0000000
--- a/NativeLibs/yasio/kcp/README.md
+++ /dev/null
@@ -1,278 +0,0 @@
-KCP - A Fast and Reliable ARQ Protocol
-======================================
-
-[![Powered][3]][1] [![Build Status][4]][5]
-[](#backers)
- [](#sponsors)
-
-[1]: https://github.com/skywind3000/kcp
-[2]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
-[3]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
-[4]: https://api.travis-ci.org/skywind3000/kcp.svg?branch=master
-[5]: https://travis-ci.org/skywind3000/kcp
-
-[README in English](https://github.com/skywind3000/kcp/blob/master/README.en.md)
-
-# 简介
-
-KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。
-
-整个协议只有 ikcp.h, ikcp.c两个源文件,可以方便的集成到用户自己的协议栈中。也许你实现了一个P2P,或者某个基于 UDP的协议,而缺乏一套完善的ARQ可靠协议实现,那么简单的拷贝这两个文件到现有项目中,稍微编写两行代码,即可使用。
-
-
-# 技术特性
-
-TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利用带宽。而 KCP是为流速设计的(单个数据包从一端发送到一端需要多少时间),以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。TCP信道是一条流速很慢,但每秒流量很大的大运河,而KCP是水流湍急的小激流。KCP有正常模式和快速模式两种,通过以下策略达到提高流速的结果:
-
-#### RTO翻倍vs不翻倍:
-
- TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而KCP启动快速模式后不x2,只是x1.5(实验证明1.5这个值相对比较好),提高了传输速度。
-
-#### 选择性重传 vs 全部重传:
-
- TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。
-
-#### 快速重传:
-
- 发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。
-
-#### 延迟ACK vs 非延迟ACK:
-
- TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用),这样超时计算会算出较大 RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。
-
-#### UNA vs ACK+UNA:
-
- ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而 KCP协议中,除去单独的 ACK包外,所有包都有UNA信息。
-
-#### 非退让流控:
-
- KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。
-
-
-# 快速安装
-
-您可以使用[vcpkg](https://github.com/Microsoft/vcpkg)库管理器下载并安装kcp:
-
- git clone https://github.com/Microsoft/vcpkg.git
- cd vcpkg
- ./bootstrap-vcpkg.sh
- ./vcpkg integrate install
- ./vcpkg install kcp
-
-vcpkg中的kcp库由Microsoft团队成员和社区贡献者保持最新状态。如果版本过时,请在vcpkg存储库上[创建issue或提出PR](https://github.com/Microsoft/vcpkg)。
-
-# 基本使用
-
-1. 创建 KCP对象:
-
- ```cpp
- // 初始化 kcp对象,conv为一个表示会话编号的整数,和tcp的 conv一样,通信双
- // 方需保证 conv相同,相互的数据包才能够被认可,user是一个给回调函数的指针
- ikcpcb *kcp = ikcp_create(conv, user);
- ```
-
-2. 设置回调函数:
-
- ```cpp
- // KCP的下层协议输出函数,KCP需要发送数据时会调用它
- // buf/len 表示缓存和长度
- // user指针为 kcp对象创建时传入的值,用于区别多个 KCP对象
- int udp_output(const char *buf, int len, ikcpcb *kcp, void *user)
- {
- ....
- }
- // 设置回调函数
- kcp->output = udp_output;
- ```
-
-3. 循环调用 update:
-
- ```cpp
- // 以一定频率调用 ikcp_update来更新 kcp状态,并且传入当前时钟(毫秒单位)
- // 如 10ms调用一次,或用 ikcp_check确定下次调用 update的时间不必每次调用
- ikcp_update(kcp, millisec);
- ```
-
-4. 输入一个下层数据包:
-
- ```cpp
- // 收到一个下层数据包(比如UDP包)时需要调用:
- ikcp_input(kcp, received_udp_packet, received_udp_size);
- ```
- 处理了下层协议的输出/输入后 KCP协议就可以正常工作了,使用 ikcp_send 来向
- 远端发送数据。而另一端使用 ikcp_recv(kcp, ptr, size)来接收数据。
-
-
-# 协议配置
-
-协议默认模式是一个标准的 ARQ,需要通过配置打开各项加速开关:
-
-1. 工作模式:
- ```cpp
- int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
- ```
-
- - nodelay :是否启用 nodelay模式,0不启用;1启用。
- - interval :协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms
- - resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
- - nc :是否关闭流控,默认是0代表不关闭,1代表关闭。
- - 普通模式: ikcp_nodelay(kcp, 0, 40, 0, 0);
- - 极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1);
-
-2. 最大窗口:
- ```cpp
- int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
- ```
- 该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32. 这个可以理解为 TCP的 SND_BUF 和 RCV_BUF,只不过单位不一样 SND/RCV_BUF 单位是字节,这个单位是包。
-
-3. 最大传输单元:
-
- 纯算法协议并不负责探测 MTU,默认 mtu是1400字节,可以使用ikcp_setmtu来设置该值。该值将会影响数据包归并及分片时候的最大传输单元。
-
-4. 最小RTO:
-
- 不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值:
- ```cpp
- kcp->rx_minrto = 10;
- ```
-
-
-# 文档索引
-
-协议的使用和配置都是很简单的,大部分情况看完上面的内容基本可以使用了。如果你需要进一步进行精细的控制,比如改变 KCP的内存分配器,或者你需要更有效的大规模调度 KCP链接(比如 3500个以上),或者如何更好的同 TCP结合,那么可以继续延伸阅读:
-
-- [Wiki Home](https://github.com/skywind3000/kcp/wiki)
-- [KCP 最佳实践](https://github.com/skywind3000/kcp/wiki/KCP-Best-Practice)
-- [同现有TCP服务器集成](https://github.com/skywind3000/kcp/wiki/Cooperate-With-Tcp-Server)
-- [传输数据加密](https://github.com/skywind3000/kcp/wiki/Network-Encryption)
-- [应用层流量控制](https://github.com/skywind3000/kcp/wiki/Flow-Control-for-Users)
-- [性能评测](https://github.com/skywind3000/kcp/wiki/KCP-Benchmark)
-
-
-# 开源案例
-
-- [kcptun](https://github.com/xtaci/kcptun): 基于 kcp-go做的高速远程端口转发(隧道) ,配合ssh -D,可以比 shadowsocks 更流畅的看在线视频。
-- [dog-tunnel](https://github.com/vzex/dog-tunnel): GO开发的网络隧道,使用 KCP极大的改进了传输速度,并移植了一份 GO版本 KCP
-- [v2ray](https://www.v2ray.com): 著名代理软件,Shadowsocks 代替者,1.17后集成了 kcp协议,使用UDP传输,无数据包特征。
-- [HP-Socket](https://github.com/ldcsaa/HP-Socket): 高性能网络通信框架 HP-Socket。
-- [frp](https://github.com/fatedier/frp): 高性能内网穿透的反向代理软件,可将将内网服务暴露映射到外网服务器。
-- [asio-kcp](https://github.com/libinzhangyuan/asio_kcp): 使用 KCP的完整 UDP网络库,完整实现了基于 UDP的链接状态管理,会话控制,KCP协议调度等
-- [kcp-java](https://github.com/hkspirt/kcp-java): Java版本 KCP协议实现。
-- [kcp-netty](https://github.com/szhnet/kcp-netty): kcp的Java语言实现,基于netty。
-- [java-kcp](https://github.com/l42111996/java-Kcp): JAVA版本KCP,基于netty实现(包含fec功能)
-- [csharp-kcp](https://github.com/l42111996/csharp-kcp): csharp版本KCP,基于dotNetty实现(包含fec功能)
-- [kcp-cpp](https://github.com/Unit-X/kcp-cpp): KCP 的多平台(Windows、MacOS、Linux)C++ 实现作为应用程序中的简单库。包含适用于所有平台的套接字处理和辅助函数。
-- [kcp-perl](https://github.com/Homqyy/kcp-perl): kcp的Perl实现,其是面向对象的,Perl-Like的。
-- [kcp-go](https://github.com/xtaci/kcp-go): 高安全性的kcp的 GO语言实现,包含 UDP会话管理的简单实现,可以作为后续开发的基础库。
-- [kcp-csharp](https://github.com/limpo1989/kcp-csharp): kcp的 csharp移植,同时包含一份回话管理,可以连接上面kcp-go的服务端。
-- [kcp-csharp](https://github.com/KumoKyaku/KCP): 新版本 Kcp的 csharp移植。线程安全,运行时无alloc,对gc无压力。
-- [kcp2k](https://github.com/vis2k/kcp2k/): Line-by-line translation to C#, with optional Server/Client on top.
-- [kcp-rs](https://github.com/en/kcp-rs): KCP的 rust移植
-- [kcp-rust](https://github.com/Matrix-Zhang/kcp):新版本 KCP的 rust 移植
-- [tokio-kcp](https://github.com/Matrix-Zhang/tokio_kcp):rust tokio 的 kcp 集成
-- [kcp-rust-native](https://github.com/b23r0/kcp-rust-native):rust 的 kcp bindings
-- [lua-kcp](https://github.com/linxiaolong/lua-kcp): KCP的 Lua扩展,用于 Lua服务器
-- [node-kcp](https://github.com/leenjewel/node-kcp): node-js 的 KCP 接口
-- [nysocks](https://github.com/oyyd/nysocks): 基于libuv实现的[node-addon](https://nodejs.org/api/addons.html),提供nodejs版本的代理服务,客户端接入支持SOCKS5和ss两种协议
-- [shadowsocks-android](https://github.com/shadowsocks/shadowsocks-android): Shadowsocks for android 集成了 kcptun 使用 kcp协议加速 shadowsocks,效果不错
-- [kcpuv](https://github.com/elisaday/kcpuv): 使用 libuv开发的kcpuv库,目前还在 Demo阶段
-- [Lantern](https://getlantern.org/):更好的 VPN,Github 50000 星,使用 kcpgo 加速
-- [rpcx](https://github.com/smallnest/rpcx) :RPC 框架,1000+ 星,使用 kcpgo 加速 RPC
-- [xkcptun](https://github.com/liudf0716/xkcptun): c语言实现的kcptun,主要用于[OpenWrt](https://github.com/openwrt/openwrt), [LEDE](https://github.com/lede-project/source)开发的路由器项目上
-- [et-frame](https://github.com/egametang/ET): C#前后端框架(前端unity3d),统一用C#开发游戏,实现了前后端kcp协议
-- [yasio](https://github.com/yasio/yasio): 一个跨平台专注于任意客户端程序的异步socket库, 易于使用,相同的API操作KCP/TCP/UDP, 性能测试结果: [benchmark-pump](https://github.com/yasio/yasio/blob/master/benchmark.md).
-- [gouxp](https://github.com/shaoyuan1943/gouxp): 用Go实现基于回调方式的KCP开发包,包含加解密和FEC支持,简单易用。
-- [skcp](https://github.com/xboss/skcp): 基于libev实现的库,具备传输加密及基本的连接管理能力。
-- [pykcp](https://github.com/enkiller/pykcp): Python 版本的 KCP 实现
-
-# 商业案例
-
-- [原神](https://ys.mihoyo.com/):米哈游的《原神》使用 KCP 降低游戏消息的传输耗时,提升操作的体验。
-- [SpatialOS](https://improbable.io/spatialOS): 大型多人分布式游戏服务端引擎,BigWorld 的后继者,使用 KCP 加速数据传输。
-- [西山居](https://www.xishanju.com/):使用 KCP 进行游戏数据加速。
-- [CC](http://cc.163.com/):网易 CC 使用 kcp 加速视频推流,有效提高流畅性
-- [BOBO](http://bobo.163.com/):网易 BOBO 使用 kcp 加速主播推流
-- [UU](https://uu.163.com):网易 UU 加速器使用 KCP/KCPTUN 经行远程传输加速。
-- [阿里云](https://cn.aliyun.com/):阿里云的视频传输加速服务 GRTN 使用 KCP 进行音视频数据传输优化,动态加速产品也使用 KCP。
-- [云帆加速](http://www.yfcloud.com/):使用 KCP 加速文件传输和视频推流,优化了台湾主播推流的流畅度。
-- [明日帝国](https://www.taptap.com/app/50664):Game K17 的 《明日帝国》 (Google Play),使用 KCP 加速游戏消息,让全球玩家流畅联网
-- [仙灵大作战](https://www.taptap.com/app/27242):4399 的 MOBA游戏,使用 KCP 优化游戏同步
-
-KCP 成功的运行在多个用户规模上亿的项目上,为他们提供了更加灵敏和丝滑网络体验。
-
-欢迎告知更多案例
-
-# 协议比较
-
-如果网络永远不卡,那 KCP/TCP 表现类似,但是网络本身就是不可靠的,丢包和抖动无法避免(否则还要各种可靠协议干嘛)。在内网这种几乎理想的环境里直接比较,大家都差不多,但是放到公网上,放到3G/4G网络情况下,或者使用内网丢包模拟,差距就很明显了。公网在高峰期有平均接近10%的丢包,wifi/3g/4g下更糟糕,这些都会让传输变卡。
-
-感谢 [asio-kcp](https://github.com/libinzhangyuan/asio_kcp) 的作者 [zhangyuan](https://github.com/libinzhangyuan) 对 KCP 与 enet, udt做过的一次横向评测,结论如下:
-
-- ASIO-KCP **has good performace in wifi and phone network(3G, 4G)**.
-- The kcp is the **first choice for realtime pvp game**.
-- The lag is less than 1 second when network lag happen. **3 times better than enet** when lag happen.
-- The enet is a good choice if your game allow 2 second lag.
-- **UDT is a bad idea**. It always sink into badly situation of more than serval seconds lag. And the recovery is not expected.
-- enet has the problem of lack of doc. And it has lots of functions that you may intrest.
-- kcp's doc is chinese. Good thing is the function detail which is writen in code is english. And you can use asio_kcp which is a good wrap.
-- The kcp is a simple thing. You will write more code if you want more feature.
-- UDT has a perfect doc. UDT may has more bug than others as I feeling.
-
-具体见:[横向比较](https://github.com/libinzhangyuan/reliable_udp_bench_mark) 和 [评测数据](https://github.com/skywind3000/kcp/wiki/KCP-Benchmark),为犹豫选择的人提供了更多指引。
-
-大型多人游戏服务端引擎 [SpatialOS](https://improbable.io/spatialOS) 在集成 KCP 协议后做了同 TCP/RakNet 的评测:
-
-
-
-对比了在服务端刷新率为 60 Hz 同时维护 50 个角色时的响应时间,详细对比报告见:
-
-- [Kcp a new low latency secure network stack](https://improbable.io/blog/kcp-a-new-low-latency-secure-network-stack)
-
-
-# 关于协议
-
-近年来,网络游戏和各类社交网络都在成几何倍数的增长,不管网络游戏还是各类互动社交网络,交互性和复杂度都在迅速提高,都需要在极短的时间内将数据同时投递给大量用户,因此传输技术自然变为未来制约发展的一个重要因素,而开源界里各种著名的传输协议,如 raknet/enet 之类,一发布都是整套协议栈一起发布,这种形式是不利于多样化的,我的项目只能选择用或者不用你,很难选择 “部分用你”,然而你一套协议栈设计的再好,是非常难以满足不同角度的各种需求的。
-
-因此 KCP 的方式是把协议栈 “拆开”,让大家可以根据项目需求进行灵活的调整和组装,你可以下面加一层 reed solomon 的纠删码做 FEC,上面加一层类 RC4/Salsa20 做流加密,握手处再设计一套非对称密钥交换,底层 UDP 传输层再做一套动态路由系统,同时探测多条路径,选最好路径进行传输。这些不同的 “协议单元” 可以像搭建积木一般根据需要自由组合,保证 “简单性” 和 “可拆分性”,这样才能灵活适配多变的业务需求,哪个模块不好,换了就是。
-
-未来传输方面的解决方案必然是根据使用场景深度定制的,因此给大家一个可以自由组合的 “协议单元” ,方便大家集成在自己的协议栈中。
-
-For more information, please see the [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
-
-
-# 关于作者
-
-作者:林伟 (skywind3000)
-
-欢迎关注我的:[twitter](https://twitter.com/skywind3000) 和 [zhihu](https://www.zhihu.com/people/skywind3000)。
-
-我在多年的开发经历中,一直都喜欢研究解决程序中的一些瓶颈问题,早年喜欢游戏开发,照着《VGA编程》来做游戏图形,读 Michael Abrash 的《图形程序开发人员指南》做软渲染器,爱好摆弄一些能够榨干 CPU 能够运行更快的代码,参加工作后,兴趣转移到服务端和网络相关的技术。
-
-2007 年时做了几个传统游戏后开始研究快速动作游戏的同步问题,期间写过不少文章,算是国内比较早研究同步问题的人,然而发现不管怎么解决同步都需要在网络传输方面有所突破,后来离开游戏转行互联网后也发现不少领域有这方面的需求,于是开始花时间在网络传输这个领域上,尝试基于 UDP 实现一些保守的可靠协议,仿照 BSD Lite 4.4 的代码实现一些类 TCP 协议,觉得比较有意思,又接着实现一些 P2P 和动态路由网相关的玩具。KCP 协议诞生于 2011 年,基本算是自己传输方面做的几个玩具中的一个。
-
-Kcptun 的作者 xtaci 是我的大学同学,我俩都是学通信的,经常在一起研究如何进行传输优化。
-
-# 欢迎捐赠
-
-
-
-欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。
-
-感谢:明明、星仔、进、帆、颁钊、斌铨、晓丹、余争、虎、晟敢、徐玮、王川、赵刚强、胡知锋、万新朝、何新超、刘旸、侯宪辉、吴佩仪、华斌、如涛、胡坚。。。(早先的名单实在不好意思没记录下来)等同学的捐助与支持。
-
-
-欢迎关注
-
-KCP交流群:364933586(QQ群号),KCP集成,调优,网络传输以及相关技术讨论
-
-Gitter 群:https://gitter.im/skywind3000/KCP
-
-blog: http://www.skywind.me
-
-
-
-## Contributors
-
-This project exists thanks to all the people who contribute.
-
-
diff --git a/NativeLibs/yasio/manifest.json b/NativeLibs/yasio/manifest.json
new file mode 100644
index 0000000..9ed3a2a
--- /dev/null
+++ b/NativeLibs/yasio/manifest.json
@@ -0,0 +1,14 @@
+{
+ "versions": {
+ "1kdist": "72"
+ },
+ "mirrors": {
+ "github": {
+ "1kdist": "simdsoft/1kiss/releases/download"
+ },
+ "gitee":
+ {
+ "1kdist": "simdsoft/1kiss/releases/download"
+ }
+ }
+}
diff --git a/NativeLibs/yasio/yasio/bindings/lyasio.cpp b/NativeLibs/yasio/yasio/bindings/lyasio.cpp
index 1866220..53fc916 100644
--- a/NativeLibs/yasio/yasio/bindings/lyasio.cpp
+++ b/NativeLibs/yasio/yasio/bindings/lyasio.cpp
@@ -4,7 +4,7 @@
//////////////////////////////////////////////////////////////////////////////////////////
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
@@ -259,13 +259,13 @@ YASIO_LUA_API int luaopen_yasio(lua_State* L)
"write",
sol::overload(
[](io_service* service, transport_handle_t transport, cxx17::string_view s) {
- return service->write(transport, yasio::sbyte_buffer{s.data(), s.data() + s.length(), std::true_type{}});
+ return service->write(transport, yasio::sbyte_buffer{s.data(), s.data() + s.length()});
},
[](io_service* service, transport_handle_t transport, yasio::obstream* obs) { return service->write(transport, std::move(obs->buffer())); }),
"write_to",
sol::overload(
[](io_service* service, transport_handle_t transport, cxx17::string_view s, cxx17::string_view ip, u_short port) {
- return service->write_to(transport, yasio::sbyte_buffer{s.data(), s.data() + s.length(), std::true_type{}}, ip::endpoint{ip.data(), port});
+ return service->write_to(transport, yasio::sbyte_buffer{s.data(), s.data() + s.length()}, ip::endpoint{ip.data(), port});
},
[](io_service* service, transport_handle_t transport, yasio::obstream* obs, cxx17::string_view ip, u_short port) {
return service->write_to(transport, std::move(obs->buffer()), ip::endpoint{ip.data(), port});
@@ -298,63 +298,67 @@ YASIO_LUA_API int luaopen_yasio(lua_State* L)
};
// ##-- yasio enums
-# define YASIO_EXPORT_ENUM(v) yasio_lib[#v] = v
- YASIO_EXPORT_ENUM(YCK_TCP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_TCP_SERVER);
- YASIO_EXPORT_ENUM(YCK_UDP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_UDP_SERVER);
+# define YASIO_EXPORT_ANY(v) yasio_lib[#v] = v
+ YASIO_EXPORT_ANY(YCK_TCP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_TCP_SERVER);
+ YASIO_EXPORT_ANY(YCK_UDP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_UDP_SERVER);
# if defined(YASIO_ENABLE_KCP)
- YASIO_EXPORT_ENUM(YCK_KCP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_KCP_SERVER);
+ YASIO_EXPORT_ANY(YCK_KCP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_KCP_SERVER);
# endif
# if defined(YASIO_SSL_BACKEND)
- YASIO_EXPORT_ENUM(YCK_SSL_CLIENT);
+ YASIO_EXPORT_ANY(YCK_SSL_CLIENT);
# endif
- YASIO_EXPORT_ENUM(YOPT_S_CONNECT_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_DNS_CACHE_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_DNS_QUERIES_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_TCP_KEEPALIVE);
- YASIO_EXPORT_ENUM(YOPT_S_EVENT_CB);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_PARAMS);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_STRIP);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_NO_BSWAP);
- YASIO_EXPORT_ENUM(YOPT_C_LFBFD_PARAMS); // alias for YOPT_C_UNPACK_PARAMS
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_HOST);
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_PORT);
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_ENDPOINT);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_HOST);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_PORT);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_ENDPOINT);
- YASIO_EXPORT_ENUM(YOPT_C_ENABLE_MCAST);
- YASIO_EXPORT_ENUM(YOPT_C_DISABLE_MCAST);
+ YASIO_EXPORT_ANY(YOPT_S_CONNECT_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_DNS_CACHE_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_DNS_QUERIES_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_TCP_KEEPALIVE);
+ YASIO_EXPORT_ANY(YOPT_S_EVENT_CB);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_PARAMS);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_STRIP);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_NO_BSWAP);
+ YASIO_EXPORT_ANY(YOPT_C_LFBFD_PARAMS); // alias for YOPT_C_UNPACK_PARAMS
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_HOST);
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_PORT);
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_ENDPOINT);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_HOST);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_PORT);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_ENDPOINT);
+ YASIO_EXPORT_ANY(YOPT_C_ENABLE_MCAST);
+ YASIO_EXPORT_ANY(YOPT_C_DISABLE_MCAST);
# if defined(YASIO_ENABLE_KCP)
- YASIO_EXPORT_ENUM(YOPT_C_KCP_CONV);
- YASIO_EXPORT_ENUM(YOPT_C_KCP_NODELAY);
- YASIO_EXPORT_ENUM(YOPT_C_KCP_WINDOW_SIZE);
- YASIO_EXPORT_ENUM(YOPT_C_KCP_MTU);
- YASIO_EXPORT_ENUM(YOPT_C_KCP_RTO_MIN);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_CONV);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_NODELAY);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_WINDOW_SIZE);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_MTU);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_RTO_MIN);
# endif
- YASIO_EXPORT_ENUM(YOPT_C_MOD_FLAGS);
+ YASIO_EXPORT_ANY(YOPT_C_MOD_FLAGS);
- YASIO_EXPORT_ENUM(YCF_REUSEADDR);
- YASIO_EXPORT_ENUM(YCF_EXCLUSIVEADDRUSE);
+ YASIO_EXPORT_ANY(YCF_REUSEADDR);
+ YASIO_EXPORT_ANY(YCF_EXCLUSIVEADDRUSE);
- YASIO_EXPORT_ENUM(YEK_ON_OPEN);
- YASIO_EXPORT_ENUM(YEK_ON_CLOSE);
- YASIO_EXPORT_ENUM(YEK_ON_PACKET);
- YASIO_EXPORT_ENUM(YEK_CONNECT_RESPONSE);
- YASIO_EXPORT_ENUM(YEK_CONNECTION_LOST);
- YASIO_EXPORT_ENUM(YEK_PACKET);
+ YASIO_EXPORT_ANY(YEK_ON_OPEN);
+ YASIO_EXPORT_ANY(YEK_ON_CLOSE);
+ YASIO_EXPORT_ANY(YEK_ON_PACKET);
+ YASIO_EXPORT_ANY(YEK_CONNECT_RESPONSE);
+ YASIO_EXPORT_ANY(YEK_CONNECTION_LOST);
+ YASIO_EXPORT_ANY(YEK_PACKET);
- YASIO_EXPORT_ENUM(SEEK_CUR);
- YASIO_EXPORT_ENUM(SEEK_SET);
- YASIO_EXPORT_ENUM(SEEK_END);
+ YASIO_EXPORT_ANY(SEEK_CUR);
+ YASIO_EXPORT_ANY(SEEK_SET);
+ YASIO_EXPORT_ANY(SEEK_END);
using namespace lyasio;
- YASIO_EXPORT_ENUM(BUFFER_DEFAULT);
- YASIO_EXPORT_ENUM(BUFFER_RAW);
- YASIO_EXPORT_ENUM(BUFFER_FAST);
+ YASIO_EXPORT_ANY(BUFFER_DEFAULT);
+ YASIO_EXPORT_ANY(BUFFER_RAW);
+ YASIO_EXPORT_ANY(BUFFER_FAST);
+
+ char version[32];
+ snprintf(version, sizeof(version), "%x.%x.%x", (YASIO_VERSION_NUM >> 16) & 0xff, (YASIO_VERSION_NUM >> 8) & 0xff, YASIO_VERSION_NUM & 0xff);
+ YASIO_EXPORT_ANY(version);
return yasio_lib.push(); /* return 'yasio' table */
}
@@ -399,7 +403,7 @@ struct lua_type_traits {
{
size_t size = 0;
const char* buffer = lua_tolstring(l, index, &size);
- return yasio::sbyte_buffer(buffer, buffer + size, std::true_type{});
+ return yasio::sbyte_buffer(buffer, buffer + size);
}
static int push(lua_State* l, push_type s)
{
@@ -737,57 +741,61 @@ end
});
// ##-- yasio enums
-# define YASIO_EXPORT_ENUM(v) yasio_lib[#v] = v
- YASIO_EXPORT_ENUM(YCK_TCP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_TCP_SERVER);
- YASIO_EXPORT_ENUM(YCK_UDP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_UDP_SERVER);
+# define YASIO_EXPORT_ANY(v) yasio_lib[#v] = v
+ YASIO_EXPORT_ANY(YCK_TCP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_TCP_SERVER);
+ YASIO_EXPORT_ANY(YCK_UDP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_UDP_SERVER);
# if defined(YASIO_ENABLE_KCP)
- YASIO_EXPORT_ENUM(YCK_KCP_CLIENT);
- YASIO_EXPORT_ENUM(YCK_KCP_SERVER);
+ YASIO_EXPORT_ANY(YCK_KCP_CLIENT);
+ YASIO_EXPORT_ANY(YCK_KCP_SERVER);
# endif
# if YASIO_SSL_BACKEND
- YASIO_EXPORT_ENUM(YCK_SSL_CLIENT);
+ YASIO_EXPORT_ANY(YCK_SSL_CLIENT);
# endif
- YASIO_EXPORT_ENUM(YOPT_S_CONNECT_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_DNS_CACHE_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_DNS_QUERIES_TIMEOUT);
- YASIO_EXPORT_ENUM(YOPT_S_TCP_KEEPALIVE);
- YASIO_EXPORT_ENUM(YOPT_S_EVENT_CB);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_PARAMS);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_STRIP);
- YASIO_EXPORT_ENUM(YOPT_C_UNPACK_NO_BSWAP);
- YASIO_EXPORT_ENUM(YOPT_C_LFBFD_PARAMS); // alias for YOPT_C_UNPACK_PARAMS
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_HOST);
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_PORT);
- YASIO_EXPORT_ENUM(YOPT_C_LOCAL_ENDPOINT);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_HOST);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_PORT);
- YASIO_EXPORT_ENUM(YOPT_C_REMOTE_ENDPOINT);
- YASIO_EXPORT_ENUM(YOPT_C_ENABLE_MCAST);
- YASIO_EXPORT_ENUM(YOPT_C_DISABLE_MCAST);
- YASIO_EXPORT_ENUM(YOPT_C_KCP_CONV);
- YASIO_EXPORT_ENUM(YOPT_C_MOD_FLAGS);
-
- YASIO_EXPORT_ENUM(YCF_REUSEADDR);
- YASIO_EXPORT_ENUM(YCF_EXCLUSIVEADDRUSE);
-
- YASIO_EXPORT_ENUM(YEK_ON_OPEN);
- YASIO_EXPORT_ENUM(YEK_ON_CLOSE);
- YASIO_EXPORT_ENUM(YEK_ON_PACKET);
- YASIO_EXPORT_ENUM(YEK_CONNECT_RESPONSE);
- YASIO_EXPORT_ENUM(YEK_CONNECTION_LOST);
- YASIO_EXPORT_ENUM(YEK_PACKET);
-
- YASIO_EXPORT_ENUM(SEEK_CUR);
- YASIO_EXPORT_ENUM(SEEK_SET);
- YASIO_EXPORT_ENUM(SEEK_END);
+ YASIO_EXPORT_ANY(YOPT_S_CONNECT_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_DNS_CACHE_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_DNS_QUERIES_TIMEOUT);
+ YASIO_EXPORT_ANY(YOPT_S_TCP_KEEPALIVE);
+ YASIO_EXPORT_ANY(YOPT_S_EVENT_CB);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_PARAMS);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_STRIP);
+ YASIO_EXPORT_ANY(YOPT_C_UNPACK_NO_BSWAP);
+ YASIO_EXPORT_ANY(YOPT_C_LFBFD_PARAMS); // alias for YOPT_C_UNPACK_PARAMS
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_HOST);
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_PORT);
+ YASIO_EXPORT_ANY(YOPT_C_LOCAL_ENDPOINT);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_HOST);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_PORT);
+ YASIO_EXPORT_ANY(YOPT_C_REMOTE_ENDPOINT);
+ YASIO_EXPORT_ANY(YOPT_C_ENABLE_MCAST);
+ YASIO_EXPORT_ANY(YOPT_C_DISABLE_MCAST);
+ YASIO_EXPORT_ANY(YOPT_C_KCP_CONV);
+ YASIO_EXPORT_ANY(YOPT_C_MOD_FLAGS);
+
+ YASIO_EXPORT_ANY(YCF_REUSEADDR);
+ YASIO_EXPORT_ANY(YCF_EXCLUSIVEADDRUSE);
+
+ YASIO_EXPORT_ANY(YEK_ON_OPEN);
+ YASIO_EXPORT_ANY(YEK_ON_CLOSE);
+ YASIO_EXPORT_ANY(YEK_ON_PACKET);
+ YASIO_EXPORT_ANY(YEK_CONNECT_RESPONSE);
+ YASIO_EXPORT_ANY(YEK_CONNECTION_LOST);
+ YASIO_EXPORT_ANY(YEK_PACKET);
+
+ YASIO_EXPORT_ANY(SEEK_CUR);
+ YASIO_EXPORT_ANY(SEEK_SET);
+ YASIO_EXPORT_ANY(SEEK_END);
using namespace lyasio;
- YASIO_EXPORT_ENUM(BUFFER_DEFAULT);
- YASIO_EXPORT_ENUM(BUFFER_RAW);
- YASIO_EXPORT_ENUM(BUFFER_FAST);
+ YASIO_EXPORT_ANY(BUFFER_DEFAULT);
+ YASIO_EXPORT_ANY(BUFFER_RAW);
+ YASIO_EXPORT_ANY(BUFFER_FAST);
+
+ char version[32];
+ snprintf(version, sizeof(version), "%x.%x.%x", (YASIO_VERSION_NUM >> 16) & 0xff, (YASIO_VERSION_NUM >> 8) & 0xff, YASIO_VERSION_NUM & 0xff);
+ YASIO_EXPORT_ANY(version);
return yasio_lib.push(); /* return 'yasio' table */
}
diff --git a/NativeLibs/yasio/yasio/bindings/lyasio.hpp b/NativeLibs/yasio/yasio/bindings/lyasio.hpp
index 3bb4d7f..481bf78 100644
--- a/NativeLibs/yasio/yasio/bindings/lyasio.hpp
+++ b/NativeLibs/yasio/yasio/bindings/lyasio.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_axlua.cpp b/NativeLibs/yasio/yasio/bindings/yasio_axlua.cpp
index a4c3996..00ba10a 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_axlua.cpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_axlua.cpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
+
+#include "sol/sol.hpp"
#include "yasio/bindings/yasio_axlua.hpp"
#include "yasio/bindings/lyasio.hpp"
#include "yasio/object_pool.hpp"
@@ -118,12 +120,6 @@ YASIO_LUA_API void clear()
#if YASIO__HAS_CXX14
-# if YASIO__HAS_CXX17
-# include "sol/sol.hpp"
-# else
-# include "sol2/sol.hpp"
-# endif
-
extern "C" {
struct lua_State;
YASIO_LUA_API int luaopen_yasio_axlua(lua_State* L)
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_axlua.hpp b/NativeLibs/yasio/yasio/bindings/yasio_axlua.hpp
index c60735f..45854fa 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_axlua.hpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_axlua.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_jsb.cpp b/NativeLibs/yasio/yasio/bindings/yasio_jsb.cpp
index 2aa60b6..1a7f24d 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_jsb.cpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_jsb.cpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_jsb.hpp b/NativeLibs/yasio/yasio/bindings/yasio_jsb.hpp
index a775e20..56c00fc 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_jsb.hpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_jsb.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_jsb20.cpp b/NativeLibs/yasio/yasio/bindings/yasio_jsb20.cpp
index 9c8b244..1e59762 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_jsb20.cpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_jsb20.cpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -27,16 +27,25 @@ SOFTWARE.
*/
#define YASIO_HEADER_ONLY 1
#define YASIO_HAVE_KCP 1
+#define YASIO_ENABLE_KCP 1
#define YASIO_OBS_BUILTIN_STACK 1
#include "yasio/yasio.hpp"
#include "yasio/ref_ptr.hpp"
+#if __has_include()
+# include "cocos-version.h"
+#endif
+
#if __has_include() || defined(YASIO_CREATOR_30_OR_LATER)
# include "cocos/bindings/jswrapper/SeApi.h"
# include "cocos/bindings/manual/jsb_conversions.h"
# include "cocos/bindings/manual/jsb_global.h"
-# include "cocos/platform/Application.h"
+# if __has_include()
+# include "cocos/platform/Application.h"
+# elif __has_include()
+# include "cocos/application/ApplicationManager.h"
+# endif
# include "cocos/base/Scheduler.h"
# include "cocos/base/StringUtil.h"
using namespace cc;
@@ -86,6 +95,13 @@ enum
BUFFER_FAST,
};
+// since 3.5 use ApplicationManager
+#if defined(COCOS_MAJOR_VERSION) && COCOS_MAJOR_VERSION >= 3 && COCOS_MINJOR_VERSION >= 5
+# define YASIO_JSB_SCHE CC_CURRENT_ENGINE()->getScheduler()
+#else
+# define YASIO_JSB_SCHE Application::getInstance()->getScheduler()
+#endif
+
namespace stimer
{
// The STIMER fake target: 0xfffffffe, well, any system's malloc never return a object address
@@ -101,7 +117,7 @@ struct TimerObject {
vcallback_t callback_;
static uintptr_t s_timerId;
- DEFINE_OBJECT_POOL_ALLOCATION(TimerObject, 128)
+ DEFINE_CONCURRENT_OBJECT_POOL_ALLOCATION(TimerObject, 128)
YASIO_DEFINE_REFERENCE_CLASS
};
uintptr_t TimerObject::s_timerId = 0;
@@ -116,7 +132,7 @@ TIMER_ID loop(unsigned int n, float interval, vcallback_t callback)
std::string key = StringUtil::format("STMR#%p", timerId);
- Application::getInstance()->getScheduler()->schedule(
+ YASIO_JSB_SCHE->schedule(
[timerObj](float /*dt*/) { // lambda expression hold the reference of timerObj automatically.
timerObj->callback_();
},
@@ -135,7 +151,7 @@ TIMER_ID delay(float delay, vcallback_t callback)
auto timerId = reinterpret_cast(++TimerObject::s_timerId);
std::string key = StringUtil::format("STMR#%p", timerId);
- Application::getInstance()->getScheduler()->schedule(
+ YASIO_JSB_SCHE->schedule(
[timerObj](float /*dt*/) { // lambda expression hold the reference of timerObj automatically.
timerObj->callback_();
},
@@ -149,9 +165,9 @@ TIMER_ID delay(float delay, vcallback_t callback)
void kill(TIMER_ID timerId)
{
std::string key = StringUtil::format("STMR#%p", timerId);
- Application::getInstance()->getScheduler()->unschedule(key, STIMER_TARGET_VALUE);
+ YASIO_JSB_SCHE->unschedule(key, STIMER_TARGET_VALUE);
}
-void clear() { Application::getInstance()->getScheduler()->unscheduleAllForTarget(STIMER_TARGET_VALUE); }
+void clear() { YASIO_JSB_SCHE->unscheduleAllForTarget(STIMER_TARGET_VALUE); }
} // namespace stimer
} // namespace yasio_jsb
@@ -182,8 +198,8 @@ bool jsb_yasio_setTimeout(se::State& s)
}
};
- float timeout = 0;
- seval_to_float(arg1, &timeout);
+ float timeout = arg1.toFloat();
+
auto timerId = yasio_jsb::stimer::delay(timeout, std::move(callback));
s.rval().setNumber((double)(int64_t)timerId);
@@ -222,8 +238,7 @@ bool jsb_yasio_setInterval(se::State& s)
}
};
- float interval = 0;
- seval_to_float(arg1, &interval);
+ float interval = arg1.toFloat();
auto timerId = yasio_jsb::stimer::loop((std::numeric_limits::max)(), interval, std::move(callback));
s.rval().setNumber((double)(int64_t)timerId);
@@ -340,36 +355,49 @@ cxx17::string_view seval_to_string_view(const se::Value& v, bool* unrecognized_o
//////////////////// common template functions //////////////
+#if defined(JSB_MAKE_PRIVATE_OBJECT)
+#define YASIO_JSB_USE_SHARED_OBJECT 1
+# define yasio_jsb_make_object(kls, ...) JSB_MAKE_PRIVATE_OBJECT(kls, __VA_ARGS__)
+#else
+# define yasio_jsb_make_object(kls, ...) new kls(__VA_ARGS__)
+#endif
+
template
static bool jsb_yasio__ctor(se::State& s)
{
- auto cobj = new T();
+ auto cobj = yasio_jsb_make_object(T);
+#if defined(YASIO_JSB_USE_SHARED_OBJECT)
+ s.thisObject()->setPrivateObject(cobj);
+#else
s.thisObject()->setPrivateData(cobj);
se::NonRefNativePtrCreatedByCtorMap::emplace(cobj);
+#endif
return true;
}
template
static bool jsb_yasio__dtor(se::State& s)
{
+#if !defined(JSB_MAKE_PRIVATE_OBJECT)
auto iter = se::NonRefNativePtrCreatedByCtorMap::find(s.nativeThisObject());
if (iter != se::NonRefNativePtrCreatedByCtorMap::end())
- {
+ { // finalize created by ctor < 3.6.0
CC_LOG_DEBUG("jsbindings: finalizing JS object(created by ctor) %p(%s)", s.nativeThisObject(), typeid(T).name());
se::NonRefNativePtrCreatedByCtorMap::erase(iter);
T* cobj = reinterpret_cast(s.nativeThisObject());
delete cobj;
+ return true;
}
- else
- { // finalize not created by ctor
- auto iter2 = se::NativePtrToObjectMap::find(s.nativeThisObject());
- if (iter2 != se::NativePtrToObjectMap::end())
- {
- CC_LOG_DEBUG("jsbindings: finalizing JS object(created by native) %p(%s)", s.nativeThisObject(), typeid(T).name());
- T* cobj = reinterpret_cast(s.nativeThisObject());
- delete cobj;
- }
+#else
+ // finalize not created by ctor
+ auto iter2 = se::NativePtrToObjectMap::find(s.nativeThisObject());
+ if (iter2 != se::NativePtrToObjectMap::end())
+ {
+ CC_LOG_DEBUG("jsbindings: finalizing JS object(created by native) %p(%s)", s.nativeThisObject(), typeid(T).name());
+ T* cobj = reinterpret_cast(s.nativeThisObject());
+ delete cobj;
}
+#endif
return true;
}
@@ -604,22 +632,22 @@ static bool jsb_yasio_obstream__ctor(se::State& s)
const auto& args = s.args();
size_t argc = args.size();
- yasio::obstream* cobj = nullptr;
- if (argc == 0)
- {
- cobj = new yasio::obstream();
- }
- else
+ int capacity = 128;
+ if (argc >= 1)
{
auto arg0 = args[0];
if (arg0.isNumber())
- cobj = new yasio::obstream(arg0.toUint32());
- else
- cobj = new yasio::obstream();
+ capacity = arg0.toUint32();
}
+ auto cobj = yasio_jsb_make_object(yasio::obstream, capacity);
+
+#if defined(YASIO_JSB_USE_SHARED_OBJECT)
+ s.thisObject()->setPrivateObject(cobj);
+#else
s.thisObject()->setPrivateData(cobj);
se::NonRefNativePtrCreatedByCtorMap::emplace(cobj);
+#endif
return true;
}
@@ -795,8 +823,12 @@ static bool js_yasio_obstream_write_dx(se::State& s)
const auto& args = s.args();
size_t argc = args.size();
+#if defined(COCOS_MAJOR_VERSION) && COCOS_MAJOR_VERSION >= 3 && COCOS_MINJOR_VERSION >= 6
+ double argval = args[0].toDouble();
+#else
double argval = 0;
seval_to_double(args[0], &argval);
+#endif
cobj->write(static_cast(argval));
s.rval().setUndefined();
@@ -894,10 +926,8 @@ bool js_yasio_obstream_sub(se::State& s)
{
count = args[1].toInt32();
}
-
auto subobj = new yasio::obstream(cobj->sub(offset, count));
native_ptr_to_seval(subobj, &s.rval());
-
return true;
} while (false);
@@ -1003,11 +1033,11 @@ bool js_yasio_io_event_packet(se::State& s)
case yasio_jsb::BUFFER_RAW:
s.rval().setObject(se::HandleObject(se::Object::createArrayBufferObject(packet.data(), packet.size())));
break;
- case yasio_jsb::BUFFER_FAST:
- native_ptr_to_seval(new yasio::ibstream(yasio::forward_packet((yasio::packet &&) packet)), &s.rval());
+ case yasio_jsb::BUFFER_FAST: // fast_ibstream also require export otherwise will assert fail
+ // native_ptr_to_seval(new yasio::fast_ibstream(yasio::forward_packet((yasio::packet_t &&) packet)), &s.rval());
break;
default:
- native_ptr_to_seval(new yasio::fast_ibstream(yasio::forward_packet((yasio::packet &&) packet)), &s.rval());
+ native_ptr_to_seval(new yasio::ibstream(yasio::forward_packet((yasio::packet_t &&) packet)), &s.rval());
}
}
else
@@ -1083,7 +1113,11 @@ se::Class* __jsb_yasio_io_service_class = nullptr;
static bool jsb_yasio_io_service__ctor(se::State& s)
{
+#if defined(YASIO_JSB_USE_SHARED_OBJECT)
+ se::PrivateObjectBase* cobj = nullptr;
+ #else
io_service* cobj = nullptr;
+ #endif
const auto& args = s.args();
size_t argc = args.size();
@@ -1096,23 +1130,28 @@ static bool jsb_yasio_io_service__ctor(se::State& s)
{
std::vector hostents;
seval_to_std_vector_hostent(arg0, &hostents);
- cobj = new io_service(!hostents.empty() ? &hostents.front() : nullptr, (std::max)((int)hostents.size(), 1));
+ cobj = yasio_jsb_make_object(io_service, !hostents.empty() ? &hostents.front() : nullptr, (std::max)((int)hostents.size(), 1));
}
else
{
inet::io_hostent ioh;
seval_to_hostent(arg0, &ioh);
- cobj = new io_service(&ioh, 1);
+ cobj = yasio_jsb_make_object(io_service, &ioh, 1);
}
}
else if (arg0.isNumber())
- cobj = new io_service(arg0.toInt32());
+ cobj = yasio_jsb_make_object(io_service, arg0.toInt32());
}
else
- cobj = new io_service();
+ cobj = yasio_jsb_make_object(io_service);
+#if defined(YASIO_JSB_USE_SHARED_OBJECT)
+ s.thisObject()->setPrivateObject(cobj);
+#else
s.thisObject()->setPrivateData(cobj);
se::NonRefNativePtrCreatedByCtorMap::emplace(cobj);
+#endif
+
return true;
}
@@ -1499,10 +1538,14 @@ bool jsb_register_yasio(se::Object* obj)
// ##-- yasio enums
se::Value __jsvalIntVal;
-#define YASIO_SET_INT_PROP(name, value) \
+#define YASIO_EXPORT_ENUM(value) \
__jsvalIntVal.setInt32(value); \
- yasio->setProperty(name, __jsvalIntVal)
-#define YASIO_EXPORT_ENUM(v) YASIO_SET_INT_PROP(#v, v)
+ yasio->setProperty(#value, __jsvalIntVal)
+
+#define YASIO_EXPORT_STR(value) \
+ __jsvalIntVal.setString(value); \
+ yasio->setProperty(#value, __jsvalIntVal)
+
YASIO_EXPORT_ENUM(YCK_TCP_CLIENT);
YASIO_EXPORT_ENUM(YCK_TCP_SERVER);
YASIO_EXPORT_ENUM(YCK_UDP_CLIENT);
@@ -1554,6 +1597,10 @@ bool jsb_register_yasio(se::Object* obj)
YASIO_EXPORT_ENUM(SEEK_SET);
YASIO_EXPORT_ENUM(SEEK_END);
+ char version[32];
+ snprintf(version, sizeof(version), "%x.%x.%x", (YASIO_VERSION_NUM >> 16) & 0xff, (YASIO_VERSION_NUM >> 8) & 0xff, YASIO_VERSION_NUM & 0xff);
+ YASIO_EXPORT_STR(version);
+
using namespace yasio_jsb;
YASIO_EXPORT_ENUM(BUFFER_DEFAULT);
YASIO_EXPORT_ENUM(BUFFER_RAW);
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_jsb20.hpp b/NativeLibs/yasio/yasio/bindings/yasio_jsb20.hpp
index 27ce488..31093e2 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_jsb20.hpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_jsb20.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_ni.cpp b/NativeLibs/yasio/yasio/bindings/yasio_ni.cpp
index 181ef58..94f32f5 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_ni.cpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_ni.cpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -77,21 +77,32 @@ YASIO_NI_API void yasio_init_globals(void(YASIO_INTEROP_DECL* pfn)(int level, co
}
YASIO_NI_API void yasio_cleanup_globals() { io_service::cleanup_globals(); }
-struct yasio_event_data {
- int kind;
- int status;
- int channel;
- void* session; // transport
- void* packet;
- void* user; // event source
+struct yasio_io_event {
+ int kind; //
+ int channel;
+ void* thandle;
+ union {
+ void* msg;
+ int status; //
+ };
+ void* user;
};
-YASIO_NI_API void* yasio_create_service(int channel_count, void(YASIO_INTEROP_DECL* event_cb)(yasio_event_data* event), void* user)
+
+YASIO_NI_API void* yasio_create_service(int channel_count, void(YASIO_INTEROP_DECL* event_cb)(yasio_io_event* event), void* user)
{
assert(!!event_cb);
io_service* service = new io_service(channel_count);
service->start([=](event_ptr e) {
auto& pkt = e->packet();
- yasio_event_data event{e->kind(), e->status(), e->cindex(), e->transport(), !is_packet_empty(pkt) ? &pkt : nullptr, user};
+ yasio_io_event event;
+ event.kind = e->kind();
+ event.channel = e->cindex();
+ event.thandle = e->transport();
+ event.user = user;
+ if (event.kind == yasio::YEK_ON_PACKET)
+ event.msg = !is_packet_empty(pkt) ? &pkt : nullptr;
+ else
+ event.status = e->status();
event_cb(&event);
});
return service;
@@ -232,22 +243,24 @@ YASIO_NI_API void yasio_close_handle(void* service_ptr, void* thandle)
if (service)
service->close(reinterpret_cast(thandle));
}
-YASIO_NI_API int yasio_write(void* service_ptr, void* thandle, const unsigned char* bytes, int len)
+YASIO_NI_API int yasio_write(void* service_ptr, void* thandle, const char* bytes, int len)
{
auto service = reinterpret_cast(service_ptr);
if (service)
- return service->write(reinterpret_cast(thandle), yasio::sbyte_buffer(bytes, bytes + len, std::true_type{}));
+ return service->write(reinterpret_cast(thandle), yasio::sbyte_buffer(bytes, bytes + len));
return -1;
}
-YASIO_NI_API int yasio_forward(void* service_ptr, void* thandle, void* bufferHandle, const unsigned char*(YASIO_INTEROP_DECL* pfnLockBuffer)(void* bufferHandle, int* bufferDataLen), void(YASIO_INTEROP_DECL* pfnUnlockBuffer)(void* bufferHandle))
+YASIO_NI_API int yasio_forward(void* service_ptr, void* thandle, void* bufferHandle,
+ const char*(YASIO_INTEROP_DECL* pfnLockBuffer)(void* bufferHandle, int* bufferDataLen),
+ void(YASIO_INTEROP_DECL* pfnUnlockBuffer)(void* bufferHandle))
{
auto service = reinterpret_cast(service_ptr);
- if (service) {
- int len = 0;
+ if (service)
+ {
+ int len = 0;
auto bytes = pfnLockBuffer(bufferHandle, &len);
- return service->forward(reinterpret_cast(thandle), bytes, len, [bufferHandle,pfnUnlockBuffer](int,size_t){
- pfnUnlockBuffer(bufferHandle);
- });
+ return service->forward(reinterpret_cast(thandle), bytes, len,
+ [bufferHandle, pfnUnlockBuffer](int, size_t) { pfnUnlockBuffer(bufferHandle); });
}
return -1;
}
diff --git a/NativeLibs/yasio/yasio/bindings/yasio_sol.hpp b/NativeLibs/yasio/yasio/bindings/yasio_sol.hpp
index 8de03fc..8945df6 100644
--- a/NativeLibs/yasio/yasio/bindings/yasio_sol.hpp
+++ b/NativeLibs/yasio/yasio/bindings/yasio_sol.hpp
@@ -4,7 +4,7 @@
//////////////////////////////////////////////////////////////////////////////////////////
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
diff --git a/NativeLibs/yasio/yasio/buffer_alloc.hpp b/NativeLibs/yasio/yasio/buffer_alloc.hpp
new file mode 100644
index 0000000..8947804
--- /dev/null
+++ b/NativeLibs/yasio/yasio/buffer_alloc.hpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////////////////
+// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
+// client application.
+//////////////////////////////////////////////////////////////////////////////////////////
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-2024 HALX99
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef YASIO__BUFFER_ALLOC_HPP
+#define YASIO__BUFFER_ALLOC_HPP
+#include
+#include
+#include
+#include
+#include
+#include "yasio/compiler/feature_test.hpp"
+#include "yasio/type_traits.hpp"
+
+#define _YASIO_VERIFY_RANGE(cond, mesg) \
+ do \
+ { \
+ if (cond) \
+ ; /* contextually convertible to bool paranoia */ \
+ else \
+ { \
+ throw std::out_of_range(mesg); \
+ } \
+ \
+ } while (false)
+
+namespace yasio
+{
+template
+struct buffer_allocator_traits {
+ using value_type = typename _Alty::value_type;
+ using size_type = size_t;
+ static YASIO__CONSTEXPR size_type max_size() { return static_cast(-1) / sizeof(value_type); }
+ static value_type* reallocate(void* block, size_t size, size_t new_size)
+ {
+ return static_cast(_Alty::reallocate(block, size, new_size * sizeof(value_type)));
+ }
+ static void deallocate(void* block, size_t size) { _Alty::deallocate(block, size); }
+};
+template ::value, int> = 0>
+struct buffer_allocator {
+ using value_type = _Ty;
+ static value_type* reallocate(void* block, size_t /*size*/, size_t new_size)
+ {
+ return static_cast(::realloc(block, new_size * sizeof(value_type)));
+ }
+ static void deallocate(void* block, size_t /*size*/) { ::free(block); }
+};
+template ::value, int> = 0>
+struct std_buffer_allocator {
+ using value_type = _Ty;
+ static value_type* reallocate(void* block, size_t size, size_t new_size)
+ {
+ if (!block)
+ return new (std::nothrow) value_type[new_size];
+ void* new_block = nullptr;
+ if (new_size)
+ {
+ if (new_size <= size)
+ return block;
+ new_block = new (std::nothrow) value_type[new_size];
+ if (new_block)
+ memcpy(new_block, block, size);
+ }
+ delete[] (value_type*)block;
+ return (value_type*)new_block;
+ }
+ static void deallocate(void* block, size_t /*size*/) { delete[] (value_type*)block; }
+};
+template
+struct construct_helper {
+ template
+ static _Ty* construct_at(_Ty* p, Args&&... args)
+ {
+ return ::new (static_cast(p)) _Ty(std::forward(args)...);
+ }
+};
+template
+struct construct_helper<_Ty, false> {
+ template
+ static _Ty* construct_at(_Ty* p, Args&&... args)
+ {
+ return ::new (static_cast(p)) _Ty{std::forward(args)...};
+ }
+};
+
+template
+inline _Ty* construct_at(_Ty* p, Args&&... args)
+{
+ return construct_helper<_Ty, std::is_constructible<_Ty, Args&&...>::value>::construct_at(p, std::forward(args)...);
+}
+
+} // namespace yasio
+
+#endif
diff --git a/NativeLibs/yasio/yasio/byte_buffer.hpp b/NativeLibs/yasio/yasio/byte_buffer.hpp
index 7363709..837461e 100644
--- a/NativeLibs/yasio/yasio/byte_buffer.hpp
+++ b/NativeLibs/yasio/yasio/byte_buffer.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -24,413 +24,19 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-
-Version: 3.39.5
-
-The byte_buffer concepts:
- a. The memory model is similar to to std::vector, std::string
- b. Support resize fit
- c. By default resize without fill (uninitialized and for overwrite)
- d. Support release internal buffer ownership with `release_pointer`
- e. Since 3.39.5, default allocator use new/delete instead `malloc/free`
- - yasio::default_byte_allocator (new/delete)
- - yasio::crt_byte_allocator (malloc/free)
*/
#ifndef YASIO__BYTE_BUFFER_HPP
#define YASIO__BYTE_BUFFER_HPP
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "yasio/compiler/feature_test.hpp"
+#include "yasio/pod_vector.hpp"
namespace yasio
{
-#define _YASIO_VERIFY_RANGE(cond, mesg) \
- do \
- { \
- if (cond) \
- ; /* contextually convertible to bool paranoia */ \
- else \
- { \
- throw std::out_of_range(mesg); \
- } \
- \
- } while (false)
-
-template
-using enable_if_t = typename ::std::enable_if<_Test, _Ty>::type;
-
-template
-struct is_byte_type {
- static const bool value =
- std::is_same<_Elem, char>::value || std::is_same<_Elem, unsigned char>::value;
-};
-
-template ::value, int> = 0>
-struct default_byte_allocator {
- static _Elem* allocate(size_t count) { return new _Elem[count]; }
- static void deallocate(_Elem* pBlock, size_t) { delete[] pBlock; }
-};
-
-template ::value, int> = 0>
-struct crt_byte_allocator {
- static _Elem* allocate(size_t count) { return malloc(count); }
- static void deallocate(_Elem* pBlock, size_t) { free(pBlock); }
-};
-
-template ,
- enable_if_t::value, int> = 0>
-class basic_byte_buffer {
-public:
- using pointer = _Elem*;
- using const_pointer = const _Elem*;
- using reference = _Elem&;
- using const_reference = const _Elem&;
- using size_type = size_t;
- using value_type = _Elem;
- using iterator = _Elem*; // byte_buffer only needs transparent iterator
- using const_iterator = const _Elem*;
- using allocator_type = _Alloc;
- basic_byte_buffer() {}
- explicit basic_byte_buffer(size_type count) { resize(count); }
- basic_byte_buffer(size_type count, std::true_type /*fit*/) { resize_fit(count); }
- basic_byte_buffer(size_type count, const_reference val) { resize(count, val); }
- basic_byte_buffer(size_type count, const_reference val, std::true_type /*fit*/)
- {
- resize_fit(count, val);
- }
- template
- basic_byte_buffer(_Iter first, _Iter last)
- {
- assign(first, last);
- }
- template
- basic_byte_buffer(_Iter first, _Iter last, std::true_type /*fit*/)
- {
- assign(first, last, std::true_type{});
- }
- basic_byte_buffer(const basic_byte_buffer& rhs) { assign(rhs); };
- basic_byte_buffer(const basic_byte_buffer& rhs, std::true_type /*fit*/)
- {
- assign(rhs, std::true_type{});
- }
- basic_byte_buffer(basic_byte_buffer&& rhs) YASIO__NOEXCEPT { assign(std::move(rhs)); }
- template ::value, int> = 0>
- basic_byte_buffer(std::initializer_list<_Ty> rhs)
- {
- assign(rhs);
- }
- template ::value, int> = 0>
- basic_byte_buffer(std::initializer_list<_Ty> rhs, std::true_type /*fit*/)
- {
- assign(rhs, std::true_type{});
- }
- ~basic_byte_buffer() { _Tidy(); }
- basic_byte_buffer& operator=(const basic_byte_buffer& rhs)
- {
- assign(rhs);
- return *this;
- }
- basic_byte_buffer& operator=(basic_byte_buffer&& rhs) YASIO__NOEXCEPT
- {
- this->swap(rhs);
- return *this;
- }
- template
- basic_byte_buffer& operator+=(const _Cont& rhs)
- {
- return this->append(std::begin(rhs), std::end(rhs));
- }
- basic_byte_buffer& operator+=(const_reference rhs)
- {
- this->push_back(rhs);
- return *this;
- }
- template
- void assign(const _Iter first, const _Iter last)
- {
- _Assign_range(first, last);
- }
- template
- void assign(const _Iter first, const _Iter last, std::true_type /*fit*/)
- {
- _Assign_range(first, last, std::true_type{});
- }
- void assign(const basic_byte_buffer& rhs) { _Assign_range(rhs.begin(), rhs.end()); }
- void assign(const basic_byte_buffer& rhs, std::true_type)
- {
- _Assign_range(rhs.begin(), rhs.end(), std::true_type{});
- }
- void assign(basic_byte_buffer&& rhs) { _Assign_rv(std::move(rhs)); }
- template ::value, int> = 0>
- void assign(std::initializer_list<_Ty> rhs)
- {
- _Assign_range((iterator)rhs.begin(), (iterator)rhs.end());
- }
- template ::value, int> = 0>
- void assign(std::initializer_list<_Ty> rhs, std::true_type /*fit*/)
- {
- _Assign_range((iterator)rhs.begin(), (iterator)rhs.end(), std::true_type{});
- }
- void swap(basic_byte_buffer& rhs) YASIO__NOEXCEPT
- {
- std::swap(_Myfirst, rhs._Myfirst);
- std::swap(_Mylast, rhs._Mylast);
- std::swap(_Myend, rhs._Myend);
- }
- template
- iterator insert(iterator _Where, _Iter first, const _Iter last)
- {
- _YASIO_VERIFY_RANGE(_Where >= _Myfirst && _Where <= _Mylast && first <= last,
- "byte_buffer: out of range!");
- if (first != last)
- {
- auto ifirst = (iterator)std::addressof(*first);
- auto ilast = (iterator)(std::addressof(*first) + std::distance(first, last));
- auto count = std::distance(ifirst, ilast);
- auto insertion_pos = std::distance(_Myfirst, _Where);
- if (_Where == _Mylast)
- {
- if (count > 1)
- {
- auto old_size = _Mylast - _Myfirst;
- resize(old_size + count);
- std::copy_n(ifirst, count, _Myfirst + old_size);
- }
- else if (count == 1)
- push_back(static_cast(*ifirst));
- }
- else
- {
- if (insertion_pos >= 0)
- {
- auto old_size = _Mylast - _Myfirst;
- resize(old_size + count);
- _Where = _Myfirst + insertion_pos;
- auto move_to = _Where + count;
- std::copy_n(_Where, _Mylast - move_to, move_to);
- std::copy_n(ifirst, count, _Where);
- }
- }
- return _Myfirst + insertion_pos;
- }
- return _Where;
- }
- template
- basic_byte_buffer& append(_Iter first, const _Iter last)
- {
- insert(end(), first, last);
- return *this;
- }
- void push_back(value_type v)
- {
- resize(this->size() + 1);
- *(_Mylast - 1) = v;
- }
- iterator erase(iterator _Where)
- {
- _YASIO_VERIFY_RANGE(_Where >= _Myfirst && _Where < _Mylast, "byte_buffer: out of range!");
- _Mylast = std::move(_Where + 1, _Mylast, _Where);
- return _Where;
- }
- iterator erase(iterator first, iterator last)
- {
- _YASIO_VERIFY_RANGE((first <= last) && first >= _Myfirst && last <= _Mylast,
- "byte_buffer: out of range!");
- _Mylast = std::move(last, _Mylast, first);
- return first;
- }
- value_type& front()
- {
- _YASIO_VERIFY_RANGE(_Myfirst < _Mylast, "byte_buffer: out of range!");
- return *_Myfirst;
- }
- value_type& back()
- {
- _YASIO_VERIFY_RANGE(_Myfirst < _Mylast, "byte_buffer: out of range!");
- return *(_Mylast - 1);
- }
- static YASIO__CONSTEXPR size_type max_size() YASIO__NOEXCEPT
- {
- return (std::numeric_limits::max)();
- }
- iterator begin() YASIO__NOEXCEPT { return _Myfirst; }
- iterator end() YASIO__NOEXCEPT { return _Mylast; }
- const_iterator begin() const YASIO__NOEXCEPT { return _Myfirst; }
- const_iterator end() const YASIO__NOEXCEPT { return _Mylast; }
- pointer data() YASIO__NOEXCEPT { return _Myfirst; }
- const_pointer data() const YASIO__NOEXCEPT { return _Myfirst; }
- size_type capacity() const YASIO__NOEXCEPT { return static_cast(_Myend - _Myfirst); }
- size_type size() const YASIO__NOEXCEPT { return static_cast(_Mylast - _Myfirst); }
- void clear() YASIO__NOEXCEPT { _Mylast = _Myfirst; }
- bool empty() const YASIO__NOEXCEPT { return _Mylast == _Myfirst; }
- const_reference operator[](size_type index) const { return this->at(index); }
- reference operator[](size_type index) { return this->at(index); }
- const_reference at(size_type index) const
- {
- _YASIO_VERIFY_RANGE(index < this->size(), "byte_buffer: out of range!");
- return _Myfirst[index];
- }
- reference at(size_type index)
- {
- _YASIO_VERIFY_RANGE(index < this->size(), "byte_buffer: out of range!");
- return _Myfirst[index];
- }
- void resize(size_type new_size, const_reference val)
- {
- auto old_size = this->size();
- resize(new_size);
- if (old_size < new_size)
- memset(_Myfirst + old_size, val, new_size - old_size);
- }
- void resize(size_type new_size)
- {
- auto old_cap = this->capacity();
- if (old_cap < new_size)
- _Reallocate_exactly(_Calculate_growth(new_size), new_size);
- else
- _Mylast = _Myfirst + new_size;
- }
- void resize_fit(size_type new_size, const_reference val)
- {
- auto old_size = this->size();
- resize_fit(new_size);
- if (old_size < new_size)
- memset(_Myfirst + old_size, val, new_size - old_size);
- }
- void resize_fit(size_type new_size)
- {
- if (this->capacity() < new_size)
- _Reallocate_exactly(new_size, new_size);
- else
- _Mylast = _Myfirst + new_size;
- }
- void reserve(size_type new_cap)
- {
- if (this->capacity() < new_cap)
- _Reallocate_exactly(new_cap, this->size());
- }
- void shrink_to_fit()
- { // reduce capacity to size, provide strong guarantee
- const pointer _Oldlast = _Mylast;
- if (_Oldlast != _Myend)
- { // something to do
- const pointer _Oldfirst = _Myfirst;
- if (_Oldfirst == _Oldlast)
- _Tidy();
- else
- {
- const auto _OldSize = static_cast(_Oldlast - _Oldfirst);
- _Reallocate_exactly(_OldSize, _OldSize);
- }
- }
- }
- /** Release internal buffer ownership
- * Note: this is a unsafe operation, after take the internal buffer, you are responsible for
- * destroy it once you don't need it, i.e:
- * yasio::byte_buffer buf;
- * buf.push_back('I');
- * auto rawbufCapacity = buf.capacity();
- * auto rawbufLen = buf.size();
- * auto rawbuf = buf.release_pointer();
- * // use rawbuf to do something
- * // ...
- * // done, destroy the memory
- * yasio::byte_buffer::allocator_type::deallocate(rawbuf, rawbufCapacity);
- *
- */
- pointer release_pointer() YASIO__NOEXCEPT
- {
- auto ptr = _Myfirst;
- _Myfirst = nullptr;
- _Mylast = nullptr;
- _Myend = nullptr;
- return ptr;
- }
+template , enable_if_t::value, int> = 0>
+using basic_byte_buffer = array_buffer<_Ty, _Alloc>;
-private:
- template
- void _Assign_range(_Iter first, _Iter last)
- {
- _Mylast = _Myfirst;
- if (last > first)
- {
- auto ifirst = (iterator)std::addressof(*first);
- auto ilast = (iterator)std::addressof(*last);
- resize(std::distance(ifirst, ilast));
- std::copy(ifirst, ilast, _Myfirst);
- }
- }
- template
- void _Assign_range(_Iter first, _Iter last, std::true_type)
- {
- _Mylast = _Myfirst;
- if (last > first)
- {
- resize_fit(std::distance(first, last));
- std::copy(first, last, _Myfirst);
- }
- }
- void _Assign_rv(basic_byte_buffer&& rhs)
- {
- memcpy(this, &rhs, sizeof(rhs));
- memset(&rhs, 0, sizeof(rhs));
- }
- void _Reallocate_exactly(size_type new_cap, size_type new_size)
- {
- const pointer _Newvec = _Alloc::allocate(new_cap);
- if (_Myfirst)
- {
- std::copy(_Myfirst, _Mylast, _Newvec);
- _Alloc::deallocate(_Myfirst, static_cast(_Myend - _Myfirst));
- }
- _Myfirst = _Newvec;
- _Mylast = _Newvec + new_size;
- _Myend = _Newvec + new_cap;
- }
- size_type _Calculate_growth(const size_type _Newsize) const
- {
- // given _Oldcapacity and _Newsize, calculate geometric growth
- const size_type _Oldcapacity = capacity();
- YASIO__CONSTEXPR auto _Max = max_size();
-
- if (_Oldcapacity > _Max - _Oldcapacity / 2)
- return _Max; // geometric growth would overflow
-
- const size_type _Geometric = _Oldcapacity + (_Oldcapacity >> 1);
-
- if (_Geometric < _Newsize)
- return _Newsize; // geometric growth would be insufficient
-
- return _Geometric; // geometric growth is sufficient
- }
- void _Tidy() YASIO__NOEXCEPT
- { // free all storage
- if (_Myfirst)
- { // destroy and deallocate old array
- _Alloc::deallocate(_Myfirst, static_cast(_Myend - _Myfirst));
-
- _Myfirst = nullptr;
- _Mylast = nullptr;
- _Myend = nullptr;
- }
- }
-
- pointer _Myfirst = nullptr;
- pointer _Mylast = nullptr;
- pointer _Myend = nullptr;
-};
using sbyte_buffer = basic_byte_buffer;
using byte_buffer = basic_byte_buffer;
+
} // namespace yasio
#endif
diff --git a/NativeLibs/yasio/yasio/compiler/feature_test.hpp b/NativeLibs/yasio/yasio/compiler/feature_test.hpp
index 2a7123a..42eb79b 100644
--- a/NativeLibs/yasio/yasio/compiler/feature_test.hpp
+++ b/NativeLibs/yasio/yasio/compiler/feature_test.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -48,12 +48,10 @@ SOFTWARE.
#if !defined(_MSC_VER) || _MSC_VER >= 1900
# define YASIO__HAS_CXX11 1
# define YASIO__NS_INLINE inline
-# define YASIO__CONSTEXPR constexpr
# define YASIO__NOEXCEPT noexcept
#else
# define YASIO__HAS_CXX11 0
# define YASIO__NS_INLINE
-# define YASIO__CONSTEXPR const
# define YASIO__NOEXCEPT throw()
#endif
@@ -78,6 +76,12 @@ SOFTWARE.
# define YASIO__HAS_CXX17 0
#endif
+#if YASIO__HAS_CXX17
+# define YASIO__CONSTEXPR constexpr
+#else
+# define YASIO__CONSTEXPR
+#endif
+
// Tests whether compiler has c++20 support
#if (defined(__cplusplus) && __cplusplus > 201703L) || \
(defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX20) && _HAS_CXX20 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201703L))))
@@ -172,6 +176,12 @@ SOFTWARE.
# define YASIO__HAS_NTOP 0
#endif
+#if defined(_WIN32) && (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_APP)) && !defined(__MINGW64__) && !defined(__MINGW32__)
+# define YASIO__HAS_WIN32_TIMEAPI 1
+#else
+# define YASIO__HAS_WIN32_TIMEAPI 0
+#endif
+
// 64bits Sense Macros
#if defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(__x86_64) || defined(__arm64__) || defined(__aarch64__)
# define YASIO__64BITS 1
diff --git a/NativeLibs/yasio/yasio/config.hpp b/NativeLibs/yasio/yasio/config.hpp
index ccb33a0..4f4e5cf 100644
--- a/NativeLibs/yasio/yasio/config.hpp
+++ b/NativeLibs/yasio/yasio/config.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -93,6 +93,11 @@ SOFTWARE.
*/
// #define YASIO_NT_COMPAT_GAI 1
+/*
+** Uncomment or add compiler flag -DYASIO_NT_XHRES_TIMER to forcing use undocumented NT API to setup high-resolution timer
+*/
+// #define YASIO_NT_XHRES_TIMER 1
+
/*
** Uncomment or add compiler flag -DYASIO_MINIFY_EVENT to minfy size of io_event
*/
@@ -134,9 +139,14 @@ SOFTWARE.
*/
// #define YASIO_ENABLE_HPERF_IO 1
-#if defined(_WIN32) && defined(YASIO_ENABLE_HPERF_IO)
-# undef YASIO__HAS_EPOLL
-# define YASIO__HAS_EPOLL 1
+#if defined(_WIN32)
+# if defined(YASIO_ENABLE_HPERF_IO)
+# undef YASIO__HAS_EPOLL
+# define YASIO__HAS_EPOLL 1
+# endif
+# if YASIO__HAS_WIN32_TIMEAPI && !defined(YASIO_NT_XHRES_TIMER)
+# define YASIO__USE_TIMEAPI 1
+# endif
#endif
#if defined(YASIO_HEADER_ONLY)
@@ -195,7 +205,7 @@ SOFTWARE.
/*
** The yasio version macros
*/
-#define YASIO_VERSION_NUM 0x040100
+#define YASIO_VERSION_NUM 0x050000
/*
** The macros used by io_service.
@@ -206,9 +216,6 @@ SOFTWARE.
// The default ttl of multicast
#define YASIO_DEFAULT_MULTICAST_TTL (int)128
-// The max internet buffer size
-#define YASIO_INET_BUFFER_SIZE 65536
-
// The max pdu buffer length, avoid large memory allocation when application decode a huge length.
#define YASIO_MAX_PDU_BUFFER_SIZE static_cast(1 * 1024 * 1024)
diff --git a/NativeLibs/yasio/yasio/endian_portable.hpp b/NativeLibs/yasio/yasio/endian_portable.hpp
index 76ea246..bd14f8b 100644
--- a/NativeLibs/yasio/yasio/endian_portable.hpp
+++ b/NativeLibs/yasio/yasio/endian_portable.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,7 @@ SOFTWARE.
#include
#include
#include
+#include
#ifdef _WIN32
# if !defined(WIN32_LEAN_AND_MEAN)
diff --git a/NativeLibs/yasio/yasio/errc.hpp b/NativeLibs/yasio/yasio/errc.hpp
index 207c76c..ad696a9 100644
--- a/NativeLibs/yasio/yasio/errc.hpp
+++ b/NativeLibs/yasio/yasio/errc.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/ibstream.hpp b/NativeLibs/yasio/yasio/ibstream.hpp
index be5649f..b166f62 100644
--- a/NativeLibs/yasio/yasio/ibstream.hpp
+++ b/NativeLibs/yasio/yasio/ibstream.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -306,7 +306,7 @@ class basic_ibstream : public binary_reader_impl<_Traits> {
auto size = fin.tellg();
if (size > 0)
{
- blob_.resize_fit(static_cast(size));
+ blob_.resize(static_cast(size));
fin.seekg(0, std::ios_base::beg);
fin.read(blob_.data(), blob_.size());
this->reset(blob_.data(), static_cast(blob_.size()));
diff --git a/NativeLibs/yasio/yasio/impl/ares.hpp b/NativeLibs/yasio/yasio/impl/ares.hpp
index f16d5c6..224ab60 100644
--- a/NativeLibs/yasio/yasio/impl/ares.hpp
+++ b/NativeLibs/yasio/yasio/impl/ares.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/impl/char_traits.hpp b/NativeLibs/yasio/yasio/impl/char_traits.hpp
new file mode 100644
index 0000000..d6bb8c3
--- /dev/null
+++ b/NativeLibs/yasio/yasio/impl/char_traits.hpp
@@ -0,0 +1,268 @@
+#pragma once
+#include
+
+template
+inline size_t __xxtraits_find(const typename _Traits::char_type* _Haystack, const size_t _Hay_size,
+ const size_t _Start_at, const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // search [_Haystack, _Haystack +
+ // _Hay_size) for [_Needle, _Needle +
+ // _Needle_size), at/after _Start_at
+ if (_Needle_size > _Hay_size || _Start_at > _Hay_size - _Needle_size)
+ { // xpos cannot exist, report failure
+ // N4659 24.3.2.7.2 [string.find]/1 says:
+ // 1. _Start_at <= xpos
+ // 2. xpos + _Needle_size <= _Hay_size;
+ // therefore:
+ // 3. _Needle_size <= _Hay_size (by 2)
+ // (checked above)
+ // 4. _Start_at + _Needle_size <=
+ // _Hay_size (substitute 1 into 2)
+ // 5. _Start_at <= _Hay_size -
+ // _Needle_size (4, move _Needle_size to
+ // other side) (also checked above)
+ return static_cast(-1);
+ }
+
+ if (_Needle_size == 0)
+ { // empty string always matches if xpos is possible
+ return _Start_at;
+ }
+
+ const auto _Possible_matches_end = _Haystack + (_Hay_size - _Needle_size) + 1;
+ for (auto _Match_try = _Haystack + _Start_at;; ++_Match_try)
+ {
+ _Match_try = _Traits::find(_Match_try, static_cast(_Possible_matches_end - _Match_try),
+ *_Needle);
+ if (!_Match_try)
+ { // didn't find first character; report failure
+ return static_cast(-1);
+ }
+
+ if (_Traits::compare(_Match_try, _Needle, _Needle_size) == 0)
+ { // found match
+ return static_cast(_Match_try - _Haystack);
+ }
+ }
+}
+
+template
+inline size_t __xxtraits_find_ch(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type _Ch)
+{ // search [_Haystack, _Haystack + _Hay_size)
+ // for _Ch, at/after _Start_at
+ if (_Start_at < _Hay_size)
+ {
+ const auto _Found_at = _Traits::find(_Haystack + _Start_at, _Hay_size - _Start_at, _Ch);
+ if (_Found_at)
+ {
+ return static_cast(_Found_at - _Haystack);
+ }
+ }
+
+ return static_cast(-1); // (npos) no match
+}
+
+template
+inline size_t __xxtraits_rfind(const typename _Traits::char_type* _Haystack, const size_t _Hay_size,
+ const size_t _Start_at, const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // search [_Haystack, _Haystack + _Hay_size)
+ // for [_Needle, _Needle + _Needle_size)
+ // beginning before _Start_at
+ if (_Needle_size == 0)
+ {
+ return (std::min)(_Start_at, _Hay_size); // empty string always matches
+ }
+
+ if (_Needle_size <= _Hay_size)
+ { // room for match, look for it
+ for (auto _Match_try = _Haystack + (std::min)(_Start_at, _Hay_size - _Needle_size);;
+ --_Match_try)
+ {
+ if (_Traits::eq(*_Match_try, *_Needle) &&
+ _Traits::compare(_Match_try, _Needle, _Needle_size) == 0)
+ {
+ return static_cast(_Match_try - _Haystack); // found a match
+ }
+
+ if (_Match_try == _Haystack)
+ {
+ break; // at beginning, no more chance for match
+ }
+ }
+ }
+
+ return static_cast(-1); // no match
+}
+
+template
+inline size_t __xxtraits_rfind_ch(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type _Ch)
+{ // search [_Haystack, _Haystack +
+ // _Hay_size) for _Ch before _Start_at
+ if (_Hay_size != 0)
+ { // room for match, look for it
+ for (auto _Match_try = _Haystack + (std::min)(_Start_at, _Hay_size - 1);; --_Match_try)
+ {
+ if (_Traits::eq(*_Match_try, _Ch))
+ {
+ return static_cast(_Match_try - _Haystack); // found a match
+ }
+
+ if (_Match_try == _Haystack)
+ {
+ break; // at beginning, no more chance for match
+ }
+ }
+ }
+
+ return static_cast(-1); // no match
+}
+
+template
+inline size_t __xxtraits_find_last_of(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // in [_Haystack, _Haystack + _Hay_size), look for
+ // last of [_Needle, _Needle + _Needle_size), before
+ // _Start_at general algorithm
+ if (_Needle_size != 0 && _Hay_size != 0)
+ { // worth searching, do it
+ for (auto _Match_try = _Haystack + (std::min)(_Start_at, _Hay_size - 1);; --_Match_try)
+ {
+ if (_Traits::find(_Needle, _Needle_size, *_Match_try))
+ {
+ return static_cast(_Match_try - _Haystack); // found a match
+ }
+
+ if (_Match_try == _Haystack)
+ {
+ break; // at beginning, no more chance for match
+ }
+ }
+ }
+
+ return static_cast(-1); // no match
+}
+
+template
+inline size_t __xxtraits_find_last_not_of(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // in [_Haystack, _Haystack + _Hay_size), look for
+ // none of [_Needle, _Needle + _Needle_size), before
+ // _Start_at general algorithm
+ if (_Hay_size != 0)
+ { // worth searching, do it
+ for (auto _Match_try = _Haystack + (std::min)(_Start_at, _Hay_size - 1);; --_Match_try)
+ {
+ if (!_Traits::find(_Needle, _Needle_size, *_Match_try))
+ {
+ return static_cast(_Match_try - _Haystack); // found a match
+ }
+
+ if (_Match_try == _Haystack)
+ {
+ break; // at beginning, no more chance for match
+ }
+ }
+ }
+
+ return static_cast(-1); // no match
+}
+
+template
+inline size_t __xxtraits_find_first_of(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // in [_Haystack, _Haystack + _Hay_size), look for
+ // one of [_Needle, _Needle + _Needle_size), at/after
+ // _Start_at general algorithm
+ if (_Needle_size != 0 && _Start_at < _Hay_size)
+ { // room for match, look for it
+ const auto _End = _Haystack + _Hay_size;
+ for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try)
+ {
+ if (_Traits::find(_Needle, _Needle_size, *_Match_try))
+ {
+ return (static_cast(_Match_try - _Haystack)); // found a match
+ }
+ }
+ }
+
+ return (static_cast(-1)); // no match
+}
+
+template
+inline size_t __xxtraits_find_first_not_of(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type* _Needle,
+ const size_t _Needle_size)
+{ // in [_Haystack, _Haystack + _Hay_size), look for none
+ // of [_Needle, _Needle + _Needle_size), at/after
+ // _Start_at general algorithm
+ if (_Start_at < _Hay_size)
+ { // room for match, look for it
+ const auto _End = _Haystack + _Hay_size;
+ for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try)
+ {
+ if (!_Traits::find(_Needle, _Needle_size, *_Match_try))
+ {
+ return (static_cast(_Match_try - _Haystack)); // found a match
+ }
+ }
+ }
+
+ return (static_cast(-1)); // no match
+}
+
+template
+inline size_t __xxtraits_find_not_ch(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type _Ch)
+{ // search [_Haystack, _Haystack + _Hay_size) for any value other
+ // than _Ch, at/after _Start_at
+ if (_Start_at < _Hay_size)
+ { // room for match, look for it
+ const auto _End = _Haystack + _Hay_size;
+ for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try)
+ {
+ if (!_Traits::eq(*_Match_try, _Ch))
+ {
+ return (static_cast(_Match_try - _Haystack)); // found a match
+ }
+ }
+ }
+
+ return (static_cast(-1)); // no match
+}
+
+template
+inline size_t __xxtraits_rfind_not_ch(const typename _Traits::char_type* _Haystack,
+ const size_t _Hay_size, const size_t _Start_at,
+ const typename _Traits::char_type _Ch)
+{ // search [_Haystack, _Haystack + _Hay_size) for any value other than _Ch before _Start_at
+ if (_Hay_size != 0)
+ { // room for match, look for it
+ for (auto _Match_try = _Haystack + (std::min)(_Start_at, _Hay_size - 1);; --_Match_try)
+ {
+ if (!_Traits::eq(*_Match_try, _Ch))
+ {
+ return (static_cast(_Match_try - _Haystack)); // found a match
+ }
+
+ if (_Match_try == _Haystack)
+ {
+ break; // at beginning, no more chance for match
+ }
+ }
+ }
+
+ return (static_cast(-1)); // no match
+}
diff --git a/NativeLibs/yasio/yasio/impl/concurrent_queue.hpp b/NativeLibs/yasio/yasio/impl/concurrent_queue.hpp
index 8475657..57955fd 100644
--- a/NativeLibs/yasio/yasio/impl/concurrent_queue.hpp
+++ b/NativeLibs/yasio/yasio/impl/concurrent_queue.hpp
@@ -5,7 +5,7 @@
/*
The MIT License (MIT)
-Copyright (c) 2012-2023 HALX99
+Copyright (c) 2012-2024 HALX99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NativeLibs/yasio/yasio/impl/epoll_io_watcher.hpp b/NativeLibs/yasio/yasio/impl/epoll_io_watcher.hpp
index 239e8b9..0a4b1c0 100644
--- a/NativeLibs/yasio/yasio/impl/epoll_io_watcher.hpp
+++ b/NativeLibs/yasio/yasio/impl/epoll_io_watcher.hpp
@@ -3,14 +3,14 @@
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
//
-// Copyright (c) 2012-2023 HALX99 (halx99 at live dot com)
+// Copyright (c) 2012-2024 HALX99 (halx99 at live dot com)
#ifndef YASIO__EPOLL_IO_WATCHER_HPP
#define YASIO__EPOLL_IO_WATCHER_HPP
#include
#include
#include