/// <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); } }