Package erjang.driver.inet_gethost

Source Code of erjang.driver.inet_gethost.GetHostDriver

/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2010 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package erjang.driver.inet_gethost;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;

import kilim.Pausable;
import erjang.EHandle;
import erjang.EString;
import erjang.NotImplemented;
import erjang.driver.EAsync;
import erjang.driver.EDriver;
import erjang.driver.EDriverInstance;
import erjang.driver.IO;

public class GetHostDriver extends EDriverInstance {

  public static final byte OP_GETHOSTBYNAME = 1;
  public static final byte OP_GETHOSTBYADDR = 2;
  public static final byte OP_CANCEL_REQUEST = 3;
  public static final byte OP_CONTROL = 4;

  public static final byte PROTO_IPV4 = 1;
  public static final byte PROTO_IPV6 = 2;

  public static final byte SETOPT_DEBUG_LEVEL = 0;

  public static final byte UNIT_ERROR = 0;
  public static final byte UNIT_IPV4 = 4;
  public static final byte UNIT_IPV6 = 16;

 
  private EString command;

  public GetHostDriver(EDriver driver, EString command) {
    super(driver);
    this.command = command;
  }

  @Override
  protected void flush() throws Pausable {

  }

  @Override
  protected void output(EHandle caller, ByteBuffer buf) throws IOException,
      Pausable {

    // log.fine(EBinary.make(buf).toString());
   
    final int seq = buf.getInt();
    byte op = buf.get();
    EAsync eas;
   
    switch (op) {
    case OP_GETHOSTBYNAME: {
      eas = gethostbyname(buf, seq);
      break;
    }

    case OP_GETHOSTBYADDR: {
      eas = gethostbyaddr(buf, seq);
      break;
    }

    default:
      throw new NotImplemented("inet_gethost seq="+seq+"; op="+op);

    }
   
   
    driver_async(eas);
  }

  private EAsync gethostbyname(ByteBuffer buf, final int seq) {
    final byte proto = buf.get();
    final String host = IO.getstr(buf, true);
    // log.fine(" gethostsbyname["+seq+"][call] "+host);

    return new EAsync() {
     
      InetAddress[] addr;
      String[] names;
      private UnknownHostException err;
      InetAddress primary;
     
      @Override
      public void async() {
       
        // log.fine(" gethostsbyname["+seq+"][async] "+host);
        try {
          primary = InetAddress.getByName(host);
          addr = InetAddress.getAllByName(host);
          names = new String[addr.length];
          for (int i = 0; i < addr.length; i++) {
            names[i] = addr[i].getCanonicalHostName();
            // log.fine(">> " + addr[i]+" -> "+names[i]);
          }
        } catch (UnknownHostException e) {
          this.err = e;
        }
      }

      @Override
      public void ready() throws Pausable {
       
        // log.fine(" gethostsbyname["+seq+"][ready] "+host);
        if (addr != null) {
          // we're ok
          byte[][] bytes = new byte[addr.length][];
         
          int size = 4 + 1 + 4;
         
          int first = -1;
          int acount = 0;
          for (int i = 0; i < addr.length; i++) {
            //log.fine("gethostbyname["+i+"]="+addr[i]+" / "+names[i]);
            if ((proto==PROTO_IPV4 && (addr[i] instanceof Inet4Address))
                || (proto==PROTO_IPV6 && (addr[i] instanceof Inet6Address))) {
              bytes[i] = addr[i].getAddress();
              size += bytes[i].length;   
              acount += 1;
              if (first == -1) first = i;
              if (host.equals(names[i])) {
                //log.fine("gethostbyname["+i+"]=>"+primary);
                first = i;
              }
            }
          }
         
          size += 4;
          size += host.length() + 1;
         
          ByteBuffer rep = ByteBuffer.allocate(size);
         
          rep.putInt(seq);
         
          if (proto == PROTO_IPV4) {
            rep.put(UNIT_IPV4);
            rep.putInt(acount);
            if (acount > 0) {
              rep.put(bytes[first]);
              for (int i = 0; i < addr.length; i++) {
                if (i != first && bytes[i] != null) {
                  rep.put(bytes[i]);
                }
              }
            }           
            rep.putInt(1);
            rep.put(host.getBytes(IO.ISO_LATIN_1));
            rep.put((byte)0);
           
            // dump_write(new ByteBuffer[] {rep});
           
            driver_output(rep);
           
            return;
           
          } else if (proto == PROTO_IPV6) {
            rep.put(UNIT_IPV6);
            rep.putInt(acount);
            for (int i = 0; i < addr.length; i++) {
              if (bytes[i] != null) {
                rep.put(bytes[i]);
              }
            }
           
            rep.putInt(1);
            rep.put(host.getBytes(IO.ISO_LATIN_1));
            rep.put((byte)0);
           
            // dump_write(new ByteBuffer[] {rep});
            driver_output(rep);
            return;
          }
        }
         
        String message = "unknown";
       
        if (err != null) {
          message = err.getMessage();
        }
         
         
        byte[] msg = message.getBytes(IO.ISO_LATIN_1);
        int len = 4 + 1 + msg.length;
       
        ByteBuffer rep = ByteBuffer.allocate(len);
        rep.putInt(seq);
        rep.put(UNIT_ERROR);
        rep.put(msg);
       
        dump_buffer(new ByteBuffer[] {rep});
       
        driver_output(rep);
      }
     
    };
  }


  private EAsync gethostbyaddr(ByteBuffer buf, final int seq) {
    final byte proto = buf.get();
    final byte[] host = new byte[ proto == PROTO_IPV4 ? 4 : 16 ];
    buf.get(host);
   
    // log.fine(" gethostbyaddr["+seq+"][call] "+host);

    return new EAsync() {
     
      String name;
      private UnknownHostException err;
      InetAddress primary;
      InetAddress[] addr;
     
      @Override
      public void async() {
       
        // log.fine(" gethostbyaddr["+seq+"][async] "+host);
        try {
          primary = InetAddress.getByAddress(host);
          name = primary.getCanonicalHostName();
          addr = InetAddress.getAllByName(name);
        } catch (UnknownHostException e) {
          this.err = e;
        }
      }

      @Override
      public void ready() throws Pausable {
       
        // log.fine(" gethostsbyname["+seq+"][ready] "+host);
        if (addr != null) {
          // we're ok
          byte[][] bytes = new byte[addr.length][];
         
          int size = 4 + 1 + 4;
         
          int first = -1;
          int acount = 0;
          for (int i = 0; i < addr.length; i++) {
            //log.fine("gethostbyname["+i+"]="+addr[i]+" / "+names[i]);
            if ((proto==PROTO_IPV4 && (addr[i] instanceof Inet4Address))
                || (proto==PROTO_IPV6 && (addr[i] instanceof Inet6Address))) {
              bytes[i] = addr[i].getAddress();
              size += bytes[i].length;   
              acount += 1;
              if (first == -1) first = i;
            }
          }
         
          size += 4;
          size += name.length() + 1;
         
          ByteBuffer rep = ByteBuffer.allocate(size);
         
          rep.putInt(seq);
         
          if (proto == PROTO_IPV4) {
            rep.put(UNIT_IPV4);
            rep.putInt(acount);
            if (acount > 0) {
              rep.put(bytes[first]);
              for (int i = 0; i < addr.length; i++) {
                if (i != first && bytes[i] != null) {
                  rep.put(bytes[i]);
                }
              }
            }           
            rep.putInt(1);
            rep.put(name.getBytes(IO.ISO_LATIN_1));
            rep.put((byte)0);
           
            // dump_write(new ByteBuffer[] {rep});
           
            driver_output(rep);
           
            return;
           
          } else if (proto == PROTO_IPV6) {
            rep.put(UNIT_IPV6);
            rep.putInt(acount);
            for (int i = 0; i < addr.length; i++) {
              if (bytes[i] != null) {
                rep.put(bytes[i]);
              }
            }
           
            rep.putInt(1);
            rep.put(name.getBytes(IO.ISO_LATIN_1));
            rep.put((byte)0);
           
            // dump_write(new ByteBuffer[] {rep});
            driver_output(rep);
            return;
          }
        }
         
        String message = "unknown";
       
        if (err != null) {
          message = err.getMessage();
        }
         
         
        byte[] msg = message.getBytes(IO.ISO_LATIN_1);
        int len = 4 + 1 + msg.length;
       
        ByteBuffer rep = ByteBuffer.allocate(len);
        rep.putInt(seq);
        rep.put(UNIT_ERROR);
        rep.put(msg);
       
        dump_buffer(new ByteBuffer[] {rep});
       
        driver_output(rep);
      }
     
    };
  }

  @Override
  protected void readyAsync(EAsync data) throws Pausable {
    data.ready();
  }

  @Override
  protected void readyInput(SelectableChannel ch) throws Pausable {
    throw new erjang.NotImplemented();

  }

  @Override
  protected void readyOutput(SelectableChannel evt) throws Pausable {
    throw new erjang.NotImplemented();

  }

  @Override
  protected void timeout() throws Pausable {
    throw new erjang.NotImplemented();

  }
}
TOP

Related Classes of erjang.driver.inet_gethost.GetHostDriver

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.