Code Search for Developers
 
 
  

receive_ping_device.c from EmStar at Krugle


Show receive_ping_device.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.
 *
 */
 

/*
 * receive_ping_device.c: This a "ping" daemon, which waits for ping-type network
 * packets.  Whenever one is received, pingd sends a reply back to the
 * sender.  This program, and the corresponding 'ping' client, 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
 *
 */

#include <stdio.h>
#include <stdlib.h>

#include "emrun/emrun.h"
#include "link/link.h"
#include "ping.h"


/*****************************************************************/
#define MAX_SOURCES 60

uint16_t last_seqno[MAX_SOURCES];
int pkt_type = PKT_TYPE_PING;

/*
 * Simple callback activated when we are asked to shut down by emrun
 */
void pingd_shutdown(void *data)
{
  elog(LOG_NOTICE, "ping daemon shutting down");
  exit(0);
}


static void usage(char *name)
{
  misc_print_usage
    (name, "-U <device> -p <pkt-type>",
     "  --uses <device>: Specify device to use\n -p <45=short/46=long>\n"
     );
  exit(1);
}


/*
 * This callback is called whenever a packet arrives on the link we
 * opened.  "pkt" is a pointer to a link_pkt_t header followed by
 * data_len bytes of data.  (data_len is the length of the data
 * following the header; it doesn't include the size of the link_pkt_t
 * header itself.)  "link" is a pointer to the link that the packet
 * was received on, and can be used for sending a reply packet.
 */
int pingd_receiver(lu_context_t *link, link_pkt_t *link_pkt, 
                   ssize_t data_len)
{
  ping_pkt_t *ping_pkt = (ping_pkt_t *) link_pkt->data;

  elog(LOG_CRIT, "got a packet from source %d and destination %d", 
       link_pkt->src.id, link_pkt->dst.id);
  
  /*
   * Make sure the packet has the right packet type.  Since we
   * specified the desired packet type when we registered to receive
   * packets, this test should never fail.
   */
  if (link_pkt->type != pkt_type) {
    elog(LOG_WARNING, "WARN got a packet not meant for us - filter failed!");
    goto done;
  }

  /*
   * Make sure the data portion of the packet is exactly the right
   * size (i.e., the size of our "ping" application-layer protocol
   * frame.
   */
  if (data_len != sizeof(ping_pkt_t)) {
    elog(LOG_ERR, "got a short ping packet (%d bytes, not %d)!",
	 data_len, sizeof(ping_pkt_t));
    goto done;
  }

  /* We now know that the data pointed to by ping_pkt is valid */
  elog(LOG_DEBUG(50), "got a ping packet: cmd: %u, random_id: %u,"
       "seqno: %u, node id: %u", ping_pkt->cmd, ping_pkt->random_id,
       ping_pkt->seqno, ping_pkt->node_id);      
  
  /*
   * Ignore everything but ping requests.  Note that we might get
   * PING_REPLY packets, e.g. if another process on this same
   * interface is acting as a ping client and getting their
   * responses.
   */
  if (ping_pkt->cmd != PING_REQUEST) {
    elog(LOG_DEBUG(2), "got non-request packet - dropping");
    goto done;
  }

  /* 
   * Verify that we haven't recieve this packet yet (we can receive 
   * duplicates if using hbh and acks are lost) 
   */
  if (ping_pkt->seqno <= last_seqno[ping_pkt->node_id])
    goto done; /* we ignore the duplicate */
  else
    last_seqno[ping_pkt->node_id] = ping_pkt->seqno; /* update state */

  /*
   * Now, we turn the packet around and send it back out again.
   */

  /* Fill in our node ID (this is not the same as interface ID) */
  ping_pkt->node_id = my_node_id;

  /* Destination link interface ID is the packet's source */
  link_pkt->dst.id = link_pkt->src.id;

  /* Source link interface ID is our id */
  link_pkt->src.id = my_node_id;
  
  /* Set the maximum number of hops, in case we're using a routed
   * interface */
  link_pkt->max_hops = PING_MAX_HOPS;

  /* Change cmd from request to reply; seqno stays the same */
  ping_pkt->cmd = PING_REPLY;

  elog(LOG_DEBUG(1), "Got a ping packet on %s - replying",
       lu_name(link, NULL));

  /* Now send it out on the interface we received it from */
  lu_send(link, link_pkt, data_len);

 done:
  /* note, packet must be freed! */
  free(link_pkt);
  return EVENT_RENEW;
}

int main(int argc, char *argv[])
{
  int arg, i;
  char *uses = NULL;
  
  emrun_opts_t emrun_opts = {
    shutdown: pingd_shutdown
  };

  /* init seqno state */
  for (i = 0; i < MAX_SOURCES; i++)
    last_seqno[i] = 0;
    
  /* generic initialization common to all programs */
  misc_init(&argc, argv, CVSTAG);

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

  uses = link_parse_uses(&argc, argv, NULL);
  if (misc_parse_option_as_uint(&argc, argv, "", 'p', &pkt_type))
  {
    elog(LOG_DEBUG(1), "pkt-type %d\n", pkt_type);
  }

  elog(LOG_DEBUG(1), "now pkt-type %d\n", pkt_type);
  
  opterr = 0;
  while ((arg = getopt(argc, argv, "hs")) != EOF) {
    switch (arg) {
    default:
    case '?':
      elog_g(LOG_CRIT, "invalid option '-%c' (use -h for help)", optopt);
    case 'h':
      usage(argv[0]);
      break;
    }
  }

  /* add'l args? */
  if (misc_args_remain(&argc, argv)) {
    elog(LOG_CRIT, "Additional unparsed arguments!");
    usage(argv[0]);
  }

  /* advance past parsed options */
  argc -= optind;
  argv += optind;
  
  /* If no link interfaces were explicitly given with --uses argument, fail */
  if (uses == NULL) {
    elog(LOG_CRIT, "Please specify a --uses argument!");
    exit(1);
  }

  /*
   * Pingd is a "link user".  We use lu_open() to open the link layer
   * device.  The options struct tells it we want
   * the ping_receiver function to be called every time a packet of
   * type PKT_TYPE_PING arrives.
   *
   * Note, we are passing NULL as the 2nd argument since we don't need
   * to save the link reference in this case.  See the 'ping' program
   * for an example where we do use it.
   */
  {
    lu_opts_t lu_opts = {
      opts: {
	name: uses,
	pkt_type: pkt_type	 /* only give us ping-type packets */
      },
      receive: pingd_receiver	 /* call this func when packets arrive */
    };  
   
    if (lu_open(&lu_opts, NULL) < 0) {
      elog(LOG_CRIT, "can't open %s: %m", link_name(&(lu_opts.opts), NULL));
      exit(1);
    } else {
      elog(LOG_NOTICE, "listening to %s", link_name(&(lu_opts.opts), 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

  link_quality
  pd.run
  ping-flood.run
  ping-flood.sim
  ping-ls-udp.run
  ping.c
  ping.h
  ping_device.sim
  ping_device_rcvr.run
  ping_device_sndr.run
  pingd.c
  pingd.run
  pingd.sim
  receive_ping_device.c
  send_ping_device.c
  test.run
  test.sim
  test_mote.run
  test_mote.sim