Beispiel #1
0
        private void Listen()
        {
            try
            {
                byte[] buffer = null;

                logger.Debug("SIPUDPChannel socket on 0.0.0.0:" + m_localSIPEndPoint.GetIPEndPoint().Port + " listening started.");

                while (!Closed)
                {
                    IPEndPoint inEndPoint = new IPEndPoint(IPAddress.Any, 0);
                    //logger.Debug("SIPUDPChannel socket start.Receive.");
                    try
                    {
                        buffer = m_sipConn.Receive(ref inEndPoint);
                    }
                    catch (SocketException sockex)
                    {
                        // ToDo. Pretty sure these exceptions get thrown when an ICMP message comes back indicating there is no listening
                        // socket on the other end. It would be nice to be able to relate that back to the socket that the data was sent to
                        // so that we know to stop sending.
                        //logger.Warn("SocketException SIPUDPChannel Receive (" + sockExcp.ErrorCode + "). " + sockExcp.Message);

                        //inEndPoint = new SIPEndPoint(new IPEndPoint(IPAddress.Any, 0));

                        logger.Error("SocketException listening on SIPUDPChannel. " + sockex.Message);
                        continue;
                    }
                    catch (Exception listenExcp)
                    {
                        // There is no point logging this as without processing the ICMP message it's not possible to know which socket the rejection came from.
                        logger.Error("Exception listening on SIPUDPChannel. " + listenExcp.Message);

                        inEndPoint = new IPEndPoint(IPAddress.Any, 0);
                        continue;
                    }
                    //logger.Debug("SIPUDPChannel socket end.Receive.");
                    if (buffer == null || buffer.Length == 0)
                    {
                        // No need to care about zero byte packets.
                        //string remoteEndPoint = (inEndPoint != null) ? inEndPoint.ToString() : "could not determine";
                        //logger.Error("Zero bytes received on SIPUDPChannel " + m_localSIPEndPoint.ToString() + ".");
                    }
                    else
                    {
                        SIPMessageReceived?.Invoke(this, new SIPEndPoint(SIPProtocolsEnum.udp, inEndPoint), buffer);
                    }
                    //logger.Debug("SIPUDPChannel socket message handled.");
                }

                logger.Debug("SIPUDPChannel socket on " + m_localSIPEndPoint + " listening halted.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPUDPChannel Listen. " + excp.Message);
                //throw excp;
            }
        }
        private void EndReceiveMessageFrom(IAsyncResult ar)
        {
            EndPoint remoteEP = (ListeningIPAddress.AddressFamily == AddressFamily.InterNetwork)
                ? new IPEndPoint(IPAddress.Any, 0)
                : new IPEndPoint(IPAddress.IPv6Any, 0);

            try
            {
                if (!Closed)
                {
                    SocketFlags flags = SocketFlags.None;

                    int bytesRead = m_udpSocket.EndReceiveMessageFrom(ar, ref flags, ref remoteEP, out var packetInfo);

                    if (bytesRead > 0)
                    {
                        SIPEndPoint remoteEndPoint =
                            new SIPEndPoint(SIPProtocolsEnum.udp, remoteEP as IPEndPoint, ID, null);
                        SIPEndPoint localEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp,
                                                                    new IPEndPoint(packetInfo.Address, Port), ID, null);
                        byte[] sipMsgBuffer = new byte[bytesRead];
                        Buffer.BlockCopy(m_recvBuffer, 0, sipMsgBuffer, 0, bytesRead);
                        SIPMessageReceived?.Invoke(this, localEndPoint, remoteEndPoint, sipMsgBuffer);
                    }
                }
            }
            catch (SocketException sockExcp)
            {
                // This exception can occur as the result of a Send operation. It's caused by an ICMP packet from a remote host
                // rejecting an incoming UDP packet. If that happens we want to stop further sends to the socket for a short period.
                Logger.Logger.Warn(
                    $"SocketException SIPUDPChannel EndReceiveMessageFrom from {remoteEP} ({sockExcp.ErrorCode}). {sockExcp.Message}");
                if (remoteEP != null)
                {
                    m_sendFailures.TryAdd(remoteEP as IPEndPoint, DateTime.Now);
                }
            }
            catch (ObjectDisposedException) // Thrown when socket is closed. Can be safely ignored.
            {
            }
            catch (Exception excp)
            {
                Logger.Logger.Error($"Exception SIPUDPChannel EndReceiveMessageFrom. ->{excp.Message}");
            }
            finally
            {
                if (!Closed)
                {
                    Receive();
                }
            }
        }
Beispiel #3
0
        private void SIPTCPMessageReceived(SIPChannel channel, SIPEndPoint remoteEndPoint, byte[] buffer)
        {
            if (m_connectionFailures.ContainsKey(remoteEndPoint.GetIPEndPoint().ToString()))
            {
                m_connectionFailures.Remove(remoteEndPoint.GetIPEndPoint().ToString());
            }

            if (m_connectionFailureStrikes.ContainsKey(remoteEndPoint.GetIPEndPoint().ToString()))
            {
                m_connectionFailureStrikes.Remove(remoteEndPoint.GetIPEndPoint().ToString());
            }

            SIPMessageReceived?.Invoke(channel, remoteEndPoint, buffer);
        }
Beispiel #4
0
        private async Task Listen()
        {
            logger.LogDebug("SIPUDPChannel socket on " + m_localSIPEndPoint.ToString() + " listening started.");

            while (!Closed)
            {
                try
                {
                    var receiveResult = await m_sipConn.ReceiveAsync();

                    if (receiveResult.Buffer != null && receiveResult.Buffer.Length > 0)
                    {
                        SIPMessageReceived?.Invoke(this, new SIPEndPoint(SIPProtocolsEnum.udp, receiveResult.RemoteEndPoint), receiveResult.Buffer);
                    }
                }
                catch (ObjectDisposedException)
                {
                    // it's ok to be here after invoking Close()
                    break;
                }
                catch (SocketException)
                {
                    // ToDo. Pretty sure these exceptions get thrown when an ICMP message comes back indicating there is no listening
                    // socket on the other end. It would be nice to be able to relate that back to the socket that the data was sent to
                    // so that we know to stop sending.
                    //logger.LogWarning("SocketException SIPUDPChannel Receive (" + sockExcp.ErrorCode + "). " + sockExcp.Message);

                    //inEndPoint = new SIPEndPoint(new IPEndPoint(IPAddress.Any, 0));
                    continue;
                }
                catch (Exception listenExcp)
                {
                    logger.LogError("Exception listening on SIPUDPChannel. " + listenExcp.Message);
                    continue;
                }
            }

            logger.LogDebug("SIPUDPChannel socket on " + m_localSIPEndPoint + " listening halted.");
        }
Beispiel #5
0
        private void EndReceiveMessageFrom(IAsyncResult ar)
        {
            try
            {
                SocketFlags flags    = SocketFlags.None;
                EndPoint    remoteEP = (ListeningIPAddress.AddressFamily == AddressFamily.InterNetwork) ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0);

                int bytesRead = m_udpSocket.EndReceiveMessageFrom(ar, ref flags, ref remoteEP, out var packetInfo);

                if (bytesRead > 0)
                {
                    SIPEndPoint remoteEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, remoteEP as IPEndPoint, ID, null);
                    SIPEndPoint localEndPoint  = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(packetInfo.Address, Port), ID, null);
                    byte[]      sipMsgBuffer   = new byte[bytesRead];
                    Buffer.BlockCopy(m_recvBuffer, 0, sipMsgBuffer, 0, bytesRead);
                    SIPMessageReceived?.Invoke(this, localEndPoint, remoteEndPoint, sipMsgBuffer);
                }
            }
            catch (SocketException sockExcp)
            {
                // ToDo. Pretty sure these exceptions get thrown when an ICMP message comes back indicating there is no listening
                // socket on the other end. It would be nice to be able to relate that back to the socket that the data was sent to
                // so that we know to stop sending.
                logger.LogWarning($"SocketException SIPUDPChannel Receive ({sockExcp.ErrorCode}). {sockExcp.Message}");
            }
            catch (ObjectDisposedException) { } // Thrown when socket is closed. Can be safely ignored.
            catch (Exception excp)
            {
                logger.LogError($"Exception SIPUDPChannel.EndReceiveMessageFrom. {excp.Message}");
            }
            finally
            {
                if (!Closed)
                {
                    Receive();
                }
            }
        }
Beispiel #6
0
 private void SIPTLSMessageReceived(SIPChannel channel, SIPEndPoint remoteEndPoint, byte[] buffer)
 {
     SIPMessageReceived?.Invoke(channel, remoteEndPoint, buffer);
 }
Beispiel #7
0
 /// <summary>
 /// Use to cause a mock message to be passed through to the SIP Transport class monitoring this mock channel.
 /// </summary>
 public void FireMessageReceived(SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint, byte[] sipMsgBuffer)
 {
     SIPMessageReceived.Invoke(this, localEndPoint, remoteEndPoint, sipMsgBuffer);
 }
Beispiel #8
0
 /// <summary>
 /// Gets fired when a suspected SIP message is extracted from the TCP data stream.
 /// </summary>
 protected Task SIPTCPMessageReceived(SIPChannel channel, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint,
                                      byte[] buffer)
 {
     return(SIPMessageReceived?.Invoke(channel, localEndPoint, remoteEndPoint, buffer));
 }
Beispiel #9
0
 /// <summary>
 /// Gets fired when a suspected SIP message is extracted from the TCP data stream.
 /// </summary>
 protected void SIPTCPMessageReceived(SIPChannel channel, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint, byte[] buffer)
 {
     SIPMessageReceived?.Invoke(channel, localEndPoint, remoteEndPoint, buffer);
 }
Beispiel #10
0
        private void EndReceiveFrom(IAsyncResult ar)
        {
            EndPoint remoteEP = (ListeningIPAddress.AddressFamily == AddressFamily.InterNetwork) ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0);

            try
            {
                if (!Closed)
                {
                    SocketFlags flags = SocketFlags.None;

                    int bytesRead = m_udpSocket.EndReceiveFrom(ar, ref remoteEP);

                    if (flags == SocketFlags.Truncated)
                    {
                        logger.LogWarning($"The message was too large to fit into the specified buffer and was truncated.");
                    }

                    if (bytesRead > 0)
                    {
                        // In addition to the note in the RTPChannel class about IPPacketInformation some versions of the mono runtime
                        // on Android are unable to use Begin/EndReceiveMessageFrom.
                        // See https://github.com/sipsorcery/sipsorcery/issues/302.
                        // Those specific Begin/End calls were being used to get the packet information and identify which local
                        // IP address a receive occurred on. Upon investigation it does not seem that the local IP address is
                        // required on incoming SIP packets. The outgoing socket was previously chosen based on this address but
                        // subsequent to https://github.com/sipsorcery/sipsorcery/issues/97 the mechanism has changed.
                        // The calls have been changed to Begin/EndReceiveFrom in order to support Android. The consequence is the localEndPoint
                        // parameter for the SIPMessageReceived will have an IP address of 0.0.0.0 or [::0] if wildcard addresses are in use.

                        SIPEndPoint remoteEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, remoteEP as IPEndPoint, ID, null);
                        //SIPEndPoint localEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(packetInfo.Address, Port), ID, null);
                        SIPEndPoint localEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(ListeningIPAddress, Port), ID, null);
                        byte[]      sipMsgBuffer  = new byte[bytesRead];
                        Buffer.BlockCopy(m_recvBuffer, 0, sipMsgBuffer, 0, bytesRead);
                        SIPMessageReceived?.Invoke(this, localEndPoint, remoteEndPoint, sipMsgBuffer);
                    }
                }
            }
            catch (SocketException sockExcp)
            {
                if (remoteEP != null)
                {
                    // Note the SIPEndPoint is being used to take care of any IPv4 mapped to IPv6 addresses.
                    SIPEndPoint remSIPEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, remoteEP as IPEndPoint);

                    // This exception can occur as the result of a Send operation. It's caused by an ICMP packet from a remote host
                    // rejecting an incoming UDP packet. If that happens we want to stop further sends to the socket for a short period.
                    logger.LogWarning(sockExcp, $"SocketException SIPUDPChannel EndReceiveFrom from {remSIPEndPoint} ({sockExcp.ErrorCode}). {sockExcp.Message}");

                    m_sendFailures.TryAdd(remSIPEndPoint.GetIPEndPoint(), DateTime.Now);
                }
                else
                {
                    logger.LogError($"SocketException SIPUDPChannel EndReceiveFrom. {sockExcp}");
                }
            }
            catch (ObjectDisposedException) // Thrown when socket is closed. Can be safely ignored.
            { }
            catch (Exception excp)
            {
                logger.LogError($"Exception SIPUDPChannel EndReceiveFrom. {excp}");
            }
            finally
            {
                if (!Closed)
                {
                    Receive();
                }
            }
        }