I’ m currently debugging a webrtc UWP app, and it is fairly working.
But it happens that the remote stream is not displayed on my MediaElement each time. It’s like the video track is not received although I add it ASAP as recommended. I can’t figure out why it is happening ; is it a code or a network problem ? I grab the stream randomly whatever the network, sometimes successfully, other times not (staying with the same confits).
I use the google STUN servers, and the google webrtc « peer connection server » signaling server on a remote windows server, nothing is installed on my LAN (but my UWP program).
I don’t know what to do to figure out the cause ... any help would be appreciated.
private void Signaller_OnMessageFromPeer(int peerId, string message)
{
Task.Run(async () =>
{
// Debug.Assert(_peerId == peerId || _peerId == -1);
Debug.Assert(message.Length > 0);
if (_peerId != peerId && _peerId != -1)
{
Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
return;
}
if (!JsonObject.TryParse(message, out JsonObject jMessage))
{
Debug.WriteLine("[Error] Conductor: Received unknown message." + message);
return;
}
string type = jMessage.ContainsKey(kSessionDescriptionTypeName) ? jMessage.GetNamedString(kSessionDescriptionTypeName) : null;
if (_peerConnection == null)
{
if (!String.IsNullOrEmpty(type))
{
// Create the peer connection only when call is
// about to get initiated. Otherwise ignore the
// messages from peers which could be a result
// of old (but not yet fully closed) connections.
if (type == "offer" || type == "answer")
{
Debug.Assert(_peerId == -1);
_peerId = peerId;
connectToPeerCancelationTokenSource = new CancellationTokenSource();
connectToPeerTask = CreatePeerConnection(connectToPeerCancelationTokenSource.Token);
bool connectResult = await connectToPeerTask;
connectToPeerTask = null;
connectToPeerCancelationTokenSource.Dispose();
if (!connectResult)
{
Debug.WriteLine("[Error] Conductor: Failed to initialize our PeerConnection instance");
await Signaller.SignOut();
return;
}
else if (_peerId != peerId)
{
Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
return;
}
}
}
else
{
Debug.WriteLine("[Warn] Conductor: Received an untyped message after closing peer connection.");
return;
}
}
if (!String.IsNullOrEmpty(type))
{
if (type == "offer-loopback")
{
// Loopback not supported
Debug.Assert(false);
}
string sdp = jMessage.ContainsKey(kSessionDescriptionSdpName) ? jMessage.GetNamedString(kSessionDescriptionSdpName) : null;
if (String.IsNullOrEmpty(sdp))
{
Debug.WriteLine("[Error] Conductor: Can't parse received session description message.");
return;
}
RTCSdpType sdpType = RTCSdpType.Offer;
switch (type)
{
case "offer":
sdpType = RTCSdpType.Offer;
break;
case "answer":
sdpType = RTCSdpType.Answer;
break;
case "pranswer":
sdpType = RTCSdpType.Pranswer;
break;
default:
Debug.Assert(false, type);
break;
}
Debug.WriteLine("Conductor: Received session description: " + message + "\r\n" + sdp);
await _peerConnection.SetRemoteDescription(new RTCSessionDescription(sdpType, sdp));
if (sdpType == RTCSdpType.Offer)
{
RTCSessionDescription answer = await _peerConnection.CreateAnswer();
await _peerConnection.SetLocalDescription(answer);
// Send answer
SendSdp(answer);
Debug.WriteLine(String.Format("Conductor: Session Description to be sent : {0}", answer.Sdp));
}
}
else
{
var sdpMid = jMessage.ContainsKey(kCandidateSdpMidName) ? jMessage.GetNamedString(kCandidateSdpMidName) : null;
var sdpMlineIndex = jMessage.ContainsKey(kCandidateSdpMlineIndexName) ? jMessage.GetNamedNumber(kCandidateSdpMlineIndexName) : -1;
var sdp = jMessage.ContainsKey(kCandidateSdpName) ? jMessage.GetNamedString(kCandidateSdpName) : null;
if (String.IsNullOrEmpty(sdpMid) || sdpMlineIndex == -1 || String.IsNullOrEmpty(sdp))
{
Debug.WriteLine("[Error] Conductor: Can't parse received message.\n" + message);
return;
}
var candidate = new RTCIceCandidate(sdp, sdpMid, (ushort)sdpMlineIndex);
await _peerConnection.AddIceCandidate(candidate);
Debug.WriteLine("Conductor: Received candidate : " + message);
}
}).Wait();
}
Related
In my case I want to send the message to all sessions not only user (user can have many sessions), I used foreach to send message to all connections belong to friends with its others sessions,
there is a problem in await asynchronous and a message:
Failed writing message. Aborting connection. System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOption
// Test if the user is offline :
// Find My opened sessions and target opened sessions
if (userInfoReciever != null)
{
var targetSessions = _context.Connections.Where(C => (C.Username == targetUserModel.UserName) && (C.Connected == true)).ToList();
if (targetSessions != null)
{
foreach (var targetSeesion in targetSessions)
{
await Clients.Client(targetSeesion.ConnectionID).SendAsync("SendDM", messageModel, userInfoSender);
await Clients.Client(targetSeesion.ConnectionID).SendAsync("SendDN", notificationModel, userInfoSender);
}
}
}
await Clients.Caller.SendAsync("MyMessage", messageModel, userInfoSender);
if (userInfoSender != null)
{
var mySessions = _context.Connections.Where(C => ((C.ConnectionID != Context.ConnectionId) && (C.Username == Context.User.Identity.Name) && (C.Connected == true))).ToList();
if (mySessions != null)
{
foreach(var mySession in mySessions)
{
await Clients.Client(mySession.ConnectionID).SendAsync("MyMessage", messageModel, userInfoSender);
}
}
}
// Send my message to the the others sessions :
// Build the message
var _message = _mapper.Map<MessageViewModel,Message>(messageModel);
var _notification = _mapper.Map<NotificationViewModel, Notification>(notificationModel);
await _context.Messages.AddAsync(_message);
await _context.Notifications.AddAsync(_notification);
await _context.SaveChangesAsync();
So I have this giant monstrosity of code, which works as expected, goes to the respective URL and if it's not a URL it goes to search for the string(s). The problem is
the websites that are down but exist or don't give a response are deemed as not a URL and therefore are being searched for instead
pinging the same site too many times leads to being blocked, eg google.
The ping method takes too long to respond.
[...]
try
{
timer1.Start();
if (SearchBox.Text.Contains(SearchBox.Text.ToString()))
{
if (webView21 != null && webView21.CoreWebView2 != null)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 0;
PingReply reply = pingSender.Send(SearchBox.Text.ToString(), timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
if (SearchBox.Text.StartsWith("https://"))
{
webView21.CoreWebView2.Navigate(SearchBox.Text);
}
else if (SearchBox.Text.StartsWith("http://"))
{
webView21.CoreWebView2.Navigate(SearchBox.Text);
}
else
{
webView21.CoreWebView2.Navigate("https://" + SearchBox.Text);
}
}
else
{
webView21.CoreWebView2.Navigate("https://duckduckgo.com/?q=" + SearchBox.Text + "&t=h_&ia=web");
}
}
}
else if (SearchBox.Text.StartsWith("https://"))
{
if (webView21 != null && webView21.CoreWebView2 != null)
{
webView21.CoreWebView2.Navigate(SearchBox.Text);
}
}
else if (SearchBox.Text.StartsWith("http://"))
{
if (webView21 != null && webView21.CoreWebView2 != null)
{
webView21.CoreWebView2.Navigate(SearchBox.Text);
}
}
else
{
if (webView21 != null && webView21.CoreWebView2 != null)
{
webView21.CoreWebView2.Navigate(SearchBox.Text);
}
}
}
catch
{
timer1.Start();
webView21.CoreWebView2.Navigate("https://duckduckgo.com/?q=" + SearchBox.Text + "&t=h_&ia=web");
}
}
Does anybody know how I could improve on this? How can I make my web browser more efficient at this. Regex maybe?
TBH i think you can replace your whole code with something like this:
string userInputtedString = SearchBox.Text;
// CHeck for a valid URI.
Uri uriResult;
bool validUrlResult = Uri.TryCreate(userInputtedString, UriKind.Absolute, out uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
if (validUrlResult)
{
webView21.CoreWebView2.Navigate(userInputtedString);
}
else
{
// We haven't gotten a valid url, so we're gonna search instead.
webView21.CoreWebView2.Navigate("https://duckduckgo.com/?q=" + userInputtedString + "&t=h_&ia=web");
}
EDIT:
Apparently Uri requires a scheme (http:// or https:// or file:// etc) for the Uri class to be constructed. Hence why google.com fails - the browser automatically adds the http(s):// scheme which is why it works if you type it in the browser.
I think for your case you can try the other answers:
bool IsValidURL(string URL)
{
string Pattern = #"^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]#!\$&'\(\)\*\+,;=.]+$";
Regex Rgx = new Regex(Pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
return Rgx.IsMatch(URL);
}
So that would become something like:
string userInputtedString = SearchBox.Text;
// CHeck for a valid URI.
Uri uriResult;
bool validUrlResult = IsValidURL(userInputtedString);
if (validUrlResult)
{
webView21.CoreWebView2.Navigate(userInputtedString);
}
else
{
// We haven't gotten a valid url, so we're gonna search instead.
webView21.CoreWebView2.Navigate("https://duckduckgo.com/?q=" + userInputtedString + "&t=h_&ia=web");
}
Check if that improves your use-case.
Background:
My program starts up and it must obtain the IP address of the machine it is running on.
It is the "server" in a client-server architecture that receives incoming tcp-ip messages.
I should also add the machine :
Has multi-ip addresses available
Is running Windows 2008 R2 Server
Here is the code that obtains the IP address:
public bool IsNetworkAvailable
{
get
{
return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
}
}
public string thisIP { get; private set; }
public void GetThisIP()
{
if (!string.IsNullOrEmpty(thisIP))
{
return;
}
thisIP = "*";
if (IsNetworkAvailable)
{
using (System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Dgram, 0))
{
socket.Connect("11.0.1.5", 65530);
System.Net.IPEndPoint endPoint = socket.LocalEndPoint as System.Net.IPEndPoint;
thisIP = endPoint.Address.ToString();
}
}
}
Here is the error message:
(0x80004005): A socket operation was attempted to an unreachable network 11.0.1.5:65530
at System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port)
SOLUTION:
I have changed my code to what rodcesar.santos suggested in this:
Get local IP address
here is my (modified) code (and it works)
System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";
After reading the accepted answer # A socket operation was attempted to an unreachable host,
I assume that the specific client-computer than receives this error has a somewhat faulty network.
Quoting #Stephen Cleary
This error indicates that the network was not connected or not configured correctly. It is definitely an error on the client machine, not your server.
There isn't much you can do to "solve" the problem. Pretty much all you can do is upgrade the client's network drivers and check for connection problems (maybe they're barely within wireless range, or the Ethernet cable is missing its locking tab).
System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";
I'm making a Discord bot and there's a channel in my server allocated to our rules and I want this bot to automatically send a message in that channel. Is it possible to check if the channel exists? Thanks.
Yes you definitely can.
if (message.Content.StartsWith("!check"))
{
SocketGuildChannel currentChannel = message.Channel as SocketGuildChannel;
SocketGuild guild = currentChannel.Guild;
foreach (SocketGuildChannel ch in guild.Channels)
{
if (ch.GetType() == typeof(SocketTextChannel)) //Checking text channels
{
if (ch.Name.Equals("rules"))
{
ISocketMessageChannel channel = (ISocketMessageChannel)ch; //Casting so we can send a message
await channel.SendMessageAsync("This is the rules channel.");
return;
}
}
}
await message.Channel.SendMessageAsync("Could not find the rules channel.");
return;
}
Assuming you are using Discord.Net 1.0.2
If you want to have it as a command:
[Command("check")]
public async Task CheckChannel(string channel)
{
foreach (SocketGuildChannel chan in Context.Guild.Channels)
{
if (channel == chan.Name)
{
// It exists!
ITextChannel ch = chan as ITextChannel;
await ch.SendMessageAsync("This is the rules channel!");
}
else
{
// It doesn't exist!
await ReplyAsync($"No channel named {channel} was found.");
}
}
}
You could also use Linq!
[Command("check")]
public async Task CheckChannel(string channelName)
{
//Makes the channel name NOT case sensitive
var channel = Context.Guild?.Channels.FirstOrDefault(c => string.Equals(c.Name, channelName, StringComparison.OrdinalIgnoreCase));
if (channel != null)
{
ITextChannel ch = channel as ITextChannel;
await ch.SendMessageAsync("This is the rules channel!");
}
else
{
// It doesn't exist!
await ReplyAsync($"No channel named {channel} was found.");
}
}
Also a warning, This will fail in a DM because Context.Guild == null in a direct message. If you so desired, you can add this snippet inside your command!
if (Context.IsPrivate)
{
await ReplyAsync("Cant call command from a direct message");
return;
}
I have this line which needs to recieve a message from the discord text channel.
choice = video[int.Parse(CommandHandler.message .Content)-1].Url;
I tried a lot of things, including searching in the api but I don't have a clue.
Here is the command
[Command("join", RunMode= RunMode.Async), Summary("joins voice channel")]
public async Task joinvoice([Remainder, Summary("The text to echo")] string searchP="")
{
IVoiceChannel voicechannel = (CommandHandler.Last as IGuildUser).VoiceChannel;
if (voicechannel == null)
{
await ReplyAsync("u have to be in a channel first");
return;
}
string choice = "";
VideoSearch SearchRisolts = new VideoSearch();
if (searchP != "")
{
if (searchP.Contains("https://"))
choice = searchP;
else
{
List<VideoInformation> video = SearchRisolts.SearchQuery(searchP, 1);
await ReplyAsync("1) " + video[0].Title + "\n\n2) " + video[1].Title + "\n\n3) " + video[2].Title);
choice = video[int.Parse(CommandHandler.message .Content)-1].Url;//here i need to recive a message from the chat
}
}
if (voicechannel != Program.voicechannel)
{
Program.audioClient = await voicechannel.ConnectAsync();
Program.voicechannel = voicechannel;
}
if (Program.audioClient!=null)
await SendAsync(Program.audioClient, choice);
}
The class containing this function should derive from BaseModule<ICommandContext>
This BaseModule contains the Context, which in place contains the message you are looking for.
Context.Message.Content