public override IAsyncResult BeginRead( byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { if (buffer == null) { throw new ArgumentNullException("buffer", "buffer can't be null"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "offset less than 0"); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset", "offset must be less than buffer length"); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "count less than 0"); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count", "count is greater than buffer length - offset"); } var proceedAfterHandshake = count != 0; var internalAsyncResult = new InternalAsyncResult( asyncCallback, asyncState, buffer, offset, count, false, proceedAfterHandshake); if (NeedHandshake) { BeginHandshake(internalAsyncResult); } else { InternalBeginRead(internalAsyncResult); } return(internalAsyncResult); }
private void InternalWriteCallback(IAsyncResult asyncResult) { InternalAsyncResult internalAsyncResult = (InternalAsyncResult)asyncResult.AsyncState; try { innerStream.EndWrite(asyncResult); internalAsyncResult.SetComplete(); } catch (Exception ex) { internalAsyncResult.SetComplete(ex); } }
public override IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { if (disposed) { return(null); } if (buffer == null) { throw new ArgumentNullException("buffer", "buffer can't be null"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "offset less than 0"); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset", "offset must be less than buffer length"); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "count less than 0"); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count", "count is greater than buffer length - offset"); } bool proceedAfterHandshake = count != 0; InternalAsyncResult asyncResult = new InternalAsyncResult(asyncCallback, asyncState, buffer, offset, count, true, proceedAfterHandshake); if (NeedHandshake) { //inHandshakeLoop = true; // Start the handshake BeginHandshake(asyncResult); } else { InternalBeginWrite(asyncResult); } return(asyncResult); }
private IAsyncResult BeginHandshake(InternalAsyncResult readwriteAsyncResult) { if (disposed) { return(null); } //!! // Move the handshake state to the next state //if (handShakeState == HandshakeState.Renegotiate) //{ // handShakeState = HandshakeState.RenegotiateInProcess; //} //else if (handShakeState != HandshakeState.Renegotiate) { handShakeState = HandshakeState.InProcess; } // Wrap the read/write InternalAsyncResult in the Handshake InternalAsyncResult instance var handshakeAsyncResult = new InternalAsyncResult( AsyncHandshakeComplete, readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessHandshake()) { handShakeState = HandshakeState.Complete; handshakeAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { handshakeAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, AsyncHandshakeCallback, handshakeAsyncResult); } else { handshakeAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, AsyncHandshakeCallback, handshakeAsyncResult); } } return(handshakeAsyncResult); }
private void InternalWriteCallback(IAsyncResult ar) { InternalAsyncResult internalResult = (InternalAsyncResult)ar.AsyncState; try { this.checkDisposed(); this.innerStream.EndWrite(ar); internalResult.SetComplete(); } catch (Exception ex) { internalResult.SetComplete(ex); } }
internal void NegotiateHandshake() { if (MightNeedHandshake) { InternalAsyncResult asyncResult = new InternalAsyncResult(null, null, null, 0, 0, fromWrite: false, proceedAfterHandshake: false); if (!BeginNegotiateHandshake(asyncResult)) { negotiationComplete.WaitOne(); } else { EndNegotiateHandshake(asyncResult); } } }
private void AsyncHandshakeCallback(IAsyncResult asyncResult) { InternalAsyncResult internalResult = asyncResult.AsyncState as InternalAsyncResult; try { try { this.OnNegotiateHandshakeCallback(asyncResult); } catch (TlsException ex) { this.protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); } catch (Exception ex) { this.protocol.SendAlert(AlertDescription.InternalError); throw new IOException("The authentication or decryption has failed.", ex); } if (internalResult.ProceedAfterHandshake) { //kick off the read or write process (whichever called us) after the handshake is complete if (internalResult.FromWrite) { InternalBeginWrite(internalResult); } else { InternalBeginRead(internalResult); } negotiationComplete.Set(); } else { negotiationComplete.Set(); internalResult.SetComplete(); } } catch (Exception ex) { negotiationComplete.Set(); internalResult.SetComplete(ex); } }
private void InternalWriteCallback(IAsyncResult ar) { if (!disposed) { InternalAsyncResult internalAsyncResult = (InternalAsyncResult)ar.AsyncState; try { innerStream.EndWrite(ar); internalAsyncResult.SetComplete(); } catch (Exception complete) { internalAsyncResult.SetComplete(complete); } } }
private void InternalBeginRead(InternalAsyncResult asyncResult) { try { int num = 0; lock (read) { bool flag = inputBuffer.Position == inputBuffer.Length && inputBuffer.Length > 0; bool flag2 = inputBuffer.Length > 0 && asyncResult.Count > 0; if (flag) { resetBuffer(); } else if (flag2) { num = inputBuffer.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); } } if (0 < num) { asyncResult.SetComplete(num); } else if (!context.ReceivedConnectionEnd) { innerStream.BeginRead(recbuf, 0, recbuf.Length, InternalReadCallback, new object[2] { recbuf, asyncResult }); } else { asyncResult.SetComplete(0); } } catch (TlsException ex) { protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); IL_012c :; } catch (Exception innerException) { throw new IOException("IO exception during read.", innerException); IL_0140 :; } }
private void AsyncHandshakeCallback(IAsyncResult asyncResult) { InternalAsyncResult internalAsyncResult = asyncResult.AsyncState as InternalAsyncResult; try { try { OnNegotiateHandshakeCallback(asyncResult); } catch (TlsException ex) { protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); IL_0036 :; } catch (Exception innerException) { protocol.SendAlert(AlertDescription.InternalError); throw new IOException("The authentication or decryption has failed.", innerException); IL_0055 :; } if (internalAsyncResult.ProceedAfterHandshake) { if (internalAsyncResult.FromWrite) { InternalBeginWrite(internalAsyncResult); } else { InternalBeginRead(internalAsyncResult); } negotiationComplete.Set(); } else { negotiationComplete.Set(); internalAsyncResult.SetComplete(); } } catch (Exception complete) { negotiationComplete.Set(); internalAsyncResult.SetComplete(complete); } }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { if (disposed) { return; } var new_buffer = asyncResult.Buffer; if (asyncResult.Offset != 0 && asyncResult.Count != 0) { new_buffer = new byte[asyncResult.Count]; Array.Copy(asyncResult.Buffer, asyncResult.Offset, new_buffer, 0, asyncResult.Count); } // Only write to the SSL object if we have data if (asyncResult.Count != 0) { var bytesWritten = ssl.Write(new_buffer, asyncResult.Count); if (bytesWritten < 0) { var lastError = ssl.GetError(bytesWritten); if (lastError == SslError.SSL_ERROR_WANT_READ) { //!!TODO - Log - unexpected renogiation request } throw new OpenSslException(); } } var bytesPending = write_bio.BytesPending; if (bytesPending > 0) { var buf = write_bio.ReadBytes((int)bytesPending); if (buf.Count > 0) { innerStream.BeginWrite( buf.Array, 0, buf.Count, InternalWriteCallback, asyncResult ); } } }
internal void NegotiateHandshake() { if (this.MightNeedHandshake) { InternalAsyncResult ar = new InternalAsyncResult(null, null, null, 0, 0, false, false); //if something already started negotiation, wait for it. //otherwise end it ourselves. if (!BeginNegotiateHandshake(ar)) { this.negotiationComplete.WaitOne(); } else { this.EndNegotiateHandshake(ar); } } }
public override void EndWrite(IAsyncResult asyncResult) { checkDisposed(); InternalAsyncResult internalAsyncResult = asyncResult as InternalAsyncResult; if (internalAsyncResult == null) { throw new ArgumentNullException("asyncResult is null or was not obtained by calling BeginWrite."); } if (!asyncResult.IsCompleted && !internalAsyncResult.AsyncWaitHandle.WaitOne(300000, exitContext: false)) { throw new TlsException(AlertDescription.InternalError, "Couldn't complete EndWrite"); } if (internalAsyncResult.CompletedWithError) { throw internalAsyncResult.AsyncException; } }
private void InternalBeginRead(InternalAsyncResult asyncResult) { // Check to see if the decrypted data stream should be reset if (decrypted_data_stream.Position == decrypted_data_stream.Length) { decrypted_data_stream.Seek(0, SeekOrigin.Begin); decrypted_data_stream.SetLength(0); } // Check to see if we have data waiting in the decrypted data stream if (decrypted_data_stream.Length > 0 && (decrypted_data_stream.Position != decrypted_data_stream.Length)) { // Process the pre-existing data int bytesRead = decrypted_data_stream.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); asyncResult.SetComplete(bytesRead); return; } // Start the async read from the inner stream innerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(InternalReadCallback), asyncResult); }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { byte[] new_buffer = asyncResult.Buffer; if (asyncResult.Offset != 0 && asyncResult.Count != 0) { new_buffer = new byte[asyncResult.Count]; Array.Copy(asyncResult.Buffer, asyncResult.Offset, new_buffer, 0, asyncResult.Count); } // Only write to the SSL object if we have data if (asyncResult.Count != 0) { int bytesWritten = ssl.Write(new_buffer, asyncResult.Count); if (bytesWritten < 0) { SslError lastError = ssl.GetError(bytesWritten); if (lastError == SslError.SSL_ERROR_WANT_READ) { //!!TODO - Log - unexpected renogiation request } throw new OpenSslException(); } } uint bytesPending = write_bio.BytesPending; //!!while (bytesPending > 0) { if (bytesPending > 0) { ArraySegment <byte> buf = write_bio.ReadBytes((int)bytesPending); innerStream.BeginWrite(buf.Array, 0, buf.Count, new AsyncCallback(InternalWriteCallback), asyncResult); } else { innerStream.BeginWrite(new byte[0], 0, 0, new AsyncCallback(InternalWriteCallback), asyncResult); } //!!bytesPending = write_bio.BytesPending; } }
public override void EndWrite(IAsyncResult asyncResult) { InternalAsyncResult internalAsyncResult = asyncResult as InternalAsyncResult; if (internalAsyncResult == null) { throw new ArgumentException("AsyncResult object was not obtained from SslStream.BeginWrite", "asyncResult"); } if (!internalAsyncResult.IsCompleted) { if (!internalAsyncResult.AsyncWaitHandle.WaitOne(WaitTimeOut, false)) { throw new IOException("Failed to complete the Write operation"); } } if (internalAsyncResult.CompletedWithError) { throw internalAsyncResult.AsyncException; } }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { checkDisposed(); if (buffer == null) { throw new ArgumentNullException("buffer is a null reference."); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset is less than 0."); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); } if (count < 0) { throw new ArgumentOutOfRangeException("count is less than 0."); } if (count > buffer.Length - offset) { throw new ArgumentOutOfRangeException("count is less than the length of buffer minus the value of the offset parameter."); } InternalAsyncResult internalAsyncResult = new InternalAsyncResult(callback, state, buffer, offset, count, fromWrite: true, proceedAfterHandshake: true); if (MightNeedHandshake) { if (!BeginNegotiateHandshake(internalAsyncResult)) { negotiationComplete.WaitOne(); InternalBeginWrite(internalAsyncResult); } } else { InternalBeginWrite(internalAsyncResult); } return(internalAsyncResult); }
private void EndHandshake(IAsyncResult asyncResult) { if (disposed) { return; } InternalAsyncResult handshakeAsyncResult = asyncResult as InternalAsyncResult; InternalAsyncResult readwriteAsyncResult = asyncResult.AsyncState as InternalAsyncResult; if (!handshakeAsyncResult.IsCompleted) { handshakeAsyncResult.AsyncWaitHandle.WaitOne(WaitTimeOut, false); } if (handshakeAsyncResult.CompletedWithError) { // if there's a handshake error, pass it to the read asyncresult instance readwriteAsyncResult.SetComplete(handshakeAsyncResult.AsyncException); return; } if (readwriteAsyncResult.ContinueAfterHandshake) { // We should continue the read/write operation since the handshake is complete if (readwriteAsyncResult.IsWriteOperation) { InternalBeginWrite(readwriteAsyncResult); } else { InternalBeginRead(readwriteAsyncResult); } } else { // If we aren't continuing, we're done readwriteAsyncResult.SetComplete(); } }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { try { lock (write) { byte[] array = protocol.EncodeRecord(ContentType.ApplicationData, asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); innerStream.BeginWrite(array, 0, array.Length, InternalWriteCallback, asyncResult); } } catch (TlsException ex) { protocol.SendAlert(ex.Alert); Close(); throw new IOException("The authentication or decryption has failed.", ex); IL_0080 :; } catch (Exception innerException) { throw new IOException("IO exception during Write.", innerException); IL_0092 :; } }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { try { // Send the buffer as a TLS record lock (this.write) { byte[] record = this.protocol.EncodeRecord( ContentType.ApplicationData, asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); this.innerStream.BeginWrite( record, 0, record.Length, new AsyncCallback(InternalWriteCallback), asyncResult); } } catch (Exception ex) { this.protocol.SendAlert(ref ex); this.Close(); throw new IOException("The authentication or decryption has failed.", ex); } }
private bool BeginNegotiateHandshake(InternalAsyncResult asyncResult) { try { lock (negotiate) { if (context.HandshakeState == HandshakeState.None) { OnBeginNegotiateHandshake(AsyncHandshakeCallback, asyncResult); return(true); } return(false); IL_003f: bool result; return(result); } } catch (TlsException ex) { negotiationComplete.Set(); protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); IL_007a: bool result; return(result); } catch (Exception innerException) { negotiationComplete.Set(); protocol.SendAlert(AlertDescription.InternalError); throw new IOException("The authentication or decryption has failed.", innerException); IL_00a5: bool result; return(result); } }
private void InternalBeginRead(InternalAsyncResult asyncResult) { if (disposed) { return; } // Check to see if the decrypted data stream should be reset if (cleartext.Position == cleartext.Length) { cleartext.Seek(0, SeekOrigin.Begin); cleartext.SetLength(0); } // Check to see if we have data waiting in the decrypted data stream if (cleartext.Length > 0 && (cleartext.Position != cleartext.Length)) { // Process the pre-existing data var bytesRead = cleartext.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); asyncResult.SetComplete(bytesRead); return; } // Start the async read from the inner stream innerStream.BeginRead(read_buffer, 0, read_buffer.Length, InternalReadCallback, asyncResult); }
private bool BeginNegotiateHandshake(InternalAsyncResult asyncResult) { try { lock (negotiate) { if (context.HandshakeState == HandshakeState.None) { BeginNegotiateHandshake(AsyncHandshakeCallback, asyncResult); return(true); } return(false); } } catch (Exception ex) { negotiationComplete.Set(); protocol.SendAlert(ref ex); throw new IOException("The authentication or decryption has failed.", ex); } }
public override IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback callback, object state) { this.checkDisposed(); if (buffer == null) { throw new ArgumentNullException("buffer is a null reference."); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset is less than 0."); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); } if (count < 0) { throw new ArgumentOutOfRangeException("count is less than 0."); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count is less than the length of buffer minus the value of the offset parameter."); } InternalAsyncResult asyncResult = new InternalAsyncResult(callback, state, buffer, offset, count, true, true); if (this.MightNeedHandshake) { if (! BeginNegotiateHandshake(asyncResult)) { //we made it down here so the handshake was not started. //another thread must have started it in the mean time. //wait for it to complete and then perform our original operation this.negotiationComplete.WaitOne(); InternalBeginWrite(asyncResult); } } else { InternalBeginWrite(asyncResult); } return asyncResult; }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { try { // Send the buffer as a TLS record lock (this.write) { byte[] record = this.protocol.EncodeRecord( ContentType.ApplicationData, asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); this.innerStream.BeginWrite( record, 0, record.Length, new AsyncCallback(InternalWriteCallback), asyncResult); } } catch (TlsException ex) { this.protocol.SendAlert(ex.Alert); this.Close(); throw new IOException("The authentication or decryption has failed.", ex); } catch (Exception ex) { throw new IOException("IO exception during Write.", ex); } }
private void InternalBeginRead(InternalAsyncResult asyncResult) { try { int preReadSize = 0; lock (this.read) { // If actual buffer is fully read, reset it bool shouldReset = this.inputBuffer.Position == this.inputBuffer.Length && this.inputBuffer.Length > 0; // If the buffer isn't fully read, but does have data, we need to immediately // read the info from the buffer and let the user know that they have more data. bool shouldReadImmediately = (this.inputBuffer.Length > 0) && (asyncResult.Count > 0); if (shouldReset) { this.resetBuffer(); } else if (shouldReadImmediately) { preReadSize = this.inputBuffer.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); } } // This is explicitly done outside the synclock to avoid // any potential deadlocks in the delegate call. if (0 < preReadSize) { asyncResult.SetComplete(preReadSize); } else if (!this.context.ReceivedConnectionEnd) { // this will read data from the network until we have (at least) one // record to send back to the caller this.innerStream.BeginRead(recbuf, 0, recbuf.Length, new AsyncCallback(InternalReadCallback), new object[] { recbuf, asyncResult }); } else { // We're done with the connection so we need to let the caller know with 0 bytes read asyncResult.SetComplete(0); } } catch (TlsException ex) { this.protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); } catch (Exception ex) { throw new IOException("IO exception during read.", ex); } }
private void EndNegotiateHandshake(InternalAsyncResult asyncResult) { if (asyncResult.IsCompleted == false) asyncResult.AsyncWaitHandle.WaitOne(); if (asyncResult.CompletedWithError) { throw asyncResult.AsyncException; } }
private bool BeginNegotiateHandshake(InternalAsyncResult asyncResult) { try { lock (this.negotiate) { if (this.context.HandshakeState == HandshakeState.None) { this.OnBeginNegotiateHandshake(new AsyncCallback(AsyncHandshakeCallback), asyncResult); return true; } else { return false; } } } catch (TlsException ex) { this.negotiationComplete.Set(); this.protocol.SendAlert(ex.Alert); throw new IOException("The authentication or decryption has failed.", ex); } catch (Exception ex) { this.negotiationComplete.Set(); this.protocol.SendAlert(AlertDescription.InternalError); throw new IOException("The authentication or decryption has failed.", ex); } }
internal void NegotiateHandshake() { if (this.MightNeedHandshake) { InternalAsyncResult ar = new InternalAsyncResult(null, null, null, 0, 0, false, false); //if something already started negotiation, wait for it. //otherwise end it ourselves. if (!BeginNegotiateHandshake(ar)) { this.negotiationComplete.WaitOne(); } else { this.EndNegotiateHandshake(ar); } } }
// read encrypted data until we have enough to decrypt (at least) one // record and return are the records (may be more than one) we have private void InternalReadCallback_inner(InternalAsyncResult internalResult, byte[] recbuf, object[] state, bool didRead, int n) { if (disposed) { return; } try { var dataToReturn = false; var pos = recordStream.Position; recordStream.Position = 0; byte[] record = null; // don't try to decode record unless we have at least 5 bytes // i.e. type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { record = protocol.ReceiveRecord(recordStream); } // a record of 0 length is valid (and there may be more record after it) while (record != null) { // we probably received more stuff after the record, and we must keep it! var remainder = recordStream.Length - recordStream.Position; byte[] outofrecord = null; if (remainder > 0) { outofrecord = new byte[remainder]; recordStream.Read(outofrecord, 0, outofrecord.Length); } lock (read) { var position = inputBuffer.Position; if (record.Length > 0) { // Write new data to the inputBuffer inputBuffer.Seek(0, SeekOrigin.End); inputBuffer.Write(record, 0, record.Length); // Restore buffer position inputBuffer.Seek(position, SeekOrigin.Begin); dataToReturn = true; } } recordStream.SetLength(0); record = null; if (remainder > 0) { recordStream.Write(outofrecord, 0, outofrecord.Length); // type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { // try to see if another record is available recordStream.Position = 0; record = protocol.ReceiveRecord(recordStream); if (record == null) { pos = recordStream.Length; } } else { pos = remainder; } } else { pos = 0; } } if (!dataToReturn && (!didRead || n > 0)) { if (context.ReceivedConnectionEnd) { internalResult.SetComplete(0); } else { // there is no record to return to caller and (possibly) more data waiting // so continue reading from network (and appending to stream) recordStream.Position = recordStream.Length; innerStream.BeginRead(recbuf, 0, recbuf.Length, InternalReadCallback, state); } } else { // we have record(s) to return -or- no more available to read from network // reset position for further reading recordStream.Position = pos; var bytesRead = 0; lock (read) { bytesRead = inputBuffer.Read(internalResult.Buffer, internalResult.Offset, internalResult.Count); } internalResult.SetComplete(bytesRead); } } catch (Exception ex) { internalResult.SetComplete(ex); } }
// read encrypted data until we have enough to decrypt (at least) one // record and return are the records (may be more than one) we have private void InternalReadCallback(IAsyncResult result) { if (this.disposed) { return; } object[] state = (object[])result.AsyncState; byte[] recbuf = (byte[])state[0]; InternalAsyncResult internalResult = (InternalAsyncResult)state[1]; try { int n = innerStream.EndRead(result); if (n > 0) { // Add the just received data to the waiting data recordStream.Write(recbuf, 0, n); } else { // 0 length data means this read operation is done (lost connection in the case of a network stream). internalResult.SetComplete(0); return; } bool dataToReturn = false; long pos = recordStream.Position; recordStream.Position = 0; byte[] record = null; // don't try to decode record unless we have at least 5 bytes // i.e. type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { record = this.protocol.ReceiveRecord(recordStream); } // a record of 0 length is valid (and there may be more record after it) while (record != null) { // we probably received more stuff after the record, and we must keep it! long remainder = recordStream.Length - recordStream.Position; byte[] outofrecord = null; if (remainder > 0) { outofrecord = new byte[remainder]; recordStream.Read(outofrecord, 0, outofrecord.Length); } lock (this.read) { long position = this.inputBuffer.Position; if (record.Length > 0) { // Write new data to the inputBuffer this.inputBuffer.Seek(0, SeekOrigin.End); this.inputBuffer.Write(record, 0, record.Length); // Restore buffer position this.inputBuffer.Seek(position, SeekOrigin.Begin); dataToReturn = true; } } recordStream.SetLength(0); record = null; if (remainder > 0) { recordStream.Write(outofrecord, 0, outofrecord.Length); // type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { // try to see if another record is available recordStream.Position = 0; record = this.protocol.ReceiveRecord(recordStream); if (record == null) { pos = recordStream.Length; } } else { pos = remainder; } } else { pos = 0; } } if (!dataToReturn && (n > 0)) { if (context.ReceivedConnectionEnd) { internalResult.SetComplete(0); } else { // there is no record to return to caller and (possibly) more data waiting // so continue reading from network (and appending to stream) recordStream.Position = recordStream.Length; this.innerStream.BeginRead(recbuf, 0, recbuf.Length, new AsyncCallback(InternalReadCallback), state); } } else { // we have record(s) to return -or- no more available to read from network // reset position for further reading recordStream.Position = pos; int bytesRead = 0; lock (this.read) { bytesRead = this.inputBuffer.Read(internalResult.Buffer, internalResult.Offset, internalResult.Count); } internalResult.SetComplete(bytesRead); } } catch (Exception ex) { internalResult.SetComplete(ex); } }
/* public override void Write(byte[] buffer, int offset, int count) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "Offset must be greater than or equal to 0"); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset", "Offset is greater than length of the buffer"); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "Count must be greater than 0"); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count", "Count is greater than buffer length - offset"); } byte[] new_buffer = buffer; if (offset != 0) { byte[] temp = new byte[count]; Array.Copy(buffer, offset, temp, 0, count); new_buffer = temp; } int bytesWritten = ssl.Write(new_buffer, count); if (bytesWritten <= 0) { SslError lastError = ssl.GetError(bytesWritten); if (lastError == SslError.SSL_ERROR_WANT_READ) { //!!TODO - Log - unexpected renogiation request } throw new OpenSslException((uint)lastError); } uint bytesPending = write_bio.BytesPending; while (bytesPending > 0) { ArraySegment<byte> buf = write_bio.ReadBytes((int)bytesPending); innerStream.Write(buf.Array, 0, buf.Count); bytesPending = write_bio.BytesPending; } } */ public override IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { if (buffer == null) { throw new ArgumentNullException("buffer", "buffer can't be null"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "offset less than 0"); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset", "offset must be less than buffer length"); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "count less than 0"); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count", "count is greater than buffer length - offset"); } bool proceedAfterHandshake = true; if (count == 0) proceedAfterHandshake = false; InternalAsyncResult asyncResult = new InternalAsyncResult(asyncCallback, asyncState, buffer, offset, count, true, proceedAfterHandshake); if (NeedHandshake) { //inHandshakeLoop = true; // Start the handshake BeginHandshake(asyncResult); } else { InternalBeginWrite(asyncResult); } return asyncResult; }
private void InternalBeginRead(InternalAsyncResult asyncResult) { // Check to see if the decrypted data stream should be reset if (decrypted_data_stream.Position == decrypted_data_stream.Length) { decrypted_data_stream.Seek(0, SeekOrigin.Begin); decrypted_data_stream.SetLength(0); } // Check to see if we have data waiting in the decrypted data stream if (decrypted_data_stream.Length > 0 && (decrypted_data_stream.Position != decrypted_data_stream.Length)) { // Process the pre-existing data int bytesRead = decrypted_data_stream.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); asyncResult.SetComplete(bytesRead); return; } // Start the async read from the inner stream innerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(InternalReadCallback), asyncResult); }
private void InternalBeginRead(InternalAsyncResult asyncResult) { if (disposed) return; // Check to see if the decrypted data stream should be reset if (cleartext.Position == cleartext.Length) { cleartext.Seek(0, SeekOrigin.Begin); cleartext.SetLength(0); } // Check to see if we have data waiting in the decrypted data stream if (cleartext.Length > 0 && (cleartext.Position != cleartext.Length)) { // Process the pre-existing data var bytesRead = cleartext.Read(asyncResult.Buffer, asyncResult.Offset, asyncResult.Count); asyncResult.SetComplete(bytesRead); return; } // Start the async read from the inner stream innerStream.BeginRead(read_buffer, 0, read_buffer.Length, InternalReadCallback, asyncResult); }
public override IAsyncResult BeginRead( byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { if (buffer == null) { throw new ArgumentNullException("buffer", "buffer can't be null"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "offset less than 0"); } if (offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset", "offset must be less than buffer length"); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "count less than 0"); } if (count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count", "count is greater than buffer length - offset"); } var proceedAfterHandshake = count != 0; var internalAsyncResult = new InternalAsyncResult( asyncCallback, asyncState, buffer, offset, count, false, proceedAfterHandshake); if (NeedHandshake) { BeginHandshake(internalAsyncResult); } else { InternalBeginRead(internalAsyncResult); } return internalAsyncResult; }
private void InternalReadCallback(IAsyncResult result) { if (!disposed) { object[] array = (object[])result.AsyncState; byte[] array2 = (byte[])array[0]; InternalAsyncResult internalAsyncResult = (InternalAsyncResult)array[1]; try { int num = innerStream.EndRead(result); if (num > 0) { recordStream.Write(array2, 0, num); bool flag = false; long position = recordStream.Position; recordStream.Position = 0L; byte[] array3 = null; if (recordStream.Length >= 5) { array3 = protocol.ReceiveRecord(recordStream); } while (array3 != null) { long num2 = recordStream.Length - recordStream.Position; byte[] array4 = null; if (num2 > 0) { array4 = new byte[num2]; recordStream.Read(array4, 0, array4.Length); } lock (read) { long position2 = inputBuffer.Position; if (array3.Length > 0) { inputBuffer.Seek(0L, SeekOrigin.End); inputBuffer.Write(array3, 0, array3.Length); inputBuffer.Seek(position2, SeekOrigin.Begin); flag = true; } } recordStream.SetLength(0L); array3 = null; if (num2 > 0) { recordStream.Write(array4, 0, array4.Length); if (recordStream.Length >= 5) { recordStream.Position = 0L; array3 = protocol.ReceiveRecord(recordStream); if (array3 == null) { position = recordStream.Length; } } else { position = num2; } } else { position = 0L; } } if (!flag && num > 0) { if (context.ReceivedConnectionEnd) { internalAsyncResult.SetComplete(0); } else { recordStream.Position = recordStream.Length; innerStream.BeginRead(array2, 0, array2.Length, InternalReadCallback, array); } } else { recordStream.Position = position; int complete = 0; lock (read) { complete = inputBuffer.Read(internalAsyncResult.Buffer, internalAsyncResult.Offset, internalAsyncResult.Count); } internalAsyncResult.SetComplete(complete); } } else { internalAsyncResult.SetComplete(0); } } catch (Exception complete2) { internalAsyncResult.SetComplete(complete2); } } }
// read encrypted data until we have enough to decrypt (at least) one // record and return are the records (may be more than one) we have private void InternalReadCallback_inner(InternalAsyncResult internalResult, byte[] recbuf, object[] state, bool didRead, int n) { if (this.disposed) return; try { bool dataToReturn = false; long pos = recordStream.Position; recordStream.Position = 0; byte[] record = null; // don't try to decode record unless we have at least 5 bytes // i.e. type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { record = this.protocol.ReceiveRecord(recordStream); } // a record of 0 length is valid (and there may be more record after it) while (record != null) { // we probably received more stuff after the record, and we must keep it! long remainder = recordStream.Length - recordStream.Position; byte[] outofrecord = null; if (remainder > 0) { outofrecord = new byte[remainder]; recordStream.Read(outofrecord, 0, outofrecord.Length); } lock (this.read) { long position = this.inputBuffer.Position; if (record.Length > 0) { // Write new data to the inputBuffer this.inputBuffer.Seek(0, SeekOrigin.End); this.inputBuffer.Write(record, 0, record.Length); // Restore buffer position this.inputBuffer.Seek(position, SeekOrigin.Begin); dataToReturn = true; } } recordStream.SetLength(0); record = null; if (remainder > 0) { recordStream.Write(outofrecord, 0, outofrecord.Length); // type (1), protocol (2) and length (2) if (recordStream.Length >= 5) { // try to see if another record is available recordStream.Position = 0; record = this.protocol.ReceiveRecord(recordStream); if (record == null) pos = recordStream.Length; } else pos = remainder; } else pos = 0; } if (!dataToReturn && (!didRead || (n > 0))) { if (context.ReceivedConnectionEnd) { internalResult.SetComplete (0); } else { // there is no record to return to caller and (possibly) more data waiting // so continue reading from network (and appending to stream) recordStream.Position = recordStream.Length; this.innerStream.BeginRead(recbuf, 0, recbuf.Length, new AsyncCallback(InternalReadCallback), state); } } else { // we have record(s) to return -or- no more available to read from network // reset position for further reading recordStream.Position = pos; int bytesRead = 0; lock (this.read) { bytesRead = this.inputBuffer.Read(internalResult.Buffer, internalResult.Offset, internalResult.Count); } internalResult.SetComplete(bytesRead); } } catch (Exception ex) { internalResult.SetComplete(ex); } }
private void InternalBeginWrite(InternalAsyncResult asyncResult) { byte[] new_buffer = asyncResult.Buffer; if (asyncResult.Offset != 0 && asyncResult.Count != 0) { new_buffer = new byte[asyncResult.Count]; Array.Copy(asyncResult.Buffer, asyncResult.Offset, new_buffer, 0, asyncResult.Count); } // Only write to the SSL object if we have data if (asyncResult.Count != 0) { int bytesWritten = ssl.Write(new_buffer, asyncResult.Count); if (bytesWritten < 0) { SslError lastError = ssl.GetError(bytesWritten); if (lastError == SslError.SSL_ERROR_WANT_READ) { //!!TODO - Log - unexpected renogiation request } throw new OpenSslException(); } } uint bytesPending = write_bio.BytesPending; //!!while (bytesPending > 0) { ArraySegment<byte> buf = write_bio.ReadBytes((int)bytesPending); innerStream.BeginWrite(buf.Array, 0, buf.Count, new AsyncCallback(InternalWriteCallback), asyncResult); //!!bytesPending = write_bio.BytesPending; } }
private void InternalReadCallback(IAsyncResult asyncResult) { InternalAsyncResult internalAsyncResult = (InternalAsyncResult)asyncResult.AsyncState; bool haveDataToReturn = false; try { int bytesRead = 0; try { bytesRead = innerStream.EndRead(asyncResult); } catch (Exception ex) { // Set the exception into the internal async result internalAsyncResult.SetComplete(ex); } if (bytesRead <= 0) { // Zero byte read most likely indicates connection closed (if it's a network stream) internalAsyncResult.SetComplete(0); return; } else { // Copy encrypted data into the SSL read_bio read_bio.Write(read_buffer, bytesRead); if (handShakeState == HandshakeState.InProcess || handShakeState == HandshakeState.RenegotiateInProcess) { // We are in the handshake, complete the async operation to fire the async // handshake callback for processing internalAsyncResult.SetComplete(bytesRead); return; } uint nBytesPending = read_bio.BytesPending; byte[] decrypted_buf = new byte[SSL3_RT_MAX_PACKET_SIZE]; while (nBytesPending > 0) { int decryptedBytesRead = ssl.Read(decrypted_buf, decrypted_buf.Length); if (decryptedBytesRead <= 0) { SslError lastError = ssl.GetError(decryptedBytesRead); if (lastError == SslError.SSL_ERROR_WANT_READ) { // if we have bytes pending in the write bio. // the client has requested a renegotiation if (write_bio.BytesPending > 0) { // Start the renegotiation by writing the write_bio data, and use the RenegotiationWriteCallback // to handle the rest of the renegotiation ArraySegment <byte> buf = write_bio.ReadBytes((int)write_bio.BytesPending); innerStream.BeginWrite(buf.Array, 0, buf.Count, new AsyncCallback(RenegotiationWriteCallback), internalAsyncResult); return; } // no data in the out bio, we just need more data to complete the record //break; } else if (lastError == SslError.SSL_ERROR_WANT_WRITE) { // unexpected error! //!!TODO debug log } else if (lastError == SslError.SSL_ERROR_ZERO_RETURN) { // Shutdown alert SendShutdownAlert(); break; } else { throw new OpenSslException(); } } if (decryptedBytesRead > 0) { // Write decrypted data to memory stream long pos = decrypted_data_stream.Position; decrypted_data_stream.Seek(0, SeekOrigin.End); decrypted_data_stream.Write(decrypted_buf, 0, decryptedBytesRead); decrypted_data_stream.Seek(pos, SeekOrigin.Begin); haveDataToReturn = true; } // See if we have more data to process nBytesPending = read_bio.BytesPending; } // Check to see if we have data to return, if not, fire the async read again if (!haveDataToReturn) { innerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(InternalReadCallback), internalAsyncResult); } else { int bytesReadIntoUserBuffer = 0; // Read the data into the buffer provided by the user (now hosted in the InternalAsyncResult) bytesReadIntoUserBuffer = decrypted_data_stream.Read(internalAsyncResult.Buffer, internalAsyncResult.Offset, internalAsyncResult.Count); internalAsyncResult.SetComplete(bytesReadIntoUserBuffer); } } } catch (Exception ex) { internalAsyncResult.SetComplete(ex); } }
private void AsyncHandshakeCallback(IAsyncResult asyncResult) { // Get the handshake internal result instance InternalAsyncResult internalAsyncResult = (InternalAsyncResult)asyncResult.AsyncState; int bytesRead = 0; if (internalAsyncResult.IsWriteOperation) { EndWrite(asyncResult); // Check to see if the handshake is complete (this could have been // the last response packet from the server. If so, we want to finalize // the async operation and call the HandshakeComplete callback if (handShakeState == HandshakeState.Complete) { internalAsyncResult.SetComplete(); return; } // Check to see if we saved an exception from the last Handshake process call // the if the client gets an error code, it needs to send the alert, and then // throw the exception here. if (handshakeException != null) { internalAsyncResult.SetComplete(handshakeException); return; } // We wrote out the handshake data, now read to get the response internalAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } else { try { bytesRead = EndRead(asyncResult); if (bytesRead > 0) { if (ProcessHandshake()) { //inHandshakeLoop = false; handShakeState = HandshakeState.Complete; // We have completed the handshake, but need to send the // last response packet. if (write_bio.BytesPending > 0) { internalAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } else { internalAsyncResult.SetComplete(); return; } } else { // Not complete with the handshake yet, write the handshake packet out internalAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } } else { // Read read 0 bytes, the remote socket has been closed, so complete the operation internalAsyncResult.SetComplete(new IOException("The remote stream has been closed")); } } catch (Exception ex) { internalAsyncResult.SetComplete(ex); } } }
/* public abstract virtual bool ProcessRenegotiation(); private IAsyncResult BeginRenegotiate(InternalAsyncResult readwriteAsyncResult) { Console.WriteLine("BeginRenegotiate"); handShakeState = HandshakeState.Renegotiate; // Wrap the readwriteAsyncResult in the renegotiateAsyncResult InternalAsyncResult renegotiateAsyncResult = new InternalAsyncResult(new AsyncCallback(RenegotiateComplete), readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessRenegotiation()) { handShakeState = HandshakeState.Complete; renegotiateAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { renegotiateAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(RenegotiateCallback), renegotiateAsyncResult); } else { renegotiateAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(RenegotiateCallback), renegotiateAsyncResult); } } return renegotiateAsyncResult; } private void RenegotiateCallback(IAsyncResult asyncResult) { InternalAsyncResult renegotiateAsyncResult = asyncResult.AsyncState as InternalAsyncResult; } */ private IAsyncResult BeginHandshake(InternalAsyncResult readwriteAsyncResult) { //!! // Move the handshake state to the next state //if (handShakeState == HandshakeState.Renegotiate) //{ // handShakeState = HandshakeState.RenegotiateInProcess; //} //else if (handShakeState != HandshakeState.Renegotiate) { handShakeState = HandshakeState.InProcess; } // Wrap the read/write InternalAsyncResult in the Handshake InternalAsyncResult instance InternalAsyncResult handshakeAsyncResult = new InternalAsyncResult(new AsyncCallback(AsyncHandshakeComplete), readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessHandshake()) { //inHandshakeLoop = false; handShakeState = HandshakeState.Complete; handshakeAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { handshakeAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), handshakeAsyncResult); } else { handshakeAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), handshakeAsyncResult); } } return handshakeAsyncResult; }