6

What I am doing is attempting to send an IPEndpoint through protobuf-net and what I observed is that when deserializing the array of 4 bytes into the IP4 address, the set code recieves a value of 8 bytes. Four bytes containing the orignal address, and 4 more bytes containing the address that was serialized. By stepping through the code I have been able to confirm that when Deserialize is called, it first reads the bytes, and then sets they bytes.

After doing some reading I learned about OverwriteList, and as can been seen in the example below, I have set that to true. However the setter is still provided an 8 byte value.

Does anyone have a clue what I am doing wrong?

This sample code should throw an exception when used with protobuf-net r480, Visual Studio 2010 as a .Net 4.0 console application.

using ProtoBuf;
using System.Net;
using System.IO;

namespace ConsoleApplication1
{

    [ProtoContract]
    class AddressOWner
    {
        private IPEndPoint endpoint;

        public AddressOWner() 
        { endpoint = new IPEndPoint(new IPAddress(new byte[] {8,8,8,8}), 0); }

        public AddressOWner(IPEndPoint newendpoint)
        { this.endpoint = newendpoint; }

        [ProtoMember(1, OverwriteList=true)]
        public byte[] AddressBytes
        {
            get { return endpoint.Address.GetAddressBytes(); }
            set { endpoint.Address = new IPAddress(value); }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            AddressOWner ao = new AddressOWner(new IPEndPoint(new IPAddress(new byte[] { 192, 168, 1, 1 }), 80));

            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, ao);
            byte[] messageData = ms.GetBuffer();
            ms = new MemoryStream(messageData);
            AddressOWner aoCopy = Serializer.Deserialize<AddressOWner>(ms);
        }
    }
}
William Leader
  • 814
  • 6
  • 20

1 Answers1

3

It looks like this is actually a bug, specific to byte[], which is handled as a particular protobuf primitive. Other arrays/lists are mapped to repeated (in protobuf terms), and handle the OverwriteList option correctly. I will tweak the byte[] handling to support this option.

Edit: this is fixed in r484, with supporting integration test

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I tried to build from source and I thought I was successful, but the dll I created still had the same behavior. Is there any kind of release schedule? My work around for now is to copy the right bytes to a new array during the property setter. – William Leader Feb 05 '12 at 02:58
  • @William as soon as I've validates some other fixes. – Marc Gravell Feb 05 '12 at 09:04
  • I'm using the version 2.0.0.480 from Nuget which contains this bug. It would be great to have a newer package available, or at least some kind of workaround. – Jozef Izso Aug 01 '12 at 14:38
  • @Josef yes, it is a bit behind; the trunk is on r560. I have one potential regression to address, but I'll try to deploy soon. – Marc Gravell Aug 01 '12 at 19:59
  • 1
    Is there some possibility that this exists in protobuf-net version 2.0.0.640 when working with arrays of 8 bytes? It generates 16 bytes on deserialization – Bob Claerhout Nov 12 '13 at 13:47
  • @BobClaerhout: this is an old comment, but I just noticed this behavior and didn't know about until now. If you didn't specify `OverwriteList = true` explicitly, then it's not a bug, since Protobuf spec says that arrays should be *appended* on deserialization, if they already contain some elements. This is indeed not too "idiomatic" for C#, since mutating array size is usually considered bad practice, especially if the array property has a public setter. Anyway, specifying `[ProtoMember(OverwriteList = true)]` on that property would tell protobuf-net to overwrite the array. – vgru Aug 11 '17 at 15:50