open-dis / open-dis-java

Java implementation of the IEEE-1278.1 Distributed Interactive Simulation (DIS) application protocol v6 and v7 :boom:

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Application, Site & Entity values in EntityID should be short

IanMayo opened this issue · comments

I've encountered a problem, where my Application identifier can get mangled.

The API for EntityID allows site, application and entity to be stored as int values. But, on marshalling the data it gets converted to a short:

       dos.writeShort( (short)site);
       dos.writeShort( (short)application);
       dos.writeShort( (short)entity);

This will mangle the values if they are greater than 32768.

I was declaring (& sending) an application value of 230318, but my OriginatingEntityId was received as 33710.

I believe the correct fix is to change the storage & getters/setters of site, application and entity so that they handle short values, and correctly reflect the spec:
http://faculty.nps.edu/brutzman/vrtp/mil/navy/nps/disEnumerations/JdbeHtmlFiles/pdu/2c.htm

Each of those fields are 16 bits. So a value of 230318 is too large to represent.

If you need to represent more than 65536 entities what I've seen some sims do (e.g. JCATS) is spread them across multiple app id's.

Hi there @leif81,
isn't the tidy fix to change the storage format, so the compiler does the work for us?

https://github.com/open-dis/open-dis-java/pull/22/files#diff-1eb60207f4db64faccdc7d3109d35c8fR20

Hmm, have come across a similar occurrence. The exercise id should be 8 bits. But, the API is specifying a short then casting that to a byte:
https://github.com/open-dis/open-dis-java/blob/master/src/main/java/edu/nps/moves/dis/Pdu.java#L189

Well, I say _come across. I mean to say _spent 30 minutes trying to find out why the exercise id I was passing (2000) was arriving as a different value (208) ;-) . Correcting the API would prevent the next opendis user from encountering this problem (since the compiler would warn that 2000 was too large):

   dos.writeByte( (byte)protocolVersion);
   dos.writeByte( (byte)exerciseID);
   dos.writeByte( (byte)pduType);
   dos.writeByte( (byte)protocolFamily);

I'm happy to include this fix in my PR too. Is there any reason why we shouldn't correct the API?

@mcgredonps would know best for why an int was chosen. Most of the API is generated from xmlpg.

But I'm guessing an int was chosen because in Java there's no concept of an unsigned short. A Java short is 16 bits, but the problem I think with using that is it's signed so it only represents a valid range from -32,768 to 32,767. Where we want to able to represent 0 to 65536.

If the api were changed to a short, what happens when a value between 32,768 and 65536 is provided?

the exercise id I was passing (2000) was arriving as a different value (208)

That sounds like a similar problem. An ex id of 2000 is too large to represent according to the spec. The exercise id field is 8 bits. So valid range is 1-256.

But I'm guessing an int was chosen because in Java there's no concept of 
an unsigned short. A Java short is 16 bits, but the problem I think with using 
that is it's signed so it only represents a valid range from -32,768 to 32,767. 
Where we want to able to represent 0 to 65536.

Aaah, I guess this is the lesser of two evils.

Hmm, so how would my grief have been avoided? I guess I could add some code to throw a runtime exception is out-of-range values are assigned. That would have helped me to get to the bottom of my troubles.

What do you think?

I guess I could add some code to throw a runtime exception is out-of-range values are assigned.

Ya that's not a bad idea.

A challenge I'm starting to encounter is how to make changes to the API without creating larger and larger deltas with what XMLPG generates.

>  A challenge I'm starting to encounter is how to make changes to the API
>  without creating larger and larger deltas with what XMLPG generates.

Yes. I guess the first priority is to capture as many fixes as possible, then the second priority is to reduce the maintenance burden of applying them. Well, until the maintenance burden becomes too large for someone to take on, when it becomes the first priority :-D

Ya that makes sense 👍

I think the solution is to just change what XMLPG generates. It’s pretty agile about
mass changes. The problem is of course keeping the minor tweaks applied after
re-generating the code for things like VariableDatum. I’ve been using a patch
system—after the code is generated apply a Unix patch to tweak the code. But
if the code changes too much the patches start to fail.

Yes, the underlying problem was lack of unsigned shorts/ints in Java.

On Mar 4, 2016, at 7:34 AM, Leif Gruenwoldt <notifications@github.commailto:notifications@github.com> wrote:

I guess I could add some code to throw a runtime exception is out-of-range values are assigned.

Ya that's not a bad idea.

A challenge I'm starting to encounter is how to make changes to the API without creating larger and larger deltas with what XMLPG generates.


Reply to this email directly or view it on GitHubhttps://github.com//issues/21#issuecomment-192325330.

It’s possible to use the char type as a ghetto unsigned short in Java. I’s Unicode and two bytes
long, and can be used as a numeric type. but that’s likely to confuse everyone looking at the API,
and require all sorts of type conversions when performing operations. One could also use an
object in the place of a primitive, but that’s likely to cause a lot of memory bloat and GC issues.

The Ant build scripts have a section for applying a patch after the xmlpg code generation—it calls
a bash script in the patches directory:

case "$1" in
dis)
# Pdu.java, apply patch file
patch src/main/edu/nps/moves/dis/Pdu.java patches/dis/Pdu.patch

  # Marking.java, apply patch file to ensure character fields are exactly 11 bytes long after set operations
  patch src/main/edu/nps/moves/dis/Marking.java patches/dis/Marking.patch

Closing issue, it doesn't have a tidy resolution. The underlying problem relates to the lack of unsigned data types in Java.