UsbBulkInPipe doesn't return the actual values - c#

I am using UsbBulkInPipe to obtain data from my USB device. When I read data the length is correct but value are all zeros. How I can read the real data?
This is what I've tried:
UInt32 bytesRead = 0;
UsbBulkInPipe bulkIn = device.DefaultInterface.BulkInPipes[0];
var stream = bulkIn.InputStream;
DataReader reader = new DataReader(stream);
try
{
bytesRead = await reader.LoadAsync(bulkIn.EndpointDescriptor.MaxPacketSize);
}
catch (Exception exception)
{
//ShowStatus(exception.Message.ToString());
}
finally
{
byte[] value = new byte[bytesRead];
reader.ReadBytes(value);
}

At the moment I am using this method:
var t = reader.LoadAsync(buf.MaxPacketSize).AsTask(cancellationTokenSourceBulkIn.Token);
uint len = t.Result;
byte[] data = reader.ReadBuffer(len).ToArray();

Related

Cant decompress message from NetworkSteam(zlib)

I have problem.
I send XML request to NetworkStream, and i get answer [head] - not compressed, and [body] - compressed zlib.
When i used code
public static string UnZipStr(byte[] input)
{
using (MemoryStream inputStream = new MemoryStream(input))
{
using (DeflateStream gzip =
new DeflateStream(inputStream, CompressionMode.Decompress))
{
using (StreamReader reader =
new StreamReader(gzip, System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
I get error
System.IO.InvalidDataException: "Bad data detected during decoding."
I did delele [head](just dont read first 100 byte = size head), but result is same.
When i used it
private MemoryStream Deflate(byte[] data, int level, bool zlib)
{
var memoryStream = new MemoryStream();
var deflater = new Deflater(level, !zlib);
using (DeflaterOutputStream outStream = new DeflaterOutputStream(memoryStream, deflater))
{
outStream.IsStreamOwner = false;
outStream.Write(data, 0, data.Length);
outStream.Flush();
outStream.Finish();
}
return memoryStream;
}
My message is not true read. I dont know level, because i used all - from 1 to 9. And two time - with flags true and false.
Piece of uncompress message:
(��]�r�F\u0012}�W�����n��r�5\0F���ƅ\n��uT[�J�-���_��(Q$H��,��v�+���i#����\u0003��Vl˔h���ӧ/x������ã��\u000e��z��-g���O��\u001f��ۭ<�~\U00017b7f=���������_8Γ�\aG��;t���\u000f/
)
How can i decompress my message?
p.s. when server send me non-compress message - i get true message.
all my code. I just dont know, where can i mistake?
public string postXMLData(string request)
{
int port = XXXXX;
string ip = "XXX.XXX.XXX.XX";
int idClient = XXX;
StringBuilder response = new StringBuilder();
int byteSizeBuf = 1024;
byte[] buff = new byte[byteSizeBuf * 100];
byte[] byteRequest = Encoding.UTF8.GetBytes(request);
ConnectionMode connectionMode = ConnectionMode.Plain;
QueryHeader test = new QueryHeader(idClient, byteRequest.Length, connectionMode);
byte[] data = new byte[byteSizeBuf];
byte[] res = new byte[test.MessageLength + byteRequest.Length];
test.HeaderData.CopyTo(res, 0);
byteRequest.CopyTo(res, test.HeaderData.Length);
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(ip, port);
NetworkStream netStream = tcpClient.GetStream();
netStream.Write(res, 0, res.Length);
string final = response.ToString(); //куда записывать
int pos = 0;
do
{
int bytes = netStream.Read(data, 0, data.Length);
response.Append(Encoding.UTF8.GetString(data, 0, bytes));
data.CopyTo(buff, pos);
pos += data.Length;
}
while (netStream.DataAvailable);
string decodedStr = UnZipStr(buff);
netStream.Close();
tcpClient.Close();
return final;
}
I can't see any problem with your posted code. The problem must be in the code you didn't post. So, whatever is done in between of Deflate(...) and UnZipStr(...) it must have changed your compressed data.
Just try it yourself by directly using the output of Deflate(...) as the input of UnZipStr(...) :
Console.WriteLine(UnZipStr(
Deflate(System.Text.Encoding.UTF8.GetBytes("Hello World!"), 9, false).ToArray()
));

UWP c# read XML from StreamSocket

I'm trying to communicate with an XMPP (Jabber) server via a TCP network socket (StreamSocket) and I'm using the following code to read what the server has send to me:
StreamSocket tcpSocket;
StreamReader reader;
int BUFFER_SIZE = 4096;
// Connecting to a remote XMPP server ....
reader = new StreamReader(tcpSocket.InputStream.AsStreamForRead());
string result;
while (true)
{
result = "";
while (true)
{
char[] buffer = new char[BUFFER_SIZE];
await reader.ReadAsync(buffer, 0, BUFFER_SIZE);
string data = new string(buffer);
// Detecting if all elements in the buffer array got replaced => there is more to read
if (data.IndexOf("\0") >= 0 || reader.EndOfStream)
{
result + data.Substring(0, data.IndexOf("\0"));
break;
}
result += data;
}
Debug.WriteLine(result);
}
My Code works just fine for strings with a length < 4096 chars, but as soon as the string gets longer than 4096 chars it fails (won't detect the message end). It waits until it receives a new string < 4096 chars, concatenates both strings and returns them as one string.
Is there a way to get the actual length of a string and read them successively?
You have set 4096 to the BUFFER_SIZE and it is be set to the count parameter in StreamReader.ReadAsync and the char Array. When the string contain more than 4096 chars, it will fails.
You should be able to get the actual length in the Stream, we can use Stream.Length to get the length of the stream in bytes. The last char of Array is "\0". When you create the char Array, you should be able to set the Stream.Length plus one to the char Array.
For example:
StreamSocket socket;
StreamSocket tcpSocket;
StreamReader reader;
reader = new StreamReader(tcpSocket.InputStream.AsStreamForRead());
var BUFFER_SIZE=(int)(tcpSocket.InputStream.AsStreamForRead()).Length;
string result;
while (true)
{
result = "";
while (true)
{
char[] buffer = new char[BUFFER_SIZE+1];
await reader.ReadAsync(buffer, 0, BUFFER_SIZE);
string data = new string(buffer);
if (data.IndexOf("\0") >= 0 || reader.EndOfStream)
{
result = data.Substring(0, data.IndexOf("\0"));
break;
}
result += data;
}
Debug.WriteLine(result);
}
If you want to reads all characters from the current position to the end of the stream, you can use StreamReader.ReadToEnd or StreamReader.ReadToEndAsync method.
I finally figured out to read long messages:
I had to user DataReader and DataWriter instead of StreamReader and StreamWriter.
/// <summary>
/// How many characters should get read at once max.
/// </summary>
private static readonly int BUFFER_SIZE = 4096;
private StreamSocket socket;
private DataReader dataReader;
private DataWriter dataWriter;
public string readNextString() {
string result = "";
readingCTS = new CancellationTokenSource();
try {
uint readCount = 0;
// Read the first batch:
Task < uint > t = dataReader.LoadAsync(BUFFER_SIZE).AsTask();
t.Wait(readingCTS.Token);
readCount = t.Result;
if (dataReader == null) {
return result;
}
while (dataReader.UnconsumedBufferLength > 0) {
result +=dataReader.ReadString(dataReader.UnconsumedBufferLength);
}
// If there is still data left to read, continue until a timeout occurs or a close got requested:
while (!readingCTS.IsCancellationRequested && readCount >= BUFFER_SIZE) {
t = dataReader.LoadAsync(BUFFER_SIZE).AsTask();
t.Wait(100, readingCTS.Token);
readCount = t.Result;
while (dataReader.UnconsumedBufferLength > 0) {
result += dataReader.ReadString(dataReader.UnconsumedBufferLength);
}
}
}
catch(AggregateException) {}
catch(NullReferenceException) {}
return result;
}

Parsing variable-sized packets

I'm working on a multiplayer game and I'm having an issue with the the way I parse the packets from the connection. When I'm debugging the game it runs at a lower performance and the packets are received, when I'm not, packets aren't fully received and the ParsePacket method isn't called.
My packet structure is this:
2 Bytes Short Command, 2 Bytes Short Payload Size, (Optional) Payload Bytes
IInputStream inputStream = null;
DataReader dataReader = null;
byte[] data = new byte[1024];
IBuffer buffer = data.AsBuffer();
try
{
inputStream = StreamSocket.InputStream;
dataReader = DataReader.FromBuffer(buffer);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataReader.ByteOrder = ByteOrder.LittleEndian;
while (connected)
{
await inputStream.ReadAsync(buffer, 1024, InputStreamOptions.Partial);
Debug.WriteLine("Buffer " + buffer.Length);
if (buffer.Length >= PacketHeaderSize)
{
short command = dataReader.ReadInt16();
short payloadSize = dataReader.ReadInt16();
byte[] payload = null;
if (payloadSize == 0)
{
UpdateBuffer(buffer, (uint)(PacketHeaderSize + payloadSize));
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
}
else if (payloadSize > 0)
{
if (buffer.Length >= (PacketHeaderSize + payloadSize))
{
payload = new byte[payloadSize];
dataReader.ReadBytes(payload);
UpdateBuffer(buffer, (uint)(PacketHeaderSize + payloadSize));
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
}
}
}
}
}
catch (Exception e) {
// ...
}
private void UpdateBuffer(IBuffer buffer, uint bytesRead)
{
if (buffer.Length > bytesRead)
{
byte[] bufferBytes = new byte[buffer.Length - bytesRead];
System.Buffer.BlockCopy(buffer.ToArray(), (int)bytesRead, bufferBytes, 0, (int)(buffer.Length - bytesRead));
buffer = bufferBytes.AsBuffer();
}
else
{
byte[] bufferBytes = new byte[1024];
buffer = bufferBytes.AsBuffer();
}
}
What I'm doing wrong?
Things fixed to make this work:
Take important variables outside the parsing packets loop as we need the value next time we need to parse another packet.
Read the packet header once if a incomplete app or game packet is received.
Load only the bytes we need
Read the header and payload once it has been fully received using UnconsumedBufferLength.
Code:
short command = 0;
short payloadSize = 0;
byte[] payload = null;
bool packetHeaderRead = false;
while (connected)
{
if (!packetHeaderRead)
{
if (dataReader.UnconsumedBufferLength < PacketHeaderSize)
{
int headerBytesLeft = PacketHeaderSize - (int)dataReader.UnconsumedBufferLength;
if (headerBytesLeft > 0)
{
await dataReader.LoadAsync((uint)headerBytesLeft);
continue;
}
}
else
{
command = dataReader.ReadInt16();
payloadSize = dataReader.ReadInt16();
packetHeaderRead = true;
continue;
}
}
else
{
int payloadBytesLeft = payloadSize - (int)dataReader.UnconsumedBufferLength;
if (payloadBytesLeft > 0)
{
await dataReader.LoadAsync((uint)payloadBytesLeft);
}
if (payloadSize == 0)
{
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
packetHeaderRead = false;
}
else if (dataReader.UnconsumedBufferLength >= payloadSize)
{
payload = new byte[payloadSize];
dataReader.ReadBytes(payload);
Packet packet = new Packet(command, payloadSize, payload);
ParsePacket(packet);
packetHeaderRead = false;
}
}
}

Streaming image over ssl socket doesn't come across correctly

I'm trying to securely transfer files between 2 devices, so I'm using an SslStream attached to a TcpClient. Documents and text files come across just fine, but image files don't show up correctly. The following is the server code:
listener = new TcpListener(IPAddress.Any, 1337);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback), new LocalCertificateSelectionCallback(CertificateSelectionCallback));
var certificate = Connection.GetClientCertificate(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
try
{
sslStream.AuthenticateAsServer(certificate, true, SslProtocols.Default, true);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
var messageData = ReadMessage(sslStream);
var mode = messageData[0];
var tokenBytes = messageData.Splice(1, 16);
var fileNameBytes = messageData.Splice(17, 128);
var fileBytes = messageData.Splice(146);
var fileName = Encoding.ASCII.GetString(fileNameBytes).TrimEnd('\0');
using (var tempFile = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
{
tempFile.Write(fileBytes, 0, fileBytes.Length);
tempFile.Flush();
}
if (mode == 0)
tempFiles.Add(fileName);
Process.Start(fileName);
}
catch (AuthenticationException e)
{
MessageBox.Show("The other side failed to authenticate.");
}
finally
{
sslStream.Close();
client.Close();
}
}
And ReadMessage is defined as follows:
private static byte[] ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[2048];
MemoryStream stream = new MemoryStream();
int bytes = -1;
while (bytes != 0)
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
stream.Write(buffer, 0, bytes);
}
return stream.ToArray();
}
And then the client code is this:
TcpClient client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Parse(ip), 1337));
SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback), new LocalCertificateSelectionCallback(CertificateSelectionCallback));
var certificate = Connection.GetClientCertificate(ip);
try
{
sslStream.AuthenticateAsClient(ip, new X509CertificateCollection() { certificate }, SslProtocols.Default, false);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
sslStream.Write(data);
}
catch (AuthenticationException e)
{
MessageBox.Show("The other side failed to authenticate.");
}
finally
{
sslStream.Close();
client.Close();
}
And the code that calls into it just does:
var fileBytes = File.ReadAllBytes(file);
var tokenBytes = Encoding.UTF8.GetBytes(token);
var fileNameBytes = Encoding.UTF8.GetBytes(Path.GetFileName(file));
var buffer = new byte[145 + fileBytes.Length];
buffer[0] = 1;
for (int i = 0; i < 16; i++)
{
buffer[i + 1] = tokenBytes[i];
}
for (int i = 0; i < fileNameBytes.Length; i++)
{
buffer[i + 17] = fileNameBytes[i];
}
for (int i = 0; i < fileBytes.Length; i++)
{
buffer[i + 145] = fileBytes[i];
}
SocketConnection.Send(ip, buffer);
Is there anything inherently wrong with what I'm doing, or do I need to do something different for images?
EDIT: I have changed it to reflect the current code, and also, after doing a dump of the raw bytes on both ends, it looks like for some reason the bytes are getting rearranged when they come over the wire. Is there any way to ensure that the bytes come across in the original order?
In ReadMessage you're writing bytes.Length bytes to the stream, regardless of the number of bytes that were actually read. Try:
private static byte[] ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[2048];
MemoryStream stream = new MemoryStream();
int bytes = -1;
while (bytes != 0)
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use "bytes" instead of "buffer.Length" here
stream.Write(buffer, 0, bytes);
}
return stream.ToArray();
}
Based on your follow-up, you're also taking the file data from the wrong point in the buffer, and so you're losing the first byte of the file.
Your code should be:
var fileBytes = messageData.Splice(145); // File data starts at 145, not 146
Is this possibly a conflict between endianness? If the bytes from the server are ABCDEF and the client is seeing the image bytes as BADCFE then that's the issue.
I haven't worked with image files, but when I read a short or an int instead of a String from the bytes coming in over the wire, I do something like this:
int intFromStream = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(byteArrayWithLength4, 0));

MSMQ c++ to c# problem

I want to write messages to a MSMQ queue using C++ and read them using C#.
I send the messages as strings.
It works fine if I both write and read the messages in C++ but if I try to read the message using C#, I get only the first character of the message. (eg: I send "abcd" and I receive only "a").
I also must mention that I am using this code in Windows Mobile.
Here is the c++ code:
HRESULT MSMQManager::WriteMessage(LPWSTR text){
// define the required constants and variables.
const int NUMBEROFPROPERTIES = 5; // number of properties
DWORD cPropId = 0; // property counter
HRESULT hr = MQ_OK; // return code
HANDLE hQueue = NULL; // queue handle
// define an MQMSGPROPS structure.
MQMSGPROPS msgProps;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
HRESULT aMsgStatus[NUMBEROFPROPERTIES];
// message label
aMsgPropId[cPropId] = PROPID_M_LABEL;
aMsgPropVar[cPropId].vt = VT_LPWSTR;
aMsgPropVar[cPropId].pwszVal = L"msg";
cPropId++;
// message body
aMsgPropId[cPropId] = PROPID_M_BODY;
aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1;
aMsgPropVar[cPropId].caub.pElems = (LPBYTE)text;
aMsgPropVar[cPropId].caub.cElems = wcslen(text)*2;
cPropId++;
// message body type
aMsgPropId[cPropId] = PROPID_M_BODY_TYPE;
aMsgPropVar[cPropId].vt = VT_UI4;
aMsgPropVar[cPropId].ulVal = VT_LPWSTR;
cPropId++;
// initialize the MQMSGPROPS structure.
msgProps.cProp = cPropId;
msgProps.aPropID = aMsgPropId;
msgProps.aPropVar = aMsgPropVar;
msgProps.aStatus = aMsgStatus;
// Call MQSendMessage to send the message to the queue.
hr = MQSendMessage(
this->writeHandle, // Queue handle
&msgProps, // Message property structure
MQ_NO_TRANSACTION // Not in a transaction
);
Here is the c# code:
public string ReadMessageUnformatted()
{
try
{
Message received;
Stream bodyStream = null;
StreamReader sr = null;
char[] buffer = new char[256];
received = this.readMQ.Receive();
bodyStream = received.BodyStream;
sr = new StreamReader(bodyStream);
//this.lastReceived = sr.ReadLine();
sr.Read(buffer, 0, 256);
this.lastReceived = new string(buffer);
return lastReceived;
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString(), "Exception");
return null;
}
}
I am using BodyStream instead of Body for the message because I don't want to use any message formatter.
Thanks
I solved myself the problem. I shall post here the code maybe there is someone else interested.
try
{
Message received;
Stream bodyStream = null;
int bufLength = 512;
byte[] buffer = new byte[bufLength];
received = this.readMQ.Receive();
bodyStream = received.BodyStream;
bodyStream.Read(buffer, 0, bufLength);
this.lastReceived = Encoding.Unicode.GetString(buffer, 0, buffer.Length);
return lastReceived;
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString(), "Exception");
return null;
}
Maybe you can try:
aMsgPropVar[cPropId].ulVal = VT_BSTR;
VT_BSTR is used to indicate a unicode string.
VT_LPWSTR needs to be null-terminated, which I don't think your string is.

Categories

Resources