protected AsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncResult asyncResult, DataType type) // not synced! { int position = m_ToSendList.Count; if (type == DataType.ProtocolData) { position = 0; } TransferItem item = new TransferItem(buffer, offset, size, asyncResult, type); m_ToSendList.Insert(position, item); ResumeSending(); return(item.AsyncResult); }
public AsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { lock (this) { if (m_ActiveReceive != null) { throw new SocketException(); } AsyncResult ret = new AsyncResult(callback, state, this); m_ActiveReceive = new TransferItem(buffer, offset, size, ret, DataType.ApplicationData); if (m_DecryptedBuffer.Length > 0) { ProcessDecryptedBytes(null); } else { if (!m_Socket.Connected && m_ActiveReceive.AsyncResult != null) { m_ActiveReceive.AsyncResult.Notify(null); } } return(ret); } }
public SocketController(SecureSocket parent, Socket socket, SecurityOptions options) { m_Parent = parent; m_Socket = socket; m_IsDisposed = false; m_ActiveSend = null; m_ActiveReceive = null; m_DecryptedBuffer = new XBuffer(); m_ToSendList = new ArrayList(2); m_SentList = new ArrayList(2); m_ReceiveBuffer = new byte[m_ReceiveBufferLength]; m_Compatibility = new CompatibilityLayer(this, options); // m_RecordLayer = new RecordLayer(this, options); try { m_Socket.BeginReceive(m_ReceiveBuffer, 0, m_ReceiveBufferLength, SocketFlags.None, new AsyncCallback(this.OnReceive), null); } catch (Exception e) { CloseConnection(e); } if (options.Entity == ConnectionEnd.Client) { // byte[] hello = m_RecordLayer.GetControlBytes(ControlType.ClientHello); byte[] hello = m_Compatibility.GetClientHello(); BeginSend(hello, 0, hello.Length, null, DataType.ProtocolData); } }
protected AsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncResult asyncResult, DataType type) // not synced! //MsgMe("BeginSend(AS)", "client sending buffer"); { int position = m_ToSendList.Count; if (type == DataType.ProtocolData) { position = 0; } else { if (!IsNegotiationCompleted) { throw new SslException(AlertDescription.InternalError, "Attempt to send data before negotiation is complete"); } } TransferItem item = new TransferItem(buffer, offset, size, asyncResult, type); m_ToSendList.Insert(position, item); ResumeSending(); //MsgMe("BeginSend(AS)", " client returns"); return(item.AsyncResult); }
public AsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { lock(this) { if (m_ActiveReceive != null) throw new SocketException(); AsyncResult ret = new AsyncResult(callback, state, this); m_ActiveReceive = new TransferItem(buffer, offset, size, ret, DataType.ApplicationData); if (m_DecryptedBuffer.Length > 0) { ProcessDecryptedBytes(null); } else { if (!m_Socket.Connected && m_ActiveReceive.AsyncResult != null) m_ActiveReceive.AsyncResult.Notify(null); } return ret; } }
protected AsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncResult asyncResult, DataType type) { // not synced! int position = m_ToSendList.Count; if (type == DataType.ProtocolData) position = 0; TransferItem item = new TransferItem(buffer, offset, size, asyncResult, type); m_ToSendList.Insert(position, item); ResumeSending(); return item.AsyncResult; }
protected void ResumeSending() { // not synced! if (m_IsSending) // if we're already sending, return return; if (m_ToSendList.Count == 0) // is there anything to send? return; // we should not send application data if a negotiation is in progress if ((m_RecordLayer == null && ((TransferItem)m_ToSendList[0]).Type == DataType.ApplicationData) || (m_RecordLayer != null && m_RecordLayer.IsNegotiating() && ((TransferItem)m_ToSendList[0]).Type == DataType.ApplicationData)) return; m_ActiveSend = (TransferItem)m_ToSendList[0]; m_ToSendList.RemoveAt(0); m_IsSending = true; try { // if we're sending application data, encrypt it before sending // protocol data should not be touched if (m_ActiveSend.Type == DataType.ApplicationData) { m_ActiveSend.Buffer = m_RecordLayer.EncryptBytes(m_ActiveSend.Buffer, m_ActiveSend.Offset, m_ActiveSend.Size, ContentType.ApplicationData); m_ActiveSend.Offset = 0; m_ActiveSend.Size = m_ActiveSend.Buffer.Length; } m_Socket.BeginSend(m_ActiveSend.Buffer, m_ActiveSend.Offset, m_ActiveSend.Size, SocketFlags.None, new AsyncCallback(this.OnSent), null); } catch (Exception e) { CloseConnection(e); } }
protected void CloseConnection(Exception e) { // not synced! // e == SocketException || SslException if (!m_IsDisposed) { m_IsDisposed = true; try { m_Socket.Shutdown(SocketShutdown.Both); } catch { } m_Socket.Close(); if (m_ActiveSend != null) { if (m_ActiveSend.AsyncResult != null) { m_SentList.Add(m_ActiveSend); m_ActiveSend.AsyncResult.Notify(e); } } Exception f = e; if (f == null) f = new SslException(AlertDescription.UnexpectedMessage, "The bytes could not be sent because the connection has been closed."); for (int i = 0; i < m_ToSendList.Count; i++) { m_ActiveSend = (TransferItem)m_ToSendList[i]; m_SentList.Add(m_ActiveSend); m_ActiveSend.AsyncResult.Notify(f); } m_ToSendList.Clear(); if (m_ActiveReceive != null && m_ActiveReceive.AsyncResult != null) { m_ActiveReceive.AsyncResult.Notify(e); } if (m_ShutdownCallback != null) { m_ShutdownCallback.Notify(e); } // destroy sensitive data if (m_RecordLayer != null) m_RecordLayer.Dispose(); } }
public TransferItem EndReceive(IAsyncResult ar) { // returns null if the specified IAsyncResult is not ours TransferItem ret; lock (this) { // synchronize if (ar != m_ActiveReceive.AsyncResult) { return null; } else { ret = m_ActiveReceive; } } // do _not_ call this method inside the critical section, or the code may deadlock! while (!ret.AsyncResult.IsCompleted) { ret.AsyncResult.AsyncWaitHandle.WaitOne(200, false); } lock (this) { m_ActiveReceive = null; } return ret; }
/// <summary> /// Begins an asynchronous write to a stream. /// </summary> /// <param name="buffer">The location in memory that holds the data to send.</param> /// <param name="offset">The location in buffer to begin sending the data.</param> /// <param name="size">The size of buffer.</param> /// <param name="callback">The delegate to call when the asynchronous call is complete.</param> /// <param name="state">An object containing additional information supplied by the client.</param> /// <returns>An <see cref="IAsyncResult"/> representing the asynchronous call.</returns> /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception> /// <exception cref="ArgumentOutOfRangeException">The specified <paramref name="offset"/> or <paramref name="size"/> exceeds the size of <paramref name="buffer"/>.</exception> /// <exception cref="IOException">There is a failure while writing to the network.</exception> // Thanks go out to Martin Plante for notifying us about a bug in this method. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (buffer == null) throw new ArgumentNullException(); if (offset < 0 || offset > buffer.Length || size < 0 || size > buffer.Length - offset) throw new ArgumentOutOfRangeException(); if (Socket == null) throw new IOException(); if (WriteResult != null) throw new IOException(); TransferItem localResult = new TransferItem(new byte[size], 0, size, new AsyncResult(callback, state, null), DataType.ApplicationData); WriteResult = localResult; Array.Copy(buffer, offset, localResult.Buffer, 0, size); try { Socket.BeginSend(localResult.Buffer, 0, size, SocketFlags.None, new AsyncCallback(OnBytesSent), (int)0); return localResult.AsyncResult; } catch { throw new IOException(); } }
public SocketController(SecureSocket parent, Socket socket, SecurityOptions options) { this.m_Parent = parent; this.m_Socket = socket; this.m_IsDisposed = false; this.m_ActiveSend = null; this.m_ActiveReceive = null; this.m_DecryptedBuffer = new XBuffer(); this.m_ToSendList = new ArrayList(2); this.m_SentList = new ArrayList(2); this.m_ReceiveBuffer = new byte[m_ReceiveBufferLength]; this.m_End = options.Entity; this.OnConnectionClose += parent.ConnectionCloseHandler; this.m_Compatibility = new CompatibilityLayer(this, options); }
protected AsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncResult asyncResult, DataType type) { // not synced! //MsgMe("BeginSend(AS)", "client sending buffer"); int position = m_ToSendList.Count; if (type == DataType.ProtocolData) { position = 0; } else { if (!IsNegotiationCompleted) throw new SslException(AlertDescription.InternalError, "Attempt to send data before negotiation is complete"); } TransferItem item = new TransferItem(buffer, offset, size, asyncResult, type); m_ToSendList.Insert(position, item); ResumeSending(); //MsgMe("BeginSend(AS)", " client returns"); return item.AsyncResult; }