Can a packet contains several Websocket? - websocket

I was inspecting the websocket traffic between my server and my browser with Wireshark when I noticed this kind of frame :
No. Time Source Destination Protocol Length Info
144342 8212.033150000 127.0.0.1 127.0.0.1 WebSocket 821 WebSocket Text [FIN]
Frame 144342: 821 bytes on wire (6568 bits), 821 bytes captured (6568 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1)
Transmission Control Protocol, Src Port: http-alt (8080), Dst Port: 53749 (53749), Seq: 1132, Ack: 603, Len: 755
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x00
.... 0001 = Opcode: Text (1)
0... .... = Mask: False
.111 1110 = Payload length: 126 Extended Payload Length (16 bits)
Extended Payload length (16 bits): 140
Payload
Text: {"type":"COLLABORATIVE_COMMANDS","remoteUser":"null","key":"1c78c08f-5d2d-445a-a63c-3a211d2f0336","messageBroadcast":{"smartPath":["null"]}}
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x00
.... 0001 = Opcode: Text (1)
0... .... = Mask: False
.111 1110 = Payload length: 126 Extended Payload Length (16 bits)
Extended Payload length (16 bits): 329
Payload
Text [truncated]: {"type":"COLLABORATIVE_COMMANDS","remoteUser":"","key":"1c78c08f-5d2d-445a-a63c-3a211d2f0336","messageBroadcast":{"cameraInfos":{"target":{"x":0,"y":0,"z":0},"camPos":{"x":557.0133301398326,"y":159.5460628202445,"z":342.4
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x00
.... 0001 = Opcode: Text (1)
0... .... = Mask: False
.111 1110 = Payload length: 126 Extended Payload Length (16 bits)
Extended Payload length (16 bits): 141
Payload
Text: {"type":"COLLABORATIVE_COMMANDS","remoteUser":"","key":"1c78c08f-5d2d-445a-a63c-3a211d2f0336","messageBroadcast":{"colourEditedMeshes":true}}
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x00
.... 0001 = Opcode: Text (1)
0... .... = Mask: False
.111 1110 = Payload length: 126 Extended Payload Length (16 bits)
Extended Payload length (16 bits): 129
Payload
Text: {"type":"COLLABORATIVE_COMMANDS","remoteUser":"","key":"1c78c08f-5d2d-445a-a63c-3a211d2f0336","messageBroadcast":{"explode":"0"}}
Does this mean there are several websockets in my packet ? How is this possible ?

If you read the WebSocket spec, RFC 6455, you will see that WebSocket packets are framed, where each frame has its own header and payload. Remember that TCP is a streaming transport. Senders and receivers are not paying attention to the TCP frames, they are paying attention to the payloads within those frames. A WebSocket sender will send a WebSocket header followed by its payload, followed by the next WebSocket header and its payload, and so on. A WebSocket receiver will read a WebSocket header and its payload, then read the next WebSocket header and its payload, and so on. Typically, the Nagle algorithm is enabled on TCP sockets, and it will split and combine application data into TCP frames as needed for efficient network transmissions. That is handled by the TCP stack transparent to the applications. So yes, it is possible to see multiple WebSocket frames appear inside of a single TCP frame, if that is how Nagle decided to transmit them. If the WebSocket packets are sent in a short period of time, Nagle may merge them so it only has to transmit a single TCP frame instead of separate TCP frames.

Related

Implementation of a teamspeak like voice server

I'm implementing a voice chat server which will be used in my Virtual Class e-learning application for Windows, which makes use of the Remote Desktop API.
So far I 've been compressing the voice in with OPUS and I 've tested various options:
To pass the voice through the RDP Virtual Channel. This works but it creates lots of lag despite the channel creation with CHANNEL_PRIORITY_HI.
To use my own TCP (or UDP) voice server. For this option I have been wondering what would be the best method to implement.
Currently I 'm sending the udp datagram received, to all other clients (later on I will do server-side mixing).
The problem with my current UDP voice server is that is has lag even within the same pc: One server, and four clients connected, two of them have open mics, for example.
I get audible lag with this setup:
void VoiceServer(int port)
{
XSOCKET Y = make_shared<XSOCKET>(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!Y->Bind(port))
return;
auto VoiceServer2 = [&]()
{
OPUSBUFF o;
char d[200] = { 0 };
map<int, vector<char>> udps;
for (;;)
{
// get datagram
int sle = sizeof(sockaddr_in6);
int r = recvfrom(*Y, o.d, 4000, 0, (sockaddr*)d, &sle);
if (r <= 0)
break;
// a MESSAGE is a header and opus data follows
MESSAGE* m = (MESSAGE*)o.d;
// have we received data from this client already?
// m->arb holds the RDP ID of the user
if (udps.find(m->arb) == udps.end())
{
vector<char>& uu = udps[m->arb];
uu.resize(sle);
memcpy(uu.data(), d, sle);
}
for (auto& att2 : aatts) // attendee list
{
long lxid = 0;
att2->get_Id(&lxid);
#ifndef _DEBUG
if (lxid == m->arb) // if same
continue;
#endif
const vector<char>& uud = udps[lxid];
sendto(*Y, o.d + sizeof(MESSAGE), r - sizeof(MESSAGE), 0, (sockaddr*)uud.data(), uud.size());
}
}
};
// 10 threads receiving
for (int i = 0; i < 9; i++)
{
std::thread t(VoiceServer2);
t.detach();
}
VoiceServer2();
}
Each client runs a VoiceServer thread:
void VoiceServer()
{
char b[4000] = { 0 };
vector<char> d2;
for (;;)
{
int r = recvfrom(Socket, b, 4000, 0, 0,0);
if (r <= 0)
break;
d2.resize(r);
memcpy(d2.data(), b, r);
if (audioin && wout)
audioin->push(d2); // this pushes the buffer to a waveOut writing class
SetEvent(hPlayEvent);
}
}
Is this because I test in the same machine? But with a TeamSpeak client I had setup in the past there is no lag whatsoever.
Thanks for your opinion.
SendTo():
For message-oriented sockets, care must be taken not to exceed the
maximum packet size of the underlying subnets, which can be obtained
by using getsockopt to retrieve the value of socket option
SO_MAX_MSG_SIZE. If the data is too long to pass atomically through
the underlying protocol, the error WSAEMSGSIZE is returned and no data
is transmitted.
A typical IPv4 header is 20 bytes, and the UDP header is 8 bytes. The theoretical limit (on Windows) for the maximum size of a UDP packet is 65507 bytes(determined by the following formula: 0xffff - 20 - 8 = 65507). Is it actually the best way to send such a large packet? If we set a packet size too large, bottom of network protocol will splits packets at the IP layer. This takes up a lot of network bandwidth, cause the delay.
MTU(maximum transmission unit), is actually related to the link layer protocol. The structure of the EthernetII frame DMAC+SMAC+Type+Data+CRC has a minimum size of 64 bytes per Ethernet frame due to the electrical limitations of Ethernet transmission, and the maximum size can not exceed 1518 bytes. For Ethernet frames less than or greater than this limitation, we can regard it as a mistake. Since the largest data frame of Ethernet EthernetII is 1518 bytes, except for the frame header 14Bytes and the frame tail CRC check part 4Bytes, there is only 1500 bytes in the data domain left. That's MTU.
In the case that the MTU is 1500 bytes, the maximum size of UDP packet should be 1500 bytes - IP header (20 bytes) - UDP header (8 bytes) = 1472 bytes if you want IP layer not to split packets. However, since the standard MTU value on the Internet is 576 bytes, it is recommended that UDP data length should be controlled within (576-8-20) 548 bytes in a sendto/recvfrom when programming UDP on the Internet.
You need to reduce the bytes of a send/receive and then control the number of times.

Localhost UDP client not receiving packets from UDP proxy [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I have a proxy that acts between a Minecraft (Windows 10 Edition) client and a server, the protocol is UDP. The client broadcasts an unconnected ping, then server replies with an unconnected pong, everything with that is okay. The thing is when the server sends the packet to my proxy, my proxy sends it to client but for some reason something happens during that part; either my proxy is not sending the packet or the client is not receiving the packet, but most likely it's the second option.
Edit: I got the unconnected pings and pongs working, now the server shows online on the server list, now the problem is mainly the open connection requests/replies. How I got the the pings and pongs working was I re-encoded the buffers and send them instead of sending them raw.
Here you can see from wireshark, the minecraft client sends an unconnected ping the proxy:
NO. Time. Source. Dest. Proto. Len. Packet
417 10.452413 10.0.0.248 10.0.0.255 RakNet 75 Unconnected Ping (client -> proxy)
430 10.457000 10.0.0.248 x.x.x.x RakNet 610 Unconnected Ping (proxy -> server)
431 10.587214 x.x.x.x 10.0.0.248 RakNet 212 Unconnected Pong (server -> proxy -> client)
Now the proxy receive the unconnected pong, send it to the client, and the client doesn't receive it, I can confirm this because on the game the server shows offline and doesn't show any data:
Localhost Server Screenshot
In my code, I first bind the proxy on port 19132 and set the server address I want to communicate with:
var config = NewConfig()
var proxy = Proxy{}
var err error
proxy.UDPConn, err = net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP(config.BindAddr), Port: config.BindPort})
if err != nil {
Panic(err.Error())
os.Exit(1)
}
Info("Starting proxy on " + config.BindAddr + ":" + strconv.Itoa(config.BindPort))
addrs, err := net.LookupHost(config.ServerAddr)
if err != nil {
Panic(err.Error())
os.Exit(1)
}
conn := NewConnection(&proxy)
conn.server.SetAddress(net.UDPAddr{IP: net.ParseIP(addrs[0]), Port: config.ServerPort})
conn.HandleIncomingPackets()
Now my proxy starts receiving and sending packets automatically.
for true {
buffer := make([]byte, 2048)
_, addr, err := conn.proxy.UDPConn.ReadFromUDP(buffer)
if err != nil {
Alert(err.Error())
continue
}
MessageId := buffer[0]
Debug("Message Id : " + strconv.Itoa(int(MessageId))) // this is the packet id
if conn.client.IsConnected() { // client is connected
if conn.IsServer(*addr) {
conn.pkHandler.HandleIncomingPacket(buffer, conn.client) // if server send to client
}else{
conn.pkHandler.HandleIncomingPacket(buffer, conn.server) // if client send to server
}
} else {
switch MessageId {
case byte(IdUnconnectedPingOpenConnection):
conn.handleUnconnectedPing(*addr, buffer) // send this server
break
case byte(IdUnconnectedPongOpenConnection):
conn.handleUnconnectedPong(*addr, buffer) // parse server data and send to client
break
case byte(IdOpenConnectionRequest1):
conn.handleConnectionRequest1(*addr, buffer) // connect client and send to server
break
//case byte(IdOpenConnectionReply1):
// conn.handleConnectionReply1(*addr, buffer)
// break
}
}
}
This is the message id log:
[2018-06-10 13:52:12][Log/DEBUG]: Message Id : 1
[2018-06-10 13:52:12][Log/INFO]: Received unconnected ping from client address: 10.0.0.248
[2018-06-10 13:52:12][Log/DEBUG]: Message Id : 28
[2018-06-10 13:52:12][Log/INFO]: Received unconnected pong from server address: x.x.x.x
[2018-06-10 13:52:13][Log/DEBUG]: Message Id : 1
[2018-06-10 13:52:13][Log/INFO]: Received unconnected ping from client address: 10.0.0.248
[2018-06-10 13:52:13][Log/DEBUG]: Message Id : 28
[2018-06-10 13:52:13][Log/INFO]: Received unconnected pong from server address: x.x.x.x
Another way I confirmed the client is not receiving packets is that when in the game I click the server in the server list, the client sends an open connection request 1 (5) and the server replies with open connection reply 1 (6), the client is supposed to receive this and continue with an open connection request 2 (7) then finally the server replies with open connection reply 2 (8), but the client never sends open connection request 2 (7), because it never got the open connection reply 1 (6) from the proxy and hence times out and disconnects, here is a log showing this:
[2018-06-10 11:07:46][Log/DEBUG]: Message Id : 5
[5 0 255 255 0 254 254 254 254 253 253 253 253 18 52 86 120 8]
[2018-06-10 11:07:47][Log/DEBUG]: Message Id : 6
[6 0 255 255 0 254 254 254 254 253 253 253 253 18 52 86 120 36 149 162 237 197 55 226 161 0 8 28]
[2018-06-10 11:07:47][Log/DEBUG]: Message Id : 5
[5 0 255 255 0 254 254 254 254 253 253 253 253 18 52 86 120 8]
[2018-06-10 11:07:47][Log/DEBUG]: Message Id : 6
[6 0 255 255 0 254 254 254 254 253 253 253 253 18 52 86 120 36 149 162 237 197 55 226 161 0 8 28]
[2018-06-10 11:07:47][Log/DEBUG]: Message Id : 1
[1 0 0 0 0 3 3 91 191 0 255 255 0 254 254 254 254 253 253 253 253 18 52 86 120 191 216 14 215 31 123 8 249]
After so much debugging and testing, I figured I just needed to continue sending the datagram buffers, if it came from the server send it to client and vice-versa. If I cancelled the packet from sending I needed to send an ACK. It was all that simple.

HTTP/2 data compression

I am trying to understand the way the HTTP/2 protocol compresses the Data field. I didn't find an algorithm in the rfc. I know its a binary protocol.
I am looking for a way to get the binary protocol back into human readable content. I thought it is gzip like writen in the header but it isn't anyone has a source where i can look for the binary protocol refernce?
Frame 55: 151 bytes on wire (1208 bits), 151 bytes captured (1208 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst:00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 443 (443), Dst Port: 55300 (55300), Seq: 1087, Ack: 1078, Len: 85
Secure Sockets Layer
HyperText Transfer Protocol 2
Stream: HEADERS, Stream ID: 13, Length 47
Length: 47
Type: HEADERS (1)
Flags: 0x04
0... .... .... .... .... .... .... .... = Reserved: 0x00000000
.000 0000 0000 0000 0000 0000 0000 1101 = Stream Identifier: 13
[Pad Length: 0]
Header Block Fragment: 8854012a5a839bd9ab5f87497ca589d34d1f5c0333333861...
[Header Length: 177]
[Header Count: 6]
Header: :status: 200
Header: access-control-allow-origin: *
Header: content-encoding: gzip
Header: content-type: text/html
Header: content-length: 338
Header: date: Wed, 17 Aug 2016 15:14:25 GMT
Padding: <MISSING>
Frame 56: 442 bytes on wire (3536 bits), 442 bytes captured (3536 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 443 (443), Dst Port: 55300 (55300), Seq: 1172, Ack: 1078, Len: 376
Secure Sockets Layer
HyperText Transfer Protocol 2
Stream: DATA, Stream ID: 13, Length 338
Length: 338
Type: DATA (0)
Flags: 0x01
0... .... .... .... .... .... .... .... = Reserved: 0x00000000
.000 0000 0000 0000 0000 0000 0000 1101 = Stream Identifier: 13
[Pad Length: 0]
Data: 1f8b080000096e8800ff9cd2416b1b311005e0b3ffc5eb9e...
Padding: <MISSING>
The response body of a HTTP/2 response is compressed (or not) exactly the same way as it works with HTTP/1: Accept-Encoding: in the request and Content-Encoding: in the response. HTTP/2 did nothing new with compression of the bodies, only with headers which weren't compressed at all in HTTP/1.

Create a UDP ping packet to fetch mumble(murmur) status

I'd like to send a udp packet to a mumble server using ruby to get status information about how many users are currently connected.
The documentation states there is a way using a UDP packet: http://mumble.sourceforge.net/Protocol#UDP_Ping_packet
However I don't know how to formulate that with ruby and thus get no reply from the server.
require 'socket'
sock = UDPSocket.new
sock.connect("99.99.99.99", 66666)
sock.send("00", 0)
p sock.recvfrom(1) # this does not return
sock.close
How do I format data of the udp packet?
This should work to generate your ping packet:
def ping(identifier)
v = identifier
a = []
while v > 256 # extract bytes from the identifier
a << v % 256
v = v / 256
end
a << v % 256
prefix = [0] * (8-a.length) # pad the identifier
([0,0,0,0] + prefix + a).pack("C*") # pack the message as bytes
end
usage:
# random 8 byte number as a message identifier - compare this to any packet
# received to ensure you're receiving the correct response.
identifier = rand(256**8)
sock.send ping(identifier), 0
# you should get a response here if the mumble server is
# accessible and responding to pings.
sock.recvfrom(1)

how to copy message inside icmp header

Here is the code which I don't quite understand.
struct icmphdr *icmp;
icmp = (struct icmphdr *)(sb->data + sb->nh.iph->ihl * 4);
....
char *cp_data = (char *)((char *)icmp + sizeof(struct icmphdr));
memcpy(cp_data, buffer, 4);
dev_queue_xmit(sb);
Basically what it does is copy the buffer to cp_data, which points to somewhere in icmphdr structure, but where does cp_data exactly points to? what is (char *)((char *)icmp + sizeof(struct icmphdr))?
cp_data, which points to somewhere in icmphdr structure
No, it does not, it points to the memory after the icmphdr.
That's where the ICMP payload is. Look at this image:
The ICMP payload (message) starts after the header which has a size of sizeof(struct icmphdr) so it is located at icmp + sizeof(struct icmphdr).
memcpy(cp_data, buffer, 4); therefore copies four bytes from buffer to the ICMP packet message.
sb->data + sb->nh.iph->ihl * 4 actually skips the IP packet header and points to the ICMP header (look at the above image again). The IP header is at sb->data, the ICMP header at sb->data + sb->nh.iph->ihl * 4 and the ICMP message at sb->data + sb->nh.iph->ihl * 4 + sizeof(struct icmphdr).
For example, ping (echo request / reply) uses the ICMP message field to send the data forth and back. It can also be used for ICMP tunneling.
Update:
if I want to get the size of data section, just do "size = 1500(MTU) - (sizeof(iphdr) + sizeof(icmphdr) + sizeof(ethhdr)). Is that correct?
No, not at all, for the following reasons:
MTU is just the maximal packet size that can be transmitted without fragmentation. ICMP packets should actually be smaller.
The MTU does not include the ethernet header, it defines the maximal packet length in layer 3 (IP, not ethernet!).
sizeof(iphdr) is incorrect because the header size can vary based on IP options. Use iphdr.ihl to get the size of the IP header in 32 bit words.
The correct way is to determine the total IP packet length and subtract IP header length and ICMP header length:
tot_len = sb->nh.iph->tot_len
iphdr_len = sb->nh.iph->ihl * 4
icmphdr_len = sizeof(icmphdr)
size = tot_len - iphdr_len - icmphdr_len
Note: You should always use ntohs to convert network byte order to host byte order.
In the code you pasted,
struct icmphdr *icmp; //is a pointer to the beginning of icmp header in a packet.
& by this line-
char *cp_data = (char *)((char *)icmp + sizeof(struct icmphdr));
you make cp_data point to the beginning of the payload of the icmp packet.
2.((char *)icmp + sizeof(struct icmphdr)); - icmp is typecasted to (char*) so that the addition of (char*)icmp + sizeof(struct icmphdr) will return the address (icmpheader start address) + headersize bytes.
Here is an example -
suppose you have an integer pointer and you increment it by one, it points to the next integer(that is it automatically advances 4 bytes ahead),while a character pointer advances by a single byte since a char is 1 byte.
And so, since memcpy is used to copy bytes from a buffer to where cp_data now points(the payload of the icmp packet), (char*)icmp + sizeof(struct icmphdr) is again typecasted to (char*).
Hope this helps!

Resources