kimononet's People
Forkers
ebollenskimononet's Issues
Other Issues
Hey Zorayr, it seems there are other issues with your code. I hope you don't mind that I try to help you to fix these issues. You can always do a diff to see the changes.
Data Header Size
The protocol specifies:
"The total length of the Type 0 header format, including the common header, is 92 bytes."
I believe it should be 96 bytes.
The common header is 48 bytes according to the protocol and the Type 0 header consists of:
HDR-DST-ID (8)
HDR-DST-LOC (24)
HDR-FWD-DST-ID (8)
HDR-FWD-MODE (1)
HDR-DATA-LEN (2)
HDR-QOS (1)
HDR-HDR-CHK (4)
Total: 48
48+48 = 96 not 92
Services and Threads
Hi Zorayr,
Once a thread has been started, it cannot be started again, even if you stop it first. You must create a new thread if you want to start it again, or else you get IllegalThreadStateException
(http://stackoverflow.com/questions/1215548/is-it-legal-to-call-the-start-method-twice-on-the-same-thread).
Therefore, I modified the PeerAgent.startServices()
method as follows:
public void startServices(){
//Create the services used by the agent.
this.beaconService = new BeaconService(this);
this.geoService = new GeoService(this);
this.geoService.startService();
this.beaconService.start();
}
Instead of instantiating new BeaconService
and GeoService
objects in the constructor of PeerAgent
, I do it every time the services are started.
Even though I fixed the issue, I'm still leaving it open so you will be aware of it.
No Need for External Swing/Forms Packages for Simulation UI
Hi James,
I just noticed that you are using external libraries for doing GUI designs, and I was wondering why? If possible, could you please only utilize Javax Swing library? This native Java library "provides a set of 'lightweight' (all-Java language) components that, to the maximum degree possible, work the same on all platforms." If we introduce an external library we might jeopardize platform-independence and produce code that is much harder to maintain and distribute. For a small project like this, I am confident that Java's native capabilities will suffice.
I also suggest you take a look at Java Layout Managers. I took a quick glance at your code and it seems like you are using an external library for doing layout. Try to achieve the same effect using these Layout Managers instead.
Let me know if you have any questions regarding Javax Swing or Layout Managers and I will try to help you out. The book is also a very helpful resource.
Beacon Algorithm Excludes Trivial Case
Although it's clear from the context, it would be correct to include what happens when a beacon arrives from a completely new peer. Here is an excerpt form the current version of the protocol that describes beacon exchange:
When PKT-BEACON arrives via UDP broadcast:
• If HDR-SRC-ID is the same as the node's ID:
o Discard PKT-BEACON and exit.
• If HDR-SRC-LOC is newer than ROUTING-TABLE[HDR-SRC-ID],
o Update ROUTING-TABLE[HDR-SRC-ID] = HDR-SRC-LOC
• For each NEIGHBOR-REPORT:
o If NEIGHBOR-LOC is newer than ROUTING-TABLE[NEIGHBOR-ID]
Update ROUTING-TABLE[NEIGHBOR-ID] = NEIGHBOR-LOC
• Create PKT-BEACON-ACK for node and send via UDP broadcast.
• Reset TMR-BEACON.
Simulation Functionality Overview and Changes
The following still needs to be done for the simulation component:
UI Changes
- [DONE] Create full screen frame display.
- [DONE] Functionality for changing map dimensions.
- [DONE] Disable editing property names.
- [DONE] Add grid display for a map.
- [DONE] Add some indication of a simulation running state i.e. green icon for running/red icon for stopped.
- [DONE] Side note: to start the simulation for node, click on the
startServices()
for each node. - [DONE] Change UAV image. Also the image should be much smaller.
- [DONE] Once Zorayr has the StatData completed, use the data to update the statistics info. Again, make this into a method that takes in a StatData object and displays the result.
- [DONE] Add delete peer button.
- [DONE] Add labels on top of content boxes i.e. "Peers", "Peer Property", "Environment Properties".
- [DONE] Create environment variables display. Cane make it similar to the table.
Node Simulation
- [DONE] Translate node's current location to (x,y) position on the map.
- [DONE] Direct the node's image to the specified bearing value.
- [DONE] Use a polling architecture to draw each node on the map at a certain interval.
- [DONE: All UI updates are done by the
Simulation.refresh()
method. This method also forces a repaint of theSimulationPanel
. All the painting is done bySimulationPanel.paintComponent()
] Make sure to encapsulate node drawing/handling functionality inside a single method.
OO Changes
- [DONE] Encapsulate functionality within PeerPropertiesTable, PeerList, EnvironmentPropertiesTable, and also StatDisplay class.
ToDo: Zorayr
- Add random address factory method to the PeerAddress class
- Add address validation static method to the PeerAddress class
- Implement random waypoint within the GeoDevice
- Implement statistics analysis within StatData class.
- Create StatResults class
Packet Format and Types
The idea is to have a superclass Packet object that can encapsulate common packet handling and assembling functionality. With this scheme each packet will consist of a constant length header section and a variable length content section. Furthermore, header section with a total of 12 bytes will include the following fields:
- magic flag (2)
- version flag (1)
- type (1)
- timestamp (8)
Packet type is a flag represented by a single byte and supports the following types:
- BEACON (0x01)
- HANDSHAKE (0x02)
- DATA (0x03)
Given this parent Packet class, various subclasses such as BeaconPacket, DataPacket, etc. will add more functionality to the generic packet class and add meaning to the contents field.
Is there anything else to add to this packet structure? Hop count? or TTL?
Gathering and Analyzing Data
Previously, @james-h concluded that the following are important factors for analyzing the results:
- Packets Lost: Number of packets lost.
- Packet Delivery Percentage: (Number of data packets successfully received by destination nodes) / (Total number of data packets sent by source nodes)
- Routing Packet Overhead: (Number of control packets) / (Number of successfully received data packets)
- Average Latency: The mean time (in seconds) taken by the data packets to reach their respective destinations.
What would be the best way to gather the data required for these calculations without adding too much overhead to the current implementation?
Max Number of Neighbors to Include in a Beacon/BeaconAck Packet.
There are two options to determine the number of neighbors to include in type-2/3 packets:
- Max out the packet space. In other words, somehow calculate what is the maximum number that can fit inside a packet.
- Have a constant number of neighbors that should be included in the packet.
With option (1) efficiency and complexity is an issue, while (2) might not be the best solution.
PeerAddress.PeerAddress(Parcel parcel)
Hi Zorayr,
(1) I noticed that before using PeerAddress.PeerAddress(Parcel parcel)
, the parcel must be rewound by the caller.
(2) Also, after using the parcel, the parcel must be rewound again if it is to be used a second time by the caller.
Are these things intentional?
James
Port Configuration Issues in Simulation Mode
Given that two sockets cannot be bound to the same port number within a simulation environment, there needs to be a way of selecting different port numbers that don't conflict with each other. Several solutions that are available are described bellow:
Use Peer's MAC Address or Peer's Name
It seems that since all peers have a unique MAC address it would be easy to convert this address to unique port numbers. However, this is not very simple as a MAC-48 is only 6 bytes (including padding, 8) and port numbers are represented by 4 byte integers. How would you generate three different unique port numbers given one MAC address?
Have two Operational Modes
The best approach although with a bit of complexity is to add a layer of abstraction for selecting port numbers and implement two versions of this abstraction: a simulation mode and a production mode. In case of the simulation mode, the abstraction will issue unique port numbers to a peer and will store it in a <peer, port-number> mapping for the rest of the peers to see. On the production version, with much less complexity, port numbers will be hard coded or set within the environment variables. In production mode, it is assumed that each peer will most likely get an individual NIC to work with and hence, eliminate the conflicting-port number issue.
Given these two scenarios, I would appreciate some feedback or comments before moving forward. Is there anything I haven't thought about or a use case I didn't include?
All Services Must Implement Service Interface
Any thread or object that can be started or shutdown must implement kimononet.service.Service
interface which mandates objects to include two methods: startService()
and shutdownService()
.
Utilizing this approach will allow a consistent way to start or stop services such as beacon service, data service, and also monitoring services.
How to access routing table
How do I access the routing tables for forwarding packets in the data service. @zkhalapyan, this should be updated and maintained by the beacon service correct?
I think I am blocked from implementing any routing on this presently, unless it has been implemented somewhere I can't find.
PeerAddress.hashCode()
In PeerAddress.hashCode()
, I think you need to first rewind the newly-created parcel before doing getInt
or else it will crash.
Bugs in Protocol Documentation
On pg 28
Setup of XHDR fields is flawed.
and in else statement should invoke GREEDY not PERIMETER
Peer GeoLocation seems to not work
Finally realized while testing my code that it was dropping packets because all nodes were the same distance away. Checked into this and it seems that all Peers I create are at location 0, 0 no matter what.
System.out.println("Starting Simulation");
PeerAddress addressA = new PeerAddress("12:00:00:00:00:00");
GeoLocation locationA = new GeoLocation(2000.0, 2000.0, 1.0f);
PeerAddress addressB = new PeerAddress("12:00:00:00:00:01");
GeoLocation locationB = new GeoLocation(0.0, 0.0, 1.0f);
final Peer peerA = new Peer(addressA, locationA, new GeoVelocity(0f, 0f));
final PeerAgent agentA = new PeerAgent(peerA);
agentA.startServices();
System.out.println("PeerA Location:\n"+agentA.getPeer().getLocation());
final Peer peerB = new Peer(addressB, locationB, new GeoVelocity(0f, 0f));
final PeerAgent agentB = new PeerAgent(peerB);
agentB.startServices();
System.out.println("PeerB Location:\n"+agentB.getPeer().getLocation());
Output:
Starting Simulation
PeerA Location:
Longitude: 0.0 Latitude: 0.0 Accuracy: 0.0 Timestamp: Mon Jan 05 16:49:37 PST 1970
PeerB Location:
Longitude: 0.0 Latitude: 0.0 Accuracy: 0.0 Timestamp: Mon Jan 05 16:49:37 PST 1970
Computing New Location from Bearing, Lon, Lat and Time
Zorayr, how do you propose we compute new locations based on bearing, longitude, latitude and time? I can't seem to find any formulas that handle this simply, but I'm rusty on my spherical polar geometry...
More GeoVelocity Issues
In GeoVelocity.java:
- Why is PARCEL_SIZE = 12, but in toParcel() the size of the new Parcel = 24?
- In toString(), I think you should ensure that currentLocation is not null.
6.3.2. Perimeter Forwarding (FN-RT-PERIMETER) Needs Full Circle Check
Pending Wade determining what needs to be checked for full circle to be detected.
Re-Forming Data Packet When Entering Perimeter Mode
Should we incude a blank extended header all along or should we reformat the data packet to add a extended header when we enter into perimeter mode. Since adding this extra header segment will make the packet a different length we will have to create a whole new packet when entering perimeter mode.
Basically what is more important time or packet size?
Peer.Peer(Parcel parcel)
The constructor Peer.Peer(Parcel parcel)
simply passes the parcel to Peer.parse(Parcel parcel)
without setting the name of the peer. Since the parcel does not contain an entry for the name, would it be a good idea that the name defaults to "unnamed-peer"
?
Parcel.add(int index, long data) and Parcel.getParcelSize()
Hi Zorayr,
After calling Parcel.add(int index, long data)
to add long
s to an empty Parcel
, Parcel.getParcelSize()
seems to always return 0. Is that intentional or not?
James
CRC Placement within Packets
Implementation-wise, it is much more convenient to place checksums at the end of the packet. Accordingly, beacon packet's field members should be ordered as such:
- Neighboring Peer Count
- Neighboring Peer Reports
- CRC32
Packet Handling Design Concepts
There are three different types of packets that KimonoNet either sends or receives: beacon packets, beacon ack packets, as well as data packets. To handle these packets, there are three opposing design concepts:
Multi-Service Approach
Each type of packet will be associated with a specific service, which in most generic terms, is considered to be an individual, running thread. As such, any peer will have a beacon sending service, beacon receiving service (this service will be primarily listening to incoming beacons or beacon ACKs and respond accordingly), and also data sending service, and a data receiving service. Although this design is very modularized and object oriented, it suffers from efficiency issues as broadcast packets will be handled in several services and discarded in all except one.
Multi-Service, Non-Broadcast Approach
Yet another approach is to modify the multi-service approach in a way that each service will listen to a specific port; hence, proving broadcast packets unnecessary. This seems a like a nice design, but running multiple peers bound on the same port numbers on a single simulation machine is impossible i.e. two sockets cannot be pound to port 80.
Dual-Service Approach
With this design approach, there will be two services running: one service for receiving packets and one service for sending packets. Upon receiving a packet, the receiving service will add it to a Beacon Queue, Beacon Ack Queue, or Data Queue depending on the packet type and will assume that the packet will be handled accordingly within a beacon service, beacon ack service, or the data service. If at any time a service would like to send a packet, it enqueues the packet into a sending service's priority packet queue whereby the packet will be send as soon as it is popped. The advantage of using this design is that all broadcast packets will be handled once and will only be two network-related services running at any time. However, the design adds an additional layer of services above the network services that have to be maintained.
Would appreciate some feedback on this issue.
Calculating and Representing Vectors/Velocity with GPS Locations
I am currently representing GeoVectors with <dLongitude/dt, dLatitude/dt> calculated by <(Longitude_Current - Longitude_Previous)/dt, (Latitude_Current - Latitude_Previous)/dt>, where dt is calculated by timestamp_current - timestamp_previous.
Is this a correct representation for the algorithms? Another possibility is to convert this into meters/second, or various other forms.
Another question is how to calculate the difference between two GPS points that have different accuracies?
Packet.toString()
In Packet.toString()
maybe you should check if peer == null
.
Simulation UI
Hi Zorayr,
I started making the simulation user interface. I'm wondering where I should put my code. In a new package? I would like to know before I push the code for everyone to see.
Thanks.
James
Add Line to Change FWD Mode to Perimeter in Protocol
pg 29 after "If HDR-FWD-MODE is FWD-GREEDY" we need a bullet that is "Set HDR-FWD-MODE to FWD-PERIMETER"
Packet.toParcel()
For Packet.toParcel()
it might be a good idea to throw an exception if peer == null
.
dTime
GeoVelocity.java line 98: I think you calculated dTime incorrectly, because it is negative.
Typo in protocol.docx
Hi Eric,
I believe there is a typo in protocol.docx under the section 4.1.2. Common Header Format:
The common header has a total length of 48 bytes.
should be
The common header has a total length of 44 bytes.
James
Peer.parse(Parcel parcel)
I think this might be a bug.
Create a new peer from a parcel using the constructor Peer.Peer(Parcel parcel)
. The constructor uses Peer.parse(Parcel parcel)
to extract the address, location, and velocity from the parcel to create a peer.
Apparently, the peer will initially have a location AND velocity. However, the velocity data does NOT contain current location information, and therefore, the GeoVelocity
object that will be created will NOT know that there is a current location! So the parse
method needs to be fixed as follows:
public void parse(Parcel parcel){
address = new PeerAddress(parcel);
location = new GeoLocation(parcel);
velocity = new GeoVelocity(parcel);
velocity.update(location); // Tell GeoVelocity that we already have a current location.
}
Packet.parse(Parcel parcel)
In Packet.parse(Parcel parcel)
, I think
...
if(parcel.getParcelSize() > 0){
...
is not right, because parcel.getParcelSize()
will always be equal to HEADER_LENGTH
at this point.
I think it should be:
...
if(parcel.capacity() > HEADER_LENGTH)
...
Also, there is something wrong with parcel.slice()
. Although the newly-created parcel has its capacity set to the length of the contents, which is correct, converting this parcel to a byte-array will result in an array with the length of the original packet. Try this:
contents = parcel.slice();
System.out.println(contents);
System.out.println(contents.toByteArray().length);
Average Accuracy
Hi Zorayr,
I noticed that your implementation always omits the first location in calculating the average accuracy. That is because if the current location is null
, you simply set the current location to the new location without adding the new location's accuracy to the sum. Is that intentional?
James
GeoVelocity.update(GeoLocation newLocation)
Hi Zorayr,
In GeoVelocity.update(GeoLocation newLocation)
, are you sure that dTime
is computed correctly?
int dTime = currentLocation.getLastUpdateTime() - newLocation.getLastUpdateTime();
From my understanding, dTime
would always be negative in this case. I brought up this issue last week, but since this line of code remains unchanged, I just wanted to double-check.
Thanks.
James
KimonoNet.java as a Command Line Utility: Introducing KiNCoL
Ideally, KimonoNet.java at the root package will constitute a a command line utility that can either run the simulation UI or run a simpler command line simulation with several specified parameters and output the results. Although simulation UI is fancy and user friendly, ultimately the command line utility will probably be the better tool to be used by developers and administrators.
The command line utility, also deemed as KiNCoL, will have the following input format:
KimonoNet [mode] [number-of-peers map-width map-height hostility-factor peer-speed]
- mode: Can be either "mode-gui", or "mode-cl". If left empty or if the jar file is just double clicked, the UI version will lunched.
- number-of-peers: Indicates the number of peers participating. Each peer will be assigned a random address and a random location within the bounded map.
- map-width: The width of the map in meters.
- map-height: The height of the map in meters.
- hostility-factor: Indicates the hostility of the operating environment. High hostility factor results in more node failures.
- peer-speed: Speed in m/s at which the peer is traveling.
- packet-count: The number of packets that will be sent during the entire simulation.
KiNCol deadline is 3/16/2012.
Javadoc Site for Current Implementation
Given the number of collaborators for the project, it is essential to create a Javadoc site and link it to the git repository.
Random Time Offset for Sending Beacon Packets
Please specify the algorithm for a random time offset before sending becaon packets. These will prevent attempts at the MAC layer to send packets at the same time.
Switch CRC16 to CRC32
As Java only supports CRC32, it would save time to switch to CRC32 instead of implementing a custom checksum calculator.
Parcel.toByteArray()
I am proposing that this method be modified as follows:
public byte[] toByteArray(){
int length = buffer.capacity();
byte array[] = new byte[length];
System.arraycopy(buffer.array(), buffer.arrayOffset(), array, 0, length);
return array;
}
That way, if a parcel was sliced before, the byte array returned will contain only the sliced portion and not the whole backing array.
Environment Variables i.e. Nobs
Environment variables are configuration variables that allow to modify the settings of the current nodes environment. The following environment variables are currently at place:
- beacon-service-timeout This value indicates how long in seconds a beacon service waits for receiving a beacon from a neighbor before sending out its own beacon.
- max-beacon-peers Maximum number of peers to be included in beacon packets.
- node-failure-rate With some frequency specified by this value, nodes will completely shutdown. This allows simulation of hostile environment.
- packet-loss-rate Packets will be discarded on the receiving end at some frequency according to this value. For example 0.1 will indicate 10% loss at each node.
- max-transmission-range Packets above received further away than this distance specified in meters will be discarded.
- average-gps-accuracy Indicates the average value of some distribution curve to be determined.
Are there any other values to be considered?
averageAccuracy
Hi Zorayr,
Just wondering, what kind of average are you using for averageAccuracy
in GeoVelocity.java
? Apparently, it's not (accuracy1+accuracy2+...+accuracyN)/N
.
James
Peer(PeerAddress address, String name)
The constructor Peer(PeerAddress address, String name)
creates a new GeoVelocity
object since an existing one is not specified. For consistency, should it also do the same for GeoLocation
? So the constructor would become:
public Peer(PeerAddress address, String name) {
this.name = name;
this.address = address;
this.location = new GeoLocation(); // The new line of code.
this.velocity = new GeoVelocity();
}
Since there is no GeoLocation
constructor that takes zero arguments, maybe you could create one just like how you did it in GeoVelocity
?
Location Field Ordering
Please place longitude before latitude when defining location or velocity related structures.
Discard BEACON_ACK packet types?
From implementation point of view, it seems like BEACON_ACK packets don't really serve any purpose. Would it be better to completely discard this type and just use BEACON?
Rename ROUTING-QUEUE to PACKET-QUEUE
Please rename ROUTING-QUEUE to PACKET-QUEUE.
Timestamps Testing
Since timestamps vary with system time, I need to be able to fix timestamps during testing. Would it be fine that I create a new class that returns the actual time during normal operation, but returns a fixed time during testing, and then modify your code to use this class instead of System.currentTimeMillis()
?
So for example, I create a KimonoTime
class under kimononet.util
. Then I replace all instances of System.currentTimeMillis()
with KimonoTime.currentTimeMillis()
. When I want to do testing, I do KimonoTime.setTesting(true)
before doing anything else.
Update doc for kimononet.geo.GeoLocation.setLocation()
Hey Zorayr, I think you need to update the comments for kimononet.geo.GeoLocation.setLocation(). From what I am perceiving, the new packet structure is:
\* [0-8) : GPS longitude (double).
\* [8-16) : GPS latitude (double).
\* [16-20): GPS accuracy (float).
\* [20-24): UNIX time stamp representing last GPS location update (int).
How to Extract an 8 byte string from Parcel
I need to get HDR-DST-ID which I am under the impression is the String identifier. I can't really figure out how I can pull out a specified length string from a parcel.
Issues with Protocol Documentation Sec. 3.2.1 New Location Computation
Hi Eric,
I believe t0 in the calculation is supposed to be change in time as opposed to the timestamp the neighbor's location was calculated. Otherwise the new location will be very very far.
Could you also specify what equation is the calculation based on and also clarify about the units of the variables - speed in m/s, Earth's radius in meters, time in seconds, and bearing in degrees. Also is Earth's radius the median radius ~ 6,371,000m or are you using another value? It would be nice if it was specified.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.