Code Search for Developers
 
 
  

conn-sender.c from EmStar at Krugle


Show conn-sender.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
 

/*
 * ping.c: This a "ping" client, which broadcasts a 'ping' packet, and
 * then waits for replies from the network.  This program, and the
 * corresponding 'pingd' server, serve as a useful example for various
 * tasks:
 *
 *   - How to create an application-layer protocol format
 *   - How to send packets to the network
 *   - How to wait for and react to packets that come from the network
 *   - How to filter incoming packets
 *
 * $Id: conn-sender.c,v 1.6 2003/11/18 02:08:42 cerpa Exp $
 */

char conn_sender_c_cvsid[] = "$Id: conn-sender.c,v 1.6 2003/11/18 02:08:42 cerpa Exp $";

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "emrun/emrun.h"
#include "link/link.h"
#include <string.h>
#include <libdev/logring_dev.h>
#include <libdev/command_dev.h>

#define LOGRING_SUPPORT

#define CONN_MAX_PACKET_SZ       1024 /* pkts can never be larger than this */
#define CONN_DEFAULT_PACKET_SZ    200
#define CONN_DEFAULT_SEND_DELAY  1000
#define CONN_DEFAULT_START_DELAY 3000
#define CONN_DEFAULT_TOTAL_CNT   1000
#define CONN_DEFAULT_BURST_CNT     50
#define CONN_DEFAULT_TOTAL_NODES   54

/* this is here only until this linkstats_pkt is moved to linkstats.h.
   this structure is not used by this code, but the sizeof it is! 
*/
typedef struct linkstats_pkt {
  node_id_t src_id;		/* my node ID */
  uint64_t seqno;		/* the sequence number of this packet */
  uint8_t inner_type;		/* the type of the packet once linkstats
                                   header is stripped */
  uint8_t data[0];              /* pointer to the following data packet */
} __attribute__ ((packed)) linkstats_pkt_t;

typedef struct app_state {
  int total_sent;
  link_context_t *link;
  link_context_t *control_channel;

  /* app configuration variables */
  int total_cnt;   /* total number of packets this node should send*/
  int burst_cnt;   /* number of packets that should be sent before handing
                    off token */
  int send_delay;  /* milliseconds between each packet send */
  int start_delay; /* once token is received, number of milliseconds 
                      before starting to send */
  int packet_size; /* size includes link stats header, and link_header */
  int total_nodes; /* how many nodes are in the experiment */
#ifdef LOGRING_SUPPORT
    int token_fd; 
#endif
} app_state_t;

typedef struct token_pkt {
  int id;
} token_pkt_t;

/*******************************************************************/

/*
 * Callback activated when we are asked to shut down by emrun.
 * Compute and print summary statistics of all replies received
 */  
void app_shutdown(void *data)
{
  app_state_t *u = (app_state_t *) data;
  if(close(u->token_fd)){
      elog(LOG_ERR,"error closing the token logring");
  }
  elog(LOG_NOTICE, "%d packets sent",u->total_sent);
  exit(0);
}


/*
 * Construct a packet, and send it out over the wire, using the
 * link context stored as part of our app_state.
 */
void app_send(app_state_t *u)
{
  int pktsz, i;
  /* Allocate a small buffer for the packet */
  char buf[CONN_MAX_PACKET_SZ];
  link_pkt_t *pkt = (link_pkt_t *) buf;
  char *ptr = (char *)pkt->data;

  elog(LOG_DEBUG(0), "in app_send");
  /* initialize the link_pkt header */
  memset(buf, 0, sizeof(buf));
  pktsz = u->packet_size - sizeof(link_pkt_t) - sizeof(linkstats_pkt_t);
  for (i = 0; i < pktsz; i++){
      ptr[i] = (char)(256.0*random()/(RAND_MAX+1.0));
  }

  pkt->dst.id = LINK_BROADCAST;
  pkt->type = PKT_TYPE_CONNTEST_DATA;

  u->total_sent++;


  /* now launch the packet! */
  if (link_send(u->link, pkt, pktsz) < 0)
    elog(LOG_ERR, "can't send on %s: %m", link_name(link_opts(u->link)));
  else
    elog(LOG_NOTICE, "broadcast packet %d", u->total_sent);
}
void token_send(app_state_t *u)
{
#ifdef UDPD_SUPPORT
  /* Allocate a small buffer for the packet */
  char buf[CONN_MAX_PACKET_SZ];
  link_pkt_t *pkt = (link_pkt_t *) buf;
  token_pkt_t *tpkt = (token_pkt_t *)(pkt->data);

  /* send token containing id of next node to send */
  int next_id = (my_node_id + 1) % u->total_nodes;

  elog(LOG_DEBUG(0), "in token_send");

  /* initialize the link_pkt header */
  memset(buf, 0, sizeof(buf));
  pkt->dst.id = LINK_BROADCAST;
  pkt->type = PKT_TYPE_CONNTEST_DATA;
  /* initialize the inner header */
  tpkt->id = next_id;

  /* now launch the packet! */
  if (link_send(u->control_channel, pkt, sizeof(token_pkt_t)) < 0)
    elog(LOG_ERR, "can't send on %s: %m", 
         link_name(link_opts(u->control_channel)));
  else
    elog(LOG_NOTICE, "broadcast token %d", tpkt->id);
#endif
#ifdef LOGRING_SUPPORT
  /* send token containing id of next node to send */
  char buf[CONN_MAX_PACKET_SZ];
  int retval;
  int next_id = (my_node_id + 1);
  if (next_id > u->total_nodes) next_id -= u->total_nodes;

  elog(LOG_NOTICE,"myid %d +1 = %d mod %d = %d",my_node_id, (my_node_id + 1),
       u->total_nodes, next_id);
  sprintf(buf,"%4d",next_id);

  if ((retval = write(u->token_fd,buf,5))!= 5){
      elog(LOG_ERR,"error writing token %d %d %s",retval, errno,strerror(errno));
        exit(1);
  }
  elog(LOG_NOTICE, "wrote token %d", next_id);
#endif
}

/* Called every time our periodic ping timer expies.  */
int app_periodic_timer(void *data, int interval, g_event_t *ev)
{
  app_state_t *u = (app_state_t *) data;

  elog(LOG_NOTICE, "in app_periodic timer");
  app_send(u);
  if ((u->total_sent % u->burst_cnt) == 0){
    token_send(u);
    if (u->total_sent >= u->total_cnt) app_shutdown(u);
    return EVENT_DONE;
 }
  return EVENT_RENEW;
}

int start_timer(void *data, int interval, g_event_t *ev)
{
    app_state_t *u = (app_state_t *)data;

    elog(LOG_NOTICE,"starting burst...%d",u->send_delay);
    g_timer_add(u->send_delay, app_periodic_timer, u, NULL,NULL);
    return EVENT_DONE;
}

void start_sending(app_state_t *u)
{
    elog(LOG_NOTICE,"starting to send...");
  g_timer_add(u->start_delay,start_timer,u,NULL,NULL);
}

#ifdef LOGRING_SUPPORT
int new_token(gpointer data, gint fd, int fusd_condition, g_event_t *ev)
{
    int retval, token;
    char buf[10];
    /* Get a pointer to my app state */
    app_state_t *u = (app_state_t *)data;

    if((retval = read(u->token_fd, &buf, 5))!=5){
        elog(LOG_ERR,"problem reading token - error: %d %s",
             retval,strerror(errno));
        exit(1);
    }
    token = atoi(buf);
    elog(LOG_DEBUG(0), "received token %d",token);
    if (token == my_node_id){
        elog(LOG_DEBUG(0), "Node %d has received token",my_node_id);
        start_sending(u);
    }
    return EVENT_RENEW;
}
#endif

int pkt_receiver(link_pkt_t * link_pkt, ssize_t data_len, link_context_t *link)
{
  /* got a packet, but do nothing */
  elog(LOG_DEBUG(0),"received a packet");
  free(link_pkt);
  return EVENT_RENEW;
}

#ifdef UDPD_SUPPORT
int token_receiver(link_pkt_t * link_pkt, ssize_t data_len, 
                   link_context_t *link)
{
  /* Get a pointer to the data portion of the packet */
  token_pkt_t *tpkt = (token_pkt_t *)(link_pkt->data);
  /* Get a pointer to my app state */
  app_state_t *u = (app_state_t *)(link_opts(link))->data;

  elog(LOG_DEBUG(0), "in token_receiver");
  if (tpkt->id == my_node_id){
    start_sending(u);
  }
  free(link_pkt);
  return EVENT_RENEW;
}
#endif

void usage(void)
{
  fprintf(stderr,
          /*          "conn-sender release: %s\n" */
          "\n"
          "usage: conn-sender [-t total packets][-b burst packets]\n"
          "                   [-p send delay][-d start delay]\n"
          "                   [-s packet size][-n total nodes]\n"
          /* ,CVSTAG */
          );
  exit(1);
}

int main(int argc, char *argv[])
{
  int arg;

  struct timeval tv;
  struct timezone tz;

  app_state_t u;
  link_opts_t link_opts;

  emrun_opts_t emrun_opts = {
    shutdown: app_shutdown,
    data: (void *) &u
  };

  memset(&u,0,sizeof(app_state_t));
  u.total_cnt =   CONN_DEFAULT_TOTAL_CNT;
  u.burst_cnt =   CONN_DEFAULT_BURST_CNT;
  u.send_delay =  CONN_DEFAULT_SEND_DELAY;
  u.start_delay = CONN_DEFAULT_START_DELAY;
  u.packet_size = CONN_DEFAULT_PACKET_SZ;
  u.total_nodes = CONN_DEFAULT_TOTAL_NODES;

  gettimeofday(&tv,&tz);
  srandom(tv.tv_usec);

  /* Generic initialization common to most software */
  misc_init(&argc, argv, CVSTAG);

  /************ Parse command-line arguments ***********/

  opterr = 0;
  while((arg = getopt(argc,argv, "ht:b:p:d:s:n:")) != EOF){
    switch(arg){
    case 'h':
      usage();
      break;
    case 't':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid total message count '%s'",optarg);
        exit(1);
      } else {
        u.total_cnt = atoi(optarg);
        elog_g(LOG_NOTICE,"total_cnt set to %d",u.total_cnt);
      }
      break;
    case 'b':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid burst count '%s'",optarg);
        exit(1);
      } else {
        u.burst_cnt = atoi(optarg);
        elog_g(LOG_NOTICE,"burst_cnt set to %d",u.burst_cnt);
      }
      break;
    case 'p':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid send delay '%s'",optarg);
        exit(1);
      } else {
        u.send_delay = atoi(optarg);
        elog_g(LOG_NOTICE,"send_delay set to %d",u.send_delay);
      }
      break;
    case 'd':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid start delay '%s'",optarg);
        exit(1);
      } else {
        u.start_delay = atoi(optarg);
        elog_g(LOG_NOTICE,"start_delay set to %d",u.start_delay);
      }
      break;
    case 's':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid packet size '%s'",optarg);
        exit(1);
      } else {
        u.packet_size = atoi(optarg);
        elog_g(LOG_NOTICE,"packet_size set to %d",u.packet_size);
      }
      break;
    case 'n':
      if (!isdigit(*optarg)){
        elog_g(LOG_CRIT, "invalid total nodes '%s'",optarg);
        exit(1);
      } else {
        u.total_nodes = atoi(optarg);
        elog_g(LOG_NOTICE,"total_nodes set to %d",u.total_nodes);
      }
      break;

    default:
      usage();
      break;
    }
  }

  /* advance past parsed options */
  argc -= optind;
  argv += optind;

  /*
   * Open the real link-layer device and the control channel device.  
   */

  elog(LOG_DEBUG(0),"assigning link_opts");
  link_opts.link_index = 0;
  link_opts.dev_type = LINK_DEV_DATA;
  link_opts.pkt_type = PKT_TYPE_CONNTEST_DATA;	 /* only give us ping-type packets */
  link_opts.receive = pkt_receiver;	 /* call this func when packets arrive */
  link_opts.data =  (void *) &u;	 /* store app_state so link callback can use it */
  link_opts.q_opts.outq_len = 300;
  link_opts.q_opts.inq_len = 300;
 
  elog(LOG_DEBUG(0),"link_opts assigned");

  if (link_open(&link_opts, &u.link) < 0) {
    elog(LOG_CRIT, "can't open %s: %m", link_name(&link_opts));
    exit(1);
  }
  elog_g(LOG_NOTICE, "running, using %s", link_name(&link_opts));

#ifdef UDPD_SUPPORT
  link_opts.link_index = 1;
  link_opts.dev_type = LINK_DEV_DATA;
  link_opts.receive = token_receiver;	 /* call this func when packets arrive */
 
  if (link_open(&link_opts, &u.control_channel) < 0) {
    elog(LOG_CRIT, "can't open %s: %m", link_name(&link_opts));
    exit(1);
  }
  elog_g(LOG_NOTICE, "running, using %s", link_name(&link_opts));
#endif

#ifdef LOGRING_SUPPORT
  if((u.token_fd = open("/dev/logring/l1", O_RDWR))==-1){
      elog(LOG_ERR,"can't open logring: %s",strerror(errno));
      exit(1);
  }

  g_event_add(u.token_fd,FUSD_NOTIFY_INPUT,new_token,&u,NULL,NULL);

#endif


  /* Try to set the POT of the radio to 56, just to demonstrate how
   * POT-setting is done */

  /*
    POT = 56;
    if (link_ioctl(u.link, LINK_SET_POT, &POT) < 0)
    elog(LOG_CRIT, "warning: can't set POT: %m");
  */
  
  /* node 1 starts things off */
  if (my_node_id == 1){
    g_timer_add(u.send_delay, app_periodic_timer, &u, NULL, NULL);
  }
  /*
   * Start the event loop running - it should never exit (the shutdown
   * handler is called when the program is supposed to stop)
   */
  emrun_init(&emrun_opts); /* this should be the last initialization */
  g_main();
  elog_g(LOG_CRIT, "event loop terminated abnormally!");
  return 0;
}





See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  README
  conn-dump.c
  conn-sender.c
  conn-simconfig
  conn-tab