This commit is contained in:
2023-10-08 21:13:31 +03:00
parent 64842886d7
commit c214b6ca7f
45 changed files with 116 additions and 113 deletions
@@ -0,0 +1,42 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using ENet;
using Ragon.Server.IO;
namespace Ragon.Server.ENetServer;
public sealed class ENetConnection: INetworkConnection
{
public ushort Id { get; }
public INetworkChannel Reliable { get; private set; }
public INetworkChannel Unreliable { get; private set; }
private Peer _peer;
public ENetConnection(Peer peer)
{
_peer = peer;
Id = (ushort) peer.ID;
Reliable = new ENetReliableChannel(peer, NetworkChannel.RELIABLE);
Unreliable = new ENetUnreliableChannel(peer, NetworkChannel.UNRELIABLE);
}
public void Close()
{
_peer.Disconnect(0);
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Net;
using ENet;
using Ragon.Protocol;
using Ragon.Server.IO;
namespace Ragon.Server.ENetServer;
public sealed class ENetReliableChannel: INetworkChannel
{
private Peer _peer;
private byte _channelId;
private byte[] _data;
public ENetReliableChannel(Peer peer, NetworkChannel channel)
{
_peer = peer;
_data = new byte[1500];
_channelId = (byte) channel;
}
public void Send(byte[] data)
{
var newPacket = new Packet();
newPacket.Create(data, data.Length, PacketFlags.Reliable);
_peer.Send(_channelId, ref newPacket);
}
public void Send(RagonBuffer buffer)
{
buffer.ToArray(_data);
var newPacket = new Packet();
newPacket.Create(_data, buffer.Length, PacketFlags.Reliable);
_peer.Send(_channelId, ref newPacket);
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using ENet;
using NLog;
using Ragon.Protocol;
using Ragon.Server.IO;
namespace Ragon.Server.ENetServer
{
public sealed class ENetServer : INetworkServer
{
public Executor Executor => _executor;
private readonly Host _host = new();
private readonly ILogger _logger = LogManager.GetCurrentClassLogger();
private ENetConnection[] _connections = Array.Empty<ENetConnection>();
private INetworkListener _listener;
private uint _protocol;
private ENet.Event _event;
private Executor _executor = new();
public void Start(INetworkListener listener, NetworkConfiguration configuration)
{
Library.Initialize();
_connections = new ENetConnection[configuration.LimitConnections];
_listener = listener;
_protocol = configuration.Protocol;
var address = new Address
{
Port = (ushort)configuration.Port,
};
_host.Create(address, _connections.Length, 2, 0, 0, 1024 * 1024);
var protocolDecoded = RagonVersion.Parse(_protocol);
_logger.Info($"Listen at 127.0.0.1:{configuration.Port}");
_logger.Info($"Protocol: {protocolDecoded}");
}
public void Update()
{
bool polled = false;
while (!polled)
{
if (_host.CheckEvents(out _event) <= 0)
{
if (_host.Service(0, out _event) <= 0)
break;
polled = true;
}
switch (_event.Type)
{
case EventType.None:
{
_logger.Trace("None event");
break;
}
case EventType.Connect:
{
if (!IsValidProtocol(_event.Data))
{
_logger.Warn($"Mismatched protocol Server: {RagonVersion.Parse(_protocol)} Client: {RagonVersion.Parse(_event.Data)}, close connection");
_event.Peer.DisconnectNow(0);
break;
}
var connection = new ENetConnection(_event.Peer);
_connections[_event.Peer.ID] = connection;
_listener.OnConnected(connection);
break;
}
case EventType.Disconnect:
{
var connection = _connections[_event.Peer.ID];
_listener.OnDisconnected(connection);
break;
}
case EventType.Timeout:
{
var connection = _connections[_event.Peer.ID];
_listener.OnTimeout(connection);
break;
}
case EventType.Receive:
{
var peerId = (ushort)_event.Peer.ID;
var connection = _connections[peerId];
var dataRaw = new byte[_event.Packet.Length];
_event.Packet.CopyTo(dataRaw);
_event.Packet.Dispose();
_listener.OnData(connection, (NetworkChannel)_event.ChannelID, dataRaw);
break;
}
}
}
}
public void BroadcastReliable(byte[] data)
{
var packet = new Packet();
packet.Create(data, PacketFlags.Reliable);
_host.Broadcast((byte)NetworkChannel.RELIABLE, ref packet);
}
public void BroadcastUnreliable(byte[] data)
{
var packet = new Packet();
packet.Create(data, PacketFlags.None);
_host.Broadcast((byte)NetworkChannel.UNRELIABLE, ref packet);
}
public void Stop()
{
_host?.Dispose();
Library.Deinitialize();
}
private bool IsValidProtocol(uint protocol)
{
return protocol == _protocol;
}
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using ENet;
using Ragon.Protocol;
using Ragon.Server.IO;
namespace Ragon.Server.ENetServer;
public sealed class ENetUnreliableChannel: INetworkChannel
{
private Peer _peer;
private byte _channelId;
private byte[] _data;
public ENetUnreliableChannel(Peer peer, NetworkChannel channel)
{
_peer = peer;
_channelId = (byte) channel;
}
public void Send(byte[] data)
{
var newPacket = new Packet();
newPacket.Create(data, data.Length, PacketFlags.None);
_peer.Send(_channelId, ref newPacket);
}
public void Send(RagonBuffer buffer)
{
buffer.ToArray(_data);
var newPacket = new Packet();
newPacket.Create(_data, buffer.Length, PacketFlags.None);
_peer.Send(_channelId, ref newPacket);
}
}