Commit 17292559 authored by Timothy Stack's avatar Timothy Stack

Made a pass over the mtp directory:

	* GNUmakerules: Add a "check" target that runs the executables
	listed in the "TESTS" variable.

	* robots/GNUmakefile.in: Add "mtp" to the list of SUBDIRS.

	* robots/mtp/GNUmakefile.in: Testbed-friendly makefile.

	* robots/mtp/mtp.h, robots/mtp.c: Tweaks and bug fixes.

	* robots/mtp/mtp_test.c: Test case for mtp stuff.
parent 997c5542
...@@ -68,3 +68,17 @@ vpath % $(SRCDIR) $(MOSTLY_SRCDIRS) ...@@ -68,3 +68,17 @@ vpath % $(SRCDIR) $(MOSTLY_SRCDIRS)
%: %.in %: %.in
@echo "Regenerating $@" @echo "Regenerating $@"
cd $(OBJDIR) && CONFIG_FILES=$(SUBDIR)/$@ ./config.status cd $(OBJDIR) && CONFIG_FILES=$(SUBDIR)/$@ ./config.status
ifeq ($(TESTS),)
.PHONY: check
else
check: $(TESTS)
@for tst in $<; do \
if test `basename $$tst .sh` != `basename $$tst`; then \
tst="sh $$tst"; \
fi; \
if $$tst; then \
echo "PASS: $$tst"; \
fi \
done
endif
...@@ -11,9 +11,10 @@ SUBDIR = robots ...@@ -11,9 +11,10 @@ SUBDIR = robots
include $(OBJDIR)/Makeconf include $(OBJDIR)/Makeconf
SUBDIRS = emc rmcd vmcd SUBDIRS = mtp emc rmcd vmcd
all: all-subdirs all: all-subdirs
check: check-subdirs
include $(TESTBED_SRCDIR)/GNUmakerules include $(TESTBED_SRCDIR)/GNUmakerules
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = robots/mtp
include $(OBJDIR)/Makeconf
MTPLIBS = libmtp.a
MTPPROGS = mtp_test
TESTS = mtp_test
all: $(MTPLIBS) $(MTPPROGS)
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS = mtp.o
CFLAGS += -O -g -Wall -I${OBJDIR} -I/usr/local/include
libmtp.a: $(OBJS)
$(AR) crv $@ $<
$(RANLIB) $@
mtp.o: mtp.h
mtp_test.o: mtp.h
mtp_test: mtp_test.o $(MTPLIBS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ mtp_test.o -L. -lmtp
install: $(addprefix $(INSTALL_LIBDIR), $(MTPLIBS))
clean:
/bin/rm -f *.o *.a $(MTPPROGS)
#include "mtp.h"
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#include "mtp.h"
static int readall(int fd,char *buffer,unsigned int len)
{
int rc, off = 0, retval;
assert(fd >= 0);
assert(buffer != NULL);
while ((rc = read(fd,&buffer[off],len - off)) > 0) {
off += rc;
}
if (rc < 0) {
retval = rc;
}
else {
retval = off;
}
return retval;
}
int mtp_receive_packet(int fd,struct mtp_packet **packet) { int mtp_receive_packet(int fd,struct mtp_packet **packet) {
unsigned int length; unsigned int length;
char clength[4]; uint32_t clength;
char *buf = NULL; char *buf = NULL;
int i;
int retval; int retval;
if (packet == NULL) { if (packet == NULL) {
return MTP_PP_ERROR_ARGS; return MTP_PP_ERROR_ARGS;
} }
retval = read(fd,(void*)(&clength),4); retval = readall(fd,&clength,4);
if (retval == -1) { if (retval == -1) {
return MTP_PP_ERROR_READ; return MTP_PP_ERROR_READ;
} }
else { else {
int remaining_length;
/* length is currently in bytes 0,1,2,and 3, in network byte order */ /* length is currently in bytes 0,1,2,and 3, in network byte order */
length = ntohl((uint32_t)(clength)); length = ntohl(clength);
if (length > MTP_PACKET_MAXLEN) { if (length > MTP_PACKET_MAXLEN) {
return MTP_PP_ERROR_LENGTH; return MTP_PP_ERROR_LENGTH;
} }
/* read the rest of the packet into buf */ /* read the rest of the packet into buf */
int remaining_length = length - 4; remaining_length = length - 4;
buf = (char*)malloc(sizeof(char)*(length+1)); buf = (char*)malloc(sizeof(char)*(length+1));
if (buf == NULL) { if (buf == NULL) {
return MTP_PP_ERROR_MALLOC; return MTP_PP_ERROR_MALLOC;
} }
// copy the header bytes to the new buf // copy the header bytes to the new buf
for (i = 0; i < 4; ++i) { memcpy(buf,&clength,4);
buf[i] = clength[i];
}
retval = read(fd,(void*)(buf+sizeof(char)*MTP_PACKET_HEADER_LEN),remaining_length); retval = readall(fd,(void*)&buf[MTP_PACKET_HEADER_OFFSET_OPCODE],remaining_length);
if (retval == -1) { if (retval == -1) {
free(buf); free(buf);
return MTP_PP_ERROR_READ; return MTP_PP_ERROR_READ;
...@@ -56,10 +80,10 @@ int mtp_receive_packet(int fd,struct mtp_packet **packet) { ...@@ -56,10 +80,10 @@ int mtp_receive_packet(int fd,struct mtp_packet **packet) {
int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) { int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) {
char *buf; char *buf;
int i,j,k; int i,j;
int buf_size; int buf_size;
if (packet == NULL || buf == NULL) { if (packet == NULL || buf_ptr == NULL) {
return MTP_PP_ERROR_ARGS; return MTP_PP_ERROR_ARGS;
} }
...@@ -94,13 +118,9 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) { ...@@ -94,13 +118,9 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) {
// write code field // write code field
*((int *)(buf+i)) = htonl(data->code); *((int *)(buf+i)) = htonl(data->code);
i += 4; i += 4;
// write msg field, and null-term it // write msg field
for (j = 0; j < strlen(data->msg); ++j) { strcpy(&buf[i],data->msg);
buf[i] = data->msg[j]; i += strlen(&buf[i]) + 1;
++i;
}
buf[i] = '\0';
} }
else if (packet->opcode == MTP_CONFIG_RMC) { else if (packet->opcode == MTP_CONFIG_RMC) {
struct mtp_config_rmc *data = packet->data.config_rmc; struct mtp_config_rmc *data = packet->data.config_rmc;
...@@ -127,13 +147,8 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) { ...@@ -127,13 +147,8 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) {
*((int *)(buf+i)) = htonl(data->robots[j].id); *((int *)(buf+i)) = htonl(data->robots[j].id);
i += 4; i += 4;
// write the hostname field // write the hostname field
int len = strlen(data->robots[j].hostname); strcpy(&buf[i],data->robots[j].hostname);
for (k = 0; k < len; ++k) { i += strlen(&buf[i]) + 1;
buf[i] = data->robots[j].hostname[k];
++i;
}
buf[i] = '\0';
++i;
} }
// now write the global_bound data // now write the global_bound data
*((int *)(buf+i)) = htonl(data->box.horizontal); *((int *)(buf+i)) = htonl(data->box.horizontal);
...@@ -166,13 +181,8 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) { ...@@ -166,13 +181,8 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) {
*((int *)(buf+i)) = htonl(data->robots[j].id); *((int *)(buf+i)) = htonl(data->robots[j].id);
i += 4; i += 4;
// write the hostname field // write the hostname field
int len = strlen(data->robots[j].hostname); strcpy(&buf[i],data->robots[j].hostname);
for (k = 0; k < len; ++k) { i += strlen(&buf[i]) + 1;
buf[i] = data->robots[j].hostname[k];
++i;
}
buf[i] = '\0';
++i;
} }
} }
...@@ -338,7 +348,7 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) { ...@@ -338,7 +348,7 @@ int mtp_encode_packet(char **buf_ptr,struct mtp_packet *packet) {
int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) { int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) {
struct mtp_packet *packet; struct mtp_packet *packet;
int i,j,k; int i,j;
int len; int len;
if (buf == NULL) { if (buf == NULL) {
...@@ -392,9 +402,11 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) { ...@@ -392,9 +402,11 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) {
return MTP_PP_ERROR_MALLOC; return MTP_PP_ERROR_MALLOC;
} }
for (j = 0; j < data->num_robots; ++j) { for (j = 0; j < data->num_robots; ++j) {
int len;
data->robots[j].id = ntohl(*((int *)(buf+i))); data->robots[j].id = ntohl(*((int *)(buf+i)));
i += 4; i += 4;
int len = strlen(buf+i) + 1; len = strlen(buf+i) + 1;
data->robots[j].hostname = (char *)malloc(sizeof(char)*len); data->robots[j].hostname = (char *)malloc(sizeof(char)*len);
memcpy(data->robots[j].hostname,buf+i,len); memcpy(data->robots[j].hostname,buf+i,len);
i += len; i += len;
...@@ -419,9 +431,11 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) { ...@@ -419,9 +431,11 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) {
return MTP_PP_ERROR_MALLOC; return MTP_PP_ERROR_MALLOC;
} }
for (j = 0; j < data->num_robots; ++j) { for (j = 0; j < data->num_robots; ++j) {
int len;
data->robots[j].id = ntohl(*((int *)(buf+i))); data->robots[j].id = ntohl(*((int *)(buf+i)));
i += 4; i += 4;
int len = strlen(buf+i) + 1; len = strlen(buf+i) + 1;
data->robots[j].hostname = (char *)malloc(sizeof(char)*len); data->robots[j].hostname = (char *)malloc(sizeof(char)*len);
memcpy(data->robots[j].hostname,buf+i,len); memcpy(data->robots[j].hostname,buf+i,len);
i += len; i += len;
...@@ -523,20 +537,20 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) { ...@@ -523,20 +537,20 @@ int mtp_decode_packet(char *buf,struct mtp_packet **packet_ptr) {
} }
int mtp_send_packet(int fd,struct mtp_packet *packet) { int mtp_send_packet(int fd,struct mtp_packet *packet) {
char **buf; char *buf;
int retval; int retval;
if (packet == NULL) { if (packet == NULL) {
return MTP_PP_ERROR; return MTP_PP_ERROR;
} }
retval = mtp_encode_packet(buf,packet); retval = mtp_encode_packet(&buf,packet);
if (retval < MTP_PP_SUCCESS) { if (retval < MTP_PP_SUCCESS) {
return retval; return retval;
} }
// now we can write the buffer out the socket. // now we can write the buffer out the socket.
retval = write(fd,*buf,retval); retval = write(fd,buf,retval);
if (retval != -1) { if (retval != -1) {
return MTP_PP_SUCCESS; return MTP_PP_SUCCESS;
} }
...@@ -612,7 +626,7 @@ struct mtp_packet *mtp_make_packet( unsigned char opcode, ...@@ -612,7 +626,7 @@ struct mtp_packet *mtp_make_packet( unsigned char opcode,
int mtp_calc_size(int opcode,void *data) { int mtp_calc_size(int opcode,void *data) {
int retval = -1; int retval = -1;
int i,j; int i;
if (data == NULL) { if (data == NULL) {
return retval; return retval;
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define MTP_ROLE_RMC 1 #define MTP_ROLE_RMC 1
#define MTP_ROLE_EMULAB 5 #define MTP_ROLE_EMULAB 5
/* These are used in the status fields in MTP_POSITION_UPDATE packets */ /* These are used in the status fields in MTP_UPDATE_POSITION packets */
#define MTP_POSITION_STATUS_IDLE 1 #define MTP_POSITION_STATUS_IDLE 1
#define MTP_POSITION_STATUS_MOVING 2 #define MTP_POSITION_STATUS_MOVING 2
#define MTP_POSITION_STATUS_ERROR 3 #define MTP_POSITION_STATUS_ERROR 3
...@@ -68,6 +68,18 @@ ...@@ -68,6 +68,18 @@
#define MTP_PACKET_HEADER_OFFSET_VERSION 5 #define MTP_PACKET_HEADER_OFFSET_VERSION 5
#define MTP_PACKET_HEADER_OFFSET_ROLE 6 #define MTP_PACKET_HEADER_OFFSET_ROLE 6
typedef union mtp_payload_t {
struct mtp_control *control;
struct mtp_config_rmc *config_rmc;
struct mtp_config_vmc *config_vmc;
struct mtp_request_position *request_position;
struct mtp_request_id *request_id;
struct mtp_update_position *update_position;
struct mtp_update_id *update_id;
struct mtp_command_goto *command_goto;
struct mtp_command_stop *command_stop;
} mtp_payload_t;
/* here is the protocol definition in terms of structures */ /* here is the protocol definition in terms of structures */
typedef struct mtp_packet { typedef struct mtp_packet {
/* length has no meaning for user applications -- it's just there to better /* length has no meaning for user applications -- it's just there to better
...@@ -78,17 +90,7 @@ typedef struct mtp_packet { ...@@ -78,17 +90,7 @@ typedef struct mtp_packet {
unsigned char version; unsigned char version;
unsigned char role; unsigned char role;
union { mtp_payload_t data;
struct mtp_control *control;
struct mtp_config_rmc *config_rmc;
struct mtp_config_vmc *config_vmc;
struct mtp_request_position *request_position;
struct mtp_request_id *request_id;
struct mtp_update_position *update_position;
struct mtp_update_id *update_id;
struct mtp_command_goto *command_goto;
struct mtp_command_stop *command_stop;
} data;
} mtp_packet_t; } mtp_packet_t;
......
#include "config.h"
#define DEBUG
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include "mtp.h"
int main(int argc, char *argv[])
{
static struct mtp_control mc = {
42,
MTP_PP_ERROR_MALLOC,
"I've come undone"
};
static struct robot_config rcr[3] = {
{ 1, "node1" },
{ 2, "node2" },
{ 3, "node3" },
};
static struct mtp_config_rmc mcr = {
3,
rcr,
{ 10.0, 20.0 }
};
static struct robot_config rcv[3] = {
{ 4, "vnode4" },
{ 5, "vnode5" },
{ 6, "vnode6" },
};
static struct mtp_config_vmc mcv = {
3,
rcv
};
static struct mtp_request_position mrp = {
4
};
static struct mtp_update_position mup = {
3,
{ 5, 25, 76 },
MTP_POSITION_STATUS_IDLE,
56
};
static struct mtp_request_id mri = {
{ 3, 20, 69 },
169
};
static struct mtp_update_id mui = {
30
};
static struct mtp_command_goto mcg = {
5,
3,
{ 2, 13, 73 },
};
static struct mtp_command_goto mcs = {
4,
2,
};
int fd, retval = EXIT_SUCCESS;
if ((fd = open("mtp_stream.dat", O_CREAT | O_TRUNC | O_RDWR, 0666)) < 0) {
perror("Could not open 'mtp_stream.dat'?");
}
else {
struct mtp_packet *mp;
int lpc;
assert(mp = mtp_make_packet(MTP_CONTROL_ERROR, MTP_ROLE_EMC, &mc));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_CONFIG_RMC, MTP_ROLE_RMC, &mcr));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_CONFIG_VMC, MTP_ROLE_VMC, &mcv));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_REQUEST_POSITION, MTP_ROLE_VMC, &mrp));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_UPDATE_POSITION, MTP_ROLE_VMC, &mup));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_REQUEST_ID, MTP_ROLE_VMC, &mri));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_UPDATE_ID, MTP_ROLE_VMC, &mui));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_COMMAND_GOTO, MTP_ROLE_VMC, &mcg));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
assert(mp = mtp_make_packet(MTP_COMMAND_STOP, MTP_ROLE_VMC, &mcs));
assert(mtp_send_packet(fd,mp) == MTP_PP_SUCCESS);
lseek(fd,0,SEEK_SET);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_CONTROL_ERROR);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_EMC);
assert(mp->data.control->id == mc.id);
assert(mp->data.control->code == mc.code);
assert(strcmp(mp->data.control->msg, mc.msg) == 0);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_CONFIG_RMC);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_RMC);
assert(mp->data.config_rmc->num_robots == mcr.num_robots);
assert(mp->data.config_rmc->box.horizontal == mcr.box.horizontal);
assert(mp->data.config_rmc->box.vertical == mcr.box.vertical);
for (lpc = 0; lpc < mcr.num_robots; lpc++) {
assert(mp->data.config_rmc->robots[lpc].id == mcr.robots[lpc].id);
assert(strcmp(mp->data.config_rmc->robots[lpc].hostname,
mcr.robots[lpc].hostname) == 0);
}
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_CONFIG_VMC);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.config_vmc->num_robots == mcv.num_robots);
for (lpc = 0; lpc < mcv.num_robots; lpc++) {
assert(mp->data.config_vmc->robots[lpc].id == mcv.robots[lpc].id);
assert(strcmp(mp->data.config_vmc->robots[lpc].hostname,
mcv.robots[lpc].hostname) == 0);
}
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_REQUEST_POSITION);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.request_position->robot_id == mrp.robot_id);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_UPDATE_POSITION);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.update_position->robot_id == mup.robot_id);
assert(mp->data.update_position->position.x == mup.position.x);
assert(mp->data.update_position->position.y == mup.position.y);
assert(mp->data.update_position->position.theta == mup.position.theta);
assert(mp->data.update_position->status == mup.status);
assert(mp->data.update_position->timestamp == mup.timestamp);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_REQUEST_ID);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.request_id->position.x == mri.position.x);
assert(mp->data.request_id->position.y == mri.position.y);
assert(mp->data.request_id->position.theta == mri.position.theta);
assert(mp->data.request_id->timestamp == mri.timestamp);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_UPDATE_ID);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.update_id->robot_id == mui.robot_id);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_COMMAND_GOTO);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.command_goto->command_id == mcg.command_id);
assert(mp->data.command_goto->robot_id == mcg.robot_id);
assert(mp->data.command_goto->position.x == mcg.position.x);
assert(mp->data.command_goto->position.y == mcg.position.y);
assert(mp->data.command_goto->position.theta == mcg.position.theta);
assert(mtp_receive_packet(fd,&mp) == MTP_PP_SUCCESS);
assert(mp->opcode == MTP_COMMAND_STOP);
assert(mp->version == MTP_VERSION);
assert(mp->role == MTP_ROLE_VMC);
assert(mp->data.command_goto->command_id == mcs.command_id);
assert(mp->data.command_goto->robot_id == mcs.robot_id);
close(fd);
fd = -1;
}
return retval;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment