public async Task <CharGenResult> WriteAsync(HostName address, string service, ProtocolType protocolType, string data = "") { switch (protocolType) { case ProtocolType.Tcp: return(await WriteTcpAsync(address, service, data)); case ProtocolType.Udp: return(await WriteUdpAsync(address, service, data)); } return(CharGenResult.MakeFailed(SocketErrorStatus.SocketTypeNotSupported, 0.0)); }
private CharGenResult ReadUdp(DataReader dr) { uint count = dr.UnconsumedBufferLength; if (count > 0) { byte[] buffer = new byte[dr.UnconsumedBufferLength]; dr.ReadBytes(buffer); var stringresult = BufferToString.ToString(buffer); LogCharGenBuffer(buffer); var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; return(CharGenResult.MakeSucceeded(stringresult, delta)); } else // socket is done TODO: change comment everywhere for UDP { var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; return(CharGenResult.MakeFailed(SocketErrorStatus.HttpInvalidServerResponse, delta)); } }
private void UdpSocket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) { try { var dr = args.GetDataReader(); dr.InputStreamOptions = InputStreamOptions.Partial; // | InputStreamOptions.ReadAhead; var udpResult = ReadUdp(dr); UdpResults.Add(sender.Information.LocalPort, udpResult); } catch (Exception ex) { // This can happen when we send a packet to a correct host (like localhost) but with an // incorrect service. The packet will "bounce", resuluting in a MessageReceived event // but with an args with no real data. Stats.NExceptions++; var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; var udpResult = CharGenResult.MakeFailed(ex, delta); UdpResults.Add(sender.Information.LocalPort, udpResult); } }
/// <summary> /// Ensures that the socket is made. Will return a failure EchoResult on failure /// and will return NULL for a success. /// </summary> /// <param name="address"></param> /// <param name="service"></param> /// <returns></returns> private CharGenResult EnsureUdpSocket() { var startTime = DateTime.UtcNow; lock (this) { if (udpSocket == null) { udpSocket = new DatagramSocket(); SocketStartTime = startTime; udpSocket.MessageReceived += UdpSocket_MessageReceived; } } // We made a socket and then making the datawriter somehow failed. // Just give up; there's no path that will get us into a better place. if (udpSocket == null) { return(CharGenResult.MakeFailed(SocketErrorStatus.CannotAssignRequestedAddress, 0)); } return(null); }
public async Task <CharGenResult> WriteTcpAsync(HostName address, string service, string data) { var startTime = DateTime.UtcNow; try { if (tcpSocket == null) { tcpSocket = new StreamSocket(); await tcpSocket.ConnectAsync(address, service); Log(ClientOptions.Verbosity.Verbose, $"CLIENT: TCP Connection using local port {tcpSocket.Information.LocalPort}"); tcpDw = new DataWriter(tcpSocket.OutputStream); SocketStartTime = startTime; // Now read everything TcpReadEchoResult = CharGenResult.MakeInProgress(0); // Taken no time at all so far :-) var dr = new DataReader(tcpSocket.InputStream); dr.InputStreamOptions = InputStreamOptions.Partial; TcpReadTask = ReadTcpAsync(dr); } tcpDw.WriteString(data); await tcpDw.StoreAsync(); Stats.NWrites++; var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; return(CharGenResult.MakeInProgress(delta)); } catch (Exception ex) { Stats.NExceptions++; Log($"ERROR: Client: Writing {data} to {address} exception {ex.Message}"); var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; return(CharGenResult.MakeFailed(ex, delta)); } }
public async Task <CharGenResult> WriteUdpAsync(HostName address, string service, string data) { try { var haveUdpSocket = EnsureUdpSocket(); if (haveUdpSocket != null) { // Was unable to create the socket. return(haveUdpSocket); } var stream = await udpSocket.GetOutputStreamAsync(address, service); if (string.IsNullOrEmpty(data)) { // A blank string, when written to a data writer, won't actually result in a // UDP packet being sent. For the special case of not sending any data, // use the WriteAsync on the socket's OutputStream directly. var b = new Windows.Storage.Streams.Buffer(0); await stream.WriteAsync(b); Stats.NWrites++; } else { var dw = new DataWriter(stream); dw.WriteString(data); await dw.StoreAsync(); Stats.NWrites++; } Log(ClientOptions.Verbosity.Verbose, $"Client: UDP: Sent request on local port {udpSocket.Information.LocalPort} request {data}"); // // Wait for an answer // const int START_DELAY_MS = 10; int currTotalDelay = 0; int currDelay = START_DELAY_MS; CharGenResult udpResult = null; while (!UdpResults.TryRemove(udpSocket.Information.LocalPort, out udpResult)) { await Task.Delay(currDelay); currTotalDelay += currDelay; currDelay = Math.Min(currDelay * 2, Options.MaxPollLoopInMilliseconds); // Do an exponential backup up to max (10 seconds) if (currTotalDelay >= Options.MaxWaitInMilliseconds) { Log($"ERROR: Client: reply from {address} took too long (outgoing data={data})"); var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; udpResult = CharGenResult.MakeFailed(SocketErrorStatus.ConnectionTimedOut, delta); break; } } return(udpResult); } catch (Exception ex) { Stats.NExceptions++; Log($"ERROR: Client: Writing {data} to {address} exception {ex.Message}"); var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds; return(CharGenResult.MakeFailed(ex, delta)); } }