Package com.peterhi.net3

Source Code of com.peterhi.net3.Local$Remote$Window

package com.peterhi.net3;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.peterhi.runtime.MemoryStream;

public final class Local {
 
  public static interface Listener {
    void received(SocketAddress address, byte[] data);
  }
 
  class Remote {
   
    private final SocketAddress address;
   
    class Window {
      class Frame {
        private final byte[] data;
        private int sendCount;
       
        public Frame(byte[] data) {
          if (data != null && data.length == 0) {
            throw new IllegalArgumentException();
          }
         
          this.data = data;
        }
       
        public byte[] getData() {
          return data;
        }
       
        public int getSendCount() {
          return sendCount;
        }
       
        public int incrementSendCount() {
          sendCount ++;
          return sendCount;
        }
      }
     
      private final int id;
      private final Frame[] frames;
     
      public Window(int id, int size) {
        if (id <= 0) {
          throw new IllegalArgumentException("Window ID is zero or negative.");
        }
       
        if (id > 0x0f) {
          throw new IllegalArgumentException("Window ID is too large (larger than 15).");
        }
       
        if (size <= 0) {
          throw new IllegalArgumentException("Size is negative.");
        }
       
        if (size > 65535) {
          throw new IllegalArgumentException("Size is too large (larger than 65535).");
        }
       
        this.id = id;
        this.frames = new Frame[size];
      }
     
      public int size() {
        return frames.length;
      }
     
      public Frame getFrame(int index) {
        return frames[index];
      }
     
      public void setFrame(int index, Frame value) {
        frames[index] = value;
      }
     
      public int indexOf(Frame frame) {
        if (frame == null) {
          return -1;
        }
       
        for (int i = 0; i < frames.length; i++) {
          if (frame.equals(frames[i])) {
            return i;
          }
        }
       
        return -1;
      }
     
      public boolean send(Frame frame) throws IOException {
        if (frame == null) {
          return false;
        }
       
        if (frame.getData() == null) {
          return false;
        }
       
        if (frame.getData().length == 0) {
          throw new IllegalArgumentException("Data length is zero.");
        }
       
        int header = 0;
        header |= (2 & 0x03) << 6;
        header |= (id & 0x0f) << 2;
       
        int sizeType = getSizeType();
        header |= (sizeType & 0x03) << 0;
       
        int index = indexOf(frame);
        int length = frames.length;
       
        MemoryStream ms = new MemoryStream();
        ms.write(header);
       
        if (sizeType == 1) {
          ms.write(((index & 0x0f) << 4) | ((length & 0x0f) << 0));
        } else if (sizeType == 2) {
          ms.write(index);
          ms.write(length);
        } else {
          ms.writeShort(index);
          ms.writeShort(length);
        }
       
        ms.write(frame.getData());
       
        byte[] data = ms.toByteArray();
        DatagramPacket packet = new DatagramPacket(data, data.length);
        getSocket().send(packet);
        frame.incrementSendCount();
        return true;
      }
     
      public int getSizeType() {
        if (frames.length < 16) {
          return 1;
        } else if (frames.length < 256) {
          return 2;
        } else {
          return 3;
        }
      }
    }
   
    /*class Frame {
      private byte[] data;
      private boolean acked;
      private int sendCount;
     
      public void send() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int header = 0;
        header |= (2 & 0x03) << 6;
        header |= (windowId & 0x0f) << 2;
       
      }
    }
   
    private Frame[] frames;
    private int windowId;
   
    public int indexOf(Frame frame) {
      if (frame == null) {
        throw new NullPointerException();
      }
     
      for (int i = 0; i < frames.length; i++) {
        if (frame.equals(frames[i])) {
          return i;
        }
      }
     
      return -1;
    }
   
    public int getSizeType() {
      if (f)
    }*/
   
    protected Remote(SocketAddress address) {
      if (address == null) {
        throw new NullPointerException();
      }
     
      this.address = address;
    }
   
    public SocketAddress getAddress() {
      return address;
    }
  }
 
  private final DatagramSocket socket;
  private final List<Listener> listeners = new ArrayList<Listener>();
 
  public Local() throws SocketException {
    socket = new DatagramSocket();
  }
 
  public Local(int port) throws SocketException {
    socket = new DatagramSocket(port);
  }
 
  public Local(InetAddress address, int port) throws SocketException {
    socket = new DatagramSocket(port, address);
  }
 
  public Local(SocketAddress address) throws SocketException {
    socket = new DatagramSocket(address);
  }
 
  public DatagramSocket getSocket() {
    return socket;
  }
 
  public int send(SocketAddress address, byte[] buffer, int offset, int length) throws IOException {
    if (address == null) {
      throw new NullPointerException();
    }
   
    validateBuffer(buffer, offset, length);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(0);
    baos.write(buffer, offset, length);
    DatagramPacket packet = new DatagramPacket(baos.toByteArray(), baos.size(), address);
    socket.send(packet);
    return length;
  }
 
  public DatagramPacket receive() throws IOException {
    byte[] buffer = new byte[512];
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
   
    try {
      socket.receive(packet);
    } catch (SocketTimeoutException ex) {
      return null;
    }
   
    return packet;
  }
 
  public void process(DatagramPacket packet) {
    byte[] data = packet.getData();
    int offset = packet.getOffset();
    int type = (data[offset] >>> 6) & 0x03;
   
    if (type == 0) {
      byte[] bytes = Arrays.copyOfRange(data, 1, data.length);
      fireReceived(packet.getSocketAddress(), bytes);
    }
  }
 
  public void addListener(Listener listener) {
    if (listener == null) {
      throw new NullPointerException();
    }
   
    listeners.add(listener);
  }
 
  public void removeListener(Listener listener) {
    if (listener == null) {
      throw new NullPointerException();
    }
   
    listeners.remove(listener);
  }
 
  private void fireReceived(SocketAddress address, byte[] data) {
    for (Listener listener : listeners) {
      listener.received(address, data);
    }
  }
 
  private void validateBuffer(byte[] buffer, int offset, int length) {
    if (buffer == null) {
      throw new NullPointerException();
    }
   
    if (buffer.length == 0) {
      throw new IllegalArgumentException();
    }
   
    if (offset < 0) {
      throw new IllegalArgumentException();
    }
   
    if (length <= 0) {
      throw new IllegalArgumentException();
    }
   
    if (offset + length > buffer.length) {
      throw new IllegalArgumentException();
    }
  }
}
TOP

Related Classes of com.peterhi.net3.Local$Remote$Window

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.