Top


定義場所(file name)

hotspot/src/os/linux/vm/attachListener_linux.cpp

説明(description)

// Given a socket that is connected to a peer we read the request and
// create an AttachOperation. As the socket is blocking there is potential
// for a denial-of-service if the peer does not response. However this happens
// after the peer credentials have been checked and in the worst case it just
// means that the attach listener thread is blocked.
//

名前(function name)

LinuxAttachOperation* LinuxAttachListener::read_request(int s) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      char ver_str[8];
      sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      // The request is a sequence of strings so we first figure out the
      // expected count and the maximum possible length of the request.
      // The request is:
      //   <ver>0<cmd>0<arg>0<arg>0<arg>0
      // where <ver> is the protocol version (1), <cmd> is the command
      // name ("load", "datadump", ...), and <arg> is an argument
      int expected_str_count = 2 + AttachOperation::arg_count_max;
      const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
        AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);

      char buf[max_len];
      int str_count = 0;

  {- -------------------------------------------
  (1) クライアントからのリクエストを read() で受信する.
      ---------------------------------------- -}

      // Read until all (expected) strings have been read, the buffer is
      // full, or EOF.

      int off = 0;
      int left = max_len;

      do {
        int n;
        RESTARTABLE(read(s, buf+off, left), n);
        if (n == -1) {
          return NULL;      // reset by peer or other error
        }
        if (n == 0) {
          break;
        }
        for (int i=0; i<n; i++) {
          if (buf[off+i] == 0) {
            // EOS found
            str_count++;

            // The first string is <ver> so check it now to
            // check for protocol mis-match
            if (str_count == 1) {
              if ((strlen(buf) != strlen(ver_str)) ||
                  (atoi(buf) != ATTACH_PROTOCOL_VER)) {
                char msg[32];
                sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
                write_fully(s, msg, strlen(msg));
                return NULL;
              }
            }
          }
        }
        off += n;
        left -= n;
      } while (left > 0 && str_count < expected_str_count);

  {- -------------------------------------------
  (1) 受信が上手くいかなかった場合はリターン.
      ---------------------------------------- -}

      if (str_count != expected_str_count) {
        return NULL;        // incomplete request
      }

  {- -------------------------------------------
  (1) 届いた文字列をパースして LinuxAttachOperation オブジェクトを生成する.
      ---------------------------------------- -}

      // parse request

      ArgumentIterator args(buf, (max_len)-left);

      // version already checked
      char* v = args.next();

      char* name = args.next();
      if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
        return NULL;
      }

      LinuxAttachOperation* op = new LinuxAttachOperation(name);

      for (int i=0; i<AttachOperation::arg_count_max; i++) {
        char* arg = args.next();
        if (arg == NULL) {
          op->set_arg(i, NULL);
        } else {
          if (strlen(arg) > AttachOperation::arg_length_max) {
            delete op;
            return NULL;
          }
          op->set_arg(i, arg);
        }
      }

      op->set_socket(s);

  {- -------------------------------------------
  (1) 結果をリターン
      ---------------------------------------- -}

      return op;
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.