using System;
using System.IO;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Xiaoxiao.Net;namespace Xiaoxiao.Net.POP3.Server
{
/// <summary>
/// POP3 Session.
/// </summary>
public class POP3_Session : ISocketServerSession
{
private BufferedSocket m_pSocket        = null;  // Referance to client Socket.
private POP3_Server    m_pServer        = null;  // Referance to POP3 server.
private string         m_SessionID      = "";    // Holds session ID.
private string         m_UserName       = "";    // Holds loggedIn UserName.
private string         m_Password       = "";    // Holds loggedIn Password.
private bool           m_Authenticated  = false; // Holds authentication flag.
private string         m_MD5_prefix     = "";    // Session MD5 prefix for APOP command
private int            m_BadCmdCount    = 0;     // Holds number of bad commands.
private POP3_Messages  m_POP3_Messages  = null;
private DateTime       m_SessionStartTime;
private DateTime       m_LastDataTime;
// private _LogWriter     m_pLogWriter     = null;
private object         m_Tag            = null;

/// <summary>
/// Default constructor.
/// </summary>
/// <param name="clientSocket">Referance to socket.</param>
/// <param name="server">Referance to POP3 server.</param>
/// <param name="logWriter">Log writer.</param>
public POP3_Session(Socket clientSocket,POP3_Server server,SocketLogger logWriter)
{
m_pSocket = new BufferedSocket(clientSocket);
m_pServer = server; m_SessionID        = Guid.NewGuid().ToString();
m_POP3_Messages    = new POP3_Messages();
m_SessionStartTime = DateTime.Now;
m_LastDataTime     = DateTime.Now; if(m_pServer.LogCommands){
m_pSocket.Logger = logWriter;
m_pSocket.Logger.SessionID = m_SessionID;
} m_pSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.NoDelay,1);
m_pSocket.Activity += new EventHandler(OnSocketActivity); // Start session proccessing
StartSession();
} #region method StartSession /// <summary>
/// Starts session.
/// </summary>
private void StartSession()
{
// Add session to session list
m_pServer.AddSession(this); if(m_pServer.LogCommands){
// m_pSocket.Logger.AddTextEntry();
// m_pLogWriter.AddEntry("//----- Sys: 'Session:'" + this.SessionID + " added " + DateTime.Now);
}

try{
// Check if ip is allowed to connect this computer
if(m_pServer.OnValidate_IpAddress(this.RemoteEndPoint)){
// Notify that server is ready
m_MD5_prefix = "<" + Guid.NewGuid().ToString().ToLower() + ">";
m_pSocket.SendLine("+OK " + m_pServer.HostName + " POP3 Server ready " + m_MD5_prefix); BeginRecieveCmd();
}
else{
EndSession();
}
}
catch(Exception x){
OnError(x);
}
} #endregion #region method EndSession /// <summary>
/// Ends session, closes socket.
/// </summary>
private void EndSession()
{
// Write logs to log file, if needed
if(m_pServer.LogCommands){
// m_pLogWriter.AddEntry("//----- Sys: 'Session:'" + this.SessionID + " removed " + DateTime.Now);

// m_pLogWriter.Flush(); m_pSocket.Logger.Flush();
} if(m_pSocket != null){
m_pSocket.Shutdown(SocketShutdown.Both);
m_pSocket.Close();
m_pSocket = null;
} m_pServer.RemoveSession(this);
} #endregion
#region method OnSessionTimeout /// <summary>
/// Is called by server when session has timed out.
/// </summary>
public void OnSessionTimeout()
{
try{
m_pSocket.SendLine("-ERR Session timeout, closing transmission channel");
}
catch{
} EndSession();
} #endregion #region method OnSocketActivity /// <summary>
/// Is called if there was some activity on socket, some data sended or received.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSocketActivity(object sender,EventArgs e)
{
m_LastDataTime = DateTime.Now;
} #endregion #region method OnError /// <summary>
/// Is called when error occures.
/// </summary>
/// <param name="x"></param>
private void OnError(Exception x)
{
try{
if(x is SocketException){
SocketException xs = (SocketException)x; // Client disconnected without shutting down
if(xs.ErrorCode == 10054 || xs.ErrorCode == 10053){
if(m_pServer.LogCommands){
// m_pLogWriter.AddEntry("Client aborted/disconnected",this.SessionID,this.RemoteEndPoint.Address.ToString(),"C"); m_pSocket.Logger.AddTextEntry("Client aborted/disconnected");
} EndSession(); // Exception handled, return
return;
}
} m_pServer.OnSysError("",x);
}
catch(Exception ex){
m_pServer.OnSysError("",ex);
}
} #endregion
#region method BeginRecieveCmd

/// <summary>
/// Starts recieveing command.
/// </summary>
private void BeginRecieveCmd()
{
MemoryStream strm = new MemoryStream();
// AsyncSocketHelper.BeginRecieve(m_pSocket,strm,1024,"\r\n","\r\n",strm,new SocketCallBack(this.EndRecieveCmd),new SocketActivityCallback(this.OnSocketActivity));
m_pSocket.BeginReadLine(strm,1024,strm,new SocketCallBack(this.EndRecieveCmd));
} #endregion

解决方案 »

  1.   

    #region method EndRecieveCmd /// <summary>
    /// Is called if command is recieved.
    /// </summary>
    /// <param name="result"></param>
    /// <param name="exception"></param>
    /// <param name="count"></param>
    /// <param name="tag"></param>
    private void EndRecieveCmd(SocketCallBackResult result,long count,Exception exception,object tag)
    {
    try{
    switch(result)
    {
    case SocketCallBackResult.Ok:
    MemoryStream strm = (MemoryStream)tag; string cmdLine = System.Text.Encoding.Default.GetString(strm.ToArray()); // if(m_pServer.LogCommands){
    // m_pLogWriter.AddEntry(cmdLine + "<CRLF>",this.SessionID,this.RemoteEndPoint.Address.ToString(),"C");
    // } // Exceute command
    if(SwitchCommand(cmdLine)){
    // Session end, close session
    EndSession();
    }
    break; case SocketCallBackResult.LengthExceeded:
    m_pSocket.SendLine("-ERR Line too long."); BeginRecieveCmd();
    break; case SocketCallBackResult.SocketClosed:
    EndSession();
    break; case SocketCallBackResult.Exception:
    OnError(exception);
    break;
    }
    }
    catch(Exception x){
     OnError(x);
    }
    } #endregion


    #region function SwitchCommand /// <summary>
    /// Parses and executes POP3 commmand.
    /// </summary>
    /// <param name="POP3_commandTxt">POP3 command text.</param>
    /// <returns>Returns true,if session must be terminated.</returns>
    private bool SwitchCommand(string POP3_commandTxt)
    {
    //---- Parse command --------------------------------------------------//
    string[] cmdParts = POP3_commandTxt.TrimStart().Split(new char[]{' '});
    string POP3_command = cmdParts[0].ToUpper().Trim();
    string argsText = Core.GetArgsText(POP3_commandTxt,POP3_command);
    //---------------------------------------------------------------------// bool getNextCmd = true; switch(POP3_command)
    {
    case "USER":
    USER(argsText);
    getNextCmd = false;
    break; case "PASS":
    PASS(argsText);
    getNextCmd = false;
    break;

    case "STAT":
    STAT();
    getNextCmd = false;
    break; case "LIST":
    LIST(argsText);
    getNextCmd = false;
    break; case "RETR":
    RETR(argsText);
    getNextCmd = false;
    break; case "DELE":
    DELE(argsText);
    getNextCmd = false;
    break; case "NOOP":
    NOOP();
    getNextCmd = false;
    break; case "RSET":
    RSET();
    getNextCmd = false;
    break; case "QUIT":
    QUIT();
    getNextCmd = false;
    return true;
    //----- Optional commands ----- //
    case "UIDL":
    UIDL(argsText);
    getNextCmd = false;
    break; case "APOP":
    APOP(argsText);
    getNextCmd = false;
    break; case "TOP":
    TOP(argsText);
    getNextCmd = false;
    break; case "AUTH":
    AUTH(argsText);
    getNextCmd = false;
    break;

    default:
    m_pSocket.SendLine("-ERR Invalid command"); //---- Check that maximum bad commands count isn't exceeded ---------------//
    if(m_BadCmdCount > m_pServer.MaxBadCommands-1){
    m_pSocket.SendLine("-ERR Too many bad commands, closing transmission channel");
    return true;
    }
    m_BadCmdCount++;
    //-------------------------------------------------------------------------//
    break;
    }

    if(getNextCmd){
    BeginRecieveCmd();
    }

    return false;
    } #endregion
    #region function USER private void USER(string argsText)
    {
    /* RFC 1939 7. USER
    Arguments:
    a string identifying a mailbox (required), which is of
    significance ONLY to the server

    NOTE:
    If the POP3 server responds with a positive
    status indicator ("+OK"), then the client may issue
    either the PASS command to complete the authentication,
    or the QUIT command to terminate the POP3 session.
     
    */ if(m_Authenticated){
    m_pSocket.BeginSendLine("-ERR You are already authenticated",new SocketCallBack(this.EndSend));
    return;
    }
    if(m_UserName.Length > 0){
    m_pSocket.BeginSendLine("-ERR username is already specified, please specify password",new SocketCallBack(this.EndSend));
    return;
    } string[] param = argsText.Split(new char[]{' '}); // There must be only one parameter - userName
    if(argsText.Length > 0 && param.Length == 1){
    string userName = param[0];

    // Check if user isn't logged in already
    if(!m_pServer.IsUserLoggedIn(userName)){
    m_pSocket.BeginSendLine("+OK User:'" + userName + "' ok",new SocketCallBack(this.EndSend));
    m_UserName = userName;
    }
    else{
    m_pSocket.BeginSendLine("-ERR User:'" + userName + "' already logged in",new SocketCallBack(this.EndSend));
    }
    }
    else{
    m_pSocket.BeginSendLine("-ERR Syntax error. Syntax:{USER username}",new SocketCallBack(this.EndSend));
    }
    } #endregion #region function PASS
      

  2.   

    [email protected]
    我就要连pop3检查有多少封信的部分,太多我找不到