Ejemplo n.º 1
0
        /// <summary>
        /// Gets local IP binding for specified remote IP.
        /// </summary>
        /// <param name="remoteIP">Remote SMTP target IP address.</param>
        /// <returns>Returns local IP binding or null if no suitable IP binding available.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>remoteIP</b> is null reference.</exception>
        internal IPBindInfo GetLocalBinding(IPAddress remoteIP)
        {
            if (remoteIP == null)
            {
                throw new ArgumentNullException("remoteIP");
            }

            // Get round-robin local end point for that remote IP.
            // This ensures if multiple network connections, all will be load balanced.

            // IPv6
            if (remoteIP.AddressFamily == AddressFamily.InterNetworkV6)
            {
                if (m_pLocalEndPointIPv6.Count == 0)
                {
                    return(null);
                }
                else
                {
                    return(m_pLocalEndPointIPv6.Next());
                }
            }
            // IPv4
            else
            {
                if (m_pLocalEndPointIPv4.Count == 0)
                {
                    return(null);
                }
                else
                {
                    return(m_pLocalEndPointIPv4.Next());
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Processes incoming UDP data and queues it for processing.
        /// </summary>
        private void ProcessIncomingUdp()
        {
            // Create Round-Robin for listening points.
            CircleCollection <Socket> listeningEPs = new CircleCollection <Socket>();

            foreach (Socket socket in m_pSockets)
            {
                listeningEPs.Add(socket);
            }

            byte[] buffer = new byte[m_MTU];
            while (m_IsRunning)
            {
                try{
                    // Maximum allowed UDP queued packts exceeded.
                    if (m_pQueuedPackets.Count >= m_MaxQueueSize)
                    {
                        Thread.Sleep(1);
                    }
                    else
                    {
                        // Roun-Robin sockets.
                        bool receivedData = false;
                        for (int i = 0; i < listeningEPs.Count; i++)
                        {
                            Socket socket = listeningEPs.Next();
                            // Read data only when there is some, otherwise we block thread.
                            if (socket.Poll(0, SelectMode.SelectRead))
                            {
                                // Receive data.
                                EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                                int      received = socket.ReceiveFrom(buffer, ref remoteEP);
                                m_BytesReceived += received;
                                m_PacketsReceived++;

                                // Queue received packet.
                                byte[] data = new byte[received];
                                Array.Copy(buffer, data, received);
                                lock (m_pQueuedPackets){
                                    m_pQueuedPackets.Enqueue(new UdpPacket(socket, (IPEndPoint)remoteEP, data));
                                }

                                // We received data, so exit round-robin loop.
                                receivedData = true;
                                break;
                            }
                        }
                        // We didn't get any data from any listening point, we must sleep or we use 100% CPU.
                        if (!receivedData)
                        {
                            Thread.Sleep(1);
                        }
                    }
                }
                catch (Exception x) {
                    OnError(x);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Sends specified UDP packet to the specified remote end point.
        /// </summary>
        /// <param name="socket">UDP socket to use for data sending.</param>
        /// <param name="packet">UDP packet to send.</param>
        /// <param name="offset">Offset in the buffer.</param>
        /// <param name="count">Number of bytes to send.</param>
        /// <param name="remoteEP">Remote end point.</param>
        /// <param name="localEP">Returns local IP end point which was used to send UDP packet.</param>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this method is accessed.</exception>
        /// <exception cref="InvalidOperationException">Is raised whan UDP server is not running and this method is accessed.</exception>
        /// <exception cref="ArgumentNullException">Is raised when any of the arumnets is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal void SendPacket(Socket socket, byte[] packet, int offset, int count, IPEndPoint remoteEP, out IPEndPoint localEP)
        {
            // Round-Robin all local end points, if no end point specified.
            if (socket == null)
            {
                // Get right IP address family socket which matches remote end point.
                if (remoteEP.AddressFamily == AddressFamily.InterNetwork)
                {
                    if (m_pSendSocketsIPv4.Count == 0)
                    {
                        throw new ArgumentException("There is no suitable IPv4 local end point in this.Bindings.");
                    }

                    socket = m_pSendSocketsIPv4.Next();
                }
                else if (remoteEP.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    if (m_pSendSocketsIPv6.Count == 0)
                    {
                        throw new ArgumentException("There is no suitable IPv6 local end point in this.Bindings.");
                    }

                    socket = m_pSendSocketsIPv6.Next();
                }
                else
                {
                    throw new ArgumentException("Invalid remote end point address family.");
                }
            }

            //if(socket!=null)
            //    System.Windows.Forms.MessageBox.Show(m_pSendSocketsIPv4.Count .ToString() +":"+socket.IsBound .ToString());

            // Send packet.
            socket.SendTo(packet, offset, count, SocketFlags.None, remoteEP);

            localEP = (IPEndPoint)socket.LocalEndPoint;


            m_BytesSent += count;
            m_PacketsSent++;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Adds next(round-robined) optional SDES item to SDES chunk, if any available.
        /// </summary>
        /// <param name="sdes">SDES chunk where to add item.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>sdes</b> is null reference.</exception>
        internal void AddNextOptionalSdesItem(RTCP_Packet_SDES_Chunk sdes)
        {
            if (sdes == null)
            {
                throw new ArgumentNullException("sdes");
            }

            lock (m_pOtionalItemsRoundRobin)
            {
                if (m_pOtionalItemsRoundRobin.Count > 0)
                {
                    string itemName = m_pOtionalItemsRoundRobin.Next();

                    if (itemName == "name")
                    {
                        sdes.Name = m_Name;
                    }
                    else if (itemName == "email")
                    {
                        sdes.Email = m_Email;
                    }
                    else if (itemName == "phone")
                    {
                        sdes.Phone = m_Phone;
                    }
                    else if (itemName == "location")
                    {
                        sdes.Location = m_Location;
                    }
                    else if (itemName == "tool")
                    {
                        sdes.Tool = m_Tool;
                    }
                    else if (itemName == "note")
                    {
                        sdes.Note = m_Note;
                    }
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Processes relay queue.
        /// </summary>
        private void Run()
        {
            while (m_IsRunning)
            {
                try
                {
                    // Bind info has changed, create new local end points.
                    if (m_HasBindingsChanged)
                    {
                        m_pLocalEndPoints.Clear();

                        foreach (IPBindInfo binding in m_pBindings)
                        {
                            if (binding.IP == IPAddress.Any)
                            {
                                foreach (IPAddress ip in Dns.GetHostAddresses(""))
                                {
                                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                                    {
                                        IPBindInfo b = new IPBindInfo(binding.HostName,
                                                                      binding.Protocol,
                                                                      ip,
                                                                      25);
                                        if (!m_pLocalEndPoints.Contains(b))
                                        {
                                            m_pLocalEndPoints.Add(b);
                                        }
                                    }
                                }
                            }
                            else if (binding.IP == IPAddress.IPv6Any)
                            {
                                foreach (IPAddress ip in Dns.GetHostAddresses(""))
                                {
                                    if (ip.AddressFamily == AddressFamily.InterNetworkV6)
                                    {
                                        IPBindInfo b = new IPBindInfo(binding.HostName,
                                                                      binding.Protocol,
                                                                      ip,
                                                                      25);
                                        if (!m_pLocalEndPoints.Contains(b))
                                        {
                                            m_pLocalEndPoints.Add(b);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                IPBindInfo b = new IPBindInfo(binding.HostName,
                                                              binding.Protocol,
                                                              binding.IP,
                                                              25);
                                if (!m_pLocalEndPoints.Contains(b))
                                {
                                    m_pLocalEndPoints.Add(b);
                                }
                            }
                        }

                        m_HasBindingsChanged = false;
                    }

                    // There are no local end points specified.
                    if (m_pLocalEndPoints.Count == 0)
                    {
                        Thread.Sleep(10);
                    }
                    // Maximum allowed relay sessions exceeded, skip adding new ones.
                    else if (m_MaxConnections != 0 && m_pSessions.Count >= m_MaxConnections)
                    {
                        Thread.Sleep(10);
                    }
                    else
                    {
                        Relay_QueueItem item = null;

                        // Get next queued message from highest possible priority queue.
                        foreach (Relay_Queue queue in m_pQueues)
                        {
                            item = queue.DequeueMessage();
                            // There is queued message.
                            if (item != null)
                            {
                                break;
                            }
                            // No messages in this queue, see next lower priority queue.
                        }

                        // There are no messages in any queue.
                        if (item == null)
                        {
                            Thread.Sleep(10);
                        }
                        // Create new session for queued relay item.
                        else
                        {
                            // Get round-robin local end point for that session.
                            // This ensures if multiple network connections, all will be load balanced.
                            IPBindInfo localBindInfo = m_pLocalEndPoints.Next();

                            if (m_RelayMode == Relay_Mode.Dns)
                            {
                                Relay_Session session = new Relay_Session(this, localBindInfo, item);
                                m_pSessions.Add(session);
                                ThreadPool.QueueUserWorkItem(session.Start);
                            }
                            else if (m_RelayMode == Relay_Mode.SmartHost)
                            {
                                // Get smart hosts in balance mode order.
                                Relay_SmartHost[] smartHosts = null;
                                if (m_SmartHostsBalanceMode == BalanceMode.FailOver)
                                {
                                    smartHosts = m_pSmartHosts.ToArray();
                                }
                                else
                                {
                                    smartHosts = m_pSmartHosts.ToCurrentOrderArray();
                                }

                                Relay_Session session = new Relay_Session(this,
                                                                          localBindInfo,
                                                                          item,
                                                                          smartHosts);
                                m_pSessions.Add(session);
                                ThreadPool.QueueUserWorkItem(session.Start);
                            }
                        }
                    }
                }
                catch (Exception x)
                {
                    OnError(x);
                }
            }
        }
Ejemplo n.º 6
0
		/// <summary>
		/// Starts proccessiong incoming connections (Accepts and queues connections).
		/// </summary>
		private void StartProcCons()
		{	
			try{
                CircleCollection<IPBindInfo> binds = new CircleCollection<IPBindInfo>();
                foreach(IPBindInfo bindInfo in m_pBindInfo){
                    Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
				    s.Bind(new IPEndPoint(bindInfo.IP,bindInfo.Port));
				    s.Listen(500);
                
                    bindInfo.Tag = s;
                    binds.Add(bindInfo);
                }

                // Accept connections and queue them			
				while(m_Running){
					// We have reached maximum connection limit
					if(m_pSessions.Count > m_MaxConnections){
						// Wait while some active connectins are closed
						while(m_pSessions.Count > m_MaxConnections){
							Thread.Sleep(100);
						}
					}

                    // Get incomong connection
                    IPBindInfo bindInfo = binds.Next();

                    // There is waiting connection
                    if(m_Running && ((Socket)bindInfo.Tag).Poll(0,SelectMode.SelectRead)){
                        // Accept incoming connection
					    Socket s = ((Socket)bindInfo.Tag).Accept();
                                                
        				// Add session to queue
		        		lock(m_pQueuedConnections){
				        	m_pQueuedConnections.Enqueue(new QueuedConnection(s,bindInfo));
					    }
                    }
					
                    Thread.Sleep(2);
				}
			}
			catch(SocketException x){
				// Socket listening stopped, happens when StopServer is called.
				// We need just skip this error.
				if(x.ErrorCode == 10004){			
				}
				else{
					OnSysError("WE MUST NEVER REACH HERE !!! StartProcCons:",x);
				}
			}
			catch(Exception x){
				OnSysError("WE MUST NEVER REACH HERE !!! StartProcCons:",x);
			}
		}
Ejemplo n.º 7
0
        /// <summary>
        /// Processes incoming UDP data and queues it for processing.
        /// </summary>
        private void ProcessIncomingUdp()
        {
            // Create Round-Robin for listening points.
            CircleCollection<Socket> listeningEPs = new CircleCollection<Socket>();
            foreach (Socket socket in m_pSockets)
            {
                listeningEPs.Add(socket);
            }

            byte[] buffer = new byte[m_MTU];
            while (m_IsRunning)
            {
                try
                {
                    // Maximum allowed UDP queued packts exceeded.
                    if (m_pQueuedPackets.Count >= m_MaxQueueSize)
                    {
                        Thread.Sleep(1);
                    }
                    else
                    {
                        // Roun-Robin sockets.
                        bool receivedData = false;
                        for (int i = 0; i < listeningEPs.Count; i++)
                        {
                            Socket socket = listeningEPs.Next();
                            // Read data only when there is some, otherwise we block thread.
                            if (socket.Poll(0, SelectMode.SelectRead))
                            {
                                // Receive data.
                                EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                                int received = socket.ReceiveFrom(buffer, ref remoteEP);
                                m_BytesReceived += received;
                                m_PacketsReceived++;

                                // Queue received packet.
                                byte[] data = new byte[received];
                                Array.Copy(buffer, data, received);
                                lock (m_pQueuedPackets)
                                {
                                    m_pQueuedPackets.Enqueue(new UdpPacket(socket, (IPEndPoint) remoteEP, data));
                                }

                                // We received data, so exit round-robin loop.
                                receivedData = true;
                                break;
                            }
                        }
                        // We didn't get any data from any listening point, we must sleep or we use 100% CPU.
                        if (!receivedData)
                        {
                            Thread.Sleep(1);
                        }
                    }
                }
                catch (Exception x)
                {
                    OnError(x);
                }
            }
        }
        /// <summary>
        /// Processes incoming SIP UDP messages or incoming new SIP connections.
        /// </summary>
        private void ProcessIncomingData()
        {
            try{
                // If no binds, wait some to be created.
                while(m_pSipStack.BindInfo.Length == 0 && m_IsRunning){
                    System.Threading.Thread.Sleep(100);
                }

                //--- Create listening sockets --------------------------------------------------------------
                foreach(BindInfo bindInfo in m_pSipStack.BindInfo){
                    // TCP
                    if(bindInfo.Protocol == BindInfoProtocol.TCP){
                        Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                        s.Bind(new IPEndPoint(bindInfo.IP,bindInfo.Port));
                        s.Listen(500);

                        m_pListeningPoints.Add(new SipListeningPoint(bindInfo.Protocol,s,bindInfo.SSL,bindInfo.SSL_Certificate));
                    }
                    // UDP
                    else if(bindInfo.Protocol == BindInfoProtocol.UDP){
                        // If any IP, replicate socket for each IP, other can't get LocalEndpoint for UDP socket.
                        if(bindInfo.IP.Equals(IPAddress.Any)){
                            IPAddress[] addresses = System.Net.Dns.GetHostAddresses("");
                            foreach(IPAddress address in addresses){
                                // IPv4
                                if(address.AddressFamily == AddressFamily.InterNetwork){
                                    Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
                                    s.Bind(new IPEndPoint(address,bindInfo.Port));

                                    m_pListeningPoints.Add(new SipListeningPoint(bindInfo.Protocol,s,false,null));
                                }
                                // IPv6
                                /*
                                else{
                                    Socket s = new Socket(AddressFamily.InterNetworkV6,SocketType.Dgram,ProtocolType.Udp);
                                    s.Bind(new IPEndPoint(address,bindInfo.Port));

                                    m_pListeningPoints.Add(new SipListeningPoint(bindInfo.Protocol,s,false,null));
                                }*/
                            }
                        }
                        else{
                            Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
                            s.Bind(new IPEndPoint(bindInfo.IP,bindInfo.Port));

                            m_pListeningPoints.Add(new SipListeningPoint(bindInfo.Protocol,s,false,null));
                        }
                    }
                }

                CircleCollection<SipListeningPoint> binds = new CircleCollection<SipListeningPoint>();
                binds.Add(m_pListeningPoints.ToArray());
                //-------------------------------------------------------------------------------------------

                // Accept incoming connections and datagrams.
                while(m_IsRunning){
                    try{
                        // Check that maximum allowed connections not exceeded.
                        if(m_pSipStack.MaximumConnections > 0 && m_pTcpReceiviePipes.Count > m_pSipStack.MaximumConnections){
                            // Sleep here or CPU used 100%
                            Thread.Sleep(1);

                            // Step to next while loop.
                            continue;
                        }

                        // Check next listening point and queue it up when Socket has data or connection attampt.
                        SipListeningPoint listeningPoint = binds.Next();
                        if(listeningPoint.Socket.Poll(0,SelectMode.SelectRead)){
                            Socket socket = listeningPoint.Socket;

                            // TCP, TLS
                            if(listeningPoint.Protocol == BindInfoProtocol.TCP){
                                // Accept incoming connection.
                                SocketEx clientSocket = new SocketEx(socket.Accept());

                                // SSL
                                if(listeningPoint.SSL){
                                    clientSocket.SwitchToSSL(listeningPoint.Certificate);
                                }

                                // Queue for futher processing.
                                m_pTcpReceiviePipes.Add(new SipTcpPipe(this,clientSocket));
                            }
                            // UDP
                            else if(listeningPoint.Protocol == BindInfoProtocol.UDP){
                                // Receive data packet.
                                byte[] dataBuffer = new byte[32000];
                                EndPoint remoteEndPoint = (EndPoint)new IPEndPoint(IPAddress.Any,0);
                                int size = socket.ReceiveFrom(dataBuffer,ref remoteEndPoint);

                                // Copy received data to new buffer what is exactly received size.
                                byte[] data = new byte[size];
                                Array.Copy(dataBuffer,data,size);

                                // Queue UDP datagram for processing.
                                ThreadPool.QueueUserWorkItem(
                                    new WaitCallback(this.Process),
                                    new SIP_Packet(socket,(IPEndPoint)remoteEndPoint,data)
                                );
                            }
                        }

                        // Sleep here or CPU used 100%
                        Thread.Sleep(1);
                    }
                    catch(SocketException x){
                        // Just skip recieve errors.

                        /* WSAETIMEDOUT 10060 Connection timed out.
                            A connection attempt failed because the connected party did not properly respond
                            after a period of time, or the established connection failed because the connected
                            host has failed to respond.
                        */
                        if(x.ErrorCode == 10060){
                            // Skip
                        }
                        /* WSAECONNRESET 10054 Connection reset by peer.
                            An existing connection was forcibly closed by the remote host. This normally results
                            if the peer application on the remote host is suddenly stopped, the host is rebooted,
                           the host or remote network interface is disabled, or the remote host uses a hard close.
                        */
                        else if(x.ErrorCode == 10054){
                            // Skip
                        }
                        else{
                            m_pSipStack.OnError(x);
                        }
                    }
                    catch(Exception x){
                        m_pSipStack.OnError(x);
                    }
                }
            }
            catch(Exception x){
                m_pSipStack.OnError(x);
            }
        }