public async Task Connect(CancellationToken cancellationToken = default) { TransitionState(ConnectionState.Connecting); try { await ConnectImpl(cancellationToken); StartHandshaking(); if (Handshaker != null) { Log.Info($"{this}: Handshaking..."); HandshakeResult = await Handshaker.Handshake(this, cancellationToken); if (!HandshakeResult.Successful) { var ex = new HandshakeException(HandshakeResult.ErrorCode); Log.Info($"{this}: Handshake Failed {HandshakeResult.ErrorCode}: {ex.Message}"); throw ex; } User = HandshakeResult.User; } TransitionState(ConnectionState.Connected); } catch (Exception) { TransitionState(ConnectionState.Closed); throw; } }
public Handler(Handshaker handshaker) { this.handshaker = handshaker; }
void TestHttpResponseAndFrameInSameBuffer(bool codec) { string url = "ws://localhost:9999/ws"; WebSocketClientHandshaker shaker = this.NewHandshaker(new Uri(url)); var handshaker = new Handshaker(shaker); // use randomBytes helper from utils to check that it functions properly byte[] data = WebSocketUtil.RandomBytes(24); // Create a EmbeddedChannel which we will use to encode a BinaryWebsocketFrame to bytes and so use these // to test the actual handshaker. var factory = new WebSocketServerHandshakerFactory(url, null, false); IFullHttpRequest request = shaker.NewHandshakeRequest(); WebSocketServerHandshaker socketServerHandshaker = factory.NewHandshaker(request); request.Release(); var websocketChannel = new EmbeddedChannel(socketServerHandshaker.NewWebSocketEncoder(), socketServerHandshaker.NewWebsocketDecoder()); Assert.True(websocketChannel.WriteOutbound(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(data)))); byte[] bytes = Encoding.ASCII.GetBytes("HTTP/1.1 101 Switching Protocols\r\nContent-Length: 0\r\n\r\n"); CompositeByteBuffer compositeByteBuf = Unpooled.CompositeBuffer(); compositeByteBuf.AddComponent(true, Unpooled.WrappedBuffer(bytes)); for (; ;) { var frameBytes = websocketChannel.ReadOutbound <IByteBuffer>(); if (frameBytes == null) { break; } compositeByteBuf.AddComponent(true, frameBytes); } var ch = new EmbeddedChannel(new HttpObjectAggregator(int.MaxValue), new Handler(handshaker)); if (codec) { ch.Pipeline.AddFirst(new HttpClientCodec()); } else { ch.Pipeline.AddFirst(new HttpRequestEncoder(), new HttpResponseDecoder()); } // We need to first write the request as HttpClientCodec will fail if we receive a response before a request // was written. shaker.HandshakeAsync(ch).Wait(); for (; ;) { // Just consume the bytes, we are not interested in these. var buf = ch.ReadOutbound <IByteBuffer>(); if (buf == null) { break; } buf.Release(); } Assert.True(ch.WriteInbound(compositeByteBuf)); Assert.True(ch.Finish()); var frame = ch.ReadInbound <BinaryWebSocketFrame>(); IByteBuffer expect = Unpooled.WrappedBuffer(data); try { Assert.Equal(expect, frame.Content); Assert.True(frame.IsFinalFragment); Assert.Equal(0, frame.Rsv); } finally { expect.Release(); frame.Release(); } }
/// <summary> /// 初始化网络监听 /// </summary> /// <param name="path"></param> private void InitNetFacade(string path) { string policy = null; try { using (FileStream fs = File.OpenRead(Path.Combine(path, "crossdomain.txt"))) using (StreamReader sr = new StreamReader(fs, Encoding.UTF8, false)) { policy = sr.ReadToEnd(); } } catch { } GMManager.Instance.Load(Path.Combine(path, "GMList.txt")); FrontManager.Instance.Load(Path.Combine(path, "FrontIP.txt")); AmfStringZip zip = new CommandMap(); zip.Load(Path.Combine(path, "Command.txt")); string ip = "0.0.0.0"; string ports = "8005"; int maxClient = 1000; int maxWaitSend = 64; const int receiveSize = 8 * 1024; const int sendSize = 64 * 1024; AmfCodec.Init(maxClient, zip); IHandshake hander = new Handshaker(policy); CommandProcessor gameProcessor = new CommandProcessor(receiveSize, zip); SessionFactory gameFactory = new SessionFactory(receiveSize, sendSize, maxWaitSend, gameProcessor); server = new GMService(gameFactory, gameFactory, hander); server.Start(ip, ports.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)); }
protected async Task ProcessReceivedData(ulong packetId, byte[] data, ISerializer serializer) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (serializer == null) { throw new ArgumentNullException(nameof(serializer)); } if (State == ConnectionState.Closed) { throw new DisconnectedException(); } var serializedPacket = SerializedPacket.Read(data); Log.TracePacketReceived(this, serializedPacket); { var args = new PacketReceivedEventArgs() { PacketId = packetId, Packet = serializedPacket, Connection = this }; var packetEventHandler = PacketReceived; if (packetEventHandler != null) { foreach (var handler in packetEventHandler.GetInvocationList().Cast <PacketReceived>()) { if (State == ConnectionState.Closed) { throw new DisconnectedException(); } try { await handler(this, args); } catch (Exception ex) { Log.Error($"Error in {nameof(PacketReceived)} event handler", ex); } if (args.IsHandled) { return; } } } } if (State == ConnectionState.Closed) { throw new DisconnectedException(); } Packet packet; try { packet = serializedPacket.DeserializePacket(serializer); } catch (Exception ex) { throw new InvalidDataException($"Error deserializing {serializedPacket}: {ex.Message}", data, ex); } if (State == ConnectionState.Closed) { throw new DisconnectedException(); } if (packet is HandshakeRequestPacket helloPacket) { //TODO: Move this into the Server class if (Handshaker == null) { throw new InvalidOperationException($"{this}: Can't handle {helloPacket} because there is no {nameof(Handshaker)}"); } HandshakeResult result; try { result = await Handshaker.OnHandshakeRequest(helloPacket, this, ClosedCancellationToken); } catch (Exception ex) { result = HandshakeResult.Failure("Handshake Failed"); Log.Error($"{this}: Handshake Failure: {ex}"); } if (result.Successful) { User = result.User; } var response = new ResponsePacket(result); await Respond(packetId, response, ClosedCancellationToken); TransitionState(result.Successful ? ConnectionState.Connected : ConnectionState.Closed); } else if (packet is RequestPacket requestPacket) { var requestContext = new RequestContext() { Client = Client, Server = Server, Connection = this }; var requestEventHandler = RequestReceived; if (requestEventHandler == null) { throw new InvalidOperationException($"{this}: Receiving Requests, but nothing is reading them."); } requestPacket.Context = requestContext; var args = new RequestReceivedEventArgs() { Request = requestPacket, Context = requestContext }; foreach (var handler in requestEventHandler.GetInvocationList().Cast <RequestReceived>()) { object result = null; try { result = await handler(this, args); } catch (Exception ex) { Log.Error($"{this}: Error invoking event {nameof(RequestReceived)}: {ex}"); } if (result != null) { args.Response = result; args.IsHandled = true; } if (args.IsHandled) { break; } } if (requestPacket.Flags.HasFlag(PacketFlag.AckRequired)) { var unhandledRequestResponse = new ResponsePacket(new ErrorResponseData(ErrorResponseCodes.UnhandledRequest, $"Packet {requestPacket} not expected.", false)); var response = (!args.IsHandled ? unhandledRequestResponse : new ResponsePacket(args.Response)); try { await Respond(packetId, response, ClosedCancellationToken); } catch (Exception ex) { Log.Error($"{this}: Error sending response to Request {requestPacket}: Response={response}: {ex}"); } } } else if (packet is IAck ack) { if (_awaitingAck.TryGetValue(ack.PacketId, out var tcs)) { tcs.SetResult(packet); } else { Log.Warn($"{this}: Ack: Could not find packet #{ack.PacketId}"); } } else { throw new InvalidDataException($"{this}: {packet.GetType().Name} packet not supported."); } }
/// <summary> /// 初始化网络监听 /// </summary> /// <param name="crossdomain"></param> private void InitNetFacade(string crossdomain) { string policy = null; try { if (!string.IsNullOrEmpty(crossdomain)) { using (FileStream fs = File.OpenRead(crossdomain)) using (StreamReader sr = new StreamReader(fs, Encoding.UTF8, false)) { policy = sr.ReadToEnd(); } } } catch { } int maxClient = ConfigLoader.Config.MaxClient; int sendQueueSize = ConfigLoader.Config.SendQueueSize; const int receiveSize = 8 * 1024; const int sendSize = 64 * 1024; AmfCodec.Init(maxClient, CommandManager.Instance); IHandshake hander = new Handshaker(policy); GMProcessor gmProcessor = new GMProcessor(receiveSize); SessionFactory gmFactory = new SessionFactory(8, receiveSize, sendSize, 8, gmProcessor); gmServer = new AmfServer(gmFactory, gmFactory, hander); gmServer.Start(ConfigLoader.Config.EpGM); GameProcessor gameProcessor = new GameProcessor(receiveSize); SessionFactory gameFactory = new SessionFactory(maxClient, receiveSize, sendSize, sendQueueSize, gameProcessor); server = new AmfServer(gameFactory, gameFactory, hander); server.Start(ConfigLoader.Config.EpGame); Notifier.Instance.Publish(new Notification(GMCommand.GMStart, new object[] { this }), false); }