package api.java_net;

import java.net.*;

public class DatagramTest
{


   public static void main(String args[]) {
      try {
          new DatagramTest().testPacketLength();
      } catch (Exception e) {
          e.printStackTrace();
      }
   }

   class ErrorThread extends Thread {
      String error;
   }

   /**
    * Verify that we correctly update the length of packets when
    * receiving datagrams.
    */
   public void testPacketLength() throws Exception {

      // The idea here is to first receive a small packet and then a
      // larger packet into the same DatagramPacket and verify that it
      // is still possible to receive a large packet after the small
      // packet.
      
      final DatagramSocket clientSocket = new DatagramSocket();
      int clientPort = ((InetSocketAddress)clientSocket.getLocalSocketAddress()).getPort();
      final InetSocketAddress clientAddr = new InetSocketAddress("127.0.0.1", clientPort);
      
      final DatagramSocket serverSocket = new DatagramSocket();            
      int serverPort = ((InetSocketAddress)serverSocket.getLocalSocketAddress()).getPort();
      final InetSocketAddress serverAddr = new InetSocketAddress("127.0.0.1", serverPort);
           
      ErrorThread server = new ErrorThread() {

            public void run() {
               try {
                  byte[] buf = new byte[100];
                  DatagramPacket packet;

                  // wait for start
                  packet = new DatagramPacket(buf, buf.length);
                  serverSocket.receive(packet);
                  System.out.println("receive");

                  // send small packet
                  packet = new DatagramPacket(buf, buf.length / 2, clientAddr);               
                  serverSocket.send(packet);
                  System.out.println("send");

                  // wait for ack
                  packet = new DatagramPacket(buf, buf.length);
                  serverSocket.receive(packet);
                  System.out.println("receive");

                  // send large packet
                  packet = new DatagramPacket(buf, buf.length, clientAddr);               
                  serverSocket.send(packet);
                  System.out.println("send");                  
               } catch(Exception ex) {
                  ex.printStackTrace();
                  error = ex.toString();
               }
                          
            }
         };
      server.start();

      ErrorThread client = new ErrorThread() {

            public void run() {
               try {
                  byte[] buf1 = new byte[100];
                  DatagramPacket tmpPacket = new DatagramPacket(buf1, buf1.length, serverAddr);
               
                  byte[] buf2 = new byte[100];
                  DatagramPacket packet = new DatagramPacket(buf2, buf2.length);

                  // send start
                  clientSocket.send(tmpPacket);

                  // receive small packet
                  clientSocket.receive(packet);
                  if (packet.getLength() != 50) {
                     error = "Expected first packet to be of length 50 but got "+packet.getLength();
                  }

                  // send ack
                  clientSocket.send(tmpPacket);

                  // receive large packet
                  clientSocket.receive(packet);
                  if (packet.getLength() != 100) {
                     error = "Expected second packet to be of length 100 but got "+packet.getLength();
                  }
                  
               } catch(Exception ex) {
                  ex.printStackTrace();
                  error = ex.toString();
               }
            }
         };
      client.start();

      server.join();
      client.join();

      if (server.error != null) {
         throw new Exception("Server: "+server.error);
      }
      if (client.error != null) {
         throw new Exception("Client: "+client.error);
      }
   }
   
}
