mtp_dump.c 4.22 KB
Newer Older
1 2
/*
 * Copyright (c) 2004, 2005 University of Utah and the Flux Group.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 
 * {{{EMULAB-LICENSE
 * 
 * This file is part of the Emulab network testbed software.
 * 
 * This file is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * This file 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 Affero General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this file.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * }}}
22 23 24 25 26 27 28 29
 */

/**
 * @file mtp_dump.c
 *
 * Utility that will connect to a server and dump out any MTP packets it
 * receives.
 */
Timothy Stack's avatar
Timothy Stack committed
30 31 32 33

#include "config.h"

#include <stdio.h>
Timothy Stack's avatar
Timothy Stack committed
34
#include <string.h>
Timothy Stack's avatar
Timothy Stack committed
35 36 37
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
38 39
#include <signal.h>
#include <float.h>
Timothy Stack's avatar
Timothy Stack committed
40 41 42 43 44 45 46

#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
47
#include <string.h>
Timothy Stack's avatar
Timothy Stack committed
48 49 50

#include "mtp.h"

51 52 53 54 55 56 57 58 59 60 61 62 63 64
static int looping = 1;

/**
 * Signal handler for SIGINT, SIGQUIT, and SIGTERM that sets looping to zero.
 *
 * @param signal The actual signal received.
 */
static void sigquit(int signal)
{
    assert((signal == SIGINT) || (signal == SIGQUIT) || (signal == SIGTERM));

    looping = 0;
}

Timothy Stack's avatar
Timothy Stack committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
static int mygethostbyname(struct sockaddr_in *host_addr, char *host)
{
    struct hostent *host_ent;
    int retval = 0;

    assert(host_addr != NULL);
    assert(host != NULL);
    assert(strlen(host) > 0);

    if( (host_ent = gethostbyname(host)) != NULL ) {
	memcpy((char *)&host_addr->sin_addr.s_addr,
	       host_ent->h_addr,
	       host_ent->h_length);
	retval = 1;
    }
    else {
	retval = inet_aton(host, &host_addr->sin_addr);
    }
    return( retval );
}

static void usage(void)
{
88
    fprintf(stderr, "Usage: mtp_dump <host> <port> [<max-packets>]\n");
Timothy Stack's avatar
Timothy Stack committed
89 90 91 92 93 94 95
}

int main(int argc, char *argv[])
{
    int port = 0, max_packets = 0, retval = EXIT_FAILURE;
    struct sockaddr_in sin;
    
96 97 98 99
    signal(SIGQUIT, sigquit);
    signal(SIGTERM, sigquit);
    signal(SIGINT, sigquit);
    
Timothy Stack's avatar
Timothy Stack committed
100 101 102 103 104 105 106 107
    memset(&sin, 0, sizeof(sin));
    
    if (argc < 3) {
	fprintf(stderr, "error: not enough arguments\n");
	usage();
    }
    else if (sscanf(argv[2], "%d", &port) != 1) {
	fprintf(stderr, "error: port is not a number\n");
108
	usage();
Timothy Stack's avatar
Timothy Stack committed
109 110 111
    }
    else if ((argc > 3) && sscanf(argv[3], "%d", &max_packets) != 1) {
	fprintf(stderr, "error: max packets argument is not a number\n");
112
	usage();
Timothy Stack's avatar
Timothy Stack committed
113 114 115 116 117
    }
    else if (mygethostbyname(&sin, argv[1]) == 0) {
	fprintf(stderr, "error: unknown host %s\n", argv[1]);
    }
    else {
118
	mtp_handle_t mh;
Timothy Stack's avatar
Timothy Stack committed
119 120
	int fd;
	
121
#ifndef linux
Timothy Stack's avatar
Timothy Stack committed
122
	sin.sin_len = sizeof(sin);
123
#endif
Timothy Stack's avatar
Timothy Stack committed
124 125 126 127 128 129 130 131 132
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	    perror("socket");
	    retval = EXIT_FAILURE;
	}
	else if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
	    perror("connect");
	}
133 134 135
	else if ((mh = mtp_create_handle(fd)) == NULL) {
	    fprintf(stderr, "error: mtp_init_handle\n");
	}
Timothy Stack's avatar
Timothy Stack committed
136
	else {
137 138
	    float minx = FLT_MAX, miny = FLT_MAX;
	    float maxx = FLT_MIN, maxy = FLT_MIN;
139
	    struct mtp_packet mp;
Timothy Stack's avatar
Timothy Stack committed
140 141
	    int lpc = 0;
	    
142
	    while (looping && ((max_packets == 0) || (lpc < max_packets)) &&
143
		   (mtp_receive_packet(mh, &mp) == MTP_PP_SUCCESS)) {
144 145 146 147 148 149 150 151 152
		if (mp.data.opcode == MTP_UPDATE_POSITION) {
		    struct mtp_update_position *mup;

		    mup = &mp.data.mtp_payload_u.update_position;
		    minx = min(minx, mup->position.x);
		    maxx = max(maxx, mup->position.x);
		    miny = min(miny, mup->position.y);
		    maxy = max(maxy, mup->position.y);
		}
Timothy Stack's avatar
Timothy Stack committed
153
		
154 155
		mtp_print_packet(stdout, &mp);

156
		mtp_free_packet(&mp);
Timothy Stack's avatar
Timothy Stack committed
157 158 159 160 161 162

		lpc += 1;
	    }
	    
	    close(fd);
	    fd = -1;
163 164 165

	    mtp_delete_handle(mh);
	    mh = NULL;
166 167 168 169 170 171

	    printf(" minx = %.2f; miny = %.2f\n"
		   " maxx = %.2f; maxy = %.2f (width = %.2f, height = %.2f\n",
		   minx, miny,
		   maxx, maxy,
		   maxx - minx, maxy - miny);
Timothy Stack's avatar
Timothy Stack committed
172 173 174 175 176 177 178
	}

	retval = EXIT_SUCCESS;
    }
    
    return retval;
}