blob: 8b004b6a56525efaaa3367d397aa1b767524d566 [file] [log] [blame]
/*****************************************************************************\
* src/common/io_hdr.c - IO connection header functions
* $Id$
*****************************************************************************
* Copyright (C) 2002 The Regents of the University of California.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Mark A. Grondona <mgrondona@llnl.gov>.
* UCRL-CODE-226842.
*
* This file is part of SLURM, a resource management program.
* For details, see <http://www.llnl.gov/linux/slurm/>.
*
* SLURM is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with SLURM; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "src/common/io_hdr.h"
#include "src/common/slurm_protocol_defs.h"
#define IO_PROTOCOL_VERSION 0xb001
/*
static void
_print_data(char *data, int datalen)
{
char buf[1024];
size_t len = 0;
int i;
for (i = 0; i < datalen; i += sizeof(char))
len += sprintf(buf+len, "%02x", data[i]);
info("data: %s", buf);
}
*/
void
io_hdr_pack(io_hdr_t *hdr, Buf buffer)
{
pack16(hdr->type, buffer);
pack16(hdr->gtaskid, buffer);
pack16(hdr->ltaskid, buffer);
pack32(hdr->length, buffer);
}
int
io_hdr_unpack(io_hdr_t *hdr, Buf buffer)
{
safe_unpack16(&hdr->type, buffer);
safe_unpack16(&hdr->gtaskid, buffer);
safe_unpack16(&hdr->ltaskid, buffer);
safe_unpack32(&hdr->length, buffer);
return SLURM_SUCCESS;
unpack_error:
error("io_hdr_unpack error: %m");
return SLURM_ERROR;
}
int
io_hdr_packed_size()
{
return sizeof(uint32_t) + 3*sizeof(uint16_t);
}
/*
* Only return when the all of the bytes have been read, or an unignorable
* error has occurred.
*/
static int _full_read(int fd, void *buf, size_t count)
{
int n;
int left;
void *ptr;
left = count;
ptr = buf;
while (left > 0) {
again:
if ((n = read(fd, (void *) ptr, left)) < 0) {
if (errno == EINTR
|| errno == EAGAIN
|| errno == EWOULDBLOCK)
goto again;
debug3("Leaving _full_read on error!");
return -1;
} else if (n == 0) { /* got eof */
debug3(" _full_read (_client_read) got eof");
return 0;
}
left -= n;
ptr += n;
}
return count;
}
/*
* Read and unpack an io_hdr_t from a file descriptor (socket).
*/
int io_hdr_read_fd(int fd, io_hdr_t *hdr)
{
Buf buffer;
int n = 0;
debug3("Entering io_hdr_read_fd");
buffer = init_buf(io_hdr_packed_size());
n = _full_read(fd, buffer->head, io_hdr_packed_size());
if (n <= 0)
goto fail;
if (io_hdr_unpack(hdr, buffer) == SLURM_ERROR) {
n = -1;
goto fail;
}
fail:
debug3("Leaving io_hdr_read_fd");
free_buf(buffer);
return n;
}
int
io_init_msg_validate(struct slurm_io_init_msg *msg, const char *sig)
{
debug2("Entering io_init_msg_validate");
debug3(" msg->version = %x", msg->version);
debug3(" msg->nodeid = %u", msg->nodeid);
if (msg->version != IO_PROTOCOL_VERSION) {
error("Invalid IO init header version");
return SLURM_ERROR;
}
if (memcmp((void *)sig, (void *)msg->cred_signature,
SLURM_IO_KEY_SIZE)) {
error("Invalid IO init header signature");
return SLURM_ERROR;
}
debug2("Leaving io_init_msg_validate");
return SLURM_SUCCESS;
}
static int
io_init_msg_packed_size(void)
{
int len;
len = sizeof(uint16_t) /* version */
+ sizeof(uint32_t) /* nodeid */
+ (SLURM_IO_KEY_SIZE + sizeof(uint16_t)) /* signature */
+ sizeof(uint32_t) /* stdout_objs */
+ sizeof(uint32_t); /* stderr_objs */
return len;
}
static void
io_init_msg_pack(struct slurm_io_init_msg *hdr, Buf buffer)
{
pack16(hdr->version, buffer);
pack32(hdr->nodeid, buffer);
pack32(hdr->stdout_objs, buffer);
pack32(hdr->stderr_objs, buffer);
packmem((char *) hdr->cred_signature,
(uint16_t) SLURM_IO_KEY_SIZE, buffer);
}
static int
io_init_msg_unpack(struct slurm_io_init_msg *hdr, Buf buffer)
{
uint16_t val;
safe_unpack16(&hdr->version, buffer);
safe_unpack32(&hdr->nodeid, buffer);
safe_unpack32(&hdr->stdout_objs, buffer);
safe_unpack32(&hdr->stderr_objs, buffer);
safe_unpackmem((char *) hdr->cred_signature, &val, buffer);
if (val != SLURM_IO_KEY_SIZE)
goto unpack_error;
return SLURM_SUCCESS;
unpack_error:
error("unpack error in io_init_msg_unpack");
return SLURM_ERROR;
}
int
io_init_msg_write_to_fd(int fd, struct slurm_io_init_msg *msg)
{
Buf buf;
void *ptr;
int n;
xassert(msg);
debug2("Entering io_init_msg_write_to_fd");
msg->version = IO_PROTOCOL_VERSION;
buf = init_buf(io_init_msg_packed_size());
debug2(" msg->nodeid = %d", msg->nodeid);
io_init_msg_pack(msg, buf);
ptr = get_buf_data(buf);
again:
if ((n = write(fd, ptr, io_init_msg_packed_size())) < 0) {
if (errno == EINTR)
goto again;
free_buf(buf);
return SLURM_ERROR;
}
if (n != io_init_msg_packed_size()) {
error("io init msg write too small");
free_buf(buf);
return SLURM_ERROR;
}
free_buf(buf);
debug2("Leaving io_init_msg_write_to_fd");
return SLURM_SUCCESS;
}
int
io_init_msg_read_from_fd(int fd, struct slurm_io_init_msg *msg)
{
Buf buf;
void *ptr;
int n;
xassert(msg);
debug2("Entering io_init_msg_read_from_fd");
buf = init_buf(io_init_msg_packed_size());
ptr = get_buf_data(buf);
again:
if ((n = read(fd, ptr, io_init_msg_packed_size())) < 0) {
if (errno == EINTR)
goto again;
free_buf(buf);
return SLURM_ERROR;
}
if (n != io_init_msg_packed_size()) {
error("io init msg read too small");
free_buf(buf);
return SLURM_ERROR;
}
debug3(" read %d bytes", n);
io_init_msg_unpack(msg, buf);
free_buf(buf);
debug2("Leaving io_init_msg_read_from_fd");
return SLURM_SUCCESS;
}