I am trying inialise a tls tunnel with the .net SslStream but after opening the stream I always get the following error:
"Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
After I establish a tls connection and after sending a second message.
I've been searching for an answer for the last four days but there isn't any helpful information online!
edit:
I am trying to connect to talk.google.com
and I'm using the code sample from MSDN. Only difference is that I'm sending data before and when it is time to use tls i do the following:
public void SecureStream()
{
netStream.Flush();
sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient("talk.google.com");}
edit: I managed to eliminate the first error (small bug on how i was handling the send) now I always get
"Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
edit2: Im not sending any whitespaces I rewrote the message passing part and I still have the same problem.
I start with
String streamInit = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='google.com' version='1.0'>";
client.Send(streamInit);
Then on receive I have the following
static void client_MessageReceived(SyncronousClient source, string Result)
{
if (Regex.IsMatch(Result, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"><required/></starttls>"))
{
String startTlS = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
source.Send(startTlS);
}
else if (Regex.IsMatch(Result, "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"))
{
//Do TLS Magic
source.SecureStream();
String streamReInit = "<stream:stream xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'to='google.com'version='1.0'>";
source.Send(streamReInit);
}
else if (Regex.IsMatch(Result, "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"))
{
//String AuthType = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-GOOGLE-TOKEN'/>";
String AuthType = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"/>";
source.Send(AuthType);
}}
It's unlikely to be your problem (unless .Net has started doing SNI under the covers), but when you call AuthenticateAsClient, pass in the same domain name that you used in your stream's to attribute (in this case, google.com). As well, you might need gmail.com instead of google.com:
sslStream.AuthenticateAsClient("gmail.com", null, SslProtocols.Tls, false);
As csharptest.net alluded to, make sure you don't have a keepalive timer that sends extra whitespace, or wait to start the timer until after TLS works. The only other way I can imagine your getting that error is if you don't have a ciphersuite that the server implements, but I know the .Net SslStream works against GTalk.
Lastly, use one of the existing .Net libraries for XMPP (there are 5 listed here), and you can start writing much more fun code right away. You're about to run into the inadequacies of the .Net XML system, and your regex-based approach won't work when you start getting partial stanzas or multiple stanzas in a single read.
That really doesn't make sense to me. The server, if using SSL, requires that the client perform the SSL handshake upon connection. Thus, I'm not sure what you mean by "I'm sending data before...". It sounds like your not immediately calling the AuthenticateAsClient. If this is the case, I suspect that is your problem. AFAIK, you cannot use the same socket/connection connection for both SSL and non-SSL communications. Either the server requires SSL, or it does not support it, it should never do both.
My previous answer above was in ignorance. Indeed it appears that the standard does in fact require that the connect send and receive data prior to the initialization of the SSL handshake. Really odd that they would do that... but whatever. After briefly reading through parts of the RFC it appears that you are expected to begin the SSL client auth immediately after the closing '>'. No trailing whitespace allowed which may be your problem?
Related
I'd like to provide my TCP/IP client class with a CheckConnection function so that I can check if something wrong has happened (my own client disconnected, server disconnected, server stuck up,...).
I have something like that:
bool isConnectionActive = false;
if (Client.Poll(100000, SelectMode.SelectWrite) == true)
isConnectionActive = true;
based on what MSDN says:
SelectWrite: true, if processing a Connect(EndPoint), and the connection has succeeded; -or- true if data can be sent; otherwise, returns false.
The point is that, testing this with simple server application, I am getting always true from CheckConnection, even if server-listener has been closed and even if server-application has been shutdown; that's weird, because I expect in those cases that both no connection is being processed (already connected minutes ago) and no data can be sent.
I have already implemented a similar connection check on server side using a combination of Poll with SelectRead and Available and it seems working properly; so now, should I write something similar also on client side? is the SelectWrite approach correct (but I'm using it improperly)?
There are lots of things you can check but none of them are assured to give you the result you are looking for. Even the implementation you have on the server will not work 100% of the time. I guarantee it will fail one day.
There are FIN packets, which should be sent from the client to the server, and vice versa when a connection is closed, but there is no guarantee that these will be delivered, or even processed.
This is generally known as the TCP Half Open problem.
Closing a TCP Socket is a mutually agreed process, you generally have a messaging protocol which tells the other end that it's closing, or you have some predefined set of instructions and you close after that.
The only reliable way to 100% detect if a remote socket is closed is to send some data to it. Only if you get an error back will you know if the socket has closed.
Some applications which don't send a lot of data implement a keep-alive protocol, they simply send/receive a few bytes every minute, so they know that the remote endpoint is present.
You can technically have two servers that are in a connected state and haven't sent data to each other for 10 years. Each end continues to believe that the other end is there until one try's to send some data and finds out it isn't.
I've tried a few methods at this point to pull this website and stuff it into a variable to later be parsed, and all of them have thrown the same errors:
IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.
SocketException: An established connection was aborted by the software in your host machine
So far I've tried WebClient.DownloadString() in the .Net lib, something similar in the .Net.Http lib, as well as the HtmlDocument.Load() from the HtmlAgilityPack lib all with the same result. In the .Net lib I've tried the commonly suggested solution of disabling keepalive, and am just assuming at this point that there is some setting on my computer causing this.
Any ideas? And thanks in advance for reading. =)
Here is my current code:
string tcgpSite;
using (var wc = new System.Net.WebClient())
tcgpSite = wc.DownloadString("http://shop.tcgplayer.com/magic?newSearch=true");
Console.WriteLine(tcgpSite);
It could be a probably with the way your using statement is set up in your actual code.
The following works for me:
var wc = new System.Net.WebClient()
string tcgpSite = wc.DownloadString("http://shop.tcgplayer.com/magic?newSearch=true");
As does the code you posted.
Otherwise, you may have some kind of fire wall or other network issue closing your connection. The error seems to indicate the same.
SocketException: An established connection was aborted by the software in your host machine.
Try temporarily disabling any firewall or anti virus your machine might be running.
I have a TCPClient that creates a stream that I read from when DataAvailable.
Every 20 seconds that !DataAvailable I ping the socket with an ACK message to keep the stream from closing.
But I seem to be getting mixed results. It seems like every other time I open the stream(basically restart my Service) I get transport errors.
This is a shortened version of my Connect function:
client = new StreamClient();
client.Connect(new IPEndPoint(clientAddress, senderPort));
stream = client.GetStream();
bool status = SendMessage(seq, sync, MessageTypes.Init);
The SendMessage function does:
if (stream == null) return false;
stream.Write(TransmitBuffer, 0, TransmitMessageLength);
My Close function does:
if (stream != null)
{
SendMessage(seq, sync, MessageTypes.Finish);
stream.Close();
}
stream = null;
client.Close();
client = null;
It is expected that the SendMessage calls will fail occasionally due to nature of the socket.
But sometimes, once I Connect, everything runs fine, no failed messages. But other times the ACK's will fail. When the ACK's fail, I call Close, which will force a Connect and validate the other end of the socket is open. If that fails then I know that end is down. But sometimes that call doesn't fail and then 20 seconds later the ACK does.
Can anyone give me an opinion on why this may happen? Is 20 seconds too long to wait? Am I not closing my end of the socket properly?
The specific error message i'm fighting with is:
Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.
And it occurs at stream.Write(TransmitBuffer, 0, TransmitMessageLength);
The main thing I see in your implementation that jumps out at me is that it looks like you're treating the Stream as the Connection, and it isn't. Your checks on the Stream instance should instead be checks on the TcpClient instance. I'm not sure if that's the source of your problem, but it definitely looks strange to me.
Instead of this:
stream = client.GetStream();
if (stream != null)
{
SendMessage(seq, sync, MessageTypes.Finish);
stream.Close();
}
stream = null;
I usually do something more like this:
if (client != null)
{
if (client.Connected)
{
client.GetStream().Close();
}
client.Close();
client = null;
}
You should be checking TcpClient.Connected before working with the stream, not the stream itself.
Another thing I would mention is to be sure to always use the async methods to connect, read, and write with your TcpClient. The synchronous ones are easier, but my experience has been that relying on them can get you into trouble.
In general, putting a protocol on top of TCP is a big mistake. It can only make the connection less reliable. TCP already makes a very strong guarantee that data sent from one machine is going to be received by another one on a network. Only very gross external circumstances can make that fail. Things like equipment power loss or unscheduled reboots.
A connection should not be broken unless one of the machines intentionally closes the socket. Which should of course always be done in a predictable way. A logical end to a transaction or an explicit message that a machine is signing-off.
You didn't give any motivation for adding this "ACK protocol" to your connection logic, other than "keep the stream from closing". I think what you are seeing here is that it just doesn't work, it does not in fact keep the stream from closing. So it still goes wrong like it did before you added the protocol layer, you are still getting unexpected "An established connection was aborted" exceptions.
An example of how you made it less reliable is the 20 second timeout check you added. TCP doesn't use a 20 second timeout. It uses an exponential back-off algorithm to check for timeouts. Typically it doesn't give up until at least 45 seconds have passed. So you'll declare the connection dead before TCP does so.
Hard to give advice on how to move forward with this. But clearly it is not by adding a protocol, you tried it and it did not work. You will have to find out why the connection is getting broken unexpectedly. Unfortunately that does require leg-work, you have to get insight in the kind of network equipment and software that sits between your machine and the server. With some expectation that the problem is located at the other end of the wire since that's the one that's hardest to diagnose. Getting the site's network admin involved with your problem is an important first step.
We had a similar problem when developing a network communication library. Rather than use ACK we found the most reliable solution was just to send some null data (aka keep alive). In this case byte[1] with a zero value. This would result in either:
A successful send and the data could be ignored on the
receive end.
A failed send which would immediately cause the connection to be closed and reestablished.
Either of these outcomes ensured the connection was always in a useable state.
Why do you send ACK? You should send SYN.
And you shouldn't send ACK, SYN, RST or setting any other flag for that matter. You're dabbling with TCP internals. You're creating Application level protocol and keeping-alive is part of that, cause, iirc, even there is http://msdn.microsoft.com/en-us/library/windows/desktop/ee470551%28v=vs.85%29.aspx connection will be open until you close it.
These errors are getting more and more frequent on my Game Server. They are causing the server to keep closing and restarting...
System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at iRP.Game.Sessions.Session.SendData(Byte[] Data)
This is the code from which these errors are generated:
public void SendData(byte[] Data)
{
try
{
if (mSocket == null)
{
//Output.WriteLine("[SND] Socket has a null exception, which means it is now invalid. Remove this socket!", OutputLevel.CriticalError);
}
else
{
mSocket.BeginSend(Data, 0, Data.Length, SocketFlags.None, sendCallback, mSocket);
}
}
catch (Exception e)
{
string WhatToWrite = "Error handled (SESSION): " + e.ToString() + "\n\n" + e.Message + "\n\nStack: " + e.StackTrace + Environment.NewLine + "\n\n";
File.AppendAllText(Environment.CurrentDirectory + "\\data\\fatal.txt", WhatToWrite);
Program.Stop();
}
}
The buffer sizes are correctly set, we are using KeepAlive on the socket and were using Send and Receive Timeouts.
People suggested that disabling the firewall would help, but whenever I do this our Game Server (Dedicated Server) restarts itself as if it's under attack, so the firewall must remain enabled.
Anyone else got any other solutions for this?
PS: We are behind DDoS Mitigation Services which may be limiting the number of connections...
An established connection was aborted by the software in your host machine
That is a boiler-plate error message, it comes out of Windows. The underlying error code is WSAECONNABORTED. Which really doesn't mean more than "connection was aborted". You have to be a bit careful about the "your host machine" part of the phrase. In the vast majority of Windows application programs, it is indeed the host that the desktop app is connected to that aborted the connection. Usually a server somewhere else.
The roles are reversed however when you implement your own server. Now you need to read the error message as "aborted by the application at the other end of the wire". Which is of course not uncommon when you implement a server, client programs that use your server are not unlikely to abort a connection for whatever reason. It can mean that a fire-wall or a proxy terminated the connection but that's not very likely since they typically would not allow the connection to be established in the first place.
You don't really know why a connection was aborted unless you have insight what is going on at the other end of the wire. That's of course hard to come by. If your server is reachable through the Internet then don't discount the possibility that you are being probed by a port scanner. Or your customers, looking for a game cheat.
This problem appear if two software use same port for connecting to the server
try to close the port by cmd according to your operating system
then reboot your Android studio or your Eclipse or your Software.
Could be related to the maximum number of concurrent requests. I was able to fix it with two solutions:
Increase the default limit of the max concurrent connections (by default it is set to 2):
ServicePointManager.DefaultConnectionLimit = 25
Wrap sending requests around a buffer: could use ConcurrentQueue to limit the rate, or implement a simple wait as the following:
while (activeRequests >= maxConcurrentRequests)
Thread.Sleep(1000);
Interlocked.Increment(ref activeRequests);
var response = await _client.GetStreamAsync(endpoint);
Interlocked.Decrement(ref activeRequests);
While the answer from Hans is an excellent high level summary of the error that worked great for getting me started, I ended up finding a page that explained the root cause well enough that I was able to recreate it with a python script.
The page presents a couple different descriptions of this error that are more detailed than the "connection was aborted" paraphrasing from Hans's answer but still pretty cryptic and not very informative.
The post then explains this scenario that would produce the error:
An HTTP POST is to be sent to an HTTP server.
The server begins reading the POST and notices that the HTTP request header is invalid.
It immediately sends an HTTP response (with an error status, perhaps status=400) and closes the connection without trying to continue reading the remainder of the HTTP request that is forthcoming.
Meanwhile, the client is still happily writing the remainder of the HTTP request to the socket. (Remember a TCP/IP socket connection needs to be closed from both sides. In this case, the server has closed its side, but the client is still pumping data into the half-open connection.)
The client finishes writing the HTTP POST to the socket — meaning that data has been buffered to Winsock. The client application then tries to read the HTTP response, but it cannot because the outgoing retransmission (of the buffered data by WinSock) failed and the socket connection was shutdown on the client side (by Winsock). Even though the HTTP server sent the response, it is lost and cannot be retrieved. The error your application will receive when trying to read the HTTP response on the socket is WSAECONNABORTED
Wikipedia also has a page to explain what winsock is, but all you really need to know for this scenario is that its the Windows socket API.
I had "ManageEngine Agent" installed on my computer, which was blocking my connection to the databases, so uninstalling it was the solution.
Check which application could block the connection to your DB.
I am trying to create a simple xmpp client that connects to Gtalk.
The first part of the handshake seems to work.
Ror the TLS handshake I created a client SslStream, connected to the intended server (talk.google.com) and successfully got authenticated .
The first SSlStream.Read is to receive the greeting reply, it went fine . I do a SslStream.write to send my first command, but when i do my Sslstream.Read() to get the reply , i get this error."System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
Can anyone point me to the right direction?
I am using code very similar to the example on msdn http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx
except that I switch from a Network stream to a Sslstream when TLS is negotiated.
netStream.Flush();
sslStream = new SslStream(netStream,
true,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("talk.google.com");
I'd try using one of the existing XMPP libraries for .Net:
Jabber-Net: http://code.google.com/p/jabber-net/
agsXMPP: http://www.ag-software.de/agsxmpp-sdk/
Even if you don't use of these libs, you'll get some good ideas from looking at the code.
In this case, you probably want:
sslStream.AuthenticateAsClient("gmail.com");
where gmail.com is the domain name from the JID you're trying to log in as.