private async Task <byte[]> MessageReadAsync() { string sourceIp = ""; int sourcePort = 0; try { #region Check-for-Null-Values if (_Client == null) { Log("*** MessageReadAsync null client supplied"); return(null); } if (!_Client.Connected) { Log("*** MessageReadAsync supplied client is not connected"); return(null); } #endregion #region Variables int bytesRead = 0; int sleepInterval = 25; int maxTimeout = 500; int currentTimeout = 0; bool timeout = false; sourceIp = ((IPEndPoint)_Client.Client.RemoteEndPoint).Address.ToString(); sourcePort = ((IPEndPoint)_Client.Client.RemoteEndPoint).Port; NetworkStream ClientStream = null; try { ClientStream = _Client.GetStream(); } catch (Exception e) { Log("*** MessageRead disconnected while attaching to stream: " + e.Message); return(null); } byte[] headerBytes; string header = ""; long contentLength; byte[] contentBytes; #endregion #region Read-Header if (!ClientStream.CanRead && !ClientStream.DataAvailable) { return(null); } using (MemoryStream headerMs = new MemoryStream()) { #region Read-Header-Bytes byte[] headerBuffer = new byte[1]; timeout = false; currentTimeout = 0; int read = 0; while ((read = await ClientStream.ReadAsync(headerBuffer, 0, headerBuffer.Length)) > 0) { if (read > 0) { await headerMs.WriteAsync(headerBuffer, 0, read); bytesRead += read; currentTimeout = 0; if (bytesRead > 1) { // check if end of headers reached if (headerBuffer[0] == 58) { break; } } } else { if (currentTimeout >= maxTimeout) { timeout = true; break; } else { currentTimeout += sleepInterval; await Task.Delay(sleepInterval); } } } if (timeout) { Log("*** MessageRead timeout " + currentTimeout + "ms/" + maxTimeout + "ms exceeded while reading header after reading " + bytesRead + " bytes"); return(null); } headerBytes = headerMs.ToArray(); if (headerBytes == null || headerBytes.Length < 1) { return(null); } #endregion #region Process-Header header = Encoding.UTF8.GetString(headerBytes); header = header.Replace(":", ""); if (!Int64.TryParse(header, out contentLength)) { Log("*** MessageRead malformed message from server (message header not an integer)"); return(null); } #endregion } #endregion #region Read-Data using (MemoryStream dataMs = new MemoryStream()) { long bytesRemaining = contentLength; timeout = false; currentTimeout = 0; int read = 0; byte[] buffer; long bufferSize = 8192; if (bufferSize > bytesRemaining) { bufferSize = bytesRemaining; } buffer = new byte[bufferSize]; while ((read = await ClientStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { if (read > 0) { await dataMs.WriteAsync(buffer, 0, read); bytesRead = bytesRead + read; bytesRemaining = bytesRemaining - read; // reduce buffer size if number of bytes remaining is // less than the pre-defined buffer size of 2KB if (bytesRemaining < bufferSize) { bufferSize = bytesRemaining; } buffer = new byte[bufferSize]; // check if read fully if (bytesRemaining == 0) { break; } if (bytesRead == contentLength) { break; } } else { if (currentTimeout >= maxTimeout) { timeout = true; break; } else { currentTimeout += sleepInterval; await Task.Delay(sleepInterval); } } } if (timeout) { Log("*** MessageReadAsync timeout " + currentTimeout + "ms/" + maxTimeout + "ms exceeded while reading content after reading " + bytesRead + " bytes"); return(null); } contentBytes = dataMs.ToArray(); } #endregion #region Check-Content-Bytes if (contentBytes == null || contentBytes.Length < 1) { Log("*** MessageRead no content read"); return(null); } if (contentBytes.Length != contentLength) { Log("*** MessageRead content length " + contentBytes.Length + " bytes does not match header value of " + contentLength); return(null); } #endregion return(_Encrypter.Decrypt(contentBytes)); } catch (Exception) { Log("*** MessageRead server disconnected"); return(null); } }
private async Task <byte[]> MessageReadAsync(ClientMetadata client) { /* * * Do not catch exceptions, let them get caught by the data reader * to destroy the connection * */ #region Variables int bytesRead = 0; int sleepInterval = 25; int maxTimeout = 500; int currentTimeout = 0; bool timeout = false; byte[] headerBytes; string header = ""; long contentLength; byte[] contentBytes; if (!client.NetworkStream.CanRead) { return(null); } if (!client.NetworkStream.DataAvailable) { return(null); } #endregion #region Read-Header using (MemoryStream headerMs = new MemoryStream()) { #region Read-Header-Bytes byte[] headerBuffer = new byte[1]; timeout = false; currentTimeout = 0; int read = 0; while ((read = await client.NetworkStream.ReadAsync(headerBuffer, 0, headerBuffer.Length)) > 0) { if (read > 0) { await headerMs.WriteAsync(headerBuffer, 0, read); bytesRead += read; // reset timeout since there was a successful read currentTimeout = 0; } else { #region Check-for-Timeout if (currentTimeout >= maxTimeout) { timeout = true; break; } else { currentTimeout += sleepInterval; await Task.Delay(sleepInterval); } if (timeout) { break; } #endregion } if (bytesRead > 1) { // check if end of headers reached if (headerBuffer[0] == 58) { break; } } else { #region Check-for-Timeout if (currentTimeout >= maxTimeout) { timeout = true; break; } else { currentTimeout += sleepInterval; await Task.Delay(sleepInterval); } if (timeout) { break; } #endregion } } if (timeout) { Log("*** MessageReadAsync timeout " + currentTimeout + "ms/" + maxTimeout + "ms exceeded while reading header after reading " + bytesRead + " bytes"); return(null); } headerBytes = headerMs.ToArray(); if (headerBytes == null || headerBytes.Length < 1) { return(null); } #endregion #region Process-Header header = Encoding.UTF8.GetString(headerBytes); header = header.Replace(":", ""); if (!Int64.TryParse(header, out contentLength)) { Log("*** MessageReadAsync malformed message from " + client.IpPort + " (message header not an integer)"); return(null); } #endregion } #endregion #region Read-Data using (MemoryStream dataMs = new MemoryStream()) { long bytesRemaining = contentLength; timeout = false; currentTimeout = 0; int read = 0; byte[] buffer; long bufferSize = 8192; if (bufferSize > bytesRemaining) { bufferSize = bytesRemaining; } buffer = new byte[bufferSize]; while ((read = await client.NetworkStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { if (read > 0) { dataMs.Write(buffer, 0, read); bytesRead = bytesRead + read; bytesRemaining = bytesRemaining - read; // reset timeout currentTimeout = 0; // reduce buffer size if number of bytes remaining is // less than the pre-defined buffer size of 2KB if (bytesRemaining < bufferSize) { bufferSize = bytesRemaining; } buffer = new byte[bufferSize]; // check if read fully if (bytesRemaining == 0) { break; } if (bytesRead == contentLength) { break; } } else { #region Check-for-Timeout if (currentTimeout >= maxTimeout) { timeout = true; break; } else { currentTimeout += sleepInterval; await Task.Delay(sleepInterval); } if (timeout) { break; } #endregion } } if (timeout) { Log("*** MessageReadAsync timeout " + currentTimeout + "ms/" + maxTimeout + "ms exceeded while reading content after reading " + bytesRead + " bytes"); return(null); } contentBytes = dataMs.ToArray(); } #endregion #region Check-Content-Bytes if (contentBytes == null || contentBytes.Length < 1) { Log("*** MessageReadAsync " + client.IpPort + " no content read"); return(null); } if (contentBytes.Length != contentLength) { Log("*** MessageReadAsync " + client.IpPort + " content length " + contentBytes.Length + " bytes does not match header value " + contentLength + ", discarding"); return(null); } #endregion return(_Encrypter.Decrypt(contentBytes)); }