hotspot/src/os/linux/vm/attachListener_linux.cpp
// 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.
//
LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
{- -------------------------------------------
(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.