Deserializing Protobuf c# from wire - c#

I am using the protobuf google implementation for c#.
The story so far..I have a server in c++ and clients in c# and the talk via protobuf messages with TCP.
On the client side, I retrieve the buffers returned from the tcpClient.BeginReceive via the callback provided and append them (so I guess it is cleared from the netstream junk). Then on a worker thread, I try to deserialize the messages.
On the server side the serialization code is:
google::protobuf::uint32 msgSize = msg->ByteSize();
int prefix_length = sizeof(msgSize);
int buffer_length = msgSize + prefix_length;
google::protobuf::uint8 buffer[buffer_length];
google::protobuf::io::ArrayoutputStream array_output(buffer, buffer_length, msgSize);
google::protobuf::io::CodedOutputStream coded_output(&array_output);
coded_output.WriteVarint32(msgSize);
msg->SerializeToCodedStream(&coded_output);
//Send to socket
mSendBuffer.Write(buffer, buffer_length);
On the client I read each chunk using CodedInputStream, read the first number and dispatch the prefix+the msg it contains for deserialization
Figuring out the length:
using (var input = new CodedInputStream(chunk))
{
int len = input.ReadInt32();
int requiredLength = len + input.Position; //(we re sure each time the codedInput starts from the beginning)
byte[] read = await AccumulateResources(requiredLength, chunk);
byte[] msg = new byte[requiredLength];
Buffer.BlockCopy(read, 0, msg , 0 , requiredLength);
Dispatch(msg);
}
Deserialization:
using (var ms = new MemoryStream(buff))
{
ServerMessageFrame msg = null;
try
{
msg = ServerMessageFrame.Parser.ParseDelimitedFrom(ms);
}
catch(Exception e)
{
Logger.Write(conn.clntPrefx + " " + e.ToString());
}
//Use the message
}
The error Messages I receive are:
1)System.InvalidOperationExeption: Wire Type is invalid
2)Protocol message contained invalid tag (zero).
The communication is correct at the beginning and it desyncs at some point, from where it breaks (until I read another msg which starts with a prefixed value aka is not a partial message)
My question is the de/serialization sound or I am missing the mark completely like there is something that I don't account for at all.

Related

C# Sockets send/receive problems and questions

Good morning all,
First of all apologies for the somewhat generic title. If in the course of this message I can come up with something a little more detailed, I will certainly change it.
I am working on a project that will contain 3 programs. The purpose is to be able to send a notification to all clients connected. For this there is a server, client, and console program.
The message itself will be an RTF file, but the notification also requires a sending department (string), and a display timer (TimeSpan).
Most of the project is done. The logic is mostly complete, it is multithreaded, all the classes are ready, and most tests work.
The problem I am having is that the server seems to not receive the data from the console in the right order. Thereby causing all sorts of problems.
The process from console to server is as follows:
Console first selects all relevant information for the notification:
Users (List, gathered from LDAP)
Expiration date and time (DateTime)
Time before close is allowed (long, amount of ticks)
Department (string)
RTF file
The server is already active, and has a separate thread for the console connections
Console connects to server
Server creates a separate thread to handle the console connection
Console sends the username of the logged on user to the server
Server checks whether user is allowed to create notification (for now it will always return true)
Console sends all the relevant information in the following order:
MessageID (string)
RecipientCount (number of users, used to loop appropriately from server side)
Recipients (foreach loop of List)
Department (string)
VisibleTime (long)
Expiration (DateTime)
and finally RTF file
I have used System.Diagnostics.Trace to check whether all information is sent correctly, and in the right order. This all checks out. But the thing is that roughly 75% of the time the server side seems to receive the RTF file at the moment it should be receiving the visibleTime.
The code is as follows:
private void SendMessage()
{
SendToServer(Environment.UserName);
if (bool.Parse(ReadFromServer()))
{
// User is allowed, continue
string messageID = DateTime.Now.ToUniversalTime().Ticks.ToString();
SendToServer(messageID); // MessageID
string recipientCount = lvRecipients.Items.Count.ToString();
SendToServer(lvRecipients.Items.Count.ToString()); // Amount of recipients
foreach (string item in lvRecipients.Items) // Loop to send each recipient
{
SendToServer(item);
}
string department = TB_Department.Text;
SendToServer(department); // Send department string
string visibleTime = TimeSpan.FromSeconds(SLIDER_VisibleTime.Value).Ticks.ToString();
SendToServer(visibleTime); // Send message visibility time
string expiration = DateTime.Now.ToUniversalTime().AddMinutes(2).ToString();
SendToServer(expiration); //TODO add UI control for this
SendRTFToServer(); // Send RTF file
MessageBox.Show(
"Your designated MessageID is: " + messageID + Environment.NewLine +
"Message upload is succesful.",
"Complete",
MessageBoxButton.OK);
}
else
{
// User is not allowed. Report to user. Disconnect (will be managed by the finally block)
MessageBox.Show(
"You are not allowed to upload messages to the server.",
"Access denied",
MessageBoxButton.OK,
MessageBoxImage.Stop);
return;
}
}
private void SendToServer(string toSend)
{
StreamWriter writer = new StreamWriter(server.GetStream());
writer.WriteLine(toSend);
writer.Flush();
}
private void SendRTFToServer()
{
StreamReader rtfFile = new StreamReader(File.Open(RTFLocation, FileMode.Open, FileAccess.Read));
StreamWriter sw = new StreamWriter(server.GetStream());
sw.Write(rtfFile.ReadToEnd());
sw.Flush();
server.GetStream().Flush();
}
private string ReadFromServer()
{
server.GetStream().Flush();
StreamReader reader = new StreamReader(server.GetStream());
return reader.ReadLine();
}
And from the server:
private void Connect()
{
string username = ReadFromConsole();
if (IsUserAllowed(username)) // Receive username
SendToConsole(bool.TrueString); // Send confirmation
else
{
SendToConsole(bool.FalseString); // Send denial
console.Close();
return;
}
string messageID = ReadFromConsole(); // Receive MessageID
string recipientCount = ReadFromConsole();
int numOfRecipients = int.Parse(recipientCount); // Receive and parse number of recipients
List<string> recipients = new List<string>();
for (int i = 0; i < numOfRecipients; i++)
{
string recipient = ReadFromConsole();
recipients.Add(recipient); // Receive recipient, add to list (required for Message)
}
string department = ReadFromConsole(); // Receive department string
string visibleTime = ReadFromConsole();
string expiration = ReadFromConsole();
StoreRTF(messageID); // Receive and store RTF file
console.Close(); // Connection is done, close
Message message = new Message(messageID, department, recipients, visibleTime, expiration);
}
private void SendToConsole(string toSend)
{
// Open client stream, and write information to it.
StreamWriter writer = new StreamWriter(console.GetStream());
writer.WriteLine(toSend);
writer.Flush();
}
private string ReadFromConsole()
{
// Read information from client stream
StreamReader reader = new StreamReader(console.GetStream());
return reader.ReadLine();
}
private void StoreRTF(string messageID)
{
// Check/create folder for Message storage
string messageFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\BMNotify\";
if (!Directory.Exists(messageFolder))
Directory.CreateDirectory(messageFolder);
// Create file to store message in
Stream rtfFile = File.Create(messageFolder + messageID + ".rtf");
// Store information from stream, and close resources
console.GetStream().CopyTo(rtfFile);
rtfFile.Close();
rtfFile.Dispose();
}
And the message class:
public class Message
{
internal string messageID;
internal string department;
internal List<string> recipients;
internal TimeSpan visibleAtLeast;
internal DateTime messageExpiration;
private static List<Message> allMessages; // Will hold te collection of Message's
public Message(string _messageID, string _department, List<string> _recipients, string visibleTime, string expiration)
{
messageID = _messageID;
recipients = _recipients;
department = _department;
visibleAtLeast = TimeSpan.FromTicks(long.Parse(visibleTime));
messageExpiration = DateTime.Parse(expiration);
if (allMessages == null)
allMessages = new List<Message>(); // Initialize if required
allMessages.Add(this);
}
internal Stream GetRTF()
{
return File.Open
(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\BMNotify\" + messageID + ".rtf",
FileMode.Open,
FileAccess.Read,
FileShare.Read);
}
static public List<Message> AllMessages()
{
if (allMessages == null)
allMessages = new List<Message>(); // Initialize if required
return allMessages;
}
static public void RemoveMessage(Message message)
{
allMessages.Remove(message);
}
}
If anyone could shed any light on this, or tell me what I should change.. Or basically anything that could get me going again, I would be very grateful!
Your problem may stem from the fact that you're using a StreamReader to read data from the connection. Internally StreamReader buffers data it reads from the underlying Stream. You are creating a new StreamReader every time you attempt to read from the connection, and then discarding it once you've read a single line. In doing so, you're also discarding any data read from the connection that was buffered by the StreamReader (which may have constituted all or part of the following fields).
You should probably attempt to create a single StreamReader on the network stream, and use that same instance for all reads.

C# AWS SQS Read all messages without deleting

I want to read all messages from queue in AWS SQS without deleting them , using C# , but I am only getting the single last message.
Here is the code
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
ReceiveMessageResponse rmrep = sq.ReceiveMessage(rmr);
ReceiveMessageResult rmres = rmrep.ReceiveMessageResult;
//DeleteMessageRequest dmr = new DeleteMessageRequest();
string msgid = "";
string rephandle = "";
XmlDocument xl = new XmlDocument();
for (int i = 0; i < rmres.Message.Count;i++ )
{
rmrep = sq.ReceiveMessage(rmr);
rmres = rmrep.ReceiveMessageResult;
object y = JsonConvert.DeserializeObject<object>(rmres.Message[0].Body);
int z= y.add();
MessageBox.Show(z.ToString());
}
A queue is not a database table; you can't just 'read all the messages'. You tell SQS you want some messages, it picks some and sends them to you; you can't ask it, or expect it, to iterate thru a unique list of messages in the queue and present them to you, it is not intended for that purpose.
If you read 1 or messages, and delete them (or put them in another queue), then eventually you can 'read all the messages', but as long as you don't delete any, its likely that you will keep getting served back some messages multiple times.
You are calling receive message multiple times and thus are not seeing some of your messages. Change your code to something like this:
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
while (true)
{
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
ReceiveMessageResponse response= sq.ReceiveMessage(rmr);
foreach (Message message in response.ReceiveMessageResult.Message)
{
MessageBox.Show(message.ReceiptHandle + ": " + message.Body);
}
}
NOTE: If there are enough messages in the queue (the number depends on the queue and is not documented), you will not be able to receive any more because you will reach your maximum number of in-flight messages.
Another NOTE: If this runs longer than your visibility timeout you will start receiving the same messages again.

netduino check email

I see lot of examples on how to send email with a but I'm looking to run an action checking an email account.
Does anyone know if that can be done (im sure it can) and point me to some examples?
There are a couple of ways you can get a gmail inbox.
OpenPop
If you do want to just use POP, and you do not mind using external libraries, this looks like the best/easiest way to go. OpenPop allows you to access a secure/unsecure email account and lets you choose the port. See this post to get started.
OpenPop is an open source C#.NET code bundle that implements mail
fetching and parsing. As of this writing, it only uses Microsoft .NET
framework libraries to do the required. But for accessing secure pop
servers, openPop can be extended by using some SSL library.
For example, to access Gmail via Pop:
POPClient poppy = new POPClient();
poppy.Connect("pop.gmail.com", 995, true);
poppy.Authenticate(username#gmail.com, "password");
int Count = poppy.GetMessageCount();
if (Count > 0)
{
for (int i = Count; i >= 1; i -= 1)
{
OpenPOP.MIMEParser.Message m = poppy.GetMessage(i, false);
//use the parsed mail in variable 'm'
}
}
TcpClient POP3:
To retrieve emails from any provider via Pop3, you could use a TcpClient. With Gmail, it is only slightly different, because Gmail uses SSL and port 995 for POP. There is an example of that here:
// create an instance of TcpClient
TcpClient tcpclient = new TcpClient();
// HOST NAME POP SERVER and gmail uses port number 995 for POP
tcpclient.Connect("pop.gmail.com", 995);
// This is Secure Stream // opened the connection between client and POP Server
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
// authenticate as client
sslstream.AuthenticateAsClient("pop.gmail.com");
Gmail Atom Feed:
The first way is to use GmailAtomFeed, which is part of the C# .Net Gmail Tools. The website says:
The GmailAtomFeed class provides a simple object layer for
programmatic access to gmails atom feed. In just a couple lines of
code the feed will be retreived from gmail and parsed. After that the
entries can be accessed through an object layer
AtomFeedEntryCollection, plus access to the raw feed and the feeds
XmlDocument is also available.
And this is an example of how you use it:
// Create the object and get the feed
RC.Gmail.GmailAtomFeed gmailFeed = new RC.Gmail.GmailAtomFeed("username", "password");
gmailFeed.GetFeed();
// Access the feeds XmlDocument
XmlDocument myXml = gmailFeed.FeedXml
// Access the raw feed as a string
string feedString = gmailFeed.RawFeed
// Access the feed through the object
string feedTitle = gmailFeed.Title;
string feedTagline = gmailFeed.Message;
DateTime feedModified = gmailFeed.Modified;
//Get the entries
for(int i = 0; i < gmailFeed.FeedEntries.Count; i++) {
entryAuthorName = gmailFeed.FeedEntries[i].FromName;
entryAuthorEmail = gmailFeed.FeedEntries[i].FromEmail;
entryTitle = gmailFeed.FeedEntries[i].Subject;
entrySummary = gmailFeed.FeedEntries[i].Summary;
entryIssuedDate = gmailFeed.FeedEntries[i].Received;
entryId = gmailFeed.FeedEntries[i].Id;
}
IMAP
Another way, if you are not LIMITED to POP, is to use IMAP. With IMAP, you can connect to a SSL server and choose a port along with that:
using (Imap imap = new Imap())
{
imap.ConnectSSL("imap.gmail.com", 993);
imap.Login("angel_y#company.com", "xyx***"); // MailID As Username and Password
imap.SelectInbox();
List<long> uids = imap.SearchFlag(Flag.Unseen);
foreach (long uid in uids)
{
string eml = imap.GetMessageByUID(uid);
IMail message = new MailBuilder()
.CreateFromEml(eml);
Console.WriteLine(message.Subject);
Console.WriteLine(message.TextDataString);
}
imap.Close(true);
}
I found this code online but "POP3_Client" isn't recognized and I don't see any refrences to add it
POP3_Client Mailbox = new POP3_Client(new >>>>IntegratedSocket<<<<<("pop.yourisp.com", 110), "yourusername", "yourpassword");
Mailbox.Connect();
Debug.Print("Message count: " + Mailbox.MessageCount.ToString());
Debug.Print("Box size in bytes: " + Mailbox.BoxSize.ToString());
uint[] Id, Size;
Mailbox.ListMails(out Id, out Size);
for (int Index = 0; Index < Id.Length; ++Index)
{
string[] Headers = Mailbox.FetchHeaders(Id[Index], new string[] { "subject", "from", "date" });
Debug.Print("Mail ID " + Id[Index].ToString() + " is " + Size[Index].ToString() + " bytes");
Debug.Print("Subject: " + Headers[0]);
Debug.Print("From: " + Headers[1]);
Debug.Print("Date: " + Headers[2]);
Debug.Print("======================================================================");
}
Mailbox.Close();

Weird Error when using SOAP Web Service

For a school project, I have to create a Java Server that is able to service a .NET client that has a Service Reference to a WSDL. I have the .NET Client code:
using (var client = new MathServiceWSDLClient())
{
Console.WriteLine("Multiplying " + Num1 + " and " + Num2 + ": " + client.Multiply(Num1, Num2));
Console.WriteLine("Adding" + Num1 + " and " + Num2 + ": " + client.Add(Num1, Num2));
}
I have also written the Java Server:
Scanner sc = new Scanner(socket.getInputStream());
boolean clientExpectContinue = false;
int contentLength = -1;
String line;
while (!(line = sc.nextLine()).isEmpty()) {
System.out.println(line);
if (line.startsWith("Content-Length")) {
String[] elements = line.split(": ");
contentLength = Integer.parseInt(elements[1]);
} else if (line.startsWith("Expect")) {
clientExpectContinue = true;
}
}
int notEmpties = 0;
byte[] soapEnvelopeData = new byte[contentLength];
char[] soapChars = new char[contentLength];
for (int i = 0; i < contentLength; i++) {
soapChars[i] = (char) socket.getInputStream().read();
if (i == 0)
System.out.println("DFSDFSDf");
}
// System.out.println(socket.getInputStream().read(soapEnvelopeData));
System.out.println(soapEnvelopeData.length);
File file = new File("tempEnvelope.txt");
FileOutputStream fileOut = new FileOutputStream(file);
// fileOut.write(soapEnvelopeData);
System.out.println("Content!");
System.out.println(new String(soapChars));
fileOut.write(new String(soapChars).getBytes());
fileOut.flush();
fileOut.close();
/* Some fancy SOAP and Reflection stuff that works */
The gist of the server is as follows:
It gets the incomming request, reads through the headers and finds the content length. It parses and saves this. From here there are two versions. The first constructs a byte array the same size as the content length, and passes the array as a parameter into the socket.getInputStream().read() method. The second constructs a char array the same length of the content and then reads individual bytes from the stream and casts them to chars.
The issue comes into play when, as shown, I attempt to run the .NET client with multiple requests in one execution. The first request goes off without any sort of discernible issue. When the second one comes in, the server reads the headers, gets the content length and constructs the array. When it comes time to read from the socket, however, the program just waits. Using the char array method, I was able to learn that it waits when reading the first value. Once one minute has expired, .NET times out, and the rest of the program breaks.
If, however, I leave the server running, and only have one request per execution of the .NET client, everything is just fine; the response comes back just as it should.
I have tried some solutions already:
Creating a new MathServiceWSDLClient for every request
Putting every request in its own using() block.
Doing two of the same request at once: two Multiply() or Add() requests.
Any help is appreciated. Thank you all in advance.
~Ryno Janse van Rensburg
.net is probably keeping the socket open for subsequent requests. There may be a bug in your server-like java code related to this.
Are you able to use a framework instead for the Java server code? I would strongly recommend this, and recommend rmbedded Jetty without hesitation. This would mean you wouldn't have to work at the socket level in Java - you can let Jetty handle all of that complication.

C# equivalent to Java SSL-socket-connection

Hey guys I'm trying to write an AXL-client (SOAP) for the Cisco Unified Communications Manager. For that purpose I need to establish an ssl-connection to the AXL-service. Unfortunatly I dont know much about all that ssl-stuff.
However I was able to find a working Java-example, that does, what I want. The problem is, i need that in C#.NET. So I'm hoping, that someone could "translate" the following Java-code in a C#-version. But it has to do exactly the same, espacially the authentication and certificate-stuff.
Here is the code:
String sAXLSOAPRequest = "...";
byte[] bArray = null; // buffer for reading response from
Socket socket = null; // socket to AXL server
OutputStream out = null; // output stream to server
InputStream in = null; // input stream from server
X509TrustManager xtm = new MyTrustManager();
TrustManager[] mytm = { xtm };
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, mytm, null);
SSLSocketFactory sslFact = (SSLSocketFactory) ctx.getSocketFactory();
socket = (SSLSocket) sslFact.createSocket("192.168.1.100", Integer.parseInt("8443"));
in = socket.getInputStream();
// send the request to the server
// read the response from the server
StringBuffer sb = new StringBuffer(2048);
bArray = new byte[2048];
int ch = 0;
int sum = 0;
out = socket.getOutputStream();
out.write(sAXLSOAPRequest.getBytes());
while ((ch = in.read(bArray)) != -1) {
sum += ch;
sb.append(new String(bArray, 0, ch));
}
socket.close();
// output the response to the standard output
System.out.println(sb.toString());
and this is the MyTrustManager-Class:
public class MyTrustManager implements X509TrustManager {
MyTrustManager() {
// create/load keystore
}
public void checkClientTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
Any help would be appreciated.
Thanks
edit: sorry i should have mentioned: youre right i can generate a proxy-class, but sadly its not working properly. cisco did a really bad job with that (not to mention the really bad documentation). the proxy class throws some xml-errors when parsing some responses. so i have to do it manually for that cases...
i'll worry about the certificate security later
Have you tried consuming the web service the "proper" way? Add a SOAP web service reference to your C# project in Visual Studio, gets the stubs etc? That's the easiest way of doing it from C#. You can just specify a https protocol in the URL when you add the reference.

Categories