Click here to Skip to main content
15,891,316 members
Articles / Programming Languages / C#

SIP Stack with SIP Proxy - (VOIP)

Rate me:
Please Sign up or sign in to vote.
4.86/5 (45 votes)
11 Jun 2007CPOL2 min read 1.6M   28.1K   162  
C# implementation of SIP
using System;
using System.IO;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;

using LumiSoft.Net;
using LumiSoft.Net.AUTH;

namespace LumiSoft.Net.IMAP.Server
{
	#region Event delegates

	/// <summary>
	/// Represents the method that will handle the AuthUser event for SMTP_Server.
	/// </summary>
	/// <param name="sender">The source of the event. </param>
	/// <param name="e">A AuthUser_EventArgs that contains the event data.</param>
	public delegate void AuthUserEventHandler(object sender,AuthUser_EventArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void FolderEventHandler(object sender,Mailbox_EventArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void FoldersEventHandler(object sender,IMAP_Folders e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void MessagesEventHandler(object sender,IMAP_eArgs_GetMessagesInfo e);

    /// <summary>
	/// 
	/// </summary>
	public delegate void MessagesItemsEventHandler(object sender,IMAP_eArgs_MessageItems e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void MessageEventHandler(object sender,Message_EventArgs e);

    /*
	/// <summary>
	/// 
	/// </summary>
	public delegate void SearchEventHandler(object sender,IMAP_eArgs_Search e);*/

	/// <summary>
	/// 
	/// </summary>
	public delegate void SharedRootFoldersEventHandler(object sender,SharedRootFolders_EventArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void GetFolderACLEventHandler(object sender,IMAP_GETACL_eArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void DeleteFolderACLEventHandler(object sender,IMAP_DELETEACL_eArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void SetFolderACLEventHandler(object sender,IMAP_SETACL_eArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void GetUserACLEventHandler(object sender,IMAP_GetUserACL_eArgs e);


    /// <summary>
	/// 
	/// </summary>
	public delegate void GetUserQuotaHandler(object sender,IMAP_eArgs_GetQuota e);

	#endregion

	/// <summary>
	/// IMAP server componet.
	/// </summary>
	public class IMAP_Server : SocketServer
	{
        private int           m_MaxConnectionsPerIP = 0;
        private SaslAuthTypes m_SupportedAuth       = SaslAuthTypes.All;
        private string        m_GreetingText        = "";
		private int           m_MaxMessageSize      = 1000000;

		#region Events declarations

		/// <summary>
		/// Occurs when new computer connected to IMAP server.
		/// </summary>
		public event ValidateIPHandler ValidateIPAddress = null;

		/// <summary>
		/// Occurs when connected user tryes to authenticate.
		/// </summary>
		public event AuthUserEventHandler AuthUser = null;

		/// <summary>
		/// Occurs when server requests to subscribe folder.
		/// </summary>
		public event FolderEventHandler SubscribeFolder = null;

		/// <summary>
		/// Occurs when server requests to unsubscribe folder.
		/// </summary>
		public event FolderEventHandler UnSubscribeFolder = null;

		/// <summary>
		/// Occurs when server requests all available folders.
		/// </summary>
		public event FoldersEventHandler GetFolders = null;

		/// <summary>
		/// Occurs when server requests subscribed folders.
		/// </summary>
		public event FoldersEventHandler GetSubscribedFolders = null;

		/// <summary>
		/// Occurs when server requests to create folder.
		/// </summary>
		public event FolderEventHandler CreateFolder = null;

		/// <summary>
		/// Occurs when server requests to delete folder.
		/// </summary>
		public event FolderEventHandler DeleteFolder = null;

		/// <summary>
		/// Occurs when server requests to rename folder.
		/// </summary>
		public event FolderEventHandler RenameFolder = null;

		/// <summary>
		/// Occurs when server requests to folder messages info.
		/// </summary>
		public event MessagesEventHandler GetMessagesInfo = null;

		/// <summary>
		/// Occurs when server requests to delete message.
		/// </summary>
		public event MessageEventHandler DeleteMessage = null;

		/// <summary>
		/// Occurs when server requests to store message.
		/// </summary>
		public event MessageEventHandler StoreMessage = null;

        /*
		/// <summary>
		/// Occurs when server requests to search specified folder messages.
		/// </summary>
		public event SearchEventHandler Search = null;*/

		/// <summary>
		/// Occurs when server requests to store message flags.
		/// </summary>
		public event MessageEventHandler StoreMessageFlags = null;

		/// <summary>
		/// Occurs when server requests to copy message to new location.
		/// </summary>
		public event MessageEventHandler CopyMessage = null;

        /// <summary>
		/// Occurs when server requests to get message items.
		/// </summary>
		public event MessagesItemsEventHandler GetMessageItems = null;

		/// <summary>
		/// Occurs when IMAP session has finished and session log is available.
		/// </summary>
		public event LogEventHandler SessionLog = null;

		/// <summary>
		/// Occurs when IMAP server requests shared root folders info.
		/// </summary>
		public event SharedRootFoldersEventHandler GetSharedRootFolders = null;

		/// <summary>
		/// Occurs when IMAP server requests folder ACL.
		/// </summary>
		public event GetFolderACLEventHandler GetFolderACL = null;

		/// <summary>
		/// Occurs when IMAP server requests to delete folder ACL.
		/// </summary>
		public event DeleteFolderACLEventHandler DeleteFolderACL = null;

		/// <summary>
		/// Occurs when IMAP server requests to set folder ACL.
		/// </summary>
		public event SetFolderACLEventHandler SetFolderACL = null;

		/// <summary>
		/// Occurs when IMAP server requests to get user ACL for specified folder.
		/// </summary>
		public event GetUserACLEventHandler GetUserACL = null;

        /// <summary>
		/// Occurs when IMAP server requests to get user quota.
		/// </summary>
		public event GetUserQuotaHandler GetUserQuota = null;
		
		#endregion

		
		/// <summary>
		/// Defalut constructor.
		/// </summary>
		public IMAP_Server() : base()
		{
			this.BindInfo = new BindInfo[]{new BindInfo(IPAddress.Any,143,false,null)};
		}


		#region override InitNewSession

		/// <summary>
		/// Initialize and start new session here. Session isn't added to session list automatically, 
		/// session must add itself to server session list by calling AddSession().
		/// </summary>
		/// <param name="socket">Connected client socket.</param>
        /// <param name="bindInfo">BindInfo what accepted socket.</param>
		protected override void InitNewSession(Socket socket,BindInfo bindInfo)
		{
            // Check maximum conncurent connections from 1 IP.
            if(m_MaxConnectionsPerIP > 0){
                lock(this.Sessions){
                    int nSessions = 0;
                    foreach(SocketServerSession s in this.Sessions){
                        IPEndPoint ipEndpoint = s.RemoteEndPoint;
                        if(ipEndpoint != null){
                            if(ipEndpoint.Address.Equals(((IPEndPoint)socket.RemoteEndPoint).Address)){
                                nSessions++;
                            }
                        }

                        // Maimum allowed exceeded
                        if(nSessions >= m_MaxConnectionsPerIP){
                            socket.Send(System.Text.Encoding.ASCII.GetBytes("* NO Maximum connections from your IP address is exceeded, try again later !\r\n"));
                            socket.Shutdown(SocketShutdown.Both);
                            socket.Close();
                            return;
                        }
                    }
                }
            }

            string   sessionID = Guid.NewGuid().ToString();
            SocketEx socketEx  = new SocketEx(socket);
            if(LogCommands){
                socketEx.Logger = new SocketLogger(socket,this.SessionLog);
				socketEx.Logger.SessionID = sessionID;
            }
			IMAP_Session session = new IMAP_Session(sessionID,socketEx,bindInfo,this);
		}

		#endregion


		#region Properties Implementaion
		
        /// <summary>
		/// Gets or sets server supported authentication types.
		/// </summary>
		public SaslAuthTypes SupportedAuthentications
		{
			get{ return m_SupportedAuth; }

			set{ m_SupportedAuth = value; }
		}

	    /// <summary>
		/// Gets or sets server greeting text.
		/// </summary>
		public string GreetingText
		{
			get{ return m_GreetingText; }

			set{ m_GreetingText = value; }
		}

        /// <summary>
		/// Gets or sets maximum allowed conncurent connections from 1 IP address. Value 0 means unlimited connections.
		/// </summary>
		public int MaxConnectionsPerIP
		{
			get{ return m_MaxConnectionsPerIP; }

			set{ m_MaxConnectionsPerIP = value; }
		}
	
		/// <summary>
		/// Maximum message size.
		/// </summary>
		public int MaxMessageSize 
		{
			get{ return m_MaxMessageSize; }

			set{ m_MaxMessageSize = value; }
		}

        /// <summary>
		/// Gets active sessions.
		/// </summary>
		public new IMAP_Session[] Sessions
		{
			get{
                SocketServerSession[] sessions     = base.Sessions;
                IMAP_Session[]        imapSessions = new IMAP_Session[sessions.Length];
                sessions.CopyTo(imapSessions,0);

                return imapSessions; 
            }
		}
		
		#endregion

		#region Events Implementation

		#region function OnValidate_IpAddress
		
		/// <summary>
		/// Raises event ValidateIP event.
		/// </summary>
		/// <param name="localEndPoint">Server IP.</param>
		/// <param name="remoteEndPoint">Connected client IP.</param>
		/// <returns>Returns true if connection allowed.</returns>
		internal bool OnValidate_IpAddress(IPEndPoint localEndPoint,IPEndPoint remoteEndPoint) 
		{			
			ValidateIP_EventArgs oArg = new ValidateIP_EventArgs(localEndPoint,remoteEndPoint);
			if(this.ValidateIPAddress != null){
				this.ValidateIPAddress(this, oArg);
			}

			return oArg.Validated;						
		}

		#endregion

		#region function OnAuthUser

		/// <summary>
		/// Raises event AuthUser.
		/// </summary>
		/// <param name="session">Reference to current IMAP session.</param>
		/// <param name="userName">User name.</param>
		/// <param name="passwordData">Password compare data,it depends of authentication type.</param>
		/// <param name="data">For md5 eg. md5 calculation hash.It depends of authentication type.</param>
		/// <param name="authType">Authentication type.</param>
		/// <returns>Returns true if user is authenticated ok.</returns>
		internal AuthUser_EventArgs OnAuthUser(IMAP_Session session,string userName,string passwordData,string data,AuthType authType)
		{
			AuthUser_EventArgs oArgs = new AuthUser_EventArgs(session,userName,passwordData,data,authType);
			if(this.AuthUser != null){
				this.AuthUser(this,oArgs);
			}

			return oArgs;
		}

		#endregion


		#region function OnSubscribeMailbox

		/// <summary>
		/// Raises event 'SubscribeMailbox'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="mailbox">Mailbox which to subscribe.</param>
		/// <returns></returns>
		internal string OnSubscribeMailbox(IMAP_Session session,string mailbox)
		{
			if(this.SubscribeFolder != null){
				Mailbox_EventArgs eArgs = new Mailbox_EventArgs(mailbox);
				this.SubscribeFolder(session,eArgs);

				return eArgs.ErrorText;
			}

			return null;
		}

		#endregion

		#region function OnUnSubscribeMailbox

		/// <summary>
		/// Raises event 'UnSubscribeMailbox'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="mailbox">Mailbox which to unsubscribe.</param>
		/// <returns></returns>
		internal string OnUnSubscribeMailbox(IMAP_Session session,string mailbox)
		{
			if(this.UnSubscribeFolder != null){
				Mailbox_EventArgs eArgs = new Mailbox_EventArgs(mailbox);
				this.UnSubscribeFolder(session,eArgs);

				return eArgs.ErrorText;
			}

			return null;
		}

		#endregion

		#region function OnGetSubscribedMailboxes

		/// <summary>
		/// Raises event 'GetSubscribedMailboxes'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="referenceName">Mailbox reference.</param>
		/// <param name="mailBox">Mailbox search pattern or mailbox.</param>
		/// <returns></returns>
		internal IMAP_Folders OnGetSubscribedMailboxes(IMAP_Session session,string referenceName,string mailBox)
		{
			IMAP_Folders retVal = new IMAP_Folders(session,referenceName,mailBox);
			if(this.GetSubscribedFolders != null){
				this.GetSubscribedFolders(session,retVal);
			}

			return retVal;
		}

		#endregion

		#region function OnGetMailboxes

		/// <summary>
		/// Raises event 'GetMailboxes'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="referenceName">Mailbox reference.</param>
		/// <param name="mailBox">Mailbox search pattern or mailbox.</param>
		/// <returns></returns>
		internal IMAP_Folders OnGetMailboxes(IMAP_Session session,string referenceName,string mailBox)
		{
			IMAP_Folders retVal = new IMAP_Folders(session,referenceName,mailBox);
			if(this.GetFolders != null){
				this.GetFolders(session,retVal);
			}

			return retVal;
		}

		#endregion

		#region function OnCreateMailbox

		/// <summary>
		/// Raises event 'CreateMailbox'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="mailbox">Mailbox to create.</param>
		/// <returns></returns>
		internal string OnCreateMailbox(IMAP_Session session,string mailbox)
		{
			if(this.CreateFolder != null){
				Mailbox_EventArgs eArgs = new Mailbox_EventArgs(mailbox);
				this.CreateFolder(session,eArgs);

				return eArgs.ErrorText;
			}

			return null;
		}

		#endregion

		#region function OnDeleteMailbox

		/// <summary>
		/// Raises event 'DeleteMailbox'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="mailbox">Mailbox which to delete.</param>
		/// <returns></returns>
		internal string OnDeleteMailbox(IMAP_Session session,string mailbox)
		{
			if(this.DeleteFolder != null){
				Mailbox_EventArgs eArgs = new Mailbox_EventArgs(mailbox);
				this.DeleteFolder(session,eArgs);

				return eArgs.ErrorText;
			}

			return null;
		}

		#endregion

		#region function OnRenameMailbox

		/// <summary>
		/// Raises event 'RenameMailbox'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="mailbox">Mailbox which to rename.</param>
		/// <param name="newMailboxName">New mailbox name.</param>
		/// <returns></returns>
		internal string OnRenameMailbox(IMAP_Session session,string mailbox,string newMailboxName)
		{
			if(this.RenameFolder != null){
				Mailbox_EventArgs eArgs = new Mailbox_EventArgs(mailbox,newMailboxName);
				this.RenameFolder(session,eArgs);

				return eArgs.ErrorText;
			}

			return null;
		}

		#endregion

		#region method OnGetMessagesInfo

		/// <summary>
		/// Raises event 'GetMessagesInfo'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="folder">Folder which messages info to get.</param>
		/// <returns></returns>
		internal IMAP_eArgs_GetMessagesInfo OnGetMessagesInfo(IMAP_Session session,IMAP_SelectedFolder folder)
		{
			IMAP_eArgs_GetMessagesInfo eArgs = new IMAP_eArgs_GetMessagesInfo(session,folder);
			if(this.GetMessagesInfo != null){
				this.GetMessagesInfo(session,eArgs);
			}

			return eArgs;
		}

		#endregion

        #region method OnGetMessageItems

        /// <summary>
        /// Raises event GetMessageItems.
        /// </summary>
        /// <param name="session">Reference to IMAP session.</param>
        /// <param name="messageInfo">Message info what message items to get.</param>
        /// <param name="messageItems">Specifies message items what must be filled.</param>
        /// <returns></returns>
        internal protected IMAP_eArgs_MessageItems OnGetMessageItems(IMAP_Session session,IMAP_Message messageInfo,IMAP_MessageItems_enum messageItems)
        {
            IMAP_eArgs_MessageItems eArgs = new IMAP_eArgs_MessageItems(session,messageInfo,messageItems);
            if(this.GetMessageItems != null){
				this.GetMessageItems(session,eArgs);
			}
            return eArgs;
        }

        #endregion

		#region function OnDeleteMessage

		/// <summary>
		/// Raises event 'DeleteMessage'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="message">Message which to delete.</param>
		/// <returns></returns>
		internal string OnDeleteMessage(IMAP_Session session,IMAP_Message message)
		{
			Message_EventArgs eArgs = new Message_EventArgs(Core.Decode_IMAP_UTF7_String(session.SelectedMailbox),message);
			if(this.DeleteMessage != null){
				this.DeleteMessage(session,eArgs);
			}

			return eArgs.ErrorText;
		}

		#endregion

		#region function OnCopyMessage

		/// <summary>
		/// Raises event 'CopyMessage'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="msg">Message which to copy.</param>
		/// <param name="location">New message location.</param>
		/// <returns></returns>
		internal string OnCopyMessage(IMAP_Session session,IMAP_Message msg,string location)
		{
			Message_EventArgs eArgs = new Message_EventArgs(Core.Decode_IMAP_UTF7_String(session.SelectedMailbox),msg,location);
			if(this.CopyMessage != null){
				this.CopyMessage(session,eArgs);
			}

			return eArgs.ErrorText;
		}

		#endregion

		#region function OnStoreMessage

		/// <summary>
		/// Raises event 'StoreMessage'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="folder">Folder where to store.</param>
		/// <param name="msg">Message which to store.</param>
		/// <param name="messageData">Message data which to store.</param>
		/// <returns></returns>
		internal string OnStoreMessage(IMAP_Session session,string folder,IMAP_Message msg,byte[] messageData)
		{
			Message_EventArgs eArgs = new Message_EventArgs(folder,msg);
			eArgs.MessageData = messageData;
			if(this.StoreMessage != null){
				this.StoreMessage(session,eArgs);
			}

			return eArgs.ErrorText;
		}

		#endregion

		#region method OnSearch
        /*
		/// <summary>
		/// Raises event 'Search'.
		/// </summary>
		/// <param name="session">IMAP session what calls this search.</param>
		/// <param name="folder">Folder what messages to search.</param>
		/// <param name="matcher">Matcher what must be used to check if message matches searching criterial.</param>
		/// <returns></returns>
		internal IMAP_eArgs_Search OnSearch(IMAP_Session session,string folder,IMAP_SearchMatcher matcher)
		{
			IMAP_eArgs_Search eArgs = new IMAP_eArgs_Search(session,folder,matcher);
			if(this.Search != null){
				this.Search(session,eArgs);
			}

			return eArgs;
		}*/

		#endregion

		#region function OnStoreMessageFlags

		/// <summary>
		/// Raises event 'StoreMessageFlags'.
		/// </summary>
		/// <param name="session">Reference to IMAP session.</param>
		/// <param name="msg">Message which flags to store.</param>
		/// <returns></returns>
		internal string OnStoreMessageFlags(IMAP_Session session,IMAP_Message msg)
		{
			Message_EventArgs eArgs = new Message_EventArgs(Core.Decode_IMAP_UTF7_String(session.SelectedMailbox),msg);
			if(this.StoreMessageFlags != null){
				this.StoreMessageFlags(session,eArgs);
			}

			return eArgs.ErrorText;
		}

		#endregion

		#region method OnGetSharedRootFolders

		internal SharedRootFolders_EventArgs OnGetSharedRootFolders(IMAP_Session session)
		{
			SharedRootFolders_EventArgs eArgs = new SharedRootFolders_EventArgs(session);
			if(this.GetSharedRootFolders != null){
				this.GetSharedRootFolders(session,eArgs);
			}

			return eArgs;
		}

		#endregion


		#region method OnGetFolderACL

		internal IMAP_GETACL_eArgs OnGetFolderACL(IMAP_Session session,string folderName)
		{
			IMAP_GETACL_eArgs eArgs = new IMAP_GETACL_eArgs(session,folderName);
			if(this.GetFolderACL != null){
				this.GetFolderACL(session,eArgs);
			}

			return eArgs;
		}

		#endregion

		#region method OnSetFolderACL

		internal IMAP_SETACL_eArgs OnSetFolderACL(IMAP_Session session,string folderName,string userName,IMAP_Flags_SetType flagsSetType,IMAP_ACL_Flags aclFlags)
		{
			IMAP_SETACL_eArgs eArgs = new IMAP_SETACL_eArgs(session,folderName,userName,flagsSetType,aclFlags);
			if(this.SetFolderACL != null){
				this.SetFolderACL(session,eArgs);
			}

			return eArgs;
		}

		#endregion

		#region method OnDeleteFolderACL

		internal IMAP_DELETEACL_eArgs OnDeleteFolderACL(IMAP_Session session,string folderName,string userName)
		{
			IMAP_DELETEACL_eArgs eArgs = new IMAP_DELETEACL_eArgs(session,folderName,userName);
			if(this.DeleteFolderACL != null){
				this.DeleteFolderACL(session,eArgs);
			}

			return eArgs;
		}

		#endregion

		#region method OnGetUserACL

		internal IMAP_GetUserACL_eArgs OnGetUserACL(IMAP_Session session,string folderName,string userName)
		{
			IMAP_GetUserACL_eArgs eArgs = new IMAP_GetUserACL_eArgs(session,folderName,userName);
			if(this.GetUserACL != null){
				this.GetUserACL(session,eArgs);
			}

			return eArgs;
		}

		#endregion


        #region method OnGetUserQuota

		internal IMAP_eArgs_GetQuota OnGetUserQuota(IMAP_Session session)
		{
			IMAP_eArgs_GetQuota eArgs = new IMAP_eArgs_GetQuota(session);
			if(this.GetUserQuota != null){
				this.GetUserQuota(session,eArgs);
			}

			return eArgs;
		}

		#endregion

		#endregion

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Estonia Estonia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions