On Sat, Aug 27, 2011 at 6:00 PM, Nader Salehi <[email protected]> wrote:
> Thanks for looking into the code. Please see my comments inline.
>
> On 8/27/2011 17:07 Jason Hsueh writes:
> > No, the issue is one and the same. You cannot receive arbitrary
> serialized
> > bytes and determine what the message type is. You can do something
> > heuristically, but there is no way for you to be absolutely certain of
> the
> > message type simply by looking at encoded bytes.
>
> Except that in this case, there is only one message. Both senders are
> sending the exact same message type. The difference is that messages
> coming from the Java sender won't get their field names displayed.
>
My point is that in the C++ client code, you are likely using the wrong
type. Instead of the actual message type, you get the first message type in
the transitive dependencies for which IsInitialized() succeeds after
ParsePartialFromString(). Given that you know the message type, you should
instantiate that type explicitly, rather than iterate over the list of all
known message types.
If you have the wrong message definition, then fields that don't match the
expected (number, wire type) pairs are treated as unknown fields. When you
print it out with DebugString(), these fields are printed using the tag
number.
>
> >
> > Specific points in the code:
> >
> > > C++
> > > void
> > > MessageDetector::insert (const pb::FileDescriptorSet &
> fDescSet,
> > > const string & typeName)
> > > {
> > > vector<DBContainerPtr>::iterator iter =
> > > std::find_if(dbContainerVec.begin(),
> > > dbContainerVec.end(),
> > > boost::bind(&DBContainer::operator(), _1)
> ==
> > > typeName);
> > > if (iter == dbContainerVec.end()) {
> > > // Need to add the file descriptor set to the data base
> > > cout << "Adding " << typeName << endl;
> > > cout << fDescSet.DebugString() << endl;
> > > shared_ptr<pb::SimpleDescriptorDatabase>
> > > db(new pb::SimpleDescriptorDatabase);
> > > for (int i = 0; i < fDescSet.file_size(); ++i) {
> > > assert(db->Add(fDescSet.file(i)));
> > > for (int j = 0; j <
> fDescSet.file(i).message_type_size();
> > ++j)
> > > {
> > > string formalName;
> > > formalName += fDescSet.file(i).has_package() ?
> > > fDescSet.file(i).package() + "." : "";
> > > formalName +=
> fDescSet.file(i).message_type(j).name
> > ();
> > > DBContainerPtr dbContainerElem(new DBContainer
> > (formalName,
> > >
> db));
> > > dbContainerVec.push_back(dbContainerElem);
> >
> > Here you add every message type found in the FileDescriptorSet into the
> list
> > of names.
> >
>
> And it is the correct approach, isn't it?
>
> >
> > > }
> > > }
> > > }
> > > }
> > >
> > > void
> > > MessageDetector::discoverAndDump (const string & msg)
> > > {
> > > bool found = false;
> > > for (int i = dbContainerVec.size() - 1; !found && i >= 0;
> --i) {
> > > pb::DynamicMessageFactory factory;
> > > const pb::Descriptor * desc =
> > > dbContainerVec[i]->pool.FindMessageTypeByName
> > > (dbContainerVec[i]->typeName);
> > > std::auto_ptr<pb::Message>
> > > revEngMessage(factory.GetPrototype(desc)->New());
> > > revEngMessage->ParsePartialFromString(msg);
> >
> > I glossed over the fact that you had actually used ParsePartialFromString
> and
> > call IsInitialized separately, but the effect is the same.
> > ParsePartialFromString will succeed on any bytes that are in the protocol
> > buffer encoding format. Again, this is true regardless of the source and
> > target message types.
>
> Agreed. I just use parse partial only to avoid G's standard error
> message when something can't be parsed.
>
> >
> > > if (revEngMessage->IsInitialized()) {
> >
> > This call _may_ return true if the message type has no required fields,
> or the
> > serialized bytes happen to contain values that correspond to the defined
> > required fields. It does not imply that the serialized bytes represent a
> > message of type dbContainerVec[i]. As such, you are likely breaking out
> of the
> > loop with the wrong message type.
>
> Correct.
>
> >
> >
> > > cout << revEngMessage->DebugString() << endl;
> > > found = true;
> > > }
> > > }
> > >
> > > if (!found) {
> > > cout << (dbContainerVec.size() == 0 ?
> > > "No valid announcement has been received" :
> > > "No message found for the message")
> > > << endl;
> > > }
> > >
> > > --
> > >
> > > --
> > > You received this message because you are subscribed to the
> Google
> > Groups
> > > "Protocol Buffers" group.
> > > To post to this group, send email to [email protected]
> .
> > > To unsubscribe from this group, send email to
> > > [email protected].
> > > For more options, visit this group at
> http://groups.google.com/group
> > /
> > > protobuf?hl=en.
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > Groups
> > > "Protocol Buffers" group.
> > > To post to this group, send email to [email protected].
> > > To unsubscribe from this group, send email to
> > > [email protected].
> > > For more options, visit this group at
> http://groups.google.com/group/
> > protobuf?
> > > hl=en.
> > >
> >
> > --
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Protocol Buffers" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to
> > [email protected].
> > For more options, visit this group at
> http://groups.google.com/group/protobuf?
> > hl=en.
> >
>
> --
>
--
You received this message because you are subscribed to the Google Groups
"Protocol Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/protobuf?hl=en.