I am using Nginx + Websockets on a precise 64 vagrant box, with c#/mono for the app server. The goal is to serve up static content directly through Nginx, and handle both plain 'ol http service requests (on /service) and also websocket requests (on /webSocket) all on the same port. Here's the relevant conf:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
# (1)
location / {
root /var/www;
index index.html;
}
# (2)
location /service {
add_header Access-Control-Allow-Origin *;
proxy_pass http://localhost:9000;
}
# (3)
location /webSocket {
proxy_pass http://localhost:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Most of it is working well. Static content, yes, service requests, yes, and even the first part of websockets. I am getting a well-formed 101 Switching Protocols request from my client (Firefox or Chrome). I am making a nice http upgrade response and sending it. And then the client does... nothing... nothing is received.
But the crazy thing is, when I give up and manually kill my server side app, and the client web socket closes with error, THEN the Response Headers show up on the client browser debugger. The whole thing looks like:
REQUEST HEADERS
Request URL: http://localhost:8086/webSocket
Request Method: GET
Status Code: HTTP/1.1 101 Switching Protocols
Request Headers 16:18:50.000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: Nx0sUAemOFWM2rsaCAJpfQ==
Sec-WebSocket-Extensions: permessage-deflate
Pragma: no-cache
Origin: http://localhost:8086
Host: localhost:8086
Connection: keep-alive, Upgrade
Cache-Control: no-cache
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
RESPONSE HEADERS Δ19660ms
Upgrade: websocket
Transfer-Encoding: chunked
Server: nginx/1.1.19
Sec-WebSocket-Accept: gNiAeqxcVjkiReIpdtP0EZiClpg=
Date: Mon, 08 Jun 2015 20:18:48 GMT
Connection: keep-alive
NO RESPONSE BODY Δ0ms
There's no evidence that my server app is not flushing out its send data right away - I'm using async TcpSocket.BeginSend and FinishSend and the send seems to complete right away. And it works fine on plain http service comm.
So where is my websocket message data going??? It seems like Nginx doesn't want to send it back to my client, except until I close the Tcp connection from the server side.
Has anybody experienced something like this before. Everything I've read on Nginx and Websockets is concerned with the basic setup that gets the hop-by-hop upgrade working, and I've got that. No one has anything to say as to why sending back from the server side doesn't seem to go anywhere.
Related
I'm following the following link https://docs.aws.amazon.com/AmazonS3/latest/dev/HLuploadFileDotNet.html
to upload files from local machine to an S3 bucket on VPC. The application is also testing and running on the on-premise machine.
var s3Client = new AmazonS3Client(RegionEndpoint.USEast2);
var fileTransferUtility = new TransferUtility(s3Client);
await fileTransferUtility.UploadAsync("c:\tmp\test.txt", "bucketName");
However, the code gets the following error.
A socket operation was attempted to an unreachable network
Should an Url be given?
Here is the network traffic captured by Fiddler. However, it gets a different exception for the code.
GET http://1xx.1xx.1xx.2xx/latest/meta-data/iam/security-credentials HTTP/1.1
Host: 1xx.1xx.1xx.2xx
HTTP/1.1 503 Service Unavailable
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Content-Length: 787
Network Error
Network Error (tcp_error)
A communication error occurred: "Operation timed out"
The Web Server may be down, too busy, or experiencing other problems preventing it from responding to requests. You may wish to try again at a later time.
For assistance, contact your network support team.
.aws\config
[default]
region = USWest2
I had the same error today, even though I had a valid $USERPROFILE\.aws\credentials file - it was actually because $USERPROFILE\AppData\Local\AWSToolkit\RegisteredAccounts.json couldn't be decrypted (not sure why), which causes AWS to think you don't have have local credentials, and hence tries to make a connection to the EC2 metadata URL which is http://169.254.169.254/latest/meta-data/?. On a local development machine that won't be accessible. For me, deleting the $USERPROFILE\AppData\Local\AWSToolkit\RegisteredAccounts.json file did the trick. FWIW, I only managed to figure this out by reading through the source of the AWS SDK...
I am writing a websocket client using C#. But I can't figure out how to send the websocket handshake request to the server in C# and how to generate sec-websocket-key.
The client request sample will be like below.
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Server response sample would be like below.
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Look at the sample websocket server code from mozilla.
To generate the key on client side you can use random generators.
String secWebSocketKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("WebSocket rocks!"));
I have a RTP multicast stream from ffmpeg that requires users to use external SDP files, as this sometimes becomes a problem I was thinking of wrapping the stream using RTSP.
I have an application that already makes some management for the RTP stream, so it would be useful to have the RTSP wrapper inside it as well, although I don't want the wrapper to do anything beyond delivering the SDP information. Right now I'd say I'm correctly delivering the SDP information (otherwise it's stuck in that request), however I'm not getting any PLAY command, the player is stuck after the SETUP request, so I guess my reply is wrong, but after testing many different values for the Transport header I haven't been able to get anything beyond this point.
This is the SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 236.0.0.1
t=0 0
a=tool:libavformat 56.7.102
m=video 2000 RTP/AVP 96
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1
This is a sample SETUP request from VLC:
SETUP rtsp://127.0.0.1:34343/live.sdp/ RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Media v2014.05.27)
Transport: RTP/AVP;multicast;client_port=2000-2001
And one of many replies I've tried:
RTSP/1.0 200 OK
CSeq: 4
Transport: RTP/AVP;multicast;client_port=2000-2001;source=236.0.0.1;port=2000-2001
Session: 0456804596
I've tried using destination instead of source, server_port instead of port, also, although the RTP multicast port is 2000, I've seen the streaming is also using other ports like 57927 and 57928, so I've tried those ones as well, etc.
Just my two cents, but from the logical point of view a PLAY command for a multicast RTSP stream does not make any sense since the clients will get the media as soon as they join the group. The multicast stream as such does not have state.
Is the multicast RTP stream active at this point? Maybe VLC is actually joining the group after the SETUP response but no data is being transmitted to it? Also you can use VLC error log to see what is going on.
EDIT
Here is an example RTSP session with a multicast stream between VLC and an IP camera:
DESCRIBE rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 5
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Accept: application/sdp
RTSP/1.0 200 OK
CSeq: 5
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Content-Type: application/sdp
Content-Length: 352
v=0
o=- 0 0 IN IP4 192.168.3.142
s=rtsp://192.168.3.142/stream/profile1
t=0 0
a=control:*
m=video 2014 RTP/AVP 99
a=rtpmap:99 H264/90000
a=fmtp:99 sprop-parameter-sets=Z0LgKdoB4Aiflm4CAgwE,aM48gA==;packetization-mode=1;profile-level-id=42e029
a=control:rtsp://192.168.3.142/stream/profile1/AVCESEnc
a=framerate:30.0
c=IN IP4 239.100.10.10/1
SETUP rtsp://192.168.3.142/stream/profile1/AVCESEnc RTSP/1.0
CSeq: 6
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Transport: RTP/AVP;multicast;client_port=2014-2015
RTSP/1.0 200 OK
CSeq: 6
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Session: 241934337;timeout=60
Transport: RTP/AVP;multicast;destination=239.100.10.10;port=2014-2015;ttl=1
PLAY rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 7
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
Range: npt=0.000-
RTSP/1.0 200 OK
CSeq: 7
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Session: 241934337
RTP-Info: url=rtsp://192.168.3.142/stream/profile1/AVCESEnc;seq=14604;rtptime=3766807430
GET_PARAMETER rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 8
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
RTSP/1.0 200 OK
CSeq: 8
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:29 GMT
Session: 241934337
TEARDOWN rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 9
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
RTSP/1.0 200 OK
CSeq: 9
Connection: Close
Date: Sat, 10 Jan 2015 16:54:31 GMT
Session: 241934337
EDIT 2
As can be seen lower in the comments, Neverbirth pointed out that the issue was not in the SETUP command but in the HTTP headers for the DESCRIBE command - a wrong content length was used in the response. After fixing that the problem was solved.
When I open a web socket to my server - it looks like the client is automatically sending an HTTP request as part of the first payload. How can I prevent this?
That is the nature of the web socket protocol. It starts with a handshake done over simple HTTP
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
More: http://en.wikipedia.org/wiki/WebSocket#WebSocket_protocol_handshake
You cannot create a websocket without this handshake.
I have created TCP proxy which listens on port 80 (port 80 is not being used by any other service) for incoming connections. The proxy is able to receive the POST Requests When I use "Localhost" or "127.0.0.1" as the IpAddress
for listener socket.
Socket listner = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80);
listner.Bind(localEndpoint);
listner.Listen();
However when I replace 'localhost' with the IP (191.151.43.22) of my machine.The proxy receives the client requests as "GET request"
Socket listner = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("191.151.43.22"), 80);
listner.Bind(localEndpoint);
listner.Listen();
Client request when listening for connections using localhost / 127.0.0.1
POST /?toke=abc455/../Control.html?s=783&i=0&t=134 HTTP/1.1
Host: localhost:58888
Connection: keep-alive
Content-Length: 0
Origin: http://localhost:58888
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) C
hrome/21.0.1180.89 Safari/537.1
Content-Type: text/plain;charset=UTF-8
Accept: */*
Referer: http://localhost:58888/?toke=abc455/../Stream.html?s=0&d=%22
localhost%22&p=0&t=1348652703126
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: style=null
Client request when listening for connections using IP (191.151.43.22) of my machine
GET /?token=abc344/../Stream.html?s=0&d=%22localhost%22&p=0&t=13486531
37269 HTTP/1.1
Host: 192.168.53.50
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) C
hrome/21.0.1180.89 Safari/537.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Why POST is not working with IP address of the system but working when 'localhost' is used in place of IP.
More than likely, your HTTP request is getting altered by a proxy server (my guess would be your router).
With that said, the proxy server (assuming that is the culprit) may not be incorrect with what it is doing. I don't see any POST data in your requests**, therefore the change made should have no functional impact on the receiving end.
** There is GET data (which resides in the URL), but no POST data (which resides after the headers).