CPSC 333 PROGRAMMING ASSIGNMENT (due next tuesday) The Spynet Protocol For this assignment you are to implement a communication protocol on top of the TCP protocol, using sockets, threads and binary communication. Here's the scenario: The agents of CSX are given the following IDs: 0. bertucci 1. eagle 2. flaco 3. fletch 4. lebowski 5. lena 6. maceo 7. panther 8. shaguar For sake of security, each agent X will only receive messages from agent X-1 (wrapping around to 9), and only send messages to agent X+1 (wrapping around to 0). For example, if fletch (4) wants to send a message to maceo(7), the message will have to go through lebowski and lena. For added security, communication between each pair of agents is encrypted by a secret key, provided to you individually. The key consists of a 32-bit randomly generated binary sequence, which is to be XOR'ed with the data sent/received. It's a tautology that (A XOR B) XOR B = A, so the first XOR will encrypt the message, and the second XOR, executed at the receiving end, will decrypt it. Since not all agents may be available to receive messages (because they've been captured by the enemy, or didn't do the assignment 'til the last minute), if agent X tries to establish a connection (socket) with X+1, but agent X+1 is unavailable, then agent X will try to communicate with agent X+2 (or X+3, until somebody is available). However, to do so agent X must inform X+2 of the secret key with which it uses to send messages. So agent X must send its key to X+2 first. Now if X+2 receives a message, it can be from either agent X or agent X+1 (who may have just come online). It must be aware of the origin of the message so it can use the appropriate key to decode it. If a message you sent out somehow comes back to you, you are to try sending it again after a timeout (of say 5 minutes). With these considerations in mind, the "packet format" of the Spynet protocol is as follows: byte 0: message type. 0 = regular ascii message; 1 = message with decryption key in payload. byte 1: source agent ID byte 2: destination agent ID bytes 3-6: integer indicating the number of remaining bytes to expect bytes 7 - : payload consisting of data in individual bytes. If byte 0 = 1, then the integer field will always be 4, and the payload will consist of 4 signed bytes (32 bits) representing the key. Only the payload bytes are to be encyrpted, and only if a regular message is being sent (keys can not be encrypted). All data are to be sent in individual bytes, except the 4-byte integer representing the number of remaining bytes, which is to be sent as an as an int (Java imposes big-endian ordering). Every packet needs to be sent seperately, using a different connection (i.e, different socket) each time. I *emphasize* that the destination ID of a message is not always your right neighbor, but the message should be *sent through* your right neighbor. Thus, if you receive a message with destination ID = your ID, then you will keep the message by storing it into a LOCAL FILE (after decrypting it, and be sure to record the origin of the message). However, if the destination ID is not yours then you are to re-encrypt it and pass it on to your right neighbor. Your application will always be running a server thread, and must handle all exceptions in a way so that your server will not crash in any event. ALL SPYNET APPLICATIONS ARE TO USE PORT 1928. (This is a group assignment. Turn in code with all messages received. Remember to be clear and comment!!!! ) ---------- Here's some additional help, though you will probably need to consult some standard Java reference to finish the assignment. // object needed for binary communication (can replace Input with Output): DataInputStream dis = new DataInputStream(somesocket.getInputStream()); byte b = dis.readByte(); // returns a byte. May throw EOFException. int i = dis.readInt(); // returns an int (java ints are 4-bytes long) byte b1, b2, b3; b1 = (byte) 'd'; // casts ascii char into a byte b2 = -68 (valid values for byte are from -128 to + 127); b3 = (byte) (b1 ^ b2); // bitwise XORs b1 and b2, stores into b3 // the ^ operator actually returns an int char c = (char) b3; // converts byte into ascii char String s = "abc"; s.charAt(1) should return a char, in this case 'b'; first char is char 0. s.length() should return length of string, Also, remember that strings are objects in Java. That is, String a = s; // will not copy s into a, but only points a to the same string To make a duplicate copy of a string, use String a = new String(s); In addition, the Integer.toBinaryString(int x) method returns the binary representation of an integer as a string. You should NOT have to use this method in your program, except for debugging purposes.