Websocket - How does the Mask work For Clientside - c#

i read the article on https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server and found it very interesting as i have not done anything with websockets before. I have already managed that my client connects and the handshake takes place (was also the easy part).
However, I can't manage to set the mask on my client so that the message arrives correctly at the server. Somehow I don't quite understand this yet....
At the server it looks like this:
bool fin = (bytes[0] & 0b10000000) != 0,
mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set"
int opcode = bytes[0] & 0b00001111, // expecting 1 - text message
offset = 2;
ulong msglen = (ulong)(bytes[1] & 0b01111111);
if (msglen == 126)
{
// bytes are reversed because websocket will print them in Big-Endian, whereas
// BitConverter will want them arranged in little-endian on windows
msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
offset = 4;
}
else if (msglen == 127)
{
// To test the below code, we need to manually buffer larger messages — since the NIC's autobuffering
// may be too latency-friendly for this code to run (that is, we may have only some of the bytes in this
// websocket frame available through client.Available).
msglen = BitConverter.ToUInt64(new byte[] { bytes[9], bytes[8], bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2] }, 0);
offset = 10;
}
if (msglen == 0)
{
Console.WriteLine("msglen == 0");
}
else if (mask)
{
byte[] decoded = new byte[msglen];
byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
offset += 4;
for (ulong i = 0; i < msglen; ++i)
decoded[i] = (byte)(bytes[offset + (int)i] ^ masks[i % 4]);
string text = Encoding.Default.GetString(decoded);
I have written the client in C# as TcpClient. But I just can't get it to encode the message so that it is decoded correctly at the server.
can someone of you help me? What is the inverse function to what is done at the server to decode this?
I only found Articles in Javascript or in C# without masks...
Thank u very much!

Related

Playing a RTP stream to PC speakers

I'm using UdpClient to get a RTP stream from phone calls through Avaya DMCC sdk. I would like to play this stream through the computer's speakers. After a lot of searching I've only been able to find solutions that require saving to a file and then playing the file but I need to play the stream through the speakers without saving to a file. I'd like to send audio to the speakers as I receive it.
public void StartClient()
{
// Create new UDP client. The IP end point tells us which IP is sending the data
client = new UdpClient(port);
endPoint = new IPEndPoint(System.Net.IPAddress.Any, port);
selectedCodec = new MuLawChatCodec();
waveOut = new WaveOut();
waveProvider = new BufferedWaveProvider(selectedCodec.RecordFormat);
waveOut.Init(waveProvider);
waveOut.Play();
listening = true;
listenerThread = new Thread(ReceiveCallback);
listenerThread.Start();
}
private void ReceiveCallback()
{
// Begin looking for the next packet
while (listening)
{
// Receive packet
byte[] packet = client.Receive(ref endPoint);
// Packet header
int version = GetRTPValue(packet, 0, 1);
int padding = GetRTPValue(packet, 2, 2);
int extension = GetRTPValue(packet, 3, 3);
int csrcCount = GetRTPValue(packet, 4, 7);
int marker = GetRTPValue(packet, 8, 8);
int payloadType = GetRTPValue(packet, 9, 15);
int sequenceNum = GetRTPValue(packet, 16, 31);
int timestamp = GetRTPValue(packet, 32, 63);
int ssrcId = GetRTPValue(packet, 64, 95);
int csrcid = (csrcCount == 0) ? -1 : GetRTPValue(packet, 96, 95 + 32 * (csrcCount));
int extHeader = (csrcCount == 0) ? -1 : GetRTPValue(packet, 128 + (32 * csrcCount), 127 + (32 * csrcCount));
int payloadIndex = csrcCount == 0 ? 96 : 128 + 32 * csrcCount;
int payload = GetRTPValue(packet, payloadIndex, packet.Length);
byte[] Payload = new byte[packet.Length - payloadIndex];
Buffer.BlockCopy(packet, payloadIndex, Payload, 0, packet.Length - payloadIndex);
byte[] decoded = selectedCodec.Decode(Payload, 0, Payload.Length);
}
}
private int GetRTPValue(byte[] packet, int startBit, int endBit)
{
int result = 0;
// Number of bits in value
int length = endBit - startBit + 1;
// Values in RTP header are big endian, so need to do these conversions
for (int i = startBit; i <= endBit; i++)
{
int byteIndex = i / 8;
int bitShift = 7 - (i % 8);
result += ((packet[byteIndex] >> bitShift) & 1) * (int)Math.Pow(2, length - i + startBit - 1);
}
return result;
}
I now successfully have audio from the call being played over the speakers by adding a byte[] containing just the payload to NAudio's BufferedWaveProvider
There's a demo of how to play audio received over the network included with the NAudio source code (see Network Chat Demo in the NAudioDemo project). Basically use an AcmStream to decode the audio, and then put it into a BufferedWaveProvider which the soundcard is playing from.

IP fragmentation cause Checksum incorrect message

I am using PcapDorNet DLLs and i try to fragment my traffic:
private IEnumerable<Packet> SplitPacket(Packet packet, int numberOfFragments)
{
IpV4Datagram ipV4Datagram = packet.Ethernet.IpV4;
Datagram datagram = packet.Ethernet.IpV4.Payload;
TransportLayer transportlayer = GetTransportLayer(packet);
if (transportlayer != null)
{
EthernetLayer ethernet = (EthernetLayer)packet.Ethernet.ExtractLayer();
ILayer layer = packet.Ethernet.IpV4.ExtractLayer();
IpV4Layer ipV4Layer = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
ipV4Layer.HeaderChecksum = null;
DateTime packetTimestamp = packet.Timestamp;
PayloadLayer payload = (PayloadLayer)packet.Ethernet.IpV4.Payload.ExtractLayer(); //extract the data
int totalLength = payload.Length;
int partialLength = totalLength / numberOfFragments; //split data into smaller segments
partialLength = (partialLength / 8) * 8; //make sure it's divisible with 8
if (partialLength == 0)
partialLength = 8;
//(http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly)
ushort offset = 0; //send one by one
while (offset < totalLength)
{
int fragmentLength = partialLength; //get length for this fragment
IpV4FragmentationOptions options = IpV4FragmentationOptions.MoreFragments;
if (offset + fragmentLength >= totalLength) //is this the last fragment ? trim length if needed
{
options = IpV4FragmentationOptions.None;
fragmentLength = totalLength - offset;
}
byte[] newBuffer = ipV4Datagram.Payload.ToArray(); //copy the actual data into a new buffer
PayloadLayer newPayload = new PayloadLayer { Data = new Datagram(newBuffer, offset, fragmentLength) };
ipV4Layer.Fragmentation = new IpV4Fragmentation(options, offset); //change IP layer fragmentation options
transportlayer.Checksum = null;
yield return PacketBuilder.Build(packetTimestamp, ethernet, ipV4Layer, transportlayer, newPayload);
offset += (ushort)fragmentLength; //next offset
}
}
}
My input packet is TCP packet and the output is 4 packets: 3 IPv4 packets and the last is TCP but this packet i received is show under TCP layer field this message:
Checksum: 0x5d17 [incorrect, should be 0xabb7 (maybe caused by "TCP
checksum offload"?)]
with UDP it seems that also every UDP packet split into several IPv4 packet and the last one is UDP but in UDP case it look fine.
I am i doing something wrong ?
Please see the original packet and the fragmentation: http://www.filedropper.com/desktop_122
It seems there is a very similar question in Pcap.Net site with corrections to the code.
I believe following the advice there would help solve your issues.

Chrome native message

I am working on sample application of "Chrome Native Messaging". I did all the set as per steps mention on website. I am able to run application as well however i am not getting response message from native application. When i start extension very firts time i get the response message.
Downloaded sample from here
When i sent message from browser native app not responding it check below image
C# code as below
static void Main(string[] args)
{
string message = "test message from native app.";
OpenStandardStreamOut(message);
while (OpenStandardStreamIn() != null || OpenStandardStreamIn() != "")
{
OpenStandardStreamOut("Received to Native App: " + OpenStandardStreamIn());
OpenStandardStreamOut("Recieved: " + OpenStandardStreamIn());
}
}
private static string OpenStandardStreamIn()
{
//// We need to read first 4 bytes for length information
Stream stdin = Console.OpenStandardInput();
int length = 0;
byte[] bytes = new byte[4];
stdin.Read(bytes, 0, 4);
length = System.BitConverter.ToInt32(bytes, 0);
string input = "";
for (int i = 0; i < length; i++)
{
input += (char)stdin.ReadByte();
}
return input;
}
private static void OpenStandardStreamOut(string stringData)
{
//// We need to send the 4 btyes of length information
string msgdata = "{\"text\":\"" + stringData + "\"}";
int DataLength = msgdata.Length;
Stream stdout = Console.OpenStandardOutput();
stdout.WriteByte((byte)((DataLength >> 0) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 8) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 16) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 24) & 0xFF));
//Available total length : 4,294,967,295 ( FF FF FF FF )
Console.Write(msgdata);
}
manifest.json as below
{"name": "com.example.native",
"description": "Native support for Chrome Extension",
"path": "NativeApp.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
],
"permissions": [
"nativeMessaging"
]
}
Some where i feel we are not receiving response from native host becoz i have added debug point to following code in browser which is not getting hit
function onNativeMessage(message) {
appendMessage("Received message: " + JSON.stringify(message) + "");
}
Am i missing something ?
I had the same problem. Make sure the message you are sending is valid JSON. In my case, the value being received by the host was "some value" with the double quotation marks. When that was getting concatenated to make the msgdata variable, it was creating invalid JSON.

Get Timestamp rtp packet

I'm using PacketDotNet to retrieve data from RTP header. But there are times when the timestamp is a negative value.
GetTimeStamp(UdpPacket packetUdp)
{
byte[] packet = packetUdp.PayloadData;
long timestamp = GetRTPHeaderValue(packet, 32, 63);
return timestamp;
}
private static int GetRTPHeaderValue(byte[] packet, int startBit, int endBit)
{
int result = 0;
// Number of bits in value
int length = endBit - startBit + 1;
// Values in RTP header are big endian, so need to do these conversions
for (int i = startBit; i <= endBit; i++)
{
int byteIndex = i / 8;
int bitShift = 7 - (i % 8);
result += ((packet[byteIndex] >> bitShift) & 1) *
(int)Math.Pow(2, length - i + startBit - 1);
}
return result;
}
It could be caused by the RTCP packets. If the RTP data is coming from a phone, then phone send periodic RTCP reports. They seem to pop in about every 200'th packet. The format is different and your code is probably reading it the same way - you will need to handle the RTCP packets.
The packets format: http://www.cl.cam.ac.uk/~jac22/books/mm/book/node162.html

Modbus Communication

I am using C# to communicate via modbus rs485 rs232 to 2 phase meters that among other log the power voltage.
I have to send data over the bus so that i can receive the readings.
I have connected a normal wire and shorted the send and receive.
The data is recieved and this event is fired:
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] buff = new byte[sp.BytesToRead];
//Read the Serial Buffer
sp.Read(buff, 0, buff.Length);
string data= sp.ReadExisting();
foreach (byte b in buff)
{
AddBuffer(b); //Add byte to buffer
}
}
Then this buffer is sent to another function which is this one:
private void AddBuffer(byte b)
{
buffer.Add(b);
byte[] msg = buffer.ToArray();
//Make sure that the message integrity is correct
if (this.CheckDataIntegrity(msg))
{
if (DataReceived != null)
{
ModbusEventArgs args = new ModbusEventArgs();
GetValue(msg, args);
DataReceived(this, args);
}
buffer.RemoveRange(0, buffer.Count);
}
}
I think that the problem lies at the data integrity check:
public bool CheckDataIntegrity(byte[] data)
{
if (data.Length < 6)
return false;
//Perform a basic CRC check:
byte[] CRC = new byte[2];
GetCRC(data, ref CRC);
if (CRC[0] == data[data.Length - 2] && CRC[1] == data[data.Length - 1])
return true;
else
return false;
}
There is a CRC check and what is strange is that it never becomes true. The CRC calculation:
private void GetCRC(byte[] message, ref byte[] CRC)
{
ushort CRCFull = 0xFFFF;
byte CRCHigh = 0xFF, CRCLow = 0xFF;
char CRCLSB;
for (int i = 0; i < (message.Length) - 2; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
CRCLSB = (char)(CRCFull & 0x0001);
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);
if (CRCLSB == 1)
CRCFull = (ushort)(CRCFull ^ 0xA001);
}
}
CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
}
The problem is the use of ReadExisting(). It was not to be used in that manner as the buffer was being filled with useless data from the serial port. This problem was identified by #glace in the comments!
You first need to establish communication with your meters through some existing MODBUS master application like MODPOLL. Then, once you have communication working and having valid replies from your device, then and only then start testing your code. This way you make sure that problem can be only in your code and nothing else.
For example, to connect to two slave devices at the same time RS485 must be used instead of RS232, and this requests different wiring and RS485 to RS232 convertor on PC side.
Having RX and TX connected in RS232 for simulation purpose is not a good idea since each MODBUS message from a master (except broadcast messages) needs a reply which is different from just message echo. Also, each MODBUS message from a master has MODBUS client address embedded in it and only single client should reply to it (MODBUS is single master multiple slaves protocol).
As for a CRC calculation, this might help for MODBUS RTU protocol (ASCII is different):
function mb_CalcCRC16(ptr: pointer to byte; ByteCount: byte): word;
var
crc: word;
b, i, n: byte;
begin
crc := $FFFF;
for i := 0 to ByteCount do
if i = 0 then // device id is 1st byte in message, and it is not in the buffer
b := mb_GetMessageID; // so we have to calculate it and put it as 1st crc byte
else
b := ptr^;
Inc(ptr);
endif;
crc := crc xor word(b);
for n := 1 to 8 do
if (crc and 1) = 1 then
crc := (crc shr 1) xor $A001;
else
crc := crc shr 1;
endif;
endfor;
endfor;
Return(crc);
end;
function mb_CalcCRC: word; // Calculate CRC for message in mb_pdu
begin // this message can be one that is just received, or in a reply we have just composed
Return(mb_CalcCRC16(#mb_pdu[1], mb_GetEndOfData));
end;
That's a quote from a working embedded AVR device with implemented MODBUS RTU slave protocol.

Categories