/// <summary> /// Begins writing period terminated data to socket. The data is terminated by a line containing only a period, that is, /// the character sequence "<CRLF>.<CRLF>". Before sending a line of text, check the first /// character of the line.If it is a period, one additional period is inserted at the beginning of the line. /// </summary> /// <param name="stream">Stream which data to write. Reading begins from stream current position and is readed to EOS.</param> /// <param name="closeStream">Specifies if stream is closed after write operation has completed.</param> /// <param name="tag">User data.</param> /// <param name="callback">The method to be called when the asynchronous write operation is completed.</param> public void BeginWritePeriodTerminated(Stream stream,bool closeStream,object tag,SocketCallBack callback) { // Allow socket to optimise sends m_pSocket.NoDelay = false; _BeginWritePeriodTerminated_State state = new _BeginWritePeriodTerminated_State(stream,closeStream,tag,callback); BeginProcessingWritePeriodTerminated(state); }
/// <summary> /// Reads data block from state.Stream and begins writing it to socket. /// This method is looped while all data has been readed from state.Stream, then sate.Callback is called. /// </summary> /// <param name="state">State info.</param> private void BeginProcessingWritePeriodTerminated(_BeginWritePeriodTerminated_State state) { /* Before sending a line of text, check the first character of the line. If it is a period, one additional period is inserted at the beginning of the line. */ byte[] buffer = new byte[4000]; int positionInBuffer = 0; int currentByte = state.Stream.ReadByte(); while(currentByte > -1){ // We have CRLF, mark it up if(state.LastByte == '\r' && currentByte == '\n'){ state.HasCRLF = true; } // There is CRLF + current byte else if(state.HasCRLF){ // If it is a period, one additional period is inserted at the beginning of the line. if(currentByte == '.'){ buffer[positionInBuffer] = (byte)'.'; positionInBuffer++; } // CRLF handled, reset it state.HasCRLF = false; } buffer[positionInBuffer] = (byte)currentByte; positionInBuffer++; state.LastByte = currentByte; // Buffer is filled up, begin writing buffer to socket. if(positionInBuffer > (4000 - 10)){ state.CountSent += positionInBuffer; m_WrittenCount += positionInBuffer; if(m_SSL){ m_pSslStream.BeginWrite(buffer,0,positionInBuffer,this.OnBeginWritePeriodTerminatedCallback,state); } else{ m_pSocketStream.BeginWrite(buffer,0,positionInBuffer,this.OnBeginWritePeriodTerminatedCallback,state); } return; } currentByte = state.Stream.ReadByte(); } // We have readed all data, write .<CRLF> or <CRLF>.<CRLF> if data not <CRLF> terminated. if(!state.HasCRLF){ buffer[positionInBuffer] = (byte)'\r'; positionInBuffer++; buffer[positionInBuffer] = (byte)'\n'; positionInBuffer++; } buffer[positionInBuffer] = (byte)'.'; positionInBuffer++; buffer[positionInBuffer] = (byte)'\r'; positionInBuffer++; buffer[positionInBuffer] = (byte)'\n'; positionInBuffer++; if(m_SSL){ m_pSslStream.Write(buffer,0,positionInBuffer); } else{ m_pSocketStream.Write(buffer,0,positionInBuffer); } state.CountSent += positionInBuffer; m_WrittenCount += positionInBuffer; m_LastActivityDate = DateTime.Now; //-------------------------------------------------------------------------------------// // Logging stuff if(m_pLogger != null){ if(state.CountSent < 200){ m_pLogger.AddSendEntry(m_pEncoding.GetString(buffer),buffer.Length); } else{ m_pLogger.AddSendEntry("Binary data, sent " + state.CountSent.ToString() + " bytes.",state.CountSent); } } // We don't need stream any more, close it if(state.CloseStream){ try{ state.Stream.Close(); } catch{ } } // Data sent ok, call callback. if(state.Callback != null){ state.Callback(SocketCallBackResult.Ok,state.CountSent,null,state.Tag); } }