public static async Task <GetResponse> ReadItemAsync(PooledSocket socket, CancellationToken cancellationToken = default) { var description = await TextSocketHelper.ReadResponseAsync(socket, cancellationToken).ConfigureAwait(false); if (String.Compare(description, "END", StringComparison.Ordinal) == 0) { return(null); } else if (description.Length < 6 || String.Compare(description, 0, "VALUE ", 0, 6, StringComparison.Ordinal) != 0) { throw new MemcachedClientException("No VALUE response received.\r\n" + description); } // response is: // VALUE <key> <flags> <bytes> [<cas unique>] // 0 1 2 3 4 // // cas only exists in 1.2.4+ // ulong cas = 0; var parts = description.Split(' '); if (parts.Length == 5) { if (!UInt64.TryParse(parts[4], out cas)) { throw new MemcachedClientException("Invalid CAS VALUE received."); } } else if (parts.Length < 4) { throw new MemcachedClientException("Invalid VALUE response received: " + description); } var flags = UInt16.Parse(parts[2], CultureInfo.InvariantCulture); var length = Int32.Parse(parts[3], CultureInfo.InvariantCulture); var allData = new byte[length]; var eod = new byte[2]; await socket.ReceiveAsync(allData, 0, length, cancellationToken).ConfigureAwait(false); await socket.ReceiveAsync(eod, 0, 2, cancellationToken).ConfigureAwait(false); // data is terminated by \r\n var result = new GetResponse(parts[1], flags, cas, allData); GetHelper.Logger = GetHelper.Logger ?? Caching.Logger.CreateLogger(typeof(GetHelper)); if (GetHelper.Logger.IsEnabled(LogLevel.Debug)) { GetHelper.Logger.LogDebug("Received value. Data type: {0}, size: {1}.", result.Item.Flags, result.Item.Data.Count); } return(result); }
/// <summary> /// Reads the response from the socket asynchronously. /// </summary> /// <param name="socket">The socket to read from.</param> /// <param name="next">The delegate which will continue processing the response. This is only called if the read completes asynchronoulsy.</param> /// <param name="ioPending">Set to true if the read is still pending when ReadASync returns. In this case 'next' will be called when the read is finished.</param> /// <returns> /// If the socket is already dead, ReadAsync returns false, next is not called, ioPending = false /// If the read completes synchronously (e.g. data is received from the buffer), it returns true/false depending on the StatusCode, and ioPending is set to true, 'next' will not be called. /// It returns true if it has to read from the socket, so the operation will complate asynchronously at a later time. ioPending will be true, and 'next' will be called to handle the data /// </returns> public bool ReadAsync(PooledSocket socket, Action <bool> next, out bool ioPending) { this.StatusCode = -1; this._socket = socket; this._nextAction = next; var asyncEvent = new AsyncIOArgs { Count = BinaryResponse.HeaderLength, Next = this.DoDecodeHeaderAsync }; this._shouldCallNext = true; if (socket.ReceiveAsync(asyncEvent)) { ioPending = true; return(true); } ioPending = false; this._shouldCallNext = false; return(asyncEvent.Fail ? false : this.DoDecodeHeader(asyncEvent, out ioPending)); }
/// <summary> /// Reads the response from the socket asynchronously. /// </summary> /// <param name="socket">The socket to read from.</param> /// <param name="next">The delegate whihc will continue processing the response. This is only called if the read completes asynchronoulsy.</param> /// <param name="ioPending">Set totrue if the read is still pending when ReadASync returns. In this case 'next' will be called when the read is finished.</param> /// <returns> /// If the socket is already dead, ReadAsync returns false, next is not called, ioPending = false /// If the read completes synchronously (e.g. data is received from the buffer), it returns true/false depending on the StatusCode, and ioPending is set to true, 'next' will not be called. /// It returns true if it has to read from the socket, so the operation will complate asynchronously at a later time. ioPending will be true, and 'next' will be called to handle the data /// </returns> public bool ReadAsync(PooledSocket socket, Action <bool> next, out bool ioPending) { this.StatusCode = -1; this.currentSocket = socket; this.next = next; var asyncEvent = new AsyncIOArgs(); asyncEvent.Count = HeaderLength; asyncEvent.Next = this.DoDecodeHeaderAsync; this.shouldCallNext = true; if (socket.ReceiveAsync(asyncEvent)) { ioPending = true; return(true); } ioPending = false; this.shouldCallNext = false; return(asyncEvent.Fail ? false : this.DoDecodeHeader(asyncEvent, out ioPending)); }
/// <summary> /// Reads the response from the socket /// </summary> /// <param name="socket"></param> /// <returns></returns> public async Task <bool> ReadAsync(PooledSocket socket, CancellationToken cancellationToken = default) { this.StatusCode = -1; if (!socket.IsAlive) { return(false); } try { var header = new byte[BinaryResponse.HeaderLength]; await socket.ReceiveAsync(header, 0, header.Length, cancellationToken).ConfigureAwait(false); this.DeserializeHeader(header, out var dataLength, out var extraLength); if (dataLength > 0) { var data = new byte[dataLength]; await socket.ReceiveAsync(data, 0, dataLength, cancellationToken).ConfigureAwait(false); this.Extra = new ArraySegment <byte>(data, 0, extraLength); this.Data = new ArraySegment <byte>(data, extraLength, data.Length - extraLength); } return(this.StatusCode == 0); } catch (OperationCanceledException) { throw; } catch (Exception ex) { this._logger.LogError(ex, "ReadAsync: Error occurred while reading socket"); throw; } }
/// <summary> /// Reads a line from the socket. A line is terninated by \r\n. /// </summary> /// <returns></returns> static async Task <string> ReadLineAsync(PooledSocket socket, CancellationToken cancellationToken = default(CancellationToken)) { using (var stream = new MemoryStream(50)) { var gotR = false; byte data; while (true) { data = await socket.ReceiveAsync(cancellationToken).ConfigureAwait(false); if (data == 13) { gotR = true; continue; } if (gotR) { if (data == 10) { break; } stream.WriteByte(13); gotR = false; } stream.WriteByte(data); } var result = Encoding.ASCII.GetString(stream.ToArray(), 0, (int)stream.Length); Logger = Logger ?? Caching.Logger.CreateLogger(typeof(TextSocketHelper)); if (Logger.IsEnabled(LogLevel.Debug)) { Logger.LogDebug("ReadLine (async): " + result); } return(result); } }
/// <summary> /// Reads the response from the socket asynchronously. /// </summary> /// <param name="socket">The socket to read from.</param> /// <param name="next">The delegate whihc will continue processing the response. This is only called if the read completes asynchronoulsy.</param> /// <param name="ioPending">Set totrue if the read is still pending when ReadASync returns. In this case 'next' will be called when the read is finished.</param> /// <returns> /// If the socket is already dead, ReadAsync returns false, next is not called, ioPending = false /// If the read completes synchronously (e.g. data is received from the buffer), it returns true/false depending on the StatusCode, and ioPending is set to true, 'next' will not be called. /// It returns true if it has to read from the socket, so the operation will complate asynchronously at a later time. ioPending will be true, and 'next' will be called to handle the data /// </returns> public bool ReadAsync(PooledSocket socket, Action<bool> next, out bool ioPending) { this.StatusCode = -1; this.currentSocket = socket; this.next = next; var asyncEvent = new AsyncIOArgs(); asyncEvent.Count = HeaderLength; asyncEvent.Next = this.DoDecodeHeaderAsync; this.shouldCallNext = true; if (socket.ReceiveAsync(asyncEvent)) { ioPending = true; return true; } ioPending = false; this.shouldCallNext = false; return asyncEvent.Fail ? false : this.DoDecodeHeader(asyncEvent, out ioPending); }