Package erjang.driver.tcp_inet

Source Code of erjang.driver.tcp_inet.TCPINetCallbacks

package erjang.driver.tcp_inet;

import kilim.Pausable;
import erjang.EAtom;
import erjang.EBinary;
import erjang.EObject;
import erjang.ERT;
import erjang.EString;
import erjang.ETuple;
import erjang.ETuple2;
import erjang.driver.tcp_inet.Packet.HTTPAtom;
import erjang.driver.tcp_inet.TCPINet.ActiveType;
import erjang.driver.tcp_inet.TCPINet.AsyncOp;

public class TCPINetCallbacks extends PacketCallbacks<TCPINet> {

  private static final EAtom am_http_request = EAtom.intern("http_request");
  private static final EAtom am_inet_async = EAtom.intern("inet_async");
  private static final EAtom am_http = EAtom.intern("http");
  private static final EAtom am_star = EAtom.intern("*");
  private static final EAtom am_abs_path = EAtom.intern("abs_path");
  private static final EAtom am_https = EAtom.intern("https");
  private static final EAtom am_absoluteURI = EAtom.intern("absoluteURI");
  private static final EAtom am_scheme = EAtom.intern("scheme");
  private static final EAtom am_http_header = EAtom.intern("http_header");
  private static final EAtom am_http_eoh = EAtom.intern("http_eoh");
  private static final EAtom am_http_error = EAtom.intern("http_error");

  @Override
  int http_eoh(TCPINet desc) throws Pausable {
    return send_http(desc, am_http_eoh);
  }

  @Override
  int http_error(TCPINet desc, byte[] data, int pos, int len) throws Pausable {

    EObject line = load_string(desc, data, pos, len);

    ETuple2 req = new ETuple2(am_http_error, line);
   
    if (desc.active == ActiveType.PASSIVE) {
          /* {inet_async, S, Ref, {error,{http_error,Line}}} */

      AsyncOp op = desc.deq_async();
      if (op == null) {
        return -1;
      }
     
      ETuple2 ok = new ETuple2(ERT.am_error, req);
      ETuple msg = ETuple.make(am_inet_async, desc.port(), ERT.box(op.id), ok);
     
      desc.driver_send_term(op.caller, msg);

    } else {
          /* {http, S, {http_error, Line}}} */
     
      ETuple http = ETuple.make(am_http, desc.port(), req);
     
      desc.driver_output_term(http);
    }
   
    return 0;
  }

  @Override
  int http_header(TCPINet desc, HTTPAtom name, byte[] nameBuf, int namePtr,
      int nameLen, byte[] valBuf, int valPtr, int valLen) throws Pausable {

    EObject bit = (name == null)
          ? ERT.box(0)
          : ERT.box( name.index + 1 );
    EObject nam = (name == null)
          ? load_string(desc, nameBuf, namePtr, nameLen)
          : name.atom;
   
    EObject value = load_string(desc, valBuf, valPtr, valLen);
         
         
    ETuple req = ETuple.make(am_http_header, bit, nam, ERT.am_undefined, value);

    return send_http(desc, req);
  }

  @Override
  int http_request(TCPINet desc, HTTPAtom method, byte[] data, int meth_ptr,
      int meth_len, PacketHttpURI uri, int major, int minor) throws Pausable {
   
    EObject meth =
        (method == null)
        ? load_string(desc, data, meth_ptr, meth_len)
        : method.atom;
   
    ETuple version = new ETuple2(ERT.box(major), ERT.box(minor));
    ETuple req = ETuple.make(am_http_request, meth, load_uri(desc, uri), version);
   
    return send_http(desc, req);

  }

  private int send_http(TCPINet desc, EObject req) throws Pausable {
    if (desc.active == ActiveType.PASSIVE) {
          /* {inet_async, S, Ref, {ok,{http_request,Meth,Uri,Version}}} */

      AsyncOp op = desc.deq_async();
      if (op == null) {
        return -1;
      }
     
      ETuple2 ok = new ETuple2(ERT.am_ok, req);
      ETuple msg = ETuple.make(am_inet_async, desc.port(), ERT.box(op.id), ok);
     
      desc.driver_send_term(op.caller, msg);

    } else {
          /* {http, S, {http_request,Meth,Uri,Version}}} */
     
      ETuple http = ETuple.make(am_http, desc.port(), req);
     
      desc.driver_output_term(http);

    }
   
    return 0;
  }

  // HttpUri = '*'
  //         | {absoluteURI, http|https, Host=HttpString, Port=int()|undefined, Path=HttpString}
  //         | {scheme, Scheme=HttpString, HttpString}
  //         | {abs_path, HttpString}
  //         | HttpString

  private EObject load_uri(TCPINet desc, PacketHttpURI uri) {
    EAtom scheme = null;
    switch (uri.type) {
    case URI_STAR:
      return (EAtom)am_star;
    case URI_ABS_PATH:
      return new ETuple2(am_abs_path, load_string(desc, uri.s1_data, uri.s1_ptr, uri.s1_len));
    case URI_HTTPS:
      scheme = am_https;
    case URI_HTTP:
      if (scheme == null) { scheme = am_http; }
      return ETuple.make(am_absoluteURI,
                 scheme,
                 load_string(desc, uri.s1_data, uri.s1_ptr, uri.s1_len),
                 (uri.port==0 ? ERT.am_undefined : ERT.box(uri.port)),
                 load_string(desc, uri.s2_data, uri.s2_ptr, uri.s2_len));
    case URI_STRING:
      return load_string(desc, uri.s1_data, uri.s1_ptr, uri.s1_len);
    case URI_SCHEME:
      return ETuple.make(am_scheme,
             load_string(desc, uri.s1_data, uri.s1_ptr, uri.s1_len),
             load_string(desc, uri.s2_data, uri.s2_ptr, uri.s2_len));
    }

    throw new InternalError("should not happen");
   
  }

  private EObject load_string(TCPINet desc, byte[] data, int data_off,
      int data_len) {

    switch(desc.htype) {
    case TCP_PB_HTTPH_BIN:
    case TCP_PB_HTTP_BIN:
      return EBinary.make(data, data_off, data_len, 0 /*extra bits*/);
    default:
      return EString.make(data, data_off, data_len);
    }
  }

  @Override
  int http_response(TCPINet arg, int major, int minor, int status,
      byte[] data, int off, int len) {
    throw new erjang.NotImplemented();

  }

}
TOP

Related Classes of erjang.driver.tcp_inet.TCPINetCallbacks

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.