SmtpReplyReaderFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / Mail / SmtpReplyReaderFactory.cs / 1 / SmtpReplyReaderFactory.cs

                            namespace System.Net.Mail 
{
    using System;
    using System.IO;
    using System.Text; 
    using System.Collections;
 
    //Streams created are read only and return 0 once a full server reply has been read 
    //To get the next server reply, call GetNextReplyReader
    class SmtpReplyReaderFactory 
    {
        enum ReadState
        {
            Status0, 
            Status1,
            Status2, 
            ContinueFlag, 
            ContinueCR,
            ContinueLF, 
            LastCR,
            LastLF,
            Done
        } 

 
        BufferedReadStream bufferedStream; 
        byte[] byteBuffer;
        char[] charBuffer; 
        SmtpReplyReader currentReader;
        const int DefaultBufferSize = 256;
        ReadState readState = ReadState.Status0;
        SmtpStatusCode statusCode; 

        internal SmtpReplyReaderFactory(Stream stream) 
        { 
            bufferedStream = new BufferedReadStream(stream);
        } 

        internal SmtpReplyReader CurrentReader
        {
            get 
            {
                return currentReader; 
            } 
        }
 
        internal SmtpStatusCode StatusCode
        {
            get
            { 
                return statusCode;
            } 
        } 

        /* Consider removing 
        internal IAsyncResult BeginClose(SmtpReplyReader caller, AsyncCallback callback, object state)
        {
            CloseAsyncResult result = new CloseAsyncResult(this, callback, state);
            result.Close(caller); 
            return result;
        } 
        */ 
        /*
        internal IAsyncResult BeginRead(SmtpReplyReader caller, byte[] buffer, int offset, int count, AsyncCallback callback, object state) 
        {
            ReadAsyncResult result = new ReadAsyncResult(this, buffer, offset, count, callback, state);
            result.Read(caller);
            return result; 
        }
        */ 
 
        internal IAsyncResult BeginReadLines(SmtpReplyReader caller, AsyncCallback callback, object state)
        { 
            ReadLinesAsyncResult result =  new ReadLinesAsyncResult(this, callback, state);
            result.Read(caller);
            return result;
        } 

        internal IAsyncResult BeginReadLine(SmtpReplyReader caller, AsyncCallback callback, object state) 
        { 
            ReadLinesAsyncResult result =  new ReadLinesAsyncResult(this, callback, state, true);
            result.Read(caller); 
            return result;
        }

 
        internal void Close(SmtpReplyReader caller)
        { 
            if (currentReader == caller) 
            {
                if (readState != ReadState.Done) 
                {
                    if (byteBuffer == null)
                    {
                        byteBuffer = new byte[SmtpReplyReaderFactory.DefaultBufferSize]; 
                    }
 
                    while (0 != Read(caller, byteBuffer, 0, byteBuffer.Length)); 
                }
 
                currentReader = null;
            }
        }
 
        /* Consider removing
        internal void EndClose(IAsyncResult result) 
        { 
            CloseAsyncResult.End(result);
        } 

        internal int EndRead(IAsyncResult result)
        {
            return ReadAsyncResult.End(result); 
        }
        */ 
 

        internal LineInfo[] EndReadLines(IAsyncResult result) 
        {
            return ReadLinesAsyncResult.End(result);
        }
 
        internal LineInfo EndReadLine(IAsyncResult result)
        { 
            LineInfo[] info = ReadLinesAsyncResult.End(result); 
            if(info != null && info.Length >0){
                return info[0]; 
            }
            return new LineInfo();
        }
 
        internal SmtpReplyReader GetNextReplyReader()
        { 
            if (currentReader != null) 
            {
                currentReader.Close(); 
            }

            readState = ReadState.Status0;
            currentReader = new SmtpReplyReader(this); 
            return currentReader;
        } 
 
        int ProcessRead(byte[] buffer, int offset, int read, bool readLine)
        { 
            // if 0 bytes were read,there was a failure
            if (read == 0)
            {
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.net_io_connectionclosed)); 
            }
 
            unsafe 
            {
                fixed (byte* pBuffer = buffer) 
                {
                    byte* start = pBuffer + offset;
                    byte* ptr = start;
                    byte* end = ptr + read; 

                    switch (readState) 
                    { 
                        case ReadState.Status0:
                        { 
                            if (ptr < end)
                            {
                                byte b = *ptr++;
                                if (b < '0' && b > '9') 
                                {
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse)); 
                                } 

                                statusCode = (SmtpStatusCode)(100*(b - '0')); 

                                goto case ReadState.Status1;
                            }
                            readState = ReadState.Status0; 
                            break;
                        } 
                        case ReadState.Status1: 
                        {
                            if (ptr < end) 
                            {
                                byte b = *ptr++;
                                if (b < '0' && b > '9')
                                { 
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse));
                                } 
 
                                statusCode += 10*(b - '0');
 
                                goto case ReadState.Status2;
                            }
                            readState = ReadState.Status1;
                            break; 
                        }
                        case ReadState.Status2: 
                        { 
                            if (ptr < end)
                            { 
                                byte b = *ptr++;
                                if (b < '0' && b > '9')
                                {
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse)); 
                                }
 
                                statusCode += b - '0'; 

                                goto case ReadState.ContinueFlag; 
                            }
                            readState = ReadState.Status2;
                            break;
                        } 
                        case ReadState.ContinueFlag:
                        { 
                            if (ptr < end) 
                            {
                                byte b = *ptr++; 
                                if (b == ' ')       // last line
                                {
                                    goto case ReadState.LastCR;
                                } 
                                else if (b == '-')  // more lines coming
                                { 
                                    goto case ReadState.ContinueCR; 
                                }
                                else                // error 
                                {
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse));
                                }
                            } 
                            readState = ReadState.ContinueFlag;
                            break; 
                        } 
                        case ReadState.ContinueCR:
                        { 
                            while (ptr < end)
                            {
                                if (*ptr++ == '\r')
                                { 
                                    goto case ReadState.ContinueLF;
                                } 
                            } 
                            readState = ReadState.ContinueCR;
                            break; 
                        }
                        case ReadState.ContinueLF:
                        {
                            if (ptr < end) 
                            {
                                if (*ptr++ != '\n') 
                                { 
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse));
                                } 
                                if (readLine)
                                {
                                    readState = ReadState.Status0;
                                    return (int)(ptr - start); 
                                }
                                goto case ReadState.Status0; 
                            } 
                            readState = ReadState.ContinueLF;
                            break; 
                        }
                        case ReadState.LastCR:
                        {
                            while (ptr < end) 
                            {
                                if (*ptr++ == '\r') 
                                { 
                                    goto case ReadState.LastLF;
                                } 
                            }
                            readState = ReadState.LastCR;
                            break;
                        } 
                        case ReadState.LastLF:
                        { 
                            if (ptr < end) 
                            {
                                if (*ptr++ != '\n') 
                                {
                                    throw new FormatException(SR.GetString(SR.SmtpInvalidResponse));
                                }
                                goto case ReadState.Done; 
                            }
                            readState = ReadState.LastLF; 
                            break; 
                        }
                        case ReadState.Done: 
                        {
                            int actual = (int)(ptr - start);
                            readState = ReadState.Done;
                            return actual; 
                        }
                    } 
                    return (int)(ptr - start); 
                }
            } 
        }

        internal int Read(SmtpReplyReader caller, byte[] buffer, int offset, int count)
        { 
            // if we've already found the delimitter, then return 0 indicating
            // end of stream. 
            if (count == 0 || currentReader != caller || readState == ReadState.Done) 
            {
                return 0; 
            }

            int read = bufferedStream.Read(buffer, offset, count);
            int actual = ProcessRead(buffer, offset, read, false); 
            if (actual < read)
            { 
                bufferedStream.Push(buffer, offset + actual, read - actual); 
            }
 
            return actual;
        }

 
        internal LineInfo ReadLine(SmtpReplyReader caller)
        { 
           LineInfo[] info = ReadLines(caller,true); 
           if(info != null && info.Length >0){
               return info[0]; 
           }
           return new LineInfo();
        }
 
        internal LineInfo[] ReadLines(SmtpReplyReader caller)
        { 
            return ReadLines(caller,false); 
        }
 

        internal LineInfo[] ReadLines(SmtpReplyReader caller, bool oneLine)
        {
            if (caller != currentReader || readState == ReadState.Done) 
            {
                return new LineInfo[0]; 
            } 

            if (byteBuffer == null) 
            {
                byteBuffer = new byte[SmtpReplyReaderFactory.DefaultBufferSize];
            }
 
            if (charBuffer == null)
            { 
                charBuffer = new char[SmtpReplyReaderFactory.DefaultBufferSize]; 
            }
 
            System.Diagnostics.Debug.Assert(readState == ReadState.Status0);

            StringBuilder builder = new StringBuilder();
            ArrayList lines = new ArrayList(); 
            int statusRead = 0;
 
            for(int start = 0, read = 0; ; ) 
            {
                if (start == read) 
                {
                    read = bufferedStream.Read(byteBuffer, 0, byteBuffer.Length);
                    start = 0;
                } 

                int actual = ProcessRead(byteBuffer, start, read - start, true); 
 
                if (statusRead < 4)
                { 
                    int left = Math.Min(4-statusRead, actual);
                    statusRead += left;
                    start += left;
                    actual -= left; 
                    if (actual == 0)
                    { 
                        continue; 
                    }
                } 

                for (int i = start; i < start + actual; i++)
                {
                    charBuffer[i] = (char)byteBuffer[i]; 
                }
 
                builder.Append(charBuffer, start, actual); // skip status stuff 
                start += actual;
 
                if (readState == ReadState.Status0)
                {
                    statusRead = 0;
                    lines.Add(new LineInfo(statusCode, builder.ToString(0, builder.Length - 2))); // return everything except CRLF 

                    if(oneLine){ 
                        bufferedStream.Push(byteBuffer, start, read - start); 
                        return (LineInfo[])lines.ToArray(typeof(LineInfo));
                    } 
                    builder = new StringBuilder();
                }
                else if (readState == ReadState.Done)
                { 
                    lines.Add(new LineInfo(statusCode, builder.ToString(0, builder.Length - 2))); // return everything except CRLF
                    bufferedStream.Push(byteBuffer, start, read - start); 
                    return (LineInfo[])lines.ToArray(typeof(LineInfo)); 
                }
            } 
        }

        /*
        class ReadAsyncResult : LazyAsyncResult 
        {
            byte[] buffer; 
            int count; 
            int offset;
            SmtpReplyReaderFactory parent; 
            static AsyncCallback readCallback = new AsyncCallback(ReadCallback);
            int read;

            internal ReadAsyncResult(SmtpReplyReaderFactory parent, byte[] buffer, int offset, int count, AsyncCallback callback, object state) : base(null, state, callback) 
            {
                this.parent = parent; 
                this.buffer = buffer; 
                this.offset = offset;
                this.count = count; 
            }

            internal void Read( SmtpReplyReader caller ){
 
                // if we've already found the delimitter, then return 0 indicating
                // end of stream. 
                if (count == 0 || parent.currentReader != caller || parent.readState == ReadState.Done) 
                {
                    InvokeCallback(); 
                    return;
                }
                IAsyncResult result = parent.bufferedStream.BeginRead(this.buffer, this.offset, this.count, readCallback, this);
                if (!result.CompletedSynchronously) 
                {
                    return; 
                } 
                this.read = parent.bufferedStream.EndRead(result);
                ProcessRead(); 
            }

            internal static int End(IAsyncResult result)
            { 
                ReadAsyncResult thisPtr = (ReadAsyncResult)result;
                thisPtr.InternalWaitForCompletion(); 
                return thisPtr.read; 
            }
            static void ReadCallback(IAsyncResult result) 
            {
                if (!result.CompletedSynchronously)
                {
                    ReadAsyncResult thisPtr = (ReadAsyncResult)result.AsyncState; 
                    try
                    { 
                        thisPtr.read = thisPtr.parent.bufferedStream.EndRead(result); 
                        thisPtr.ProcessRead();
                    } 
                    catch (Exception e)
                    {
                        thisPtr.InvokeCallback(e);
                    } 
                    catch {
                        thisPtr.InvokeCallback(new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
                    } 
                }
            } 

            void ProcessRead()
            {
                int actual = parent.ProcessRead(buffer, offset, read, false); 
                if (actual < read)
                { 
                    parent.bufferedStream.Push(buffer, offset + actual, read - actual); 
                }
                read = actual; 
                InvokeCallback();
            }

        } 
        */
 
 
        class ReadLinesAsyncResult : LazyAsyncResult
        { 
            StringBuilder builder;
            ArrayList lines;
            SmtpReplyReaderFactory parent;
            static AsyncCallback readCallback = new AsyncCallback(ReadCallback); 
            int read;
            int statusRead; 
            bool oneLine; 

            internal ReadLinesAsyncResult(SmtpReplyReaderFactory parent, AsyncCallback callback, object state) : base(null, state, callback) 
            {
                this.parent = parent;
            }
 
            internal ReadLinesAsyncResult(SmtpReplyReaderFactory parent, AsyncCallback callback, object state, bool oneLine) : base(null, state, callback)
            { 
                this.oneLine = oneLine; 
                this.parent = parent;
            } 

            internal void Read(SmtpReplyReader caller){

                // if we've already found the delimitter, then return 0 indicating 
                // end of stream.
                if (parent.currentReader != caller || parent.readState == ReadState.Done) 
                { 
                    InvokeCallback();
                    return; 
                }

                if (parent.byteBuffer == null)
                { 
                    parent.byteBuffer = new byte[SmtpReplyReaderFactory.DefaultBufferSize];
                } 
 
                if (parent.charBuffer == null)
                { 
                    parent.charBuffer = new char[SmtpReplyReaderFactory.DefaultBufferSize];
                }

                System.Diagnostics.Debug.Assert(parent.readState == ReadState.Status0); 

                builder = new StringBuilder(); 
                lines = new ArrayList(); 

                Read(); 
            }

            internal static LineInfo[] End(IAsyncResult result)
            { 
                ReadLinesAsyncResult thisPtr = (ReadLinesAsyncResult)result;
                thisPtr.InternalWaitForCompletion(); 
                return (LineInfo[])thisPtr.lines.ToArray(typeof(LineInfo)); 
            }
 
            void Read()
            {
                do
                { 
                    IAsyncResult result = parent.bufferedStream.BeginRead(parent.byteBuffer, 0, parent.byteBuffer.Length, readCallback, this);
                    if (!result.CompletedSynchronously) 
                    { 
                        return;
                    } 
                    read = parent.bufferedStream.EndRead(result);
                } while(ProcessRead());
            }
 
            static void ReadCallback(IAsyncResult result)
            { 
                if (!result.CompletedSynchronously) 
                {
                    Exception exception = null; 
                    ReadLinesAsyncResult thisPtr = (ReadLinesAsyncResult)result.AsyncState;
                    try
                    {
                        thisPtr.read = thisPtr.parent.bufferedStream.EndRead(result); 
                        if (thisPtr.ProcessRead())
                        { 
                            thisPtr.Read(); 
                        }
                    } 
                    catch (Exception e)
                    {   exception = e;
                    }
                    catch { 
                        exception = new Exception(SR.GetString(SR.net_nonClsCompliantException));
                    } 
 
                    if(exception != null){
                        thisPtr.InvokeCallback(exception); 
                    }
                }
            }
 
            bool ProcessRead()
            { 
                if (read == 0) 
                {
                    throw new IOException(SR.GetString(SR.net_io_readfailure, SR.net_io_connectionclosed)); 
                }

                for(int start = 0; start != read; )
                { 
                    int actual = parent.ProcessRead(parent.byteBuffer, start, read - start, true);
 
                    if (statusRead < 4) 
                    {
                        int left = Math.Min(4-statusRead, actual); 
                        statusRead += left;
                        start += left;
                        actual -= left;
                        if (actual == 0) 
                        {
                            continue; 
                        } 
                    }
 
                    for (int i = start; i < start + actual; i++)
                    {
                        parent.charBuffer[i] = (char)parent.byteBuffer[i];
                    } 

                    builder.Append(parent.charBuffer, start, actual); // skip status stuff 
                    start += actual; 

                    if (parent.readState == ReadState.Status0) 
                    {
                        lines.Add(new LineInfo(parent.statusCode, builder.ToString(0, builder.Length - 2))); // return everything except CRLF
                        builder = new StringBuilder();
                        statusRead = 0; 

                        if (oneLine) { 
                            parent.bufferedStream.Push(parent.byteBuffer, start, read - start); 
                            InvokeCallback();
                            return false; 
                        }
                    }
                    else if (parent.readState == ReadState.Done)
                    { 
                        lines.Add(new LineInfo(parent.statusCode, builder.ToString(0, builder.Length - 2))); // return everything except CRLF
                        parent.bufferedStream.Push(parent.byteBuffer, start, read - start); 
                        InvokeCallback(); 
                        return false;
                    } 
                }
                return true;
            }
 
        }
    } 
}
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK