// WriteStream writes the final WriteRequest internal unsafe void WriteStream(WriteRequest request) { if (request != null) { Validate(); try { // WriteRequest could keep multiple buffers, but only keeps one // so we always pass '1' as size NativeMethods.WriteStream(request.InternalHandle, InternalHandle, request.Bufs, 1, WriteCallback); } catch (Exception exception) { Log.Error($"{HandleType} Failed to write data {request}: {exception}"); throw; } } else { throw new ArgumentException("Request can't be null!"); } }
// segment data is copied internally and can be reused immediately. public void Send(ArraySegment <byte> segment) { // make sure we don't try to write anything larger than WriteRequest // internal buffer size, which is MaxMessageSize + 4 for header if (segment.Count <= MaxMessageSize) { // create <size, data> payload so we only call write once. if (Framing.Frame(payloadBuffer, segment)) { // queue write the payload ArraySegment <byte> payload = new ArraySegment <byte>(payloadBuffer, 0, segment.Count + 4); WriteRequest request = WriteRequestPool.Take(); try { // prepare request with our completion callback, and make // sure that streamHandle is passed as first parameter. request.Prepare(payload); WriteStream(request); } catch (Exception exception) { Log.Error($"{HandleType} faulted: {exception}"); WriteRequestPool.Return(request); throw; } } else { Log.Error($"Framing failed for message with size={segment.Count}. Make sure it's within MaxMessageSize={MaxMessageSize}"); } } else { Log.Error($"Failed to send message of size {segment.Count} because it's larger than MaxMessageSize={MaxMessageSize}"); } }
static void OnWriteCallback(IntPtr handle, int status) { WriteRequest request = RequestContext.GetTarget <WriteRequest>(handle); WriteRequestPool.Return(request); }