public AudioChannel() { // Set up the device that will play the audio from the RTP received from the remote end of the call. m_waveOut = new WaveOut(); m_waveProvider = new BufferedWaveProvider(_waveFormat); m_waveOut.Init(m_waveProvider); m_waveOut.Play(); // Set up the input device that will provide audio samples that can be encoded, packaged into RTP and sent to // the remote end of the call. m_waveInEvent = new WaveInEvent(); m_waveInEvent.BufferMilliseconds = 20; m_waveInEvent.NumberOfBuffers = 1; m_waveInEvent.DeviceNumber = 0; m_waveInEvent.DataAvailable += RTPChannelSampleAvailable; m_waveInEvent.WaveFormat = _waveFormat; // Create a UDP socket to use for sending and receiving RTP packets. int port = FreePort.FindNextAvailableUDPPort(DEFAULT_START_RTP_PORT); _rtpEndPoint = new IPEndPoint(_defaultLocalAddress, port); m_rtpChannel = new RTPChannel(_rtpEndPoint); m_rtpChannel.OnFrameReady += RTPChannelSampleReceived; _audioLogger.Debug("RTP channel endpoint " + _rtpEndPoint.ToString()); }
/// <summary> /// Initialises the SIP transport layer. /// </summary> private void InitialiseSIP() { // Configure the SIP transport layer. m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); if (m_sipSocketsNode != null) { // Set up the SIP channels based on the app.config file. List <SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(m_sipSocketsNode); m_sipTransport.AddSIPChannel(sipChannels); } else { // Use default options to set up a SIP channel. int port = FreePort.FindNextAvailableUDPPort(_defaultSIPUdpPort); var sipChannel = new SIPUDPChannel(new IPEndPoint(_defaultLocalAddress, port)); m_sipTransport.AddSIPChannel(sipChannel); } // Wire up the transport layer so incoming SIP requests have somewhere to go. m_sipTransport.SIPTransportRequestReceived += SIPTransportRequestReceived; // Log all SIP packets received to a log file. m_sipTransport.SIPRequestInTraceEvent += (localSIPEndPoint, endPoint, sipRequest) => { _sipTraceLogger.Debug("Request Received : " + localSIPEndPoint + "<-" + endPoint + "\r\n" + sipRequest.ToString()); }; m_sipTransport.SIPRequestOutTraceEvent += (localSIPEndPoint, endPoint, sipRequest) => { _sipTraceLogger.Debug("Request Sent: " + localSIPEndPoint + "->" + endPoint + "\r\n" + sipRequest.ToString()); }; m_sipTransport.SIPResponseInTraceEvent += (localSIPEndPoint, endPoint, sipResponse) => { _sipTraceLogger.Debug("Response Received: " + localSIPEndPoint + "<-" + endPoint + "\r\n" + sipResponse.ToString()); }; m_sipTransport.SIPResponseOutTraceEvent += (localSIPEndPoint, endPoint, sipResponse) => { _sipTraceLogger.Debug("Response Sent: " + localSIPEndPoint + "->" + endPoint + "\r\n" + sipResponse.ToString()); }; }
static void Main(string[] args) { try { // Configure the SIP transport layer. _sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); // Use default options to set up a SIP channel. var localIP = LocalIPConfig.GetDefaultIPv4Address(); // Set this manually if needed. int port = FreePort.FindNextAvailableUDPPort(_defaultSIPUdpPort); var sipChannel = new SIPUDPChannel(new IPEndPoint(localIP, port)); _sipTransport.AddSIPChannel(sipChannel); SIPCallDescriptor callDescriptor = new SIPCallDescriptor("test", null, "sip:[email protected]", "sip:[email protected]", null, null, null, null, SIPCallDirection.Out, null, null, null); SIPNonInviteClientUserAgent notifyUac = new SIPNonInviteClientUserAgent(_sipTransport, null, callDescriptor, null, null, (monitorEvent) => { Console.WriteLine("Debug: " + monitorEvent.Message); }); notifyUac.ResponseReceived += (resp) => { Console.WriteLine(resp.ToString()); }; notifyUac.SendRequest(SIPMethodsEnum.NOTIFY); ManualResetEvent mre = new ManualResetEvent(false); mre.WaitOne(); } catch (Exception excp) { Console.WriteLine("Exception Main. " + excp); } finally { Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } }
public void Init() { var port = FreePort.FindNextAvailableUDPPort(15090); transport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); publicIPAddress = STUNClient.GetPublicIPAddress("stun.ekiga.net"); localIPEndPoint = IpAddressLookup.QueryRoutingInterface(asterisk, port); var endpoint = new IPEndPoint(localIPEndPoint.Address, port); var channel = new SIPUDPChannel(endpoint); transport.AddSIPChannel(channel); transport.SIPTransportRequestReceived += Transport_SIPTransportRequestReceived; //var registration = new SIPRegistrationUserAgent( // transport, // null, // new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port), // new SIPURI("1003", asterisk, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), // "1003", // passwords[0], // null, // asterisk, // new SIPURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port)), // 180, // null, // null, // (e) => { logger.Debug($"{ prefix } SIPRegistrationUserAgent; { e.Message }"); } // ); //registration.RegistrationSuccessful += Registration_RegistrationSuccessful; //registration.RegistrationFailed += Registration_RegistrationFailed; //registration.Start(); }
public void Start(string endpoint) { this.endpoint = endpoint; var caller = "1003"; var password = passwords[0]; var port = FreePort.FindNextAvailableUDPPort(15090); rtpChannel = new RTPChannel { DontTimeout = true, RemoteEndPoint = new IPEndPoint(IPAddress.Parse(asterisk), port) }; rtpChannel.SetFrameType(FrameTypesEnum.Audio); rtpChannel.ReservePorts(15000, 15090); rtpChannel.OnFrameReady += RtpChannel_OnFrameReady; uac = new SIPClientUserAgent(transport, null, null, null, null); var uri = SIPURI.ParseSIPURIRelaxed($"{ endpoint }@{ asterisk }"); var from = (new SIPFromHeader(caller, new SIPURI(caller, asterisk, null), null)).ToString(); var random = Crypto.GetRandomInt(5).ToString(); var sdp = new SDP { Version = 2, Username = "******", SessionId = random, Address = localIPEndPoint.Address.ToString(), SessionName = "redfox_" + random, Timing = "0 0", Connection = new SDPConnectionInformation(publicIPAddress.ToString()) }; var announcement = new SDPMediaAnnouncement { Media = SDPMediaTypesEnum.audio, MediaFormats = new List <SDPMediaFormat>() { new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU, "PCMU", 8000) }, Port = rtpChannel.RTPPort }; sdp.Media.Add(announcement); var descriptor = new SIPCallDescriptor(caller, password, uri.ToString(), from, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, sdp.ToString(), null); uac.CallTrying += Uac_CallTrying; uac.CallRinging += Uac_CallRinging; uac.CallAnswered += Uac_CallAnswered; uac.CallFailed += Uac_CallFailed; uac.Call(descriptor); }
/// <summary> /// Initialises the SIP transport layer. /// </summary> public async Task InitialiseSIP() { if (_isIntialised == false) { await Task.Run(() => { _isIntialised = true; if (String.IsNullOrEmpty(m_DnsServer) == false) { // Use a custom DNS server. m_DnsServer = m_DnsServer.Contains(":") ? m_DnsServer : m_DnsServer + ":53"; DNSManager.SetDNSServers(new List <IPEndPoint> { IPSocket.ParseSocketString(m_DnsServer) }); } // Configure the SIP transport layer. m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); bool sipChannelAdded = false; if (m_sipSocketsNode != null) { // Set up the SIP channels based on the app.config file. List <SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(m_sipSocketsNode); if (sipChannels?.Count > 0) { m_sipTransport.AddSIPChannel(sipChannels); sipChannelAdded = true; } } if (sipChannelAdded == false) { // Use default options to set up a SIP channel. int port = FreePort.FindNextAvailableUDPPort(_defaultSIPUdpPort); var sipChannel = new SIPUDPChannel(new IPEndPoint(_defaultLocalAddress, port)); m_sipTransport.AddSIPChannel(sipChannel); } }); // Wire up the transport layer so incoming SIP requests have somewhere to go. m_sipTransport.SIPTransportRequestReceived += SIPTransportRequestReceived; // Log all SIP packets received to a log file. m_sipTransport.SIPRequestInTraceEvent += (localSIPEndPoint, endPoint, sipRequest) => { _sipTraceLogger.Debug("Request Received : " + localSIPEndPoint + "<-" + endPoint + "\r\n" + sipRequest.ToString()); }; m_sipTransport.SIPRequestOutTraceEvent += (localSIPEndPoint, endPoint, sipRequest) => { _sipTraceLogger.Debug("Request Sent: " + localSIPEndPoint + "->" + endPoint + "\r\n" + sipRequest.ToString()); }; m_sipTransport.SIPResponseInTraceEvent += (localSIPEndPoint, endPoint, sipResponse) => { _sipTraceLogger.Debug("Response Received: " + localSIPEndPoint + "<-" + endPoint + "\r\n" + sipResponse.ToString()); }; m_sipTransport.SIPResponseOutTraceEvent += (localSIPEndPoint, endPoint, sipResponse) => { _sipTraceLogger.Debug("Response Sent: " + localSIPEndPoint + "->" + endPoint + "\r\n" + sipResponse.ToString()); }; } }
public void Run() { server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var port = FreePort.FindNextAvailableTcpPort(20000); var endPoint = new IPEndPoint(IPAddress.Any, port); server.Bind(endPoint); server.Listen(port); var accept = new SocketAsyncEventArgs(); accept.Completed += Accept_Completed; accept.RemoteEndPoint = endPoint; accept.UserToken = server; server.AcceptAsync(accept); }
private static Dictionary <string, SIPRegistrarBinding> _sipRegistrations = new Dictionary <string, SIPRegistrarBinding>(); // [SIP Username, Contact Address], tracks SIP clients that have registered with the server. static void Main(string[] args) { try { // Configure the SIP transport layer. _sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); if (_sipSocketsNode != null) { // Set up the SIP channels based on the app.config file. List <SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(_sipSocketsNode); _sipTransport.AddSIPChannel(sipChannels); } else { // Use default options to set up a SIP channel. int port = FreePort.FindNextAvailableUDPPort(_defaultSIPUdpPort); var sipChannel = new SIPUDPChannel(new IPEndPoint(_defaultLocalAddress, port)); _sipTransport.AddSIPChannel(sipChannel); } // Wire up the transport layer so SIP requests and responses have somewhere to go. _sipTransport.SIPTransportRequestReceived += SIPTransportRequestReceived; _sipTransport.SIPTransportResponseReceived += SIPTransportResponseReceived; // If you want to see ALL the nitty gritty SIP traffic wire up the events below. //_sipTransport.SIPBadRequestInTraceEvent += SIPBadRequestInTraceEvent; //_sipTransport.SIPBadResponseInTraceEvent += SIPBadResponseInTraceEvent; //_sipTransport.SIPRequestInTraceEvent += SIPRequestInTraceEvent; //_sipTransport.SIPRequestOutTraceEvent += SIPRequestOutTraceEvent; //_sipTransport.SIPResponseInTraceEvent += SIPResponseInTraceEvent; //_sipTransport.SIPResponseOutTraceEvent += SIPResponseOutTraceEvent; ManualResetEvent mre = new ManualResetEvent(false); mre.WaitOne(); } catch (Exception excp) { Console.WriteLine("Exception Main. " + excp); } finally { Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } }
static void Main(string[] args) { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); // Logging configuration. Can be ommitted if internal SIPSorcery debug and warning messages are not required. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .Enrich.FromLogContext() .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) .WriteTo.Console() .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); SIPSorcery.Sys.Log.LoggerFactory = loggerFactory; // If your default DNS server supports SRV records there is no need to set a specific DNS server. DNSManager.SetDNSServers(new List <IPEndPoint> { IPEndPoint.Parse("8.8.8.8:53") }); // Set up a default SIP transport. var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); int port = FreePort.FindNextAvailableUDPPort(SIPConstants.DEFAULT_SIP_PORT); var sipChannel = new SIPUDPChannel(new IPEndPoint(LocalIPConfig.GetDefaultIPv4Address(), port)); sipTransport.AddSIPChannel(sipChannel); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent( sipTransport, "softphonesample", "password", "sipsorcery.com"); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => SIPSorcery.Sys.Log.Logger.LogWarning($"{uri.ToString()}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => SIPSorcery.Sys.Log.Logger.LogInformation($"{uri.ToString()} registration succeeded."); // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); }
public void Init() { var port = FreePort.FindNextAvailableUDPPort(15090); transport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); publicIPAddress = STUNClient.GetPublicIPAddress("stun.ekiga.net"); localIPEndPoint = IpAddressLookup.QueryRoutingInterface(asterisk, port); var endpoint = new IPEndPoint(localIPEndPoint.Address, port); var channel = new SIPUDPChannel(endpoint); //channel.SIPMessageReceived += (SIPChannel sipChannel, SIPEndPoint remoteEndPoint, byte[] buffer) => { logger.Debug("Channel SIP message received " + channel.SIPChannelEndPoint + "<-" + remoteEndPoint); }; transport.AddSIPChannel(channel); for (var i = 0; i < numbers.Length; i++) { var number = numbers[i]; var password = passwords[i]; var registration = new SIPRegistrationUserAgent( transport, null, new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port), new SIPURI(number, asterisk, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), number, password, null, asterisk, new SIPURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port)), 180, null, null, (e) => { logger.Debug(e.Message); } ); logger.Debug($"{prefix} Registration attempt for {number}@{endpoint.Address}:{endpoint.Port}"); registration.RegistrationSuccessful += Registration_RegistrationSuccessful; registration.RegistrationFailed += Registration_RegistrationFailed; registration.Start(); registrations.Add(registration); } }
public void Start(Action After) { if (State) { After?.Invoke(); return; } Task.Run(() => { ServerEnvironment.Instance.Port = FreePort.FindNextAvailableTCPPort(ServerEnvironment.Instance.Port); var line = $@"{ServerEnvironment.Instance.Path}{ServerEnvironment.Instance.WebName}.dll --urls=http://*:{ServerEnvironment.Instance.Port}"; var psi = SetProcessInfo(line); Process = Process.Start(psi); After?.Invoke(); Process.OutputDataReceived += new DataReceivedEventHandler(Instance.OnDataReceived); Process.BeginOutputReadLine(); Process.WaitForExit(); if (Process.ExitCode != 0) { logger.Info(Process.StandardError.ReadToEnd()); } Process.Close(); Process = null; }); }
private const int SUCCESS_REGISTRATION_COUNT = 3; // Number of successful registrations to attempt before exiting process. static void Main(string[] args) { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); // Logging configuration. Can be ommitted if internal SIPSorcery debug and warning messages are not required. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .Enrich.FromLogContext() .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) .WriteTo.Console() .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); SIPSorcery.Sys.Log.LoggerFactory = loggerFactory; // Set up a default SIP transport. var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); int port = FreePort.FindNextAvailableUDPPort(SIPConstants.DEFAULT_SIP_PORT); var sipChannel = new SIPUDPChannel(new IPEndPoint(LocalIPConfig.GetDefaultIPv4Address(), port)); sipTransport.AddSIPChannel(sipChannel); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent( sipTransport, "softphonesample", "password", "sipsorcery.com", 120); int successCounter = 0; ManualResetEvent taskCompleteMre = new ManualResetEvent(false); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => SIPSorcery.Sys.Log.Logger.LogWarning($"{uri.ToString()}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => { SIPSorcery.Sys.Log.Logger.LogInformation($"{uri.ToString()} registration succeeded."); Interlocked.Increment(ref successCounter); SIPSorcery.Sys.Log.Logger.LogInformation($"Successful registrations {successCounter} of {SUCCESS_REGISTRATION_COUNT}."); if (successCounter == SUCCESS_REGISTRATION_COUNT) { taskCompleteMre.Set(); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); taskCompleteMre.Set(); }; // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); taskCompleteMre.WaitOne(); regUserAgent.Stop(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } SIPSorcery.Net.DNSManager.Stop(); }
private static readonly int RTP_REPORTING_PERIOD_SECONDS = 5; // Period at which to write RTP stats. static void Main() { Console.WriteLine("SIPSorcery client user agent server example."); Console.WriteLine("Press ctrl-c to exit."); // Logging configuration. Can be ommitted if internal SIPSorcery debug and warning messages are not required. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .Enrich.FromLogContext() .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) .WriteTo.Console() .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); SIPSorcery.Sys.Log.LoggerFactory = loggerFactory; // Set up a default SIP transport. IPAddress defaultAddr = LocalIPConfig.GetDefaultIPv4Address(); var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); int port = FreePort.FindNextAvailableUDPPort(SIPConstants.DEFAULT_SIP_PORT); var sipChannel = new SIPUDPChannel(new IPEndPoint(defaultAddr, port)); sipTransport.AddSIPChannel(sipChannel); // To keep things a bit simpler this example only supports a single call at a time and the SIP server user agent // acts as a singleton SIPServerUserAgent uas = null; CancellationTokenSource uasCts = null; // Because this is a server user agent the SIP transport must start listening for client user agents. sipTransport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { if (sipRequest.Method == SIPMethodsEnum.INVITE) { SIPSorcery.Sys.Log.Logger.LogInformation("Incoming call request: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + "."); // If there's already a call in progress hang it up. Of course this is not ideal for a real softphone or server but it // means this example can be kept a little it simpler. uas?.Hangup(); UASInviteTransaction uasTransaction = sipTransport.CreateUASTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null); uas = new SIPServerUserAgent(sipTransport, null, null, null, SIPCallDirection.In, null, null, null, uasTransaction); uasCts = new CancellationTokenSource(); uas.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null); uas.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null); // Initialise an RTP session to receive the RTP packets from the remote SIP server. Socket rtpSocket = null; Socket controlSocket = null; NetServices.CreateRtpSocket(defaultAddr, 49000, 49100, false, out rtpSocket, out controlSocket); IPEndPoint rtpEndPoint = rtpSocket.LocalEndPoint as IPEndPoint; IPEndPoint dstRtpEndPoint = SDP.GetSDPRTPEndPoint(sipRequest.Body); var rtpSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null); var rtpTask = Task.Run(() => SendRecvRtp(rtpSocket, rtpSession, dstRtpEndPoint, AUDIO_FILE, uasCts)) .ContinueWith(_ => { if (uas?.IsHungup == false) { uas?.Hangup(); } }); uas.Answer(SDP.SDP_MIME_CONTENTTYPE, GetSDP(rtpEndPoint).ToString(), null, SIPDialogueTransferModesEnum.NotAllowed); } else if (sipRequest.Method == SIPMethodsEnum.BYE) { SIPSorcery.Sys.Log.Logger.LogInformation("Call hungup."); SIPNonInviteTransaction byeTransaction = sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null); SIPResponse byeResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); byeTransaction.SendFinalResponse(byeResponse); uas?.Hangup(); uasCts?.Cancel(); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); if (uas?.IsHungup == false) { uas?.Hangup(); } uasCts?.Cancel(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } }; }
private static readonly int RTP_REPORTING_PERIOD_SECONDS = 5; // Period at which to write RTP stats. static void Main() { Console.WriteLine("SIPSorcery client user agent example."); Console.WriteLine("Press ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource cts = new CancellationTokenSource(); bool isCallHungup = false; bool hasCallFailed = false; // Logging configuration. Can be ommitted if internal SIPSorcery debug and warning messages are not required. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .Enrich.FromLogContext() .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) .WriteTo.Console() .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); SIPSorcery.Sys.Log.LoggerFactory = loggerFactory; // Set up a default SIP transport. IPAddress defaultAddr = LocalIPConfig.GetDefaultIPv4Address(); var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); int port = FreePort.FindNextAvailableUDPPort(SIPConstants.DEFAULT_SIP_PORT + 2); var sipChannel = new SIPUDPChannel(new IPEndPoint(defaultAddr, port)); sipTransport.AddSIPChannel(sipChannel); // Initialise an RTP session to receive the RTP packets from the remote SIP server. Socket rtpSocket = null; Socket controlSocket = null; NetServices.CreateRtpSocket(defaultAddr, 49000, 49100, false, out rtpSocket, out controlSocket); var rtpSendSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null); // Create a client user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var uac = new SIPClientUserAgent(sipTransport); uac.CallTrying += (uac, resp) => SIPSorcery.Sys.Log.Logger.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); uac.CallRinging += (uac, resp) => SIPSorcery.Sys.Log.Logger.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); uac.CallFailed += (uac, err) => { SIPSorcery.Sys.Log.Logger.LogWarning($"{uac.CallDescriptor.To} Failed: {err}"); hasCallFailed = true; }; uac.CallAnswered += (uac, resp) => { if (resp.Status == SIPResponseStatusCodesEnum.Ok) { SIPSorcery.Sys.Log.Logger.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); IPEndPoint remoteRtpEndPoint = SDP.GetSDPRTPEndPoint(resp.Body); SIPSorcery.Sys.Log.Logger.LogDebug($"Sending initial RTP packet to remote RTP socket {remoteRtpEndPoint}."); // Send a dummy packet to open the NAT session on the RTP path. rtpSendSession.SendAudioFrame(rtpSocket, remoteRtpEndPoint, 0, new byte[] { 0x00 }); } else { SIPSorcery.Sys.Log.Logger.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); } }; // The only incoming request that needs to be explicitly handled for this example is if the remote end hangs up the call. sipTransport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { if (sipRequest.Method == SIPMethodsEnum.BYE) { SIPNonInviteTransaction byeTransaction = sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null); SIPResponse byeResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); byeTransaction.SendFinalResponse(byeResponse); if (uac.IsUACAnswered) { SIPSorcery.Sys.Log.Logger.LogInformation("Call was hungup by remote server."); isCallHungup = true; cts.Cancel(); } } }; // It's a good idea to start the RTP receiving socket before the call request is sent. // A SIP server will generally start sending RTP as soon as it has processed the incoming call request and // being ready to receive will stop any ICMP error response being generated. Task.Run(() => SendRecvRtp(rtpSocket, rtpSendSession, cts)); // Start the thread that places the call. SIPCallDescriptor callDescriptor = new SIPCallDescriptor( SIPConstants.SIP_DEFAULT_USERNAME, null, DESTINATION_SIP_URI, SIPConstants.SIP_DEFAULT_FROMURI, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, GetSDP(rtpSocket.LocalEndPoint as IPEndPoint).ToString(), null); uac.Call(callDescriptor); // At this point the call has been initiated and everything will be handled in an event handler or on the RTP // receive task. The code below is to gracefully exit. // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += async delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; cts.Cancel(); SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); rtpSocket?.Close(); controlSocket?.Close(); if (!isCallHungup && uac != null) { if (uac.IsUACAnswered) { SIPSorcery.Sys.Log.Logger.LogInformation($"Hanging up call to {uac.CallDescriptor.To}."); uac.Hangup(); } else if (!hasCallFailed) { SIPSorcery.Sys.Log.Logger.LogInformation($"Cancelling call to {uac.CallDescriptor.To}."); uac.Cancel(); } // Give the BYE or CANCEL request time to be transmitted. SIPSorcery.Sys.Log.Logger.LogInformation("Waiting 1s for call to clean up..."); await Task.Delay(1000); } SIPSorcery.Net.DNSManager.Stop(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } }; }
///<summary>Processes a received query.</summary> ///<param name="Query">The query to process.</param> private async Task ProcessQuery(byte[] Query) { try { Request request = null; Request.ParseRequest(Query, out request); switch (request.Command) { case Command.Connect: //CONNECT IPAddress RemoteIP = request.DstAddr; int RemotePort = 0; if (Query[3] == 1) { RemoteIP = IPAddress.Parse(Query[4].ToString() + "." + Query[5].ToString() + "." + Query[6].ToString() + "." + Query[7].ToString()); RemotePort = Query[8] * 256 + Query[9]; } else if (Query[3] == 3) { if (RemoteIP == null) { RemoteIP = Dns.GetHostAddressesAsync(Encoding.ASCII.GetString(Query, 5, Query[4])).Result[0]; } RemotePort = Query[4] + 5; RemotePort = Query[RemotePort] * 256 + Query[RemotePort + 1]; } RemoteConnection = new TcpSocket(RemoteIP.AddressFamily, false); try { await RemoteConnection.ConnectAsync(new IPEndPoint(RemoteIP, RemotePort)); await OnConnected(null); } catch (SocketException ex) { Console.WriteLine("[WARN] SocketError=" + ex.SocketErrorCode + "\r\n"); await OnConnected(ex); } catch (Exception ex) { Console.WriteLine("[WARN] " + ex.Message + "\r\n" + ex.StackTrace); await OnConnected(ex); } break; case Command.Bind: //BIND byte[] Reply = new byte[10]; long LocalIP = BitConverter.ToInt64(Listener.GetLocalExternalIP().Result.GetAddressBytes(), 0); AcceptSocket = new TcpSocket(IPAddress.Any.AddressFamily, false); AcceptSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); AcceptSocket.Listen(50); Reply[0] = 5; //Version 5 Reply[1] = 0; //Everything is ok :) Reply[2] = 0; //Reserved Reply[3] = 1; //We're going to send a IPv4 address Reply[4] = (byte)((LocalIP % 256)); //IP Address/1 Reply[5] = (byte)((LocalIP % 65536) / 256); //IP Address/2 Reply[6] = (byte)((LocalIP % 16777216) / 65536); //IP Address/3 Reply[7] = (byte)(Math.Floor(LocalIP / 16777216.0)); //IP Address/4 Reply[8] = (byte)(Math.Floor(((IPEndPoint)AcceptSocket.LocalEndPoint).Port / 256.0)); //Port/1 Reply[9] = (byte)(((IPEndPoint)AcceptSocket.LocalEndPoint).Port % 256); //Port/2 await Connection.SendAsync(Reply, async (int x) => { await this.OnStartAccept(); }); break; case Command.UdpAssociate: //UDP ASSOCIATE if (request.DstAddr.Equals(IPAddress.Any) && request.DstPort == 0) { request.DstPort = FreePort.FindNextAvailableUDPPort(4200); if (request.DstPort == 0) { await Dispose(ReplyCode.SocksFailure); return; } } if (request.DstAddr.Equals(IPAddress.Any)) { request.DstAddr = ((IPEndPoint)Connection.LocalEndPoint).Address; } UdpClientEndPoint = new IPEndPoint(request.DstAddr, request.DstPort); LocalBindEndPoint = new IPEndPoint(((IPEndPoint)(Connection.LocalEndPoint)).Address, request.DstPort); var reply = request.CreateReply(LocalBindEndPoint.Address, LocalBindEndPoint.Port); await Connection.SendAsync(reply.ToBytes(), async (int x) => { await this.StartUdpReceive(); }); break; default: await Dispose(ReplyCode.UnsupportedCommand); break; } } catch (Exception ex) { Console.WriteLine("[WARN] " + ex.Message + "\r\n" + ex.StackTrace); await Dispose(ReplyCode.SocksFailure); } }