C# Server to Android Client Behind the NAT - c#

I need to establish a connection from a public ip server implemented in c sharp to an android device behind the NAT and I was able to got SPD message from the android device using ICE4j library using this code
String toSend = SdpUtils.createSDPDescription(agent); //Each computer sends this information
and I got the following message
v=0
o=ice4j.org 0 0 IN IP4 192.168.1.14
s=-
t=0 0
a=ice-options:trickle
a=ice-ufrag:dikj41a5eequb2
a=ice-pwd:3t07qqjndu5pkneh53c6kqti3l
m=audio 5000 RTP/AVP 0
c=IN 192.168.1.14 IP4
a=mid:audio
a=candidate:1 1 udp 2130706431 fe80::1afe:34ff:fe29:c233 5000 typ host
a=candidate:2 1 udp 2130706431 192.168.1.14 5000 typ host
a=candidate:3 1 udp 1677724415 91.93.202.127 5000 typ srflx raddr 192.168.1.14 rport 5000
and the server stores this message so my question is what I have to do to establish a connection from the server to the android device using these information

Related

c# : UDPClient not receiving multicast from one of the Network Adapters

I would like to test Receive of multicast messages using UDP Client
I have two network adapters.
Network 1: with local IP : 10.239.1.1 [Multicast Group : 224.1.1.1 : 42333]
Network 2 : with local IP : 172.4.1.1 [Multicast Group : 224.0.1.1 : 42333]
Note : I can see all the multicast on wire shark
In my program I created and joined the multicast group as bellow.
_LocalUDPClient = new UdpClient(new IPEndPoint(_localIpAddress, _multiCastPort));
_LocalUDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_LocalUDPClient.JoinMulticastGroup(_multicastIpAddress, _localIpAddress);
_LocalUDPClient.BeginReceive(new AsyncCallback(ReceiveCallBack), null);
Network 1 :
_localIpAddress = 10.239.1.1
_multicastIpAddress = 224.1.1.1
_multiCastPort = 42333
I receive multicast message successfully.
BUT
Network 2 :
_localIpAddress = 172.4.1.1
_multicastIpAddress = 224.0.1.1
_multiCastPort = 42333
Not receiving any Multicast data.
It is not a c# code issue, It is Firewall issue.
open firewall and network protection under system settings
You should be able to see your .exe under "Allow an app through firewall".
In my case I can see it 3 times with different settings.
I deleted all and added manually my program .exe with allow for all network types, I got multicasts now.

Simple Webrtc relay bridge Server in C#

I have a fully working peerTopeer (P1, P2) webRTC. To handle peerTopeer failures, I am trying for a simple exchange of bytes via a server in c# between P1 and P2 on a windows machine, as I don't want to develop a turn server by specs. I have also tried to find an open source c# server turn server with turn message but its not working (able to parse request but response seems to be not accepted by latest chrome/MS Edge chromium based)
Simple C# relay bridge server:
With simple udp/tcp listener and exchange of bytes with peers, (P1 to P2 and P2 to P1) and forcing bridge machine IP as candidate I am able to achieve connections and streaming data (bytes) are exchanged.
However unable to see video/hear audio on peers and also after some exchange, the connections are dropped with connectionState failed on the client side.
Q1. It should have worked, what is going wrong?
Q2. Any opensource c# implementation of stun and turn (simple one)?
I appreciate any help in this regard.
Server and Client code samples:
Listen to tcp / udp(not in sample)
public void ListenTCP(int port) {
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true){
TcpClient tcpClient = listener.AcceptTcpClient();
..........add endpoint to list
var bytes = readfromtcpstream.......;
Task.Run(() => ProcessData(tcpClient.Client.RemoteEndPoint, bytes));
}
}
ProcessData (exchange stream bytes)
private void Process_DATA(IPEndPoint fromEndPoint, byte[] bytes) {
foreach (var endpoint in list) { //distribute to all other peers
if (endpoint == fromEndPoint) continue;
endpoint's TCPClient.Send(bytes);
}
}
On the client side (Javascript / typescript), forcing the candidate as bridge server
SignalType.Candidate...
candidate = new RTCIceCandidate(Switch the SDP(messageJson.candidate,
BridgeServerAddress, "2525", "tcp"));
m_PeerConnection.addIceCandidate(candidate)
Simply modifying the ice candidate you got from P2P is unlikely to work since TCP candidates work a bit differently. And a TURN server is very different from a simple bridge.
The following SDP contains a TCP candidate with tcptype passive which will make the other side establish a connection to it. Feed it into setRemoteDescription, then create an answer and call setLocalDescription with the answer.
v=0
o=- 2576067654554894849 3 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2698387310 1 tcp 25042943 127.0.0.1 31337 typ host tcptype passive generation 0
a=ice-ufrag:server
a=ice-pwd:Kv6yCw1HiZ1/6uNExYcE28pO
a=fingerprint:sha-256 22:46:36:8D:B1:CD:08:7B:A1:60:86:BF:95:90:06:4B:EA:47:D9:74:24:FF:6D:2F:1C:09:5B:C1:F5:8D:CC:B2
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
The browser should establish a connection to port 31337 on localhost (note that Firefox doesn't allow localhost ICE by default so try this in Chrome first).
From there, you'll have to process ICE, decrypt SRTP etc.

Can't bind DatagramSocket on "0.0.0.0"

in Win RT we have to use DatagramSocket instead of UdpClient. Ok but the following code gives me this error which I don't get on UdpClient.
var g = new DatagramSocket();
g.MessageReceived += g_MessageReceived;
await g.BindEndpointAsync(new HostName("0.0.0.0"), "5000"); //<--- this line
*IPAddress.Any = 0.0.0.0
I get this Error:
"No such host is known. (Exception from HRESULT: 0x80072AF9)"
To bind to all local interfaces (the way binding 0.0.0.0 aka INADDR_ANY does with the Berkeley Sockets API), use BindServiceNameAsync.
The BindServiceNameAsync method binds to the local IP addresses of all network interfaces on the local computer on the local service name or UDP port specified in the localServiceName parameter. If the localServiceName parameter is an empty string, the system will select the local UDP port on which to bind.

TCP Socket Sending Delays and Retransmission

I have a .NET 3.5 C# application that sends 2000-6000 byte packets to a linux machine running sles 10. The machines are on the same subnet.
About 90% of the time, everything works fine. The linux machine processes my request and responds in 5-15ms. But about 10% of the time, there is an approx 200ms-800ms delay.
Looking at the logs on the linux machine, it seems the delay is on my end. That is, if my call to socket.Send(...) returns at 1:15:00.000 and I get a response at 1:15:00.210, the log on the linux machine says that it received the request at 1:15:00.200 and then processed it in 10ms. (I'm using System.Diagnostics.Stopwatch for timing on my machine.)
To debug, I captured the traffic using wireshark. Here is the traffic. Between No. 8 and 9 is where a 600 ms delay occurs. (137.34.210.108 is my machine and 137.34.210.95 is the linux machine).
"1","11:56:27.380318","137.34.210.95","137.34.210.108","TCP","20700 > 17479 [PSH, ACK] Seq=1 Ack=1 Win=32767 Len=76"
"2","11:56:27.380393","HewlettP_29:37:0f","Broadcast","ARP","Who has 137.34.210.95? Tell 137.34.210.108"
"3","11:56:27.380558","HewlettP_29:39:93","HewlettP_29:37:0f","ARP","137.34.210.95 is at 00:1b:78:29:39:93"
"4","11:56:27.380564","137.34.210.108","137.34.210.95","TCP","17479 > 20700 [ACK] Seq=1 Ack=77 Win=65459 [TCP CHECKSUM INCORRECT] Len=0"
"5","12:04:48.096892","HewlettP_29:37:0f","Broadcast","ARP","Who has 137.34.210.95? Tell 137.34.210.108"
"6","12:04:48.097216","HewlettP_29:39:93","HewlettP_29:37:0f","ARP","137.34.210.95 is at 00:1b:78:29:39:93"
"7","12:04:48.097229","137.34.210.108","137.34.210.95","TCP","17480 > 20600 [PSH, ACK] Seq=1 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=458"
"8","12:04:48.097457","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=4294964377 Win=32767 Len=0 SLE=1 SRE=459"
"9","12:04:49.700966","137.34.210.108","137.34.210.95","TCP","17479 > 20700 [ACK] Seq=1 Ack=77 Win=65459 [TCP CHECKSUM INCORRECT] Len=1460"
"10","12:04:49.701190","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [ACK] Seq=4294964377 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=1460"
"11","12:04:49.703970","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=4294965837 Win=32767 Len=0 SLE=1 SRE=459"
"12","12:04:49.703993","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [ACK] Seq=4294965837 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=1460"
"13","12:04:49.704002","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [PSH, ACK] Seq=1 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=458"
"14","12:04:49.704211","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=459 Win=32767 Len=0"
"15","12:04:49.704215","137.34.210.95","137.34.210.108","TCP","[TCP Dup ACK 14#1] 20600 > 17480 [ACK] Seq=1 Ack=459 Win=32767 Len=0 SLE=1 SRE=459"
"16","12:04:49.705425","137.34.210.95","137.34.210.108","TCP","20700 > 17479 [PSH, ACK] Seq=77 Ack=1461 Win=32767 Len=44"
Can someone help me to interpret this? I see that a re-transmit is occurring. But I'm not sure why. The switch shows no dropped packets. And even if the packets are being lost, why would it take 600ms to re-transmit?
I thought that this (http://support.microsoft.com/kb/328890) might have something to do with the 200ms delays but I've tried changing the TcpAckFrequency and it didn't help.
Thanks,
Mike
Let's start by pruning some of that Wireshark output. We can toss the ARPs in packets 2, 3, 5 and 6. Looking at the rest, you have two sets of traffic in there. Packets 8 and 9 are two different connections, so you can't compare them. 7, 8 and 10, however, are part of one connection so let's examine those.
Packet 7 is 458 bytes of data being sent to the Linux box with a TCP sequence number of 1. However, the ACK that the Linux box returns is 4294964377. This means that Wireshark is showing relative TCP values and that the Linux box is not sending an ACK for packet 7, but for an earlier packet. Your PC then waits for a follow-up ACK and, when it doesn't get one, retransmits the required data. In this case the 458 bytes from packet 7 along with a previous 1002 bytes. That's why the sequence number from packet 10 matches the ACK from packet 8.
Unfortunately this doesn't tell you why data is being dropped. Packet 8 shows the Linux box indicating it still has a full 32k of input buffer available for this connection ("Win=32767").
This only shows the TCP packets on the Linux machine, but I'd recommend to look at the ip stats with the 'netstat -s' command. One reason for the retransmissions might be socket buffer overflows, which will be shown with this command.
I don't recall if Windows has it, but on UNIX you'd enable TCP_NODELAY.
This disables TCP's Nagle Algorithm which makes the system wait for a small time in case more data is going to be added to the transmit buffer.
int nodelay = 1;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));

How to validate SMTP server

I am working on a project where I have to validate the given SMTP server i.e in a textbox user will provide the detail and then he will click on a test button. I want to check whether the server entered by the user is an Smtp Server or not?
Any Idea??
You might want to improve on this quick code with proper exception handling and maybe also setting the timeouts - it takes about 15 seconds to fail if it can't connect but that might be a limitation of the TCP/IP handshaking.
And sending a QUIT command as Curt suggested would be nice.
private bool ValidSMTP(string hostName)
{
bool valid = false;
try
{
TcpClient smtpTest = new TcpClient();
smtpTest.Connect(hostName, 25);
if (smtpTest.Connected)
{
NetworkStream ns = smtpTest.GetStream();
StreamReader sr = new StreamReader(ns);
if (sr.ReadLine().Contains("220"))
{
valid = true;
}
smtpTest.Close();
}
}
catch
{
}
return valid;
}
Attempt to connect to the SMTP port, and ensure you get a line back from it that starts with "220 " and contains the letters "SMTP". A typical example response would be:
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
Then be polite and send "QUIT\r\n" to hang up.
You can do some further testing, if you like, such as testing that the user can likely deliver messages. For this, you'd send a HELO command with your hostname (or any string, really), a MAIL FROM command using the user's e-mail address, and a RCPT TO:<example#example.com>. Most servers at that point will tell you if relaying is not allowed. (I'm assuming you're doing this from the computer from which you will later be sending mail.) So long as you QUIT after that, rather than issuing a DATA command and
the message data, nothing will be sent.
Here's an example session, done from the shell using the "netcat" command, showing that my server exists, but will not relay mail for people from random IP addresses.
$ nc prod.monadic.cynic.net. 25
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
HELO cynic.net
250 prod.monadic.cynic.net
MAIL FROM:<cjs#cynic.net>
250 2.1.0 Ok
RCPT TO:<example#example.com>
554 5.7.1 <example#example.com>: Relay access denied
QUIT
221 2.0.0 Bye
$

Categories