public void Run(Procedure proc) { if (isDisposed) { throw new ObjectDisposedException("V5Server"); } breakFlag = false; while (!isDisposed && !breakFlag) { try { var endPoint = new IPEndPoint(IPAddress.Any, 0); V5Packet inPacket; { var buffer = udpClient.Receive(ref endPoint); using (var io = new MemoryStream(buffer)) { inPacket = io.ReadV5Packet(); } } byte[] response; if (lastResponse.requestId == inPacket.requestId) { response = lastResponse.response; } else { response = proc(inPacket.payload); if (response == null) { response = new byte[0]; } lastResponse.requestId = inPacket.requestId; lastResponse.response = response; } { V5Packet outPacket = V5Packet.MakeResponsePacket(response, inPacket.requestId); var io = new MemoryStream(); io.Write(outPacket); var buffer = io.ToArray(); udpClient.Send(buffer, buffer.Length, endPoint); } } catch (SocketException e) { if (PrintDebugInfo) { Console.WriteLine(e.Message); } } } }
public static V5Packet ReadV5Packet(this Stream io) { var packet = new V5Packet(); var reader = new BinaryReader(io); packet.magic = reader.ReadUInt32(); if (packet.magic != V5Packet.MAGIC) { throw new InvalidDataException($"Invalid magic {packet.magic}"); } packet.requestId = new Guid(reader.ReadBytes(16)); packet.flags = reader.ReadByte(); packet.length = reader.ReadUInt16(); packet.payload = reader.ReadBytes(packet.length); return(packet); }
public byte[] Call(byte[] payload, int timeout = 10000, int retryInterval = 50) { var server = Server; if (server == null) { throw new InvalidOperationException("Server is not specified"); } byte[] outBuffer; Guid outGuid; { var packet = V5Packet.MakeRequestPacket(payload); var io = new MemoryStream(); io.Write(packet); outBuffer = io.ToArray(); outGuid = packet.requestId; } void SendMe() { udpClient.Send(outBuffer, outBuffer.Length, server); } var timeoutState = new TaskCompletionSource <bool>(); var cts = new CancellationTokenSource(); var receiverTask = Task.Run(() => { while (true) { cts.Token.ThrowIfCancellationRequested(); try { IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0); var inBuffer = udpClient.Receive(ref remote); var io = new MemoryStream(inBuffer); var packet = io.ReadV5Packet(); if (packet.Reply && packet.requestId == outGuid) { return(packet.payload); } } catch (SocketException e) { if (PrintDebugInfo) { Console.WriteLine(e.Message); } } } }, cts.Token); SendMe(); var startTime = DateTime.Now; Timer timer = null; timer = new Timer((object state) => { var currentTime = DateTime.Now; var diffTime = currentTime - startTime; if (diffTime.TotalMilliseconds >= timeout) { timeoutState.SetResult(true); cts.Cancel(); timer.Dispose(); } else { SendMe(); } }, null, retryInterval, retryInterval); Task.WaitAny(new Task[] { receiverTask, timeoutState.Task }); timer.Dispose(); if (timeoutState.Task.IsCompleted) { throw new TimeoutException(); } return(receiverTask.Result); }