public static Dialog InitSipCall(DialogInfo dialogInfo, EventHandler <DialogState> stateChanged = null) { var dlg = new Dialog(Guid.NewGuid() + "@" + dialogInfo.LocalEndpoint, dialogInfo.RemoteEndpoint, dialogInfo.LocalEndpoint.Port, stateChanged); var invite = new InviteMessage(dlg.CallId, dialogInfo.To, dialogInfo.From, dialogInfo.From); dialogInfo.Fill(invite); var localEp = dialogInfo.LocalRtpEndpoint ?? dialogInfo.LocalEndpoint; localEp = new IPEndPoint(localEp.Address, MediaGateway.GetNextPort()); // TODO: select which codec will be used based on 183 session progress or prack dlg.rtp = new RtpStream(localEp, MediaGateway.CreateMedia(MediaGateway.AudioCodec.G711Alaw)); var availableCodecs = MediaGateway.GetRegisteredCodecs().Select(MediaCodecDescriptor.Describe).ToList(); var parameters = availableCodecs.SelectMany(a => a.Parameters).ToList(); invite.SdpData = new Sdp(); invite.SdpData.AddParameter("o", string.Format("- {0} 0 IN IP4 {1}", Interlocked.Increment(ref sdpIds), localEp.Address)) .AddParameter("s", "-") .AddParameter("c", string.Format("IN IP4 {0}", localEp.Address)) .AddParameter("t", "0 0") .AddParameter("m", string.Format("audio {0} RTP/AVP {1}", localEp.Port, string.Join(" ", availableCodecs.SelectMany(a => a.Identifiers).OrderBy(a => a)))); foreach (var kvp in parameters) { invite.SdpData.AddParameter(kvp.Key, kvp.Value); } invite.SdpData.AddParameter("a", "sendrecv"); invite.Headers["Via"] = string.Format("SIP/2.0/UDP {0}:{2};rport;branch=z9hG4bK7fe{1}", dialogInfo.LocalEndpoint.Address, DateTime.Now.Ticks.ToString("X8").ToLowerInvariant(), dlg.sipPort); invite.Headers["CSeq"] = Interlocked.Increment(ref dlg.callSequence) + " INVITE"; dlg.WaitForMessage(invite, dlg.HandleInviteResponse, 100, 500, 1000, 2000, 5000); dlg.Send(invite); dlg.stateChanged(dlg, DialogState.Dialing); return(dlg); }
public static void Main(string[] args) { var sessionName = (System.Environment.GetEnvironmentVariable("SESSIONNAME") ?? string.Empty).ToLower(); var isRdp = sessionName.StartsWith("rdp") || sessionName.StartsWith("console"); Console.WriteLine("IsRdp? {0}. {1}", isRdp, System.Environment.GetEnvironmentVariable("SESSIONNAME")); IRecordingDevice recordingDevice; if (isRdp) { recordingDevice = new DummyRecordDevice(); Console.WriteLine("You're connected through rdp and will not be able to record audio"); } else { recordingDevice = new NAudioRecordDevice(); } MediaGateway.RegisterCodec(MediaGateway.AudioCodec.G711Alaw, () => new AlawMediaCodec(NAudioPlaybackDevice.Instance, recordingDevice)); DialogInfo dlg; if (args.Length >= 4) { dlg = Configure(args[0], args[1], args[2], args[3], args.Length > 4 ? args[4] : null); } else if (args.Length == 0) { dlg = Configure(); } else { Console.WriteLine("usage: sipStack.exe <source_ip> <source_number> <destination_number> <destination_ip>"); return; } EventHandler <DialogState> stateHandler = (sender, state) => { Console.WriteLine("state is {0}", state); if (state == DialogState.Hungup) { recordingDevice.Stop(); } }; var dialog = Dialog.InitSipCall(dlg, stateHandler); do { var r = Console.ReadKey(); if (r.Key == ConsoleKey.W) { dialog.Hangup(); break; // TODO: send bye } Digit d; // ReSharper disable once SwitchStatementMissingSomeCases switch (r.Key) { case ConsoleKey.D0: d = Digit.Zero; break; case ConsoleKey.D1: d = Digit.One; break; case ConsoleKey.D2: d = Digit.Two; break; case ConsoleKey.D3: d = Digit.Three; break; case ConsoleKey.D4: d = Digit.Four; break; case ConsoleKey.D5: d = Digit.Five; break; case ConsoleKey.D6: d = Digit.Six; break; case ConsoleKey.D7: d = Digit.Seven; break; case ConsoleKey.D8: d = Digit.Eight; break; case ConsoleKey.D9: d = Digit.Nine; break; case ConsoleKey.A: d = Digit.A; break; case ConsoleKey.B: d = Digit.B; break; case ConsoleKey.C: d = Digit.C; break; case ConsoleKey.D: d = Digit.D; break; case ConsoleKey.H: d = Digit.Hash; break; case ConsoleKey.S: d = Digit.Star; break; default: continue; } recordingDevice.PlayDtmf(d, 320); Thread.Sleep(320); }while (true); }