[csmaild-cvs] csmaild/src/Imap/NetworkManager Connection.cs,1.6,1.7
Brought to you by:
tamc
From: <ta...@us...> - 2003-07-26 23:09:28
|
Update of /cvsroot/csmaild/csmaild/src/Imap/NetworkManager In directory sc8-pr-cvs1:/tmp/cvs-serv31922/src/Imap/NetworkManager Modified Files: Connection.cs Log Message: Modified network model to be asynchronous for idle times and synchronous during the processing of the command. This cleans up the code a bit, while still keeping some of the theoretical benefits of doing it asynchronously. Reworked some of the argument parsing Started work on the FETCH command The test client got some work to, nothing significant yet. Index: Connection.cs =================================================================== RCS file: /cvsroot/csmaild/csmaild/src/Imap/NetworkManager/Connection.cs,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Connection.cs 25 Jul 2003 23:35:24 -0000 1.6 --- Connection.cs 26 Jul 2003 23:09:25 -0000 1.7 *************** *** 10,15 **** { public delegate void ReceivedLineDelegate(Connection con, string line); - public delegate void ReceivedBlockDelegate(Connection con, byte[] block); - public delegate void SentDataDelegate(Connection con); public delegate void ConnectionClosedDelegate(Connection con); --- 10,13 ---- *************** *** 23,35 **** private NetworkStream mSocketStream; // a stream wrapping the communication socket ! private byte[] mReceiveLineBuffer; // a small storage place for receiving bytes for the line ! private string mLineString; // used to store the line the client sends ! ! private byte[] mReceiveBlockBuffer; // used to receive the buffer requested ! private int mReceiveBlockOffset; // the current offset into the receive block buffer ! private int mReceiveBlockSize; // the number of bytes left to read into the receive block buffer ! ! private Queue mWriteQueue = Queue.Synchronized(new Queue()); // the queue for writes (so we do them in order) ! private bool mCurrentlyWriting; private Listener mListener; // the listener that created us --- 21,26 ---- private NetworkStream mSocketStream; // a stream wrapping the communication socket ! private byte[] mReceiveBuffer; // a small storage place for receiving bytes for the line ! private StringBuilder mReceivedString; // used to store the line that we have received private Listener mListener; // the listener that created us *************** *** 38,47 **** #region Events private event ReceivedLineDelegate mReceivedLineEvent; - private event ReceivedBlockDelegate mReceivedBlockEvent; - private event SentDataDelegate mSentDataEvent; private event ConnectionClosedDelegate mConnectionClosedEvent; /// <summary> ! /// Fires when the requested line has been received from the client /// </summary> public event ReceivedLineDelegate ReceivedLineEvent --- 29,36 ---- #region Events private event ReceivedLineDelegate mReceivedLineEvent; private event ConnectionClosedDelegate mConnectionClosedEvent; /// <summary> ! /// Fires when the asynchronously requested line has been received from the client /// </summary> public event ReceivedLineDelegate ReceivedLineEvent *************** *** 58,91 **** /// <summary> - /// Fires when the requested block has been received from the client - /// </summary> - public event ReceivedBlockDelegate ReceivedBlockEvent - { - add - { - mReceivedBlockEvent += value; - } - remove - { - mReceivedBlockEvent -= value; - } - } - - /// <summary> - /// Fires when sending is complete - /// </summary> - public event SentDataDelegate SentDataEvent - { - add - { - mSentDataEvent += value; - } - remove - { - mSentDataEvent -= value; - } - } - - /// <summary> /// Fires when the connection is closed remotely /// </summary> --- 47,50 ---- *************** *** 114,122 **** mListener = listener; - mWriteQueue = Queue.Synchronized(new Queue()); // the queue for writes (so we do them in order) - mCurrentlyWriting = false; - mSocketStream = new NetworkStream(mClient, true); ! mReceiveLineBuffer = new byte[8192]; } #endregion --- 73,79 ---- mListener = listener; mSocketStream = new NetworkStream(mClient, true); ! mReceiveBuffer = new byte[8192]; ! mReceivedString = new StringBuilder(1024); // so the initial few growings don't have to happen } #endregion *************** *** 124,151 **** #region Public methods /// <summary> ! /// Writes the message to the socket asynchronously /// </summary> /// <param name="msg">The message to write</param> public void Write(string msg) { ! Monitor.Enter(mWriteQueue); ! if(mCurrentlyWriting) ! mWriteQueue.Enqueue(msg); ! else { byte[] b = Encoding.ASCII.GetBytes(msg); ! if(mClient.Connected) ! mSocketStream.BeginWrite(b, 0, b.Length, new AsyncCallback(SendCallback), msg); ! mCurrentlyWriting = true; } - Monitor.Exit(mWriteQueue); } /// <summary> ! /// Writes the message to the socket asynchronosously /// </summary> /// <param name="msg">The message to write (it will be suffixed with a CRLF)</param> public void WriteLine(string msg) { Write(msg + "\r\n"); } --- 81,103 ---- #region Public methods /// <summary> ! /// Writes the message to the socket /// </summary> /// <param name="msg">The message to write</param> public void Write(string msg) { ! if(mClient.Connected) { byte[] b = Encoding.ASCII.GetBytes(msg); ! mSocketStream.Write(b, 0, b.Length); } } /// <summary> ! /// Writes the message to the socket /// </summary> /// <param name="msg">The message to write (it will be suffixed with a CRLF)</param> public void WriteLine(string msg) { + System.Diagnostics.Trace.WriteLine(ToString() + " <- " + msg); Write(msg + "\r\n"); } *************** *** 154,185 **** /// Reads a line from the socket asynchronously /// </summary> ! public void ReadLine() ! { ! ReadLine(mReceivedLineEvent); ! } ! ! public void ReadLine(ReceivedLineDelegate callback) { if(mClient.Connected) ! mSocketStream.BeginRead(mReceiveLineBuffer, 0, mReceiveLineBuffer.Length, new AsyncCallback(ReceiveLineCallback), callback); } ! /// <summary> ! /// Reads a block from the socket asynchronously ! /// </summary> ! /// <param name="block">The buffer to place the bytes read</param> ! /// <param name="offset">The offset into this buffer</param> ! /// <param name="size">The number of bytes to read into the buffer</param> ! public void ReadBlock(byte[] block, uint offset, uint length) { ! // TODO: really need to handle bigger values, will need to split this up too, because an presumed 4 gigabyte buffer probably won't slide ! if(length > int.MaxValue) ! ReadBlock(block, offset, int.MaxValue, mReceivedBlockEvent); ! else ! ReadBlock(block, offset, length, mReceivedBlockEvent); } /// <summary> ! /// Reads a block from the socket asynchronously calling the passed in delegate instead of the subscribed handler /// </summary> /// <param name="block">The buffer to place the bytes read</param> --- 106,150 ---- /// Reads a line from the socket asynchronously /// </summary> ! public void BeginReadLine() { if(mClient.Connected) ! mSocketStream.BeginRead(mReceiveBuffer, 0, mReceiveBuffer.Length, new AsyncCallback(ReceiveLineCallback), null); } ! public string ReadLine() { ! while(true) ! { ! // we may have enough information for a line from the last read ! string currentData = mReceivedString.ToString(); // TODO: this happening everytime could be a performance hit ! int idx = currentData.IndexOf("\r\n"); // yay, found the line ! if(idx != -1) ! { ! // we quite possibly got too much data for this line ! // get the line, leave the rest in the string builder ! string line = currentData.Substring(0, idx); ! mReceivedString.Remove(0, idx+2); // remove the line and the \r\n ! ! return line; ! } ! else // read more ! { ! int read = mSocketStream.Read(mReceiveBuffer, 0, mReceiveBuffer.Length); ! if(read == 0) // connection was closed ! { ! OnClosed(); ! return null; ! } ! else ! { ! string incoming = Encoding.ASCII.GetString(mReceiveBuffer, 0, read); ! mReceivedString.Append(incoming); ! } ! } ! } } /// <summary> ! /// Reads a block from the socket /// </summary> /// <param name="block">The buffer to place the bytes read</param> *************** *** 187,230 **** /// <param name="size">The number of bytes to read into the buffer</param> /// <param name="callback">The callback function to call after done reading</param> ! public void ReadBlock(byte[] block, uint offset, uint length, ReceivedBlockDelegate callback) { ! // TODO: really need to handle bigger values, will need to split this up too, because an presumed 4 gigabyte buffer probably won't slide ! if(length > int.MaxValue) { ! mReceiveBlockBuffer = block; ! mReceiveBlockOffset = (int)offset; ! mReceiveBlockSize = int.MaxValue; } ! else { ! mReceiveBlockBuffer = block; ! mReceiveBlockOffset = (int)offset; ! mReceiveBlockSize = (int)length; } - - ReadBlock(callback); } #endregion #region Protected methods ! private void FireReadLineDelegate(string line, ReceivedLineDelegate func) ! { ! if(func != null) ! func(this, line); ! } ! ! private void FireReadBlockDelegate(byte[] block, ReceivedBlockDelegate func) ! { ! if(func != null) ! func(this, block); ! } ! ! /// <summary> ! /// Fires the related event, called called when the data has been sent ! /// </summary> ! protected virtual void OnSent() { ! if(mSentDataEvent != null) ! mSentDataEvent(this); } --- 152,189 ---- /// <param name="size">The number of bytes to read into the buffer</param> /// <param name="callback">The callback function to call after done reading</param> ! public void ReadBlock(byte[] block, int offset, int length) { ! int read = 0; ! if(mReceivedString.Length > 0) { ! // TODO: this could probably be made slightly more efficient ! byte[] currentData = System.Text.Encoding.ASCII.GetBytes(mReceivedString.ToString()); ! int toCopy = Math.Min(length, currentData.Length); // get the number of bytes we'll need ! ! mReceivedString.Remove(0, toCopy); ! ! Array.Copy(currentData, 0, block, offset, toCopy); ! read += toCopy; } ! ! while(read != length) { ! int readThisTime = mSocketStream.Read(block, offset+read, length-read); ! if(readThisTime == 0) // connection was closed ! { ! OnClosed(); ! return; ! } ! else ! read += readThisTime; } } #endregion #region Protected methods ! protected void OnReadLine(string line) { ! if(mReceivedLineEvent != null) ! mReceivedLineEvent(this, line); } *************** *** 240,271 **** #region Private methods - private void ReadBlock(ReceivedBlockDelegate callback) - { - if(mClient.Connected) - mSocketStream.BeginRead(mReceiveBlockBuffer, mReceiveBlockOffset, mReceiveBlockSize, new AsyncCallback(ReceiveBlockCallback), callback); - } - - private void SendCallback(IAsyncResult result) - { - mSocketStream.EndWrite(result); - - Monitor.Enter(mWriteQueue); - mCurrentlyWriting = false; - if(mWriteQueue.Count != 0) - { - string msg = (string)mWriteQueue.Dequeue(); - byte[] b = Encoding.ASCII.GetBytes(msg); - if(mClient.Connected) - mSocketStream.BeginWrite(b, 0, b.Length, new AsyncCallback(SendCallback), msg); - mCurrentlyWriting = true; - } - System.Diagnostics.Trace.Write(ToString() + " <- " + (string)result.AsyncState); - - Monitor.Exit(mWriteQueue); - - // spill event - OnSent(); - } - private void ReceiveLineCallback(IAsyncResult result) { --- 199,202 ---- *************** *** 279,293 **** { // if we're reading a line ! mLineString += Encoding.ASCII.GetString(mReceiveLineBuffer, 0, read); ! // we're reading a line and we found the eof!! ! int idx = mLineString.IndexOf("\r\n"); if(idx != -1) { // we quite possibly got too much data for this line ! // stuff everything before the <CRLF> in this ! string line = mLineString.Substring(0, idx); ! // and everything after back here ! mLineString = mLineString.Substring(idx+2); if(line != string.Empty) --- 210,225 ---- { // if we're reading a line ! string incoming = Encoding.ASCII.GetString(mReceiveBuffer, 0, read); ! mReceivedString.Append(incoming); ! // we're reading a line and we found the end of the line!! ! string currentData = mReceivedString.ToString(); // TODO: this happening everytime could be a performance hit ! int idx = currentData.IndexOf("\r\n"); if(idx != -1) { // we quite possibly got too much data for this line ! // get the line, leave the rest in the string builder ! string line = currentData.Substring(0, idx); ! mReceivedString.Remove(0, idx+2); // remove the line and the \r\n if(line != string.Empty) *************** *** 295,331 **** // spill event ! FireReadLineDelegate(line, (ReceivedLineDelegate)result.AsyncState); ! } ! else ! { ! // read some more bytes ! ReadLine(); ! } ! } ! } ! ! private void ReceiveBlockCallback(IAsyncResult result) ! { ! int read = mSocketStream.EndRead(result); ! if(read == 0) // connection was closed ! { ! // spill event ! OnClosed(); ! } ! else ! { ! // move offset by the amount we read ! mReceiveBlockOffset += read; ! // decrease the amount we have left to read by the amount we read ! mReceiveBlockSize -= read; ! ! if(mReceiveBlockSize == 0) ! { ! System.Diagnostics.Trace.WriteLine(ToString() + " -> " + System.Text.Encoding.ASCII.GetString(mReceiveBlockBuffer)); ! ! FireReadBlockDelegate(mReceiveBlockBuffer, (ReceivedBlockDelegate)result.AsyncState); } ! else ! ReadBlock((ReceivedBlockDelegate)result.AsyncState); } } --- 227,234 ---- // spill event ! OnReadLine(line); } ! else // read more ! BeginReadLine(); } } |