How implement live data stream on .net core - c#

What is a good tactic to implement mechanism on server to read data from external device by http with keep-alive connection ?
Details.
I have camera device hosted on public address. i can use request to create connection beetween server and device ( get events in live ).
Sample request
GET /live/events HTTP/1.1
Host: x.x.x.x
Connection: keep-alive
Cookie: sid=id
and now i should get response if camera detect something.
I dont sure how i should do this. HttpClient will be enough to resolve my problem , or maybe something else ?
Regards

Related

AllowAutoRedirect Functionality when using sockets

I'm aware that HttpWebRequest has a parameter available to set URL redirection to false (request.AllowAutoRedirect = False;).
How is this done when using a Socket connection directly?
I don't have any code to show since I'm just starting down the road of development on a project.
Unfortunately, I need to stick to using Socket connections and cannot use HttpWebRequest, WebClient or HTTPClient. :(
There is no such thing as a socket redirection.
An HTTP redirection is where you connect to the server specified, send your HTTP request, and server sends a HTTP response which tells you to go to a different URL instead. So then you go that URL instead.
It looks like this:
*** socket opened to example.com
*** client sends this part:
GET /some/address HTTP/1.1
Host: example.com
*** server sends this part:
HTTP/1.1 302 Found
Location: https://other.example.com/some_place?really=yes
*** socket closed to example.com
if you have auto-redirect disabled, this is the response your program gets. Otherwise, the HTTP library keeps going:
*** socket opened to other.example.com
*** client sends this part:
GET /some_place?really=yes HTTP/1.1
Host: other.example.com
*** server sends this part:
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11
hello world
*** socket closed to other.example.com
If you are just using sockets you will be doing this yourself to begin with.

What does a curl_error_56 and a HTTP_error_502 have in common?

I am working on a Chatbot in Slack that sends a POST request to http://localhost:44331/values/api an .NET Core API that i built in C#. In the Post request is a response_url in the body I can use to send back the needed information.
So I have been trying to make this work for about two weeks now and used a fiddler and to mimic the request so I can make some changes on the body and the headers to see if that makes a difference.
So after a lot of errors I have come to two specific errors that haven't changed for a long while.
sent with the Slack Chatbot: curl_error_56
There really isnt much I can change in this matter except the url I want to send the request to.
In fact this request has never even reached the post method in my API.
Thats what the Slackbot answers
sent with fiddler: HTTP error 400
I used Requestbin to get the information that has been sent by the bot and copied it into the composer in fiddler.
I am a total novice to Web programming in any kind of way so I really don't know what they have in common.
Are those errors coming because I am using localhost?
What am I missing?
here is the request so you can copy it if needed
host: localhost:44331
Accept: application/json,*/*
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
User-Agent: Slackbot 1.0 (+https://api.slack.com/robots)
X-Slack-Request-Timestamp: 1569238196
X-Slack-Signature: v0=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Length: 381
Connection: keep-alive
Alright I got some help by a friend and he explained to me that Slack is unable to access my localhost, because it is not a local app. It is taking its information from the web and making it send a request to my localhost is useless because it is not a static IP.
What i need is an Endpoint.
I can get one by requesting it from my ISP (Internet Service Provider) or getting myself a server which already has an static IP.
Thanks for any help you wanted to provide.

Http request broken after upgrading to .NET Core 2.1

I'm posting telemetry data to the Application Insights data collector endpoint at https://dc.services.visualstudio.com/v2/track using HttpClient.
This works fine when using .NET Core 2.0. However, after upgrading to .NET Core 2.1 all requests fail with HTTP status 500 Internal Server Error and an HTML response body that looks like this:
(It's an IIS 8.5 Detailed Error page)
In .NET Core 2.1 they have changed how HttpClientHandler works and added an AppContext switch that allows us to keep the old behavior:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
Indeed, setting this switch fixes the problem!
But I'd like to avoid using that switch:
Firstly, because I'd like to use the new stuff. It must be better :-)
Secondly, because that switch changes behavior for all new HttpClientHandler instances. Not just the one I'm using to post data to the Application Insights endpoint.
I've tried to figure out what's causing this by looking at the traffic using Wireshark. Trying to interpret HTTPS traffic on that low level is beyond me. I did find something suspicious in the TLS handshake though.
Both the SocketsHttpHandler (that doesn't work) and the legacy WinHttpHandler (that do work) use TLS 1.2. However, only the WinHttpHandler uses the TLS Certificate Status Request extension. Could that be the reason why requests are failing?
In any case, the TLS connection is setup a request is sent and a response is retrieved. And apparently there is an error on the server side while processing the request.
I'd like to figure out what's causing this problem. Any help is appreciated!
As suggested by #mjwills I changed my code so that it uses HTTP (not SSL) and post to a local program that allows me to capture the request. (I didn't figure out how to do this in a clean way in Wireshark, so I ended up writing my own little capture tool based on TcpListener):
Capture when using the new SocketsHttpHandler:
POST / HTTP/1.1
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345
A
[...10 bytes of data...]
F4
[...244 bytes of data...]
0
Capture when using the legacy WinHttpHandler:
POST / HTTP/1.1
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345
a
[...10 bytes of data...]
f4
[...244 bytes of data...]
0
These are the differences:
WinHttpHandler wants to keep the connection alive while SocketsHttpHandler does not.
WinHttpHandler use lower case hex for chunk lengths while SocketsHttpHandler use upper case.
The first 10 bytes contains the gzip header. The remaining 244 bytes contains the gzip encoded json telemetry data.

How to consume a socket.io WebSocket API in C#

I need to consume a third-party WebSocket API in .NET Core and C#; the WebSocket server is implemented using socket.io (using protocol version 0.9), and I am having a hard time understanding how socket.io works... besides that the API requires SSL.
I found out that the HTTP handshake must be initiated via a certain path, which is...
socket.io/1/?t=...
...whereby the value of the parameter t is a Unix-timestamp (in seconds). The service replies with a session-key, timeout information, and a list of supported transport protocols. Due to simplicity, this first request is made via HttpClient and does not involve any additional headers.
Next, another HTTP request is required, which should result in an HTTP 101 Switching Protocol response. I specified the following headers in accordance to the previous request...
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
...whereby the value of the Key-header is a Base64-encoded GUID-value that the server will use to calculate the Sec-WebSocket-Accept header value. I also precalculate the expected Sec-WebSocket-Accept header value, for validation...
I tried to make that request using HttpClient as well, but that does not seem to work... I actually don´t understand why, because I expect an HTTP response. I also tried to make the request using TcpClient by sending a manually prepared GET request over a SslStream, which accepts the remote certificate as expected. Sending data seems to work, but there´s no response data... the Read-method returns zero.
What do I miss here? Do I need to setup a listener for the WebSocket connection as well, and if yes how? I don´t want to implement a feature complete socket.io client, I´d just like to keep it as simple as possible to catch some events...
The best way of debugging these issues is to use a sniffer like wireshark or fiddler. Often connect using an IE and compare IE results with my application and modify my app so it works like the IE. Using WebClient instead of HttpClient will also work better because the WebClient does more automatically than the HttpClient.
A web connection uses the header of the client and the headers in the server webpage to negotiate a connection mode. Adding additional headers to you client will change the connection mode. Cookies are also used to select the connection mode. Cookies are the results of previous connection to the same server which shortens the negotiations and stores info from previous connection so less data has to be downloaded from server. The server remembers the cookies. Cookies have a timeout and is kept until timeout expires. The IE history in your client has a list of IP addresses and Net automatically sends the cookies associated with the server IP.
If a bad connection is made to the server the cookies is also bad so the only was of connection is to remove the cookie. Usually I go into the IE and delete cookies manually in the IE history.
To check if a response is good the server returns a status. A completed response contains a status 200 DONE. You can get status which are errors. You can also get a 100 Continue which means you need to send another request to get the rest of the webpage.
Http has 1.0 (stream mode) and 1.1 (chunk mode). Net library doesn't work with chunk. Chunk requires client to send message to get next chunk and I have not found a way in Net to send the next chunk message. So if a server responds with a 1.1 then you have to add to your client headers to use 1.0 only.
Http uses TCP as the transport layer. So in a sniffer you will see TCP and HTTP. Usually you can filter sniffer just to return Http and look at header for debugging. Occasionally TCP disconnects and then you have to look at TCP to find why the disconnect occurs.

Examining received data with system.net.socket which comes over HTTPS

I have a windows application which listens on 9002 port via system.net.socket.
If clients send the request over http url like that:
http://localhost:9002/projectName/doSomething
then in my ReceiveCallBack method the received data is:
POST /projectName/doSomething HTTP/ 1.1
Accept: * / *
Origin: http://localhost
Accept-Language: tr-TR
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
Host: localhost:9002
But if they send the request over https url which you can see below:
https://localhost:9002/projectName/doSomething
then the received data is something like:
\0?\0\0?U:vv?W?????????T??k#?=??? v\tci\0\0,?(?'??\0=\0<\05\
I tried to use UTF8 encoding to convert this data in a readable format and searched over the Internet but I could not find the solution.
What is the way of receiving a readable data over HTTPS requests?
Thanks
I've actually written a web server and SOAP stack in C# from sockets up without using any WCF or HttpListener and had to deal with adding https support. The code was actually relatively simple.
You'll need to start by constructing a SslStream from the Socket, by way of a NetworkStream adapter.
var sslStream = new SslStream(new NetworkStream(socket));
Then the hard part: you need to AuthenticateAsServer, which requires you to have an X509Certificate with corresponding private key, from an issuer the connecting client trusts, containing a subject name matching the host portion of the https URL. (It's the hard part because you can't code your way out of it unless you own both sides of the connection - it's how a client such as a browser knows if a site is legitimate or not.)
sslStream.AuthenticateAsServer(serverCertificate);
Finally, you can then read from the sslStream and get the actual, unencrypted HTTP request.
You are probably seeing the first round of the handshake protocol for https. In https the two computers go through a multi-step handshake to negotiate what encryption to use, exchange public keys, etc. Even if you get through the handshake phase the data will be encrypted (which is kinda the point of using https).

Categories