Log In
New Account
  
 
Home My Page Project Tree Code Snippets Project Openings NUTSS
 
 
Summary Tracker Lists CVS Files
 

CVS | Administration


File:  [GForge:cvsroot/nutss] / libnutss / examples / nutssping.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 11:42:45 2007 UTC (9 years, 10 months ago) by saikat
Branches: saikat
CVS tags: version_0_1_0, initial
Initial upload


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

#ifdef LINUX
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#define closesocket(x)   close((x))
#endif

#ifdef WIN32
#include <winsock2.h>
#define sleep(X) Sleep((X)*1000)
#define snprintf _snprintf

int gettimeofday(struct timeval * tp, void * tzp)
{
	time((time_t *)&tp->tv_sec);
	tp ->tv_usec = (GetTickCount() % 1000)*1000;
	return 0;
}
#endif

#define _GNU_SOURCE
#include "getopt.h"
#include "nutss.h"

#define DEFAULT_NUM_CONNECTIONS -1
#define DEFAULT_NUM_PACKETS      1
#define DEFAULT_INTERVAL         1

#ifndef timersub
#define timersub(tvp, uvp, vvp)                                         \
        do {                                                            \
                (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;          \
                (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;       \
                if ((vvp)->tv_usec < 0) {                               \
                        (vvp)->tv_sec--;                                \
                        (vvp)->tv_usec += 1000000;                      \
                }                                                       \
        } while (0)
#endif

typedef struct config {
    int transmit;                        // Client side
    int respond;                         // Server side
    int num_conn;                        // Number of connections (-1 for infinite)
    int num_pkts;                        // Number of probes per connection
    int interval;                        // Interval between packets
    int non_blocking;                    // Use non-blocking sockets
    int pthreads;                        // Use threads for multiple clients
    int select;                          // Use select for multiple clients
    struct sockaddr_ns local, remote;    // Local and remote addresses
} config_t;

int set_nonblocking(SOCKET);
void usage(void);
void init(int, char **, config_t *);
void *respond_worker(void *);
void respond(config_t *);
void transmit(config_t *);

int
set_nonblocking(SOCKET fd)
{
#ifdef WIN32
    static int one = 1;
	return ioctlsocket(fd, FIONBIO, (unsigned long *) &one);
#endif

#ifdef LINUX
    int fl = fcntl(fd, F_GETFL, 0);
    if (fl != -1)
        return fcntl(fd, F_SETFL, fl | O_NONBLOCK);
    return -1;
#endif
}

void
usage(void)
{
    printf("Usage:\n"
        "  nutssping -r [-l uri] [options]\n"
        "  nutssping -t [-l src] [options] dst \n"
        "\n"
        "  --transmit,-t        Send ping requests\n"
        "  --respond,-r         Respond to ping requests\n"
        "  --local,-l uri       Local name to use\n"
        "                       URIs of the form user@domain\n"
        "\n"
        "Transmitter Options:\n"
        "  --count,c num             Stop after num pings\n"
        "  --use-non-blocking        Use non-blocking connect\n"
        "\n"
        "Responder Options:\n"
        "  --use-pthreads            Use pthreads for multiple clients\n"
        "  --use-select              Use select for multiple clients (not implemented)\n"
        "\n"
        "  --tls,s cert.pem          Enable TLS negotiation (currently ignored)\n"
        "  --stunt,u                 Enable STUNT NAT Traversal (currently ignored)\n"
        "  --turn,n                  Enable TURN Relay NAT Traversal (currently ignored)\n"
        "\n"
        "  --registrar server:port   Use sip registrar at server\n"
        "  --password pass           Use password for registering with proxy\n"
        );
    exit(1);
}

void
init(int argc, char **argv, config_t *cfg)
{
    int c, one = 1, zero = 0;
    int digit_optind = 0;
    static struct option long_options[] = {
        {"transmit", 0, 0, 't'},
        {"respond", 0, 0, 'r'},
        {"local", 1, 0, 'l'},
        {"tls", 1, 0, 's'},
        {"stunt", 0, 0, 'u'},
        {"turn", 0, 0, 'n'},
        {"count", 1, 0, 'c'},
        {"registrar", 1, 0, 0},
        {"password", 1, 0, 0},
        {"use-non-blocking", 0, 0, 0},
        {"use-pthreads", 0, 0, 0},
        {"use-sekect", 0, 0, 0},
        {"help", 0, 0, 'h'},
        {0, 0, 0, 0}
    };

    memset(cfg, 0, sizeof(*cfg));
    cfg->num_conn = DEFAULT_NUM_CONNECTIONS;
    cfg->num_pkts = DEFAULT_NUM_PACKETS;
    cfg->interval = DEFAULT_INTERVAL;

    while (1) {
        int this_option_optind = optind ? optind : 1;
        int option_index = 0;

        c = getopt_long (argc, argv, "c:trl:s:unh", long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
            case 't':
                cfg->transmit = 1;
                break;
            case 'r':
                cfg->respond = 1;
                break;
            case 'c':
                cfg->num_conn = atoi(optarg);
                break;
            case 'l':
                if (inet_uton(&cfg->local, optarg)) {
                    if (strlen(cfg->local.user)) {
                        nutss_config_set(NUTSS_CONFIG_USERNAME, cfg->local.user,
                            sizeof(cfg->local.user));
                        nutss_config_set(NUTSS_CONFIG_PROXYUSERNAME, cfg->local.user,
                            sizeof(cfg->local.user));
                    }
                    if (strlen(cfg->local.domain))
                        nutss_config_set(NUTSS_CONFIG_DOMAINNAME, cfg->local.domain,
                            sizeof(cfg->local.domain));
                }
                break;
            case 's':
                nutss_config_set(NUTSS_CONFIG_OPT_SECURE, &one, sizeof(one));
                break;
            case 'u':
                nutss_config_set(NUTSS_CONFIG_OPT_STUNT, &one, sizeof(one));
                break;
            case 'n':
                nutss_config_set(NUTSS_CONFIG_OPT_TURN, &one, sizeof(one));
                break;
            case 0:
                if (!strcmp(long_options[option_index].name, "registrar")) {
                    nutss_config_set(NUTSS_CONFIG_SIGPROXY, optarg, strlen(optarg) + 1);
                } else if (!strcmp(long_options[option_index].name, "password")) {
                    nutss_config_set(NUTSS_CONFIG_PROXYPASSWORD, optarg, strlen(optarg) + 1);
                } else if (!strcmp(long_options[option_index].name, "use-non-blocking")) {
                    cfg->non_blocking = 1;
                } else if (!strcmp(long_options[option_index].name, "pthreads")) {
                    cfg->pthreads = 1;
                } else if (!strcmp(long_options[option_index].name, "select")) {
                    cfg->select = 1;
                    usage(); // not-implemented
                } else {
                    usage();
                }
                break;
            default:
                usage();
        }
    }

    if (cfg->transmit) {
        if (optind >= argc)
            usage();
        inet_uton(&cfg->remote, argv[optind++]);
    }

    if (optind < argc || !(cfg->transmit || cfg->respond))
        usage();

    cfg->local.family = AF_NUTSS;
    if (cfg->respond && !strlen(cfg->local.service))
        strncpy(cfg->local.service, "nutssping", sizeof(cfg->local.service));
    if (cfg->transmit && !strlen(cfg->remote.service))
        strncpy(cfg->remote.service, "nutssping", sizeof(cfg->remote.service));
}

void *
respond_worker(void *arg)
{
    SOCKET c = (SOCKET) arg;
    char buf[255], uri[255];
    struct sockaddr_ns peer;
    socklen_t lpeer = sizeof(peer);
    int l;

    memset(buf, 0, sizeof(buf));
    nutss_getpeername(c, (struct sockaddr *)&peer, &lpeer);
    inet_ntou(AF_NUTSS, &peer, uri, sizeof(uri));
    for (;;) {
        if ((l = recv(c, buf, sizeof(buf), 0)) <= 0) {
            if (l) perror("recv");
            break;
        }
        if ((l = send(c, buf, l, 0)) <= 0) {
            if (l) perror("send");
            break;
        }
        printf("%d bytes from %s: %s\n", l, uri, buf);
    }
    closesocket(c);
    // printf("Closed connection from %s\n", uri);

    return NULL;
}


void
respond(config_t *cfg)
{
    char uri[255];
    struct sockaddr_ns peer;
    socklen_t lpeer = sizeof(peer);
    pthread_attr_t attr;
    pthread_t tid;
    SOCKET s, c;

    if (cfg->pthreads) {
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    }

    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    nutss_bind(s, (struct sockaddr *)&cfg->local, sizeof(cfg->local));
    listen(s, 10);

    for (;;) {
        c = nutss_accept(s, (struct sockaddr *) &peer, &lpeer);
        inet_ntou(AF_NUTSS, &peer, uri, sizeof(uri));
        // printf("Accepted connection from %s\n", uri);
        if (cfg->pthreads) {
            if (pthread_create(&tid, &attr, respond_worker, (void *)c))
                closesocket(c);
        } else if (cfg->select) {
            // Not implemented
            closesocket(c);
        } else {
            respond_worker((void *)c);
        }
    }
}

void
transmit(config_t *cfg)
{
    struct timeval c_st, c_ok, c_rp;
    struct timeval p_st, p_en;
    int bytes;
    char buf[255], uri[255];
    struct sockaddr_ns peer;
    socklen_t lpeer = sizeof(peer);
    SOCKET s;
    int conn, mconn, seq, mseq, l;
    fd_set fds, _fds;

    memset(buf, 0, 255);
    memset(uri, 0, 255);
    conn = 0;
    mconn = cfg->num_conn;
    while (mconn == -1 || mconn-- > 0) {
        if (conn) sleep(cfg->interval);

        gettimeofday(&c_st, NULL);
        conn++;
        seq = 0;
        bytes = 0;

        s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (cfg->non_blocking) {
            set_nonblocking(s);
            FD_ZERO(&fds);
            FD_SET(s, &fds);
        }
        if (nutss_connect(s, (struct sockaddr *)&cfg->remote, sizeof(cfg->remote)) != 0) {
            perror("connect");
            closesocket(s);
            continue;
        }

        gettimeofday(&c_ok, NULL);
        timersub(&c_ok, &c_st, &c_ok);

        nutss_getpeername(s, (struct sockaddr *)&peer, &lpeer);
        inet_ntou(AF_NUTSS, &peer, uri, sizeof(uri));
        mseq = cfg->num_pkts;
        while (mseq == -1 || mseq-- > 0) {
            if (seq) sleep(cfg->interval);

            snprintf(buf, sizeof(buf), "seq=%d.%d", conn, ++seq);
            gettimeofday(&p_st, NULL);
            if (cfg->non_blocking) {
                _fds = fds;
                if (select(s+1, NULL, &_fds, NULL, NULL) != 1) {
                    perror("select");
                    break;
                }
            }
            if (send(s, buf, strlen(buf), 0) != strlen(buf)) {
                perror("send");
                break;
            }
            if (cfg->non_blocking) {
                _fds = fds;
                if (select(s+1, &_fds, NULL, NULL, NULL) != 1) {
                    perror("select");
                    break;
                }
            }
            if ((l = recv(s, buf, sizeof(buf), 0)) <= 0) {
                perror("recv");
                break;
            }
            gettimeofday(&p_en, NULL);
            if (seq == 1) {
                c_rp = p_en;
                timersub(&c_rp, &c_st, &c_rp);
            }
            bytes += l;
            timersub(&p_en, &p_st, &p_en);
            printf("%d bytes from %s: %s crtt0=%5.3fms crtt1=%5.3fms rtt%d=%5.3f ms\n", l, uri,
                   buf,
                   c_ok.tv_sec*1000 + c_ok.tv_usec/1000.0,
                   c_rp.tv_sec*1000 + c_rp.tv_usec/1000.0,
                   seq,
                   p_en.tv_sec*1000 + p_en.tv_usec/1000.0);
        }

        closesocket(s);
    }
}

int
main(int argc, char **argv)
{
    config_t cfg;

    init(argc, argv, &cfg);

    nutss_init();

    if (cfg.respond)
        respond(&cfg);

    if (cfg.transmit)
        transmit(&cfg);

    exit(0);
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
 

GForge.cis.cornell.edu is brought to you by

Cornell Computing and Information Science


Powered By GForge Collaborative Development Environment