コード例 #1
0
void
well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
    size_t strpos = 0; /* position in overall string (which is larger than the buffer) */
    size_t bufpos = 0; /* position within buffer (bytes written) */
    size_t tmplen = 0;
    resource_t* resource = NULL;

#if COAP_LINK_FORMAT_FILTERING
    /* For filtering. */
    const char *filter = NULL;
    const char *attrib = NULL;
    const char *found = NULL;
    const char *end = NULL;
    char *value = NULL;
    char lastchar = '\0';
    int len = coap_get_header_uri_query(request, &filter);

    if (len)
    {
      value = strchr(filter, '=');
      value[0] = '\0';
      ++value;
      len -= strlen(filter)+1;

      PRINTF("Filter %s = %.*s\n", filter, len, value);

      if (strcmp(filter,"href")==0 && value[0]=='/')
      {
        ++value;
        --len;
      }

      lastchar = value[len-1];
      value[len-1] = '\0';
    }
#endif

    for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next)
    {
#if COAP_LINK_FORMAT_FILTERING
      /* Filtering */
      if (len)
      {
        if (strcmp(filter,"href")==0)
        {
          attrib=strstr(resource->url, value);
          if (attrib==NULL || (value[-1]=='/' && attrib!=resource->url)) continue;
          end = attrib + strlen(attrib);
        }
        else
        {
          attrib=strstr(resource->attributes, filter);
          if (attrib==NULL || (attrib[strlen(filter)]!='=' && attrib[strlen(filter)]!='"')) continue;
          attrib += strlen(filter)+2;
          end = strchr(attrib, '"');
        }

        PRINTF("Filter: res has attrib %s (%s)\n", attrib, value);
        found = attrib;
        while ((found=strstr(found, value))!=NULL) {
            if (found > end)
            {
              found = NULL;
              break;
            }
            if (lastchar==found[len-1] || lastchar=='*')
            {
              break;
            }
            ++found;
        }
        if (found==NULL)
        {
          continue;
        }
        PRINTF("Filter: res has prefix %s\n", found);
        if (lastchar!='*' && (found[len]!='"' && found[len]!=' ' && found[len]!='\0')) continue;
        PRINTF("Filter: res has match\n");
      }
#endif

      PRINTF("res: /%s (%p)\npos: s%d, o%ld, b%d\n", resource->url, resource, strpos, *offset, bufpos);

      if (strpos>0)
      {
        if (strpos >= *offset && bufpos < preferred_size)
        {
          buffer[bufpos++] = ',';
        }
        ++strpos;
      }

      if (strpos >= *offset && bufpos < preferred_size)
      {
        buffer[bufpos++] = '<';
      }
      ++strpos;

      if (strpos >= *offset && bufpos < preferred_size)
      {
        buffer[bufpos++] = '/';
      }
      ++strpos;

      tmplen = strlen(resource->url);
      if (strpos+tmplen > *offset)
      {
        bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1,
                         "%s", resource->url + ((*offset-(int32_t)strpos > 0) ? (*offset-(int32_t)strpos) : 0));
                                                          /* minimal-net requires these casts */
        if (bufpos >= preferred_size)
        {
          break;
        }
      }
      strpos += tmplen;

      if (strpos >= *offset && bufpos < preferred_size)
      {
        buffer[bufpos++] = '>';
      }
      ++strpos;

      if (resource->attributes[0])
      {
        if (strpos >= *offset && bufpos < preferred_size)
        {
          buffer[bufpos++] = ';';
        }
        ++strpos;

        tmplen = strlen(resource->attributes);
        if (strpos+tmplen > *offset)
        {
          bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1,
                         "%s", resource->attributes + (*offset-(int32_t)strpos > 0 ? *offset-(int32_t)strpos : 0));
          if (bufpos >= preferred_size)
          {
            break;
          }
        }
        strpos += tmplen;
      }

      /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */
      if (bufpos >= preferred_size && strpos-bufpos > *offset)
      {
        PRINTF("res: BREAK at %s (%p)\n", resource->url, resource);
        break;
      }
    }

    if (bufpos>0) {
      PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *) buffer);

      coap_set_payload(response, buffer, bufpos );
      coap_set_header_content_type(response, APPLICATION_LINK_FORMAT);
    }
    else if (strpos>0)
    {
      PRINTF("well_known_core_handler(): bufpos<=0\n");

      coap_set_status_code(response, BAD_OPTION_4_02);
      coap_set_payload(response, "BlockOutOfScope", 15);
    }

    if (resource==NULL) {
      PRINTF("res: DONE\n");
      *offset = -1;
    }
    else
    {
      PRINTF("res: MORE at %s (%p)\n", resource->url, resource);
      *offset += preferred_size;
    }
}
コード例 #2
0
ファイル: c_lqe_ewma.c プロジェクト: sensorlab/CRime
void
c_lqe_ewma_recv(struct pipe *p, struct stackmodule_i *module){
	PRINTF("c_lqe_ewma_recv seqno %u \n", packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

	uint16_t crtseqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
	int16_t l = 0;

	struct c_neighbor *n;
	struct c_neighbor *new_n = memb_alloc(&p->neighbor_mem);;
	rimeaddr_copy(&new_n->addr, get_node_addr(0, 1, 0));
	double alpha = p->lqe_ewma_param.alpha;
	uint8_t list_len = list_length(p->neighbor_list);

	double highest_cost = 100.0;
	/* Find the neighbor. */
	for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
	    if(rimeaddr_cmp(&new_n->addr, &n->addr)) {
	    	if (highest_cost > n->cost) { highest_cost = n->cost; }

	    	PRINTF("node found \n");
	    	PRINTF("n-lastseqno %d n-m %d n-k %d\n", n->last_seq_no, n->m, n->k);

	    	new_n->m = crtseqno - n->last_seq_no - 1; //the current seq number - last seq number - crt packet no
	    	if (new_n->m > n->k) {
	    		l = new_n->m - n->k;
	    		new_n->k = n->k;
	    	} else { l = 0; new_n->k = 0; }

	    	PRINTF("newn-lastseqno %d newn-m %d newn-k %d\n", new_n->last_seq_no, new_n->m, new_n->k);

	    	uint8_t lost_p;
	    	for(lost_p = 0; lost_p < l; lost_p++) {	n->cost *= alpha; }
	    	new_n->cost = n->cost * alpha + (1 - alpha);
	    	PRINTF("l %d cost %f\n", l, new_n->cost);

	    	if (n->count_lock == 1) {
	    		new_n->count = n->count;
	    	} else { new_n->count = n->count + 1; }
	    	new_n->first_time_stamp = n->first_time_stamp;
	    	new_n->last_seq_no = crtseqno;
	    	new_n->last_time_stamp = clock_time();
	    	new_n->rate = (new_n->count + new_n->m) / (new_n->last_time_stamp - new_n->first_time_stamp);
	    	new_n->cost_lock = 1;

	    	list_remove(p->neighbor_list, n);
	    	memb_free(&p->neighbor_mem, n);
	    	list_push(p->neighbor_list, new_n);
	    	print_list(p->neighbor_list);

	    	return;
	    }
	 }

	new_n->count = 1;
	new_n->cost = 1;
	new_n->m = 0;
	new_n->k = 0;
	new_n->last_seq_no = crtseqno;
	new_n->rate = 1 / clock_time();
	new_n->last_time_stamp = clock_time();
	new_n->cost_lock = 1;
	new_n->first_time_stamp = new_n->last_time_stamp;

	/*If neighbor is not in the list and list is full, remove from list before adding*/
	if (list_len >= NUM_NEIGHBOR_ENTRIES) {
		for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
			if (highest_cost == n->cost) {
				list_remove(p->neighbor_list, n);
				memb_free(&p->neighbor_mem, n);
			}
		}
	}
	list_push(p->neighbor_list, new_n);
	print_list(p->neighbor_list);
}
コード例 #3
0
ファイル: gtk_mod.c プロジェクト: lmangani/baresip
static void *gtk_thread(void *arg)
{
	struct gtk_mod *mod = arg;
	GtkMenuShell *app_menu;
	GtkWidget *item;
	GError *err = NULL;
	struct le *le;

	gdk_threads_init();
	gtk_init(0, NULL);

	g_set_application_name("baresip");
	mod->app = g_application_new ("com.creytiv.baresip",
			G_APPLICATION_FLAGS_NONE);

	g_application_register (G_APPLICATION (mod->app), NULL, &err);
	if (err != NULL) {
		warning ("Unable to register GApplication: %s",
				err->message);
		g_error_free (err);
		err = NULL;
	}

#ifdef USE_LIBNOTIFY
	notify_init("baresip");
#endif

	mod->status_icon = gtk_status_icon_new_from_icon_name("call-start");
	gtk_status_icon_set_tooltip_text (mod->status_icon, "baresip");

	g_signal_connect(G_OBJECT(mod->status_icon),
			"button_press_event",
			G_CALLBACK(status_icon_on_button_press), mod);
	gtk_status_icon_set_visible(mod->status_icon, TRUE);

	mod->contacts_inited = false;
	mod->dial_dialog = NULL;
	mod->call_windows = NULL;
	mod->incoming_call_menus = NULL;

	/* App menu */
	mod->app_menu = gtk_menu_new();
	app_menu = GTK_MENU_SHELL(mod->app_menu);

	/* Account submenu */
	mod->accounts_menu = gtk_menu_new();
	mod->accounts_menu_group = NULL;
	item = gtk_menu_item_new_with_mnemonic("_Account");
	gtk_menu_shell_append(app_menu, item);
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
			mod->accounts_menu);

	/* Add accounts to submenu */
	for (le = list_head(uag_list()); le; le = le->next) {
		struct ua *ua = le->data;
		accounts_menu_add_item(mod, ua);
	}

	/* Status submenu */
	mod->status_menu = gtk_menu_new();
	item = gtk_menu_item_new_with_mnemonic("_Status");
	gtk_menu_shell_append(GTK_MENU_SHELL(app_menu), item);
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), mod->status_menu);

	/* Open */
	item = gtk_radio_menu_item_new_with_label(NULL, "Open");
	g_object_set_data(G_OBJECT(item), "presence",
			GINT_TO_POINTER(PRESENCE_OPEN));
	g_signal_connect(item, "activate",
			G_CALLBACK(menu_on_presence_set), mod);
	gtk_menu_shell_append(GTK_MENU_SHELL(mod->status_menu), item);
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);

	/* Closed */
	item = gtk_radio_menu_item_new_with_label_from_widget(
			GTK_RADIO_MENU_ITEM(item), "Closed");
	g_object_set_data(G_OBJECT(item), "presence",
			GINT_TO_POINTER(PRESENCE_CLOSED));
	g_signal_connect(item, "activate",
			G_CALLBACK(menu_on_presence_set), mod);
	gtk_menu_shell_append(GTK_MENU_SHELL(mod->status_menu), item);

	gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new());

	/* Dial */
	item = gtk_menu_item_new_with_mnemonic("_Dial...");
	gtk_menu_shell_append(app_menu, item);
	g_signal_connect(G_OBJECT(item), "activate",
			G_CALLBACK(menu_on_dial), mod);

	/* Dial contact */
	mod->contacts_menu = gtk_menu_new();
	item = gtk_menu_item_new_with_mnemonic("Dial _contact");
	gtk_menu_shell_append(app_menu, item);
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
			mod->contacts_menu);

	gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new());

	/* About */
	item = gtk_menu_item_new_with_mnemonic("A_bout");
	g_signal_connect(G_OBJECT(item), "activate",
			G_CALLBACK(menu_on_about), mod);
	gtk_menu_shell_append(app_menu, item);

	gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new());

	/* Quit */
	item = gtk_menu_item_new_with_mnemonic("_Quit");
	g_signal_connect(G_OBJECT(item), "activate",
			G_CALLBACK(menu_on_quit), mod);
	gtk_menu_shell_append(app_menu, item);

	g_action_map_add_action_entries(G_ACTION_MAP(mod->app),
			app_entries, G_N_ELEMENTS(app_entries), mod);

	info("gtk_menu starting\n");

	uag_event_register( ua_event_handler, mod );
	mod->run = true;
	gtk_main();
	mod->run = false;
	uag_event_unregister(ua_event_handler);

	if (mod->dial_dialog) {
		mem_deref(mod->dial_dialog);
		mod->dial_dialog = NULL;
	}

	return NULL;
}
コード例 #4
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint16_t seqno;

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
  
  /* If the packet is a broadcast, do not allocate a queue
     entry. Instead, just send it out.  */
  if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),&rimeaddr_null)) {
    const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

    /* Look for the neighbor entry */
    n = neighbor_queue_from_addr(addr);
    if(n == NULL) {
      /* Allocate a new neighbor entry */
      n = memb_alloc(neighbor_memb);
      if(n != NULL) {
        /* Init neighbor entry */
        rimeaddr_copy(&n->addr, addr);
        n->transmissions = 0;
        n->collisions = 0;
        n->deferrals = 0;
        /* Init packet list for this neighbor */
        n->queued_packet_list = ttc_list_create((const char*)n->queued_packet_list);
        ttc_list_init(n->queued_packet_list, (const char*)n->queued_packet_list);
        /* Add neighbor to the list */
        list_add(neighbor_list, n);
      }
    }

    if(n != NULL) {
      /* Add packet to the neighbor's queue */
      q = memb_alloc(packet_memb);
      if(q != NULL) {
        q->ptr = memb_alloc(metadata_memb);
        if(q->ptr != NULL) {
          q->buf = queuebuf_new_from_packetbuf();
          if(q->buf != NULL) {
            struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
            /* Neighbor and packet successfully allocated */
            if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
              /* Use default configuration for max transmissions */
              metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
            } else {
              metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;

            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
                PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else {
              list_add(n->queued_packet_list, q);
            }

            /* If q is the first packet in the neighbor's queue, send asap */
            if(list_head(n->queued_packet_list) == q) {
              ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
            }
            return;
          }
          memb_free(metadata_memb, q->ptr);
          PRINTF("csma: could not allocate queuebuf, dropping packet\n");
        }
        memb_free(packet_memb, q);
        PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      /* The packet allocation failed. Remove and free neighbor entry if empty. */
      if(list_length(n->queued_packet_list) == 0) {
        list_remove(neighbor_list, n);
        memb_free(neighbor_memb, n);
      }
      PRINTF("csma: could not allocate packet, dropping packet\n");
    } else {
      PRINTF("csma: could not allocate neighbor, dropping packet\n");
    }
    mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
  } else {
    PRINTF("csma: send broadcast\n");
    NETSTACK_RDC.send(sent, ptr);
  }
}
コード例 #5
0
ファイル: kbd.c プロジェクト: wm4/kernel
static void kbd_irq_thread_proc(void* arg)
{
    kbd_irq_handler = irq_handler_register_thread(1, IRQ_TYPE_EDGE_PRE_ACK);
    if (!kbd_irq_handler)
        fatal("couldn't register IRQ");
    
    KbdState* kbd_state = kbd_create();
    if (!kbd_state)
        fatal("out of memory");
    
    bool kdebug_hotkey_state = false;
    
    for (;;) {
        uint c = irq_handler_wait_for_irq(kbd_irq_handler);
        if (!c)
            fatal("huh");
        
        kbd_interrupt(kbd_state);
        KbdKeyEvent event;
        
        if (kbd_read_event(kbd_state, &event)) {
            //keyboard event, handle it
            
            //virtual console switching
            if (event.key_code >= KEYCODE_F1
                && event.key_code <= KEYCODE_F0 + 11)
            {
                VirtualConsole* vc =
                    virtual_console_find_by_number(event.key_code - KEYCODE_F0);
                if (vc)
                    virtual_console_switch_to(vc);
                continue;
            }
            
            if (event.key_code == KEYCODE_PAGEDOWN) {
                if (event.down)
                    virtual_console_current_page_down();
                continue;
            }
            if (event.key_code == KEYCODE_PAGEUP) {
                if (event.down)
                    virtual_console_current_page_up();
                continue;
            }
            
            if (event.key_code == KEYCODE_KERNELDEBUGGER) {
                //special key: drop into kernel debugger (always...)
                if (event.down && !kdebug_hotkey_state) {
                    kdebug_hotkey_state = true;
                    kdebug_enter_by_hotkey();
                } else if (!event.down) {
                    kdebug_hotkey_state = false;
                }
            }
            
            //insert into buffer
            spinlock_lock(&buffer_lock);
                if (buffer_size < KEY_BUFFER_COUNT) {
                    key_buffer[(buffer_cur+buffer_size) % KEY_BUFFER_COUNT]
                        = event;
                    buffer_size++;
                } else {
                    printf("Kbd: Kernel keyboard buffer full!\n");
                }
            spinlock_unlock(&buffer_lock);
            
            //check workqueue for new waiters
            for (;;) {
                WorkItem* cur = workqueue_nowait(kbd_queue);
                if (!cur)
                    break;
                KbdKeyMessage* curmsg = cur->data;
                list_insert_tail(&g_kbd_waiters, curmsg);
            }
            
            //find a thread that is on the current VC (if there are several,
            //it's undefined which one will get the key)
            
            for (KbdKeyMessage* cur = list_head(&g_kbd_waiters); cur;
                 cur = list_next(&g_kbd_waiters, cur))
            {
                if (virtual_console_get_thread_vc(cur->sender)
                    == virtual_console_get_current())
                {
                    list_remove(&g_kbd_waiters, cur);
                    //wakeup in order to make him read the buffer
                    thread_wakeup_safe(cur->sender, &wait_for_kbd);
                    break;
                }
            }
            
        } //if event
    } //main loop
}
コード例 #6
0
ファイル: csma.c プロジェクト: 32bitmicro/zephyr
/*---------------------------------------------------------------------------*/
static void
packet_sent(struct net_buf *buf, void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n;
  struct rdc_buf_list *q;
  struct qbuf_metadata *metadata;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_exponent;
  int backoff_transmissions;

  n = ptr;
  if(n == NULL) {
    return;
  }
  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions += num_transmissions;
    break;
  case MAC_TX_COLLISION:
    n->collisions += num_transmissions;
    n->transmissions += num_transmissions;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals += num_transmissions;
    break;
  }

  /* Find out what packet this callback refers to */
  for(q = list_head(n->queued_packet_list);
      q != NULL; q = list_item_next(q)) {
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO)) {
      break;
    }
  }

  if(q != NULL) {
    metadata = (struct qbuf_metadata *)q->ptr;

    if(metadata != NULL) {
      sent = metadata->sent;
      cptr = metadata->cptr;
      num_tx = n->transmissions;
      if(status == MAC_TX_COLLISION ||
         status == MAC_TX_NOACK) {

        /* If the transmission was not performed because of a
           collision or noack, we must retransmit the packet. */

        switch(status) {
        case MAC_TX_COLLISION:
          PRINTF("csma: rexmit collision %d transmission %d\n",
		 n->collisions, n->transmissions);
          break;
        case MAC_TX_NOACK:
          PRINTF("csma: rexmit noack %d\n", n->transmissions);
          break;
        default:
          PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
        }

        /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
        time = default_timebase();

        /* The retransmission time uses a truncated exponential backoff
         * so that the interval between the transmissions increase with
         * each retransmit. */
        backoff_exponent = num_tx;

        /* Truncate the exponent if needed. */
        if(backoff_exponent > CSMA_MAX_BACKOFF_EXPONENT) {
          backoff_exponent = CSMA_MAX_BACKOFF_EXPONENT;
        }

        /* Proceed to exponentiation. */
        backoff_transmissions = 1 << backoff_exponent;

        /* Pick a time for next transmission, within the interval:
         * [time, time + 2^backoff_exponent * time[ */
        time = time + (random_rand() % (backoff_transmissions * time));

        if(n->transmissions < metadata->max_transmissions) {
          PRINTF("csma: retransmitting with time %lu %p\n", time, q);
          ctimer_set(buf, &n->transmit_timer, time,
                     transmit_packet_list, n);
          /* This is needed to correctly attribute energy that we spent
             transmitting this packet. */
          queuebuf_update_attr_from_packetbuf(buf, q->buf);
        } else {
          PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
                 status, n->transmissions, n->collisions);
          free_packet(buf, n, q);
          mac_call_sent_callback(buf, sent, cptr, status, num_tx);
        }
      } else {
        if(status == MAC_TX_OK) {
          PRINTF("csma: rexmit ok %d\n", n->transmissions);
        } else {
          PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
        }
        free_packet(buf, n, q);
        mac_call_sent_callback(buf, sent, cptr, status, num_tx);
      }
    } else {
      PRINTF("csma: no metadata\n");
    }
  } else {
    PRINTF("csma: seqno %d not found\n", packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO));
  }
}
コード例 #7
0
ファイル: xmac.c プロジェクト: thegeek82000/lepton
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
    rtimer_clock_t t0;
    rtimer_clock_t t;
    rtimer_clock_t encounter_time = 0;
    int strobes;
#if 0
    struct xmac_hdr *hdr;
#endif
    uint8_t got_strobe_ack = 0;
    uint8_t got_ack = 0;
    uint8_t strobe[MAX_STROBE_SIZE];
    int strobe_len, len;
    int is_broadcast = 0;
    int is_reliable;
    struct encounter *e;
    struct queuebuf *packet;
    int is_already_streaming = 0;
    uint8_t collisions;

    /* Create the X-MAC header for the data packet. */
    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
    if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
        is_broadcast = 1;
        PRINTDEBUG("xmac: send broadcast\n");
    } else {
#if UIP_CONF_IPV6
        PRINTDEBUG("xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else
        PRINTDEBUG("xmac: send unicast to %u.%u\n",
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
    }
    is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
                  packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);

    packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
    len = NETSTACK_FRAMER.create();
    strobe_len = len + sizeof(struct xmac_hdr);
    if(len == 0 || strobe_len > (int)sizeof(strobe)) {
        /* Failed to send */
        PRINTF("xmac: send failed, too large header\n");
        return MAC_TX_ERR_FATAL;
    }
    memcpy(strobe, packetbuf_hdrptr(), len);
    strobe[len] = DISPATCH; /* dispatch */
    strobe[len + 1] = TYPE_STROBE; /* type */

    packetbuf_compact();
    packet = queuebuf_new_from_packetbuf();
    if(packet == NULL) {
        /* No buffer available */
        PRINTF("xmac: send failed, no queue buffer available (of %u)\n",
               QUEUEBUF_CONF_NUM);
        return MAC_TX_ERR;
    }

#if WITH_STREAMING
    if(is_streaming == 1 &&
            (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                          &is_streaming_to) ||
             rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                          &is_streaming_to_too))) {
        is_already_streaming = 1;
    }
    if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
            PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
        is_streaming = 1;
        if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
            rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
        } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
            rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
        }
        stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
    }
#endif /* WITH_STREAMING */

    off();

#if WITH_ENCOUNTER_OPTIMIZATION
    /* We go through the list of encounters to find if we have recorded
       an encounter with this particular neighbor. If so, we can compute
       the time for the next expected encounter and setup a ctimer to
       switch on the radio just before the encounter. */
    for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
        const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

        if(rimeaddr_cmp(neighbor, &e->neighbor)) {
            rtimer_clock_t wait, now, expected;

            /* We expect encounters to happen every DEFAULT_PERIOD time
            units. The next expected encounter is at time e->time +
             DEFAULT_PERIOD. To compute a relative offset, we subtract
             with clock_time(). Because we are only interested in turning
             on the radio within the DEFAULT_PERIOD period, we compute the
             waiting time with modulo DEFAULT_PERIOD. */

            now = RTIMER_NOW();
            wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
            if(wait < 2 * DEFAULT_ON_TIME) {
                wait = DEFAULT_PERIOD;
            }
            expected = now + wait - 2 * DEFAULT_ON_TIME;

#if WITH_ACK_OPTIMIZATION
            /* Wait until the receiver is expected to be awake */
            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
                    PACKETBUF_ATTR_PACKET_TYPE_ACK &&
                    is_streaming == 0) {
                /* Do not wait if we are sending an ACK, because then the
                   receiver will already be awake. */
                while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
            }
#else /* WITH_ACK_OPTIMIZATION */
            /* Wait until the receiver is expected to be awake */
            while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
#endif /* WITH_ACK_OPTIMIZATION */
        }
    }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */

    /* By setting we_are_sending to one, we ensure that the rtimer
       powercycle interrupt do not interfere with us sending the packet. */
    we_are_sending = 1;

    t0 = RTIMER_NOW();
    strobes = 0;

    LEDS_ON(LEDS_BLUE);

    /* Send a train of strobes until the receiver answers with an ACK. */

    /* Turn on the radio to listen for the strobe ACK. */
    //  on();
    collisions = 0;
    if(!is_already_streaming) {
        watchdog_stop();
        got_strobe_ack = 0;
        t = RTIMER_NOW();
        for(strobes = 0, collisions = 0;
                got_strobe_ack == 0 && collisions == 0 &&
                RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);
                strobes++) {

            while(got_strobe_ack == 0 &&
                    RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
#if 0
                rtimer_clock_t now = RTIMER_NOW();

                /* See if we got an ACK */
                packetbuf_clear();
                len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
                if(len > 0) {
                    packetbuf_set_datalen(len);
                    if(NETSTACK_FRAMER.parse()) {
                        hdr = packetbuf_dataptr();
                        if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
                            if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                            &rimeaddr_node_addr)) {
                                /* We got an ACK from the receiver, so we can immediately send
                                   the packet. */
                                got_strobe_ack = 1;
                                encounter_time = now;
                            } else {
                                PRINTDEBUG("xmac: strobe ack for someone else\n");
                            }
                        } else { /*if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE)*/
                            PRINTDEBUG("xmac: strobe from someone else\n");
                            collisions++;
                        }
                    } else {
                        PRINTF("xmac: send failed to parse %u\n", len);
                    }
                }
#endif /* 0 */
            }

            t = RTIMER_NOW();
            /* Send the strobe packet. */
            if(got_strobe_ack == 0 && collisions == 0) {

                if(is_broadcast) {
#if WITH_STROBE_BROADCAST
                    NETSTACK_RADIO.send(strobe, strobe_len);
#else
                    /* restore the packet to send */
                    queuebuf_to_packetbuf(packet);
                    NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
#endif
                    off();
                } else {
#if 0
                    rtimer_clock_t wt;
#endif
                    on();
                    NETSTACK_RADIO.send(strobe, strobe_len);
#if 0
                    /* Turn off the radio for a while to let the other side
                       respond. We don't need to keep our radio on when we know
                       that the other side needs some time to produce a reply. */
                    off();
                    wt = RTIMER_NOW();
                    while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
#endif /* 0 */

                    if(detect_ack()) {
                        got_strobe_ack = 1;
                    } else {
                        off();
                    }
                }
            }
        }
    }

#if WITH_ACK_OPTIMIZATION
    /* If we have received the strobe ACK, and we are sending a packet
       that will need an upper layer ACK (as signified by the
       PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */
    if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
                          packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
                          packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
                          PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
        on(); /* Wait for ACK packet */
        waiting_for_packet = 1;
    } else {
        off();
    }
#endif /* WITH_ACK_OPTIMIZATION */

    /* restore the packet to send */
    queuebuf_to_packetbuf(packet);
    queuebuf_free(packet);

    /* Send the data packet. */
    if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
        NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());

        if(!is_broadcast) {
            if(detect_ack()) {
                got_ack = 1;
            }
        }
    }
    off();

#if WITH_ENCOUNTER_OPTIMIZATION
    if(got_strobe_ack && !is_streaming) {
        register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
    }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
    watchdog_start();

    PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
           packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack");

#if XMAC_CONF_COMPOWER
    /* Accumulate the power consumption for the packet transmission. */
    compower_accumulate(&current_packet);

    /* Convert the accumulated power consumption for the transmitted
       packet to packet attributes so that the higher levels can keep
       track of the amount of energy spent on transmitting the
       packet. */
    compower_attrconv(&current_packet);

    /* Clear the accumulated power consumption so that it is ready for
       the next packet. */
    compower_clear(&current_packet);
#endif /* XMAC_CONF_COMPOWER */

    we_are_sending = 0;

    LEDS_OFF(LEDS_BLUE);
    if(collisions == 0) {
        if(is_broadcast == 0 && got_ack == 0) {
            return MAC_TX_NOACK;
        } else {
            return MAC_TX_OK;
        }
    } else {
        someone_is_sending++;
        return MAC_TX_COLLISION;
    }

}
コード例 #8
0
ファイル: uip-ds6-route.c プロジェクト: Jakl555/6lbr
/*---------------------------------------------------------------------------*/
void
uip_ds6_route_rm(uip_ds6_route_t *route)
{
    struct uip_ds6_route_neighbor_route *neighbor_route;
#if DEBUG != DEBUG_NONE
    assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */
    if(route != NULL && route->neighbor_routes != NULL) {

        PRINTF("uip_ds6_route_rm: removing route: ");
        PRINT6ADDR(&route->ipaddr);
        PRINTF("\n");

        /* Remove the neighbor from the route list */
        list_remove(routelist, route);

        /* Find the corresponding neighbor_route and remove it. */
        for(neighbor_route = list_head(route->neighbor_routes->route_list);
                neighbor_route != NULL && neighbor_route->route != route;
                neighbor_route = list_item_next(neighbor_route));

        if(neighbor_route == NULL) {
            PRINTF("uip_ds6_route_rm: neighbor_route was NULL for ");
            uip_debug_ipaddr_print(&route->ipaddr);
            PRINTF("\n");
        }
        list_remove(route->neighbor_routes->route_list, neighbor_route);
        if(list_head(route->neighbor_routes->route_list) == NULL) {
            /* If this was the only route using this neighbor, remove the
               neibhor from the table */
            PRINTF("uip_ds6_route_rm: removing neighbor too\n");
            nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
        }
        memb_free(&routememb, route);
        memb_free(&neighborroutememb, neighbor_route);

        num_routes--;

        PRINTF("uip_ds6_route_rm num %d\n", num_routes);

#if UIP_DS6_NOTIFICATIONS
        call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
                            &route->ipaddr, uip_ds6_route_nexthop(route));
#endif
#if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE
        /* we need to check if this was the last route towards "nexthop" */
        /* if so - remove that link (annotation) */
        uip_ds6_route_t *r;
        for(r = uip_ds6_route_head();
                r != NULL;
                r = uip_ds6_route_next(r)) {
            uip_ipaddr_t *nextr, *nextroute;
            nextr = uip_ds6_route_nexthop(r);
            nextroute = uip_ds6_route_nexthop(route);
            if(nextr != NULL &&
                    nextroute != NULL &&
                    uip_ipaddr_cmp(nextr, nextroute)) {
                /* we found another link using the specific nexthop, so keep the #L */
                return;
            }
        }
        ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]);
#endif
    }

#if DEBUG != DEBUG_NONE
    assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */
    return;
}
コード例 #9
0
ファイル: uip-ds6-route.c プロジェクト: Jakl555/6lbr
/*---------------------------------------------------------------------------*/
uip_ds6_defrt_t *
uip_ds6_defrt_list_head(void)
{
    return list_head(defaultrouterlist);
}
コード例 #10
0
ファイル: routing_chain.c プロジェクト: jluzuria2001/udtn
/**
 * \brief Callback function informing us about the status of a sent bundle
 * \param ticket CL transmit ticket of the bundle
 * \param status status code
 */
void routing_chain_bundle_sent(struct transmit_ticket_t * ticket, uint8_t status)
{
	struct routing_list_entry_t * n = NULL;
	struct routing_entry_t * entry = NULL;

	// Tell the agent to call us again to resubmit bundles
	routing_chain_schedule_resubmission();

	// Find the bundle in our internal storage
	for( n = list_head(routing_list);
		 n != NULL;
		 n = list_item_next(n) ) {

		entry = (struct routing_entry_t *) MMEM_PTR(&n->entry);

		if( entry->bundle_number == ticket->bundle_number ) {
			break;
		}
	}

	if( n == NULL ) {
		/* Free up the ticket */
		convergence_layer_free_transmit_ticket(ticket);

		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "Bundle not in storage");
		return;
	}

	/* Bundle is not busy anymore */
	entry->flags &= ~ROUTING_FLAG_IN_TRANSIT;

	if( status == ROUTING_STATUS_NACK ||
		status == ROUTING_STATUS_FAIL ) {
		// NACK = Other side rejected the bundle, try again later
		// FAIL = Transmission failed

		/* Free up the ticket */
		convergence_layer_free_transmit_ticket(ticket);

		return;
	}

	if( status == ROUTING_STATUS_ERROR ) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "Bundle %lu has fatal error, deleting", ticket->bundle_number);

		/* Bundle failed permanently, we can delete it because it will never be delivered anyway */
		entry->flags = 0;

		routing_chain_check_keep_bundle(ticket->bundle_number);

		/* Free up the ticket */
		convergence_layer_free_transmit_ticket(ticket);

		return;
	}

	// Here: status == ROUTING_STATUS_OK
	statistics_bundle_outgoing(1);

#ifndef TEST_DO_NOT_DELETE_ON_DIRECT_DELIVERY
	linkaddr_t dest_n = convert_eid_to_rime(entry->destination_node);
	if (linkaddr_cmp(&ticket->neighbour, &dest_n)) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle sent to destination node");
		uint32_t bundle_number = ticket->bundle_number;

		/* Free up the ticket */
		convergence_layer_free_transmit_ticket(ticket);
		ticket = NULL;

		// Unset the forward flag
		entry->flags &= ~ROUTING_FLAG_FORWARD;
		routing_chain_check_keep_bundle(bundle_number);

		return;
	}

	LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle for %u.%u delivered to %u.%u", dest_n.u8[0], dest_n.u8[1], ticket->neighbour.u8[0], ticket->neighbour.u8[1]);
#endif


	if (entry->send_to < ROUTING_NEI_MEM) {
		linkaddr_copy(&entry->neighbours[entry->send_to], &ticket->neighbour);
		entry->send_to++;
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle %lu sent to %u nodes", ticket->bundle_number, entry->send_to);
	} else if (entry->send_to >= ROUTING_NEI_MEM) {
		// Here we can delete the bundle from storage, because it will not be routed anyway
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle %lu sent to max number of nodes, deleting", ticket->bundle_number);

		// Unset the forward flag
		entry->flags &= ~ROUTING_FLAG_FORWARD;
		routing_chain_check_keep_bundle(ticket->bundle_number);
	}

	/* Free up the ticket */
	convergence_layer_free_transmit_ticket(ticket);
}
コード例 #11
0
ファイル: uip-ds6-route.c プロジェクト: Jakl555/6lbr
/*---------------------------------------------------------------------------*/
uip_ds6_route_t *
uip_ds6_route_head(void)
{
    return list_head(routelist);
}
コード例 #12
0
ファイル: routing_chain.c プロジェクト: jluzuria2001/udtn
/**
 * \brief Adds a new bundle to the list of bundles
 * \param bundle_number bundle number of the bundle
 * \return >0 on success, <0 on error
 */
int routing_chain_new_bundle(uint32_t * bundle_number)
{
	struct routing_list_entry_t * n = NULL;
	struct routing_entry_t * entry = NULL;
	struct mmem * bundlemem = NULL;
	struct bundle_t * bundle = NULL;

	LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "agent announces bundle %lu", *bundle_number);

	// Let us see, if we know this bundle already
	for( n = list_head(routing_list);
		 n != NULL;
		 n = list_item_next(n) ) {

		entry = (struct routing_entry_t *) MMEM_PTR(&n->entry);

		if( entry->bundle_number == *bundle_number ) {
			LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "agent announces bundle %lu that is already known", *bundle_number);
			return -1;
		}
	}

	// Notify statistics
	statistics_bundle_incoming(1);

	// Now allocate new memory for the list entry
	n = memb_alloc(&routing_mem);
	if( n == NULL ) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "cannot allocate list entry for bundle, please increase BUNDLE_STORAGE_SIZE");
		return -1;
	}

	memset(n, 0, sizeof(struct routing_list_entry_t));

	// Now allocate new MMEM memory for the struct in the list
	if( !mmem_alloc(&n->entry, sizeof(struct routing_entry_t)) ) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "cannot allocate routing struct for bundle, MMEM is full");
		memb_free(&routing_mem, n);
		return -1;
	}

	// Now go and request the bundle from storage
	bundlemem = BUNDLE_STORAGE.read_bundle(*bundle_number);
	if( bundlemem == NULL ) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "unable to read bundle %lu", *bundle_number);
		mmem_free(&n->entry);
		memb_free(&routing_mem, n);
		return -1;
	}

	// Get our bundle struct and check the pointer
	bundle = (struct bundle_t *) MMEM_PTR(bundlemem);
	if( bundle == NULL ) {
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "invalid bundle pointer for bundle %lu", *bundle_number);
		mmem_free(&n->entry);
		memb_free(&routing_mem, n);
		bundle_decrement(bundlemem);
		return -1;
	}

	// Now we have our entry
	// We have to get the pointer AFTER getting the bundle from storage, because accessing the
	// storage may change the MMEM structure and thus the pointers!
	entry = (struct routing_entry_t *) MMEM_PTR(&n->entry);
	memset(entry, 0, sizeof(struct routing_entry_t));

	// Nothing can go wrong anymore, add the (surrounding) struct to the list
	list_add(routing_list, n);

	/* Here we decide if a bundle is to be delivered locally and/or forwarded */
	if( bundle->dst_node == dtn_node_id ) {
		/* This bundle is for our node_id, deliver locally */
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for local");
		entry->flags |= ROUTING_FLAG_LOCAL;
	} else {
		/* This bundle is not (directly) for us and will be forwarded */
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for forward");
		entry->flags |= ROUTING_FLAG_FORWARD;
	}

	if( !(bundle->flags & BUNDLE_FLAG_SINGLETON) ) {
		/* Bundle is not Singleton, so forward it in any case */
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for forward");
		entry->flags |= ROUTING_FLAG_FORWARD;
	}

	if( registration_is_local(bundle->dst_srv, bundle->dst_node) && bundle->dst_node != dtn_node_id) {
		/* Bundle is for a local registration, so deliver it locally */
		LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for local and forward");
		entry->flags |= ROUTING_FLAG_LOCAL;
		entry->flags |= ROUTING_FLAG_FORWARD;
	}

	// Now copy the necessary attributes from the bundle
	entry->bundle_number = *bundle_number;
	bundle_get_attr(bundlemem, DEST_NODE, &entry->destination_node);
	bundle_get_attr(bundlemem, SRC_NODE, &entry->source_node);
	linkaddr_copy(&entry->received_from_node, &bundle->msrc);

	// Now that we have the bundle, we do not need the allocated memory anymore
	bundle_decrement(bundlemem);
	bundlemem = NULL;
	bundle = NULL;

	// Schedule to deliver and forward the bundle
	routing_chain_schedule_resubmission();

	// We do not have a failure here, so it must be a success
	return 1;
}
コード例 #13
0
ファイル: routing_chain.c プロジェクト: jluzuria2001/udtn
/**
 * \brief iterate through all bundles and forward bundles
 */
void routing_chain_send_to_known_neighbours(void)
{
	struct routing_list_entry_t * n = NULL;
	struct routing_entry_t * entry = NULL;
	int try_to_forward = 1;
	int try_local = 1;
	int h = 0;

	LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "send to known neighbours");

	/**
	 * It is likely, that we will have less neighbours than bundles - therefore, we want to to go through bundles only once
	 */
	for( n = (struct routing_list_entry_t *) list_head(routing_list);
		 n != NULL;
		 n = list_item_next(n) ) {

		entry = (struct routing_entry_t *) MMEM_PTR(&n->entry);
		if( entry == NULL ) {
			LOG(LOGD_DTN, LOG_ROUTE, LOGL_WRN, "Bundle with invalid MMEM structure");
		}

		if( try_local ) {
			/* Is the bundle for local? */
			h = routing_chain_send_to_local(entry);

			/* We can only deliver only bundle at a time to local processes to speed up the whole thing */
			if( h == CHAIN_ROUTE_RETURN_OK ) {
				try_local = 0;
			}
		}

		/* Skip this bundle, if it is not queued for forwarding */
		if( !(entry->flags & ROUTING_FLAG_FORWARD) || (entry->flags & ROUTING_FLAG_IN_TRANSIT) || !try_to_forward ) {
			continue;
		}

		/* Try to forward it to the destination, if it is our neighbour */
		h = routing_chain_forward_directly(entry);
		if( h == CHAIN_ROUTE_RETURN_OK ) {
			/* Bundle will be delivered, to skip the remainder if this function*/
			continue;
		} else if( h == CHAIN_ROUTE_RETURN_CONTINUE ) {
			/* Bundle was not delivered, continue as normal */
		} else if( h == CHAIN_ROUTE_RETURN_FAIL ) {
			/* Enqueuing the bundle failed, to stop the forwarding process */
			try_to_forward = 0;
			continue;
		}

		/* At this point, we know that the bundle is not for one of our neighbours, so send it to all the others */
		h = routing_chain_forward_normal(entry);
		if( h == CHAIN_ROUTE_RETURN_OK ) {
			/* Bundle will be forwarded, continue as normal */
		} else if( h == CHAIN_ROUTE_RETURN_CONTINUE ) {
			/* Bundle will not be forwarded, continue as normal */
		} else if( h == CHAIN_ROUTE_RETURN_FAIL ) {
			/* Enqueuing the bundle failed, to stop the forwarding process */
			try_to_forward = 0;
			continue;
		}
	}
}
コード例 #14
0
ファイル: parse_func.c プロジェクト: Aldizh/buffer_manager
/*
 *	Parse a function call
 *
 *	For historical reasons, Postgres tries to treat the notations tab.col
 *	and col(tab) as equivalent: if a single-argument function call has an
 *	argument of complex type and the (unqualified) function name matches
 *	any attribute of the type, we take it as a column projection.  Conversely
 *	a function of a single complex-type argument can be written like a
 *	column reference, allowing functions to act like computed columns.
 *
 *	Hence, both cases come through here.  The is_column parameter tells us
 *	which syntactic construct is actually being dealt with, but this is
 *	intended to be used only to deliver an appropriate error message,
 *	not to affect the semantics.  When is_column is true, we should have
 *	a single argument (the putative table), unqualified function name
 *	equal to the column name, and no aggregate or variadic decoration.
 *
 *	The argument expressions (in fargs) must have been transformed already.
 */
Node *
ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
				  bool agg_star, bool agg_distinct, bool func_variadic,
				  WindowDef *over, bool is_column, int location)
{
	Oid			rettype;
	Oid			funcid;
	ListCell   *l;
	ListCell   *nextl;
	Node	   *first_arg = NULL;
	int			nargs;
	int			nargsplusdefs;
	Oid			actual_arg_types[FUNC_MAX_ARGS];
	Oid		   *declared_arg_types;
	List	   *argdefaults;
	Node	   *retval;
	bool		retset;
	int			nvargs;
	FuncDetailCode fdresult;

	/*
	 * Most of the rest of the parser just assumes that functions do not have
	 * more than FUNC_MAX_ARGS parameters.	We have to test here to protect
	 * against array overruns, etc.  Of course, this may not be a function,
	 * but the test doesn't hurt.
	 */
	if (list_length(fargs) > FUNC_MAX_ARGS)
		ereport(ERROR,
				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
			 errmsg_plural("cannot pass more than %d argument to a function",
						   "cannot pass more than %d arguments to a function",
						   FUNC_MAX_ARGS,
						   FUNC_MAX_ARGS),
				 parser_errposition(pstate, location)));

	/*
	 * Extract arg type info in preparation for function lookup.
	 *
	 * If any arguments are Param markers of type VOID, we discard them from
	 * the parameter list.	This is a hack to allow the JDBC driver to not
	 * have to distinguish "input" and "output" parameter symbols while
	 * parsing function-call constructs.  We can't use foreach() because we
	 * may modify the list ...
	 */
	nargs = 0;
	for (l = list_head(fargs); l != NULL; l = nextl)
	{
		Node	   *arg = lfirst(l);
		Oid			argtype = exprType(arg);

		nextl = lnext(l);

		if (argtype == VOIDOID && IsA(arg, Param) &&!is_column)
		{
			fargs = list_delete_ptr(fargs, arg);
			continue;
		}

		actual_arg_types[nargs++] = argtype;
	}

	if (fargs)
	{
		first_arg = linitial(fargs);
		Assert(first_arg != NULL);
	}

	/*
	 * Check for column projection: if function has one argument, and that
	 * argument is of complex type, and function name is not qualified, then
	 * the "function call" could be a projection.  We also check that there
	 * wasn't any aggregate or variadic decoration.
	 */
	if (nargs == 1 && !agg_star && !agg_distinct && over == NULL &&
		!func_variadic && list_length(funcname) == 1)
	{
		Oid			argtype = actual_arg_types[0];

		if (argtype == RECORDOID || ISCOMPLEX(argtype))
		{
			retval = ParseComplexProjection(pstate,
											strVal(linitial(funcname)),
											first_arg,
											location);
			if (retval)
				return retval;

			/*
			 * If ParseComplexProjection doesn't recognize it as a projection,
			 * just press on.
			 */
		}
	}

	/*
	 * Okay, it's not a column projection, so it must really be a function.
	 * func_get_detail looks up the function in the catalogs, does
	 * disambiguation for polymorphic functions, handles inheritance, and
	 * returns the funcid and type and set or singleton status of the
	 * function's return value.  It also returns the true argument types to
	 * the function.  In the case of a variadic function call, the reported
	 * "true" types aren't really what is in pg_proc: the variadic argument is
	 * replaced by a suitable number of copies of its element type.  We'll fix
	 * it up below.  We may also have to deal with default arguments.
	 */
	fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
							   !func_variadic, true,
							   &funcid, &rettype, &retset, &nvargs,
							   &declared_arg_types, &argdefaults);
	if (fdresult == FUNCDETAIL_COERCION)
	{
		/*
		 * We interpreted it as a type coercion. coerce_type can handle these
		 * cases, so why duplicate code...
		 */
		return coerce_type(pstate, linitial(fargs),
						   actual_arg_types[0], rettype, -1,
						   COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location);
	}
	else if (fdresult == FUNCDETAIL_NORMAL)
	{
		/*
		 * Normal function found; was there anything indicating it must be an
		 * aggregate?
		 */
		if (agg_star)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
			   errmsg("%s(*) specified, but %s is not an aggregate function",
					  NameListToString(funcname),
					  NameListToString(funcname)),
					 parser_errposition(pstate, location)));
		if (agg_distinct)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
			errmsg("DISTINCT specified, but %s is not an aggregate function",
				   NameListToString(funcname)),
					 parser_errposition(pstate, location)));
		if (over)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("OVER specified, but %s is not a window function nor an aggregate function",
							NameListToString(funcname)),
					 parser_errposition(pstate, location)));
	}
	else if (!(fdresult == FUNCDETAIL_AGGREGATE ||
			   fdresult == FUNCDETAIL_WINDOWFUNC))
	{
		/*
		 * Oops.  Time to die.
		 *
		 * If we are dealing with the attribute notation rel.function, give an
		 * error message that is appropriate for that case.
		 */
		if (is_column)
		{
			Assert(nargs == 1);
			Assert(list_length(funcname) == 1);
			unknown_attribute(pstate, first_arg, strVal(linitial(funcname)),
							  location);
		}

		/*
		 * Else generate a detailed complaint for a function
		 */
		if (fdresult == FUNCDETAIL_MULTIPLE)
			ereport(ERROR,
					(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
					 errmsg("function %s is not unique",
							func_signature_string(funcname, nargs,
												  actual_arg_types)),
					 errhint("Could not choose a best candidate function. "
							 "You might need to add explicit type casts."),
					 parser_errposition(pstate, location)));
		else
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
					 errmsg("function %s does not exist",
							func_signature_string(funcname, nargs,
												  actual_arg_types)),
			errhint("No function matches the given name and argument types. "
					"You might need to add explicit type casts."),
					 parser_errposition(pstate, location)));
	}

	/*
	 * If there are default arguments, we have to include their types in
	 * actual_arg_types for the purpose of checking generic type consistency.
	 * However, we do NOT put them into the generated parse node, because
	 * their actual values might change before the query gets run.	The
	 * planner has to insert the up-to-date values at plan time.
	 */
	nargsplusdefs = nargs;
	foreach(l, argdefaults)
	{
		Node	   *expr = (Node *) lfirst(l);

		/* probably shouldn't happen ... */
		if (nargsplusdefs >= FUNC_MAX_ARGS)
			ereport(ERROR,
					(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
			 errmsg_plural("cannot pass more than %d argument to a function",
						   "cannot pass more than %d arguments to a function",
						   FUNC_MAX_ARGS,
						   FUNC_MAX_ARGS),
					 parser_errposition(pstate, location)));

		actual_arg_types[nargsplusdefs++] = exprType(expr);
	}
コード例 #15
0
ファイル: audio.c プロジェクト: mralexgray/baresip
int audio_alloc(struct audio **ap, const struct config *cfg,
		struct call *call, struct sdp_session *sdp_sess, int label,
		const struct mnat *mnat, struct mnat_sess *mnat_sess,
		const struct menc *menc, struct menc_sess *menc_sess,
		uint32_t ptime, const struct list *aucodecl,
		audio_event_h *eventh, audio_err_h *errh, void *arg)
{
	struct audio *a;
	struct autx *tx;
	struct aurx *rx;
	struct le *le;
	int err;

	if (!ap || !cfg)
		return EINVAL;

	a = mem_zalloc(sizeof(*a), audio_destructor);
	if (!a)
		return ENOMEM;

	MAGIC_INIT(a);

	a->cfg = cfg->audio;
	tx = &a->tx;
	rx = &a->rx;

	err = stream_alloc(&a->strm, &cfg->avt, call, sdp_sess,
			   "audio", label,
			   mnat, mnat_sess, menc, menc_sess,
			   stream_recv_handler, NULL, a);
	if (err)
		goto out;

	stream_set_bw(a->strm, AUDIO_BANDWIDTH);

	err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true,
				  "ptime", "%u", ptime);
	if (err)
		goto out;

	/* Audio codecs */
	for (le = list_head(aucodecl); le; le = le->next) {
		err = add_audio_codec(a, stream_sdpmedia(a->strm), le->data);
		if (err)
			goto out;
	}

	tx->mb = mbuf_alloc(STREAM_PRESZ + 4096);
	tx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	rx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	if (!tx->mb || !tx->sampv || !rx->sampv) {
		err = ENOMEM;
		goto out;
	}

	err = telev_alloc(&a->telev, TELEV_PTIME);
	if (err)
		goto out;

	err = add_telev_codec(a);
	if (err)
		goto out;

	tx->ptime  = ptime;
	tx->ts     = 160;
	tx->marker = true;

	rx->pt     = -1;
	rx->ptime  = ptime;

	a->eventh    = eventh;
	a->errh      = errh;
	a->arg       = arg;

	if (a->cfg.txmode == AUDIO_MODE_TMR)
		tmr_init(&tx->u.tmr);

 out:
	if (err)
		mem_deref(a);
	else
		*ap = a;

	return err;
}
コード例 #16
0
ファイル: lpm.c プロジェクト: adityasiriguppa/contiki
/*---------------------------------------------------------------------------*/
void
lpm_drop()
{
  lpm_registered_module_t *module;
  uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
  uint8_t module_pm;
  clock_time_t next_event;

  uint32_t domains = LOCKABLE_DOMAINS;

  if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(),
                     RTIMER_NOW() + STANDBY_MIN_DURATION)) {
    lpm_sleep();
    return;
  }

  /* Collect max allowed PM permission from interested modules */
  for(module = list_head(modules_list); module != NULL;
      module = module->next) {
    if(module->request_max_pm) {
      module_pm = module->request_max_pm();
      if(module_pm < max_pm) {
        max_pm = module_pm;
      }
    }
  }

  /* Check if any events fired during this process. Last chance to abort */
  if(process_nevents()) {
    return;
  }

  /* Drop */
  if(max_pm == LPM_MODE_SLEEP) {
    lpm_sleep();
  } else {
    /* Critical. Don't get interrupted! */
    ti_lib_int_master_disable();

    /*
     * Reschedule AON RTC CH1 to fire an event N ticks before the next etimer
     * event
     */
    next_event = etimer_next_expiration_time();

    if(next_event) {
      next_event = next_event - clock_time();
      soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() +
          (next_event * (RTIMER_SECOND / CLOCK_SECOND)));
    }

    /*
     * Notify all registered modules that we are dropping to mode X. We do not
     * need to do this for simple sleep.
     *
     * This is a chance for modules to delay us a little bit until an ongoing
     * operation has finished (e.g. uart TX) or to configure themselves for
     * deep sleep.
     *
     * At this stage, we also collect power domain locks, if any.
     * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time
     * we encounter a lock we just clear the respective bits in the 'domains'
     * variable as required by the lock. In the end the domains variable will
     * just hold whatever has not been cleared
     */
    for(module = list_head(modules_list); module != NULL;
        module = module->next) {
      if(module->shutdown) {
        module->shutdown(max_pm);
      }

      /* Clear the bits specified in the lock */
      domains &= ~module->domain_lock;
    }

    /* Pat the dog: We don't want it to shout right after we wake up */
    watchdog_periodic();

    /* Clear unacceptable bits, just in case a lock provided a bad value */
    domains &= LOCKABLE_DOMAINS;

    /*
     * Freeze the IOs on the boundary between MCU and AON. We only do this if
     * PERIPH is not needed
     */
    if(domains & PRCM_DOMAIN_PERIPH) {
      ti_lib_aon_ioc_freeze_enable();
    }

    /*
     * Among LOCKABLE_DOMAINS, turn off those that are not locked
     *
     * If domains is != 0, pass it as-is
     */
    if(domains) {
      ti_lib_prcm_power_domain_off(domains);
    }

    /*
     * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC
     * is predominantly controlled by the RF driver. In a build with radio
     * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before
     * using the Freq. Synth, and switch back to the RC when it is about to
     * turn back off.
     *
     * If the radio is on, we won't even reach here, and if it's off the HF
     * clock source should already be the HF RC.
     *
     * Nevertheless, request the switch to the HF RC explicitly here.
     */
    oscillators_switch_to_hf_rc();

    /* Configure clock sources for MCU and AUX: No clock */
    ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
    ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);

    /* Full RAM retention. */
    ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
                                   MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);

    /* Disable retention of AUX RAM */
    ti_lib_aon_wuc_aux_sram_config(false);

    /*
     * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off
     * already
     */
    ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
                                 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);

    /* Request JTAG domain power off */
    ti_lib_aon_wuc_jtag_power_off();

    /* Turn off AUX */
    ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
    ti_lib_aon_wuc_domain_power_down_enable();
    while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON);

    /* Configure the recharge controller */
    ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);

    /*
     * If both PERIPH and SERIAL PDs are off, request the uLDO as the power
     * source while in deep sleep.
     */
    if(domains == LOCKABLE_DOMAINS) {
      ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
    }

    /* We are only interested in IRQ energest while idle or in LPM */
    ENERGEST_IRQ_RESTORE(irq_energest);
    ENERGEST_OFF(ENERGEST_TYPE_CPU);
    ENERGEST_ON(ENERGEST_TYPE_LPM);

    /* Sync the AON interface to ensure all writes have gone through. */
    ti_lib_sys_ctrl_aon_sync();

    /*
     * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of
     * retention mismatch between VIMS logic and cache. We wait to do this
     * until right before deep sleep to be able to use the cache for as long
     * as possible.
     */
    ti_lib_prcm_cache_retention_disable();
    ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);

    /* Deep Sleep */
    ti_lib_prcm_deep_sleep();

    /*
     * When we reach here, some interrupt woke us up. The global interrupt
     * flag is off, hence we have a chance to run things here. We will wake up
     * the chip properly, and then we will enable the global interrupt without
     * unpending events so the handlers can fire
     */
    wake_up();

    ti_lib_int_master_enable();
  }
}
コード例 #17
0
int main(int argc, char **argv)
{

	Graph graph;

	DfsVertex *task, task1, *task2;

	List list;

	ListElmt *element;

	char data1[STRSIZ];

	int i;

/*****************************************************************************
*  Initialize the graph.                                                     *
*****************************************************************************/

	graph_init(&graph, match_task, destroy_task);

/*****************************************************************************
*  Insert some tasks.                                                        *
*****************************************************************************/

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "a");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "b");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "c");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "d");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "e");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "f");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "g");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "h");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task->data, "i");
	fprintf(stdout, "Inserting vertex %s\n", (char *)task->data);

	if (graph_ins_vertex(&graph, task) != 0)
		return 1;

	print_graph(&graph);

/*****************************************************************************
*  Insert some dependencies.                                                 *
*****************************************************************************/

	task1.data = data1;

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "a");
	strcpy((char *)task2->data, "b");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "a");
	strcpy((char *)task2->data, "c");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "b");
	strcpy((char *)task2->data, "i");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "c");
	strcpy((char *)task2->data, "i");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "e");
	strcpy((char *)task2->data, "f");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "e");
	strcpy((char *)task2->data, "h");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "f");
	strcpy((char *)task2->data, "c");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "f");
	strcpy((char *)task2->data, "h");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

	if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL)
		return 1;

	if ((task2->data = malloc(STRSIZ)) == NULL)
		return 1;

	strcpy((char *)task1.data, "g");
	strcpy((char *)task2->data, "h");
	fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data,
		(char *)
		task2->data);

	if (graph_ins_edge(&graph, &task1, task2) != 0)
		return 1;

	print_graph(&graph);

/*****************************************************************************
*  Perform depth-first search.                                               *
*****************************************************************************/

	fprintf(stdout, "Generating the depth-first search listing\n");

	if (dfs(&graph, &list) != 0)
		return 1;

	i = 0;

	for (element = list_head(&list); element != NULL; element =
	     list_next(element)) {

		task = list_data(element);
		fprintf(stdout, "list[%03d]=%s (color=%d)\n", i,
			(char *)task->data, task->color);
		i++;

	}

/*****************************************************************************
*  Destroy the linked list.                                                  *
*****************************************************************************/

	fprintf(stdout, "Destroying the list\n");
	list_destroy(&list);

/*****************************************************************************
*  Destroy the graph.                                                        *
*****************************************************************************/

	fprintf(stdout, "Destroying the graph\n");
	graph_destroy(&graph);

	return 0;

}
コード例 #18
0
ファイル: lpm.c プロジェクト: adityasiriguppa/contiki
/*---------------------------------------------------------------------------*/
void
lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
{
  lpm_registered_module_t *module;
  int i, j;
  uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull |
    wake_on;

  /* This procedure may not be interrupted */
  ti_lib_int_master_disable();

  /* Disable the RTC */
  ti_lib_aon_rtc_disable();
  ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
  ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
  ti_lib_aon_rtc_event_clear(AON_RTC_CH2);

  /* Reset AON even fabric to default wakeup sources */
  for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
    ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NONE);
  }
  for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
    ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NONE);
  }

  ti_lib_sys_ctrl_aon_sync();

  watchdog_periodic();

  /* fade away....... */
  j = 1000;

  for(i = j; i > 0; --i) {
    leds_on(LEDS_ALL);
    clock_delay_usec(i);
    leds_off(LEDS_ALL);
    clock_delay_usec(j - i);
  }

  leds_off(LEDS_ALL);

  /* Notify all modules that we're shutting down */
  for(module = list_head(modules_list); module != NULL;
      module = module->next) {
    if(module->shutdown) {
      module->shutdown(LPM_MODE_SHUTDOWN);
    }
  }

  /* Configure the wakeup trigger */
  ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
  ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);

  /* Freeze I/O latches in AON */
  ti_lib_aon_ioc_freeze_enable();

  /* Turn off RFCORE, SERIAL and PERIPH PDs. This will happen immediately */
  ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
                               PRCM_DOMAIN_PERIPH);

  oscillators_switch_to_hf_rc();
  oscillators_select_lf_rcosc();

  /* Configure clock sources for MCU and AUX: No clock */
  ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
  ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);

  /* Disable SRAM and AUX retentions */
  ti_lib_aon_wuc_mcu_sram_config(0);
  ti_lib_aon_wuc_aux_sram_config(false);

  /*
   * Request CPU, SYSBYS and VIMS PD off.
   * This will only happen when the CM3 enters deep sleep
   */
  ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
                               PRCM_DOMAIN_SYSBUS);

  /* Request JTAG domain power off */
  ti_lib_aon_wuc_jtag_power_off();

  /* Turn off AUX */
  ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
  ti_lib_aon_wuc_domain_power_down_enable();
  while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON);

  /*
   * Request MCU VD power off.
   * This will only happen when the CM3 enters deep sleep
   */
  ti_lib_prcm_mcu_power_off();

  /* Set MCU wakeup to immediate and disable virtual power off */
  ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
  ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);

  /* Latch the IOs in the padring and enable I/O pad sleep mode */
  ti_lib_pwr_ctrl_io_freeze_enable();

  /* Turn off VIMS cache, CRAM and TRAM - possibly not required */
  ti_lib_prcm_cache_retention_disable();
  ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);

  /* Enable shutdown and sync AON */
  ti_lib_aon_wuc_shut_down_enable();
  ti_lib_sys_ctrl_aon_sync();

  /* Deep Sleep */
  ti_lib_prcm_deep_sleep();
}
コード例 #19
0
ファイル: example-neighbors.c プロジェクト: e-nikolov/NES2015
/* This function is called whenever a broadcast message is received. */
static void
broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from)
{
  struct neighbor *n;
  struct broadcast_message *m;
  uint8_t seqno_gap;

  /* The packetbuf_dataptr() returns a pointer to the first data byte
     in the received packet. */
  m = packetbuf_dataptr();

  /* Check if we already know this neighbor. */
  for(n = list_head(neighbors_list); n != NULL; n = list_item_next(n)) {

    /* We break out of the loop if the address of the neighbor matches
       the address of the neighbor from which we received this
       broadcast message. */
    if(linkaddr_cmp(&n->addr, from)) {
      break;
    }
  }

  /* If n is NULL, this neighbor was not found in our list, and we
     allocate a new struct neighbor from the neighbors_memb memory
     pool. */
  if(n == NULL) {
    n = memb_alloc(&neighbors_memb);

    /* If we could not allocate a new neighbor entry, we give up. We
       could have reused an old neighbor entry, but we do not do this
       for now. */
    if(n == NULL) {
      return;
    }

    /* Initialize the fields. */
    linkaddr_copy(&n->addr, from);
    n->last_seqno = m->seqno - 1;
    n->avg_seqno_gap = SEQNO_EWMA_UNITY;

    /* Place the neighbor on the neighbor list. */
    list_add(neighbors_list, n);
  }

  /* We can now fill in the fields in our neighbor entry. */
  n->last_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI);
  n->last_lqi = packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY);

  /* Compute the average sequence number gap we have seen from this neighbor. */
  seqno_gap = m->seqno - n->last_seqno;
  n->avg_seqno_gap = (((uint32_t)seqno_gap * SEQNO_EWMA_UNITY) *
                      SEQNO_EWMA_ALPHA) / SEQNO_EWMA_UNITY +
                      ((uint32_t)n->avg_seqno_gap * (SEQNO_EWMA_UNITY -
                                                     SEQNO_EWMA_ALPHA)) /
    SEQNO_EWMA_UNITY;

  /* Remember last seqno we heard. */
  n->last_seqno = m->seqno;

  /* Print out a message. */
  printf("broadcast message received from %d.%d with seqno %d, RSSI %u, LQI %u, avg seqno gap %d.%02d\n",
         from->u8[0], from->u8[1],
         m->seqno,
         packetbuf_attr(PACKETBUF_ATTR_RSSI),
         packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY),
         (int)(n->avg_seqno_gap / SEQNO_EWMA_UNITY),
         (int)(((100UL * n->avg_seqno_gap) / SEQNO_EWMA_UNITY) % 100));
}
コード例 #20
0
ファイル: steiner.c プロジェクト: chris-dickson/GRAPL
int gridSteinerFH(Graph *grid_graph, AdjList**** Edge2Adj, int width, int height, CoordData *term, int no_terminals, double *L,int
	net_num, int *edge_count_OUT, int **SteinerTree_OUT, int l, int K) {
    int i,j;
	/* globals */
	
	int				GRID_WIDTH, GRID_HEIGHT, NO_TERMINALS;
	
	
	Graph			ND;					/* distance network of terminals */
	
	/*used to generate grid graph */
	PathVertex      *path_vertex;
	
	sPathData		*sPath_vertex;
	
	CoordData       *coord;
	
	/* used in shortest paths computations */
	PathVertex      **terminals;        /* a (1D) array of terminal (pointers) */
	List            *tempPaths,			/* tempporary */
					**sPaths;			/* 2d array of shortest path lists */
	ListElmt        *element;           /* temp, used to traverse a list */	
	
	/* used in computing MST of ND */
	MstVertex		*mst_start,
					*mst_vertex,
					*mst_vertex1,
					*mst_vertex2;
	List			TD;					/* spanning tree of ND */
										/* used in final steps of algorithm */
	
	Graph			NTD;				/* complete distance network */
	
	List			T;					/* spanning tree of NTD (eventually the steiner tree)*/
	int				isSteiner;			/* boolean flag */
	double			tree_cost;			/* total cost of the steiner tree (unused, this is computed after*/
	

			
	GRID_WIDTH = width;
	GRID_HEIGHT = height;
	NO_TERMINALS = no_terminals;
	
	mst_start = NULL;
	
	/*-----------------------------------------------*/
	/* If the number of terminals is two, then we    */
	/* only need to perform one call of Dijkstra to  */
	/* get the Steiner Tree                          */
	/*-----------------------------------------------*/
	if (NO_TERMINALS == 2) {
		PathVertex	*v1,*v2;	/* the two terminals*/
		CoordData	*c1,*c2;	/* coordinates of the two terminals*/
		List		P;			/* P-Array in Dijkstra's*/
		ListElmt	*e;			/* list counter*/
		List		T;			/* steiner tree*/
		double		tree_cost;
		int			j;
		int			first_edge,last_edge;
		
		PathVertex	*u;
			
		u = NULL;
	
		/* allocate vertices */
		v1 = (PathVertex*) malloc(sizeof(PathVertex));
		v2 = (PathVertex*) malloc(sizeof(PathVertex));
		c1 = (CoordData*) malloc(sizeof(CoordData));
		c2 = (CoordData*) malloc(sizeof(CoordData));		
		
		/* set terminal data */
		c1->x = term[0].x; 		c1->y = term[0].y;		c1->z = term[0].z;
		c2->x = term[1].x; 		c2->y = term[1].y;		c2->z = term[1].z;		
		v1->data = c1;
		v2->data = c2;
		
		/* compute shortest path from v1 */
		if (shortest(grid_graph, v1 , &P, match_coord,GRID_WIDTH,GRID_HEIGHT) != 0)
			return 1;

		/* initialize the tree */
		list_init(&T,NULL);
		
		/* find the end vertex (v2)*/
		for (e = list_head(&P); e != NULL; e = list_next(e)) 
			if ( match_coord(v2,list_data(e)))
				u = (PathVertex*)list_data(e);
		
		
		first_edge = 1;
		last_edge = 0;
		/* follow the end vertex back to the start vertex*/
		while (u->parent != NULL) {
			int			ux,uy,uz,upx,upy,upz;
			AdjList		*a;
			ListElmt	*ee;
			
			/*current vertex*/
			ux = ((CoordData*)((PathVertex*)u)->data)->x;
			uy = ((CoordData*)((PathVertex*)u)->data)->y;
			uz = ((CoordData*)((PathVertex*)u)->data)->z;
			
			/*connecting vertex (parent)*/
			upx = ((CoordData*)((PathVertex*)u->parent)->data)->x;
			upy = ((CoordData*)((PathVertex*)u->parent)->data)->y;
			upz = ((CoordData*)((PathVertex*)u->parent)->data)->z;
			
			
			/* get the index of the edge that connects (ux,uy,uz) and its parent*/
			a = Edge2Adj[ux][uy][uz];
			for (ee = list_head(&a->adjacent); ee != NULL; ee = list_next(ee)) {
				PathVertex	*v;
				int			*i;
				int			vx,vy,vz;
				
				v = (PathVertex*)list_data(ee);
				vx = ((CoordData*)v->data)->x;
				vy = ((CoordData*)v->data)->y;
				vz = ((CoordData*)v->data)->z;
				
				/* found it*/
				if (( vx == upx ) && ( vy == upy ) && ( vz == upz )) {
					
					/*don't insert if its a via*/
					if (first_edge) {
						first_edge = 0;
						if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2)))
							continue;
					}
						
					/*check if its the last edge*/
					if (u->parent != NULL)
						if (u->parent->parent == NULL)
							last_edge = 1;
							
					/* don't insert if its a via*/
					if (last_edge)
						if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2)))
							continue;
					
					i = (int*) malloc(sizeof(int));
					tree_cost += v->weight;
					*i = v->index;
					list_ins_next(&T, list_tail(&T),i);
				}
			}
			
			/* next */
			u = u->parent;
		}
		
		/* count total edges*/
		*edge_count_OUT = list_size(&T);

		/* write the solution (including vias)*/
		if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T))))==NULL) {
			printf("gsFH.h : SteinerTree_OUT mem allocation error\n");
			fflush(stdout);
			exit(1);
		}
		
		e = list_head(&T);
		for (j = 0; ((j < list_size(&T))&&(e!=NULL)); j++,e=list_next(e)) 
			(*SteinerTree_OUT)[j] = *((int*)list_data(e));
		
		
		/* free up some temps*/
		free(v1->data); free(v1);
		free(v2->data); free(v2);
		list_destroy(&P);
		list_destroy(&T);
		
		return 0;
	}
	
	/*--------------------------------------------------------*/
	/* General case of 3 or more terminals begins here.  The  */
	/* above code for 2 terminals or less can be removed      */
	/* without affecting the block solution.   However, it is */
	/* faster with the special case                           */
	/*--------------------------------------------------------*/	
	
	/* Create Path Vertices out of the original terminal set */
	if ((terminals = (PathVertex**) malloc(sizeof(PathVertex*)*NO_TERMINALS))==NULL) {
		printf("gsFH.h : terminals mem allocation error\n");
		fflush(stdout);
		exit(1);
	}	
	for (i = 0; i < NO_TERMINALS; i++) {
		int x,y,z;
		
		x = term[i].x;
		y = term[i].y;
		z = term[i].z;
		
		path_vertex = (PathVertex*) malloc(sizeof(PathVertex));
		coord = (CoordData*) malloc(sizeof(CoordData));
		
		if ((path_vertex == NULL)||(coord == NULL)) {
			printf("gsFH.h : terminal[i] mem allocation error\n");
			fflush(stdout);
			exit(1);
		}

		
		coord->x = x;
		coord->y = y;
		coord->z = z;
		path_vertex->data = coord;
		
		terminals[i] = path_vertex;
	}

    

	/* inialize an array of list pointers used in extracting shortest paths from Dijkstra */
	sPaths = (List**) malloc(sizeof(List*)*NO_TERMINALS);
	if (sPaths == NULL) {
		printf("gsFH.h : sPaths mem allocation error\n");
		fflush(stdout);
		exit(1);
	}
	if ((tempPaths = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) {
		printf("gsFH.h : tempPaths mem allocation error\n");
		fflush(stdout);
		exit(1);
	}	
	for (i = 0; i < NO_TERMINALS; i++)
		if ((sPaths[i] = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) {
			printf("gsFH.h : sPaths[i] mem allocation error\n");
			fflush(stdout);
			exit(1);
		}



    
    /*--------------------------------------------------------------------------------------*/
    /*                          COMPUTE THE SHORTEST PATHS                                  */
    /*  Shortest paths are computed using O(EV^2) version of Dijkstras Algorithm            */
    /*--------------------------------------------------------------------------------------*/
    
	
    
    /* for each terminal (stored as a path vertex), find the shortest path   */
    /* The shortest path for terminal[i] is stored in the List pointed to by */
    /* paths[i].                                                             */

	for (i = 0; i < NO_TERMINALS; i++) {
		
		if (shortest(grid_graph, terminals[i], &tempPaths[i], match_coord,GRID_WIDTH,GRID_HEIGHT) != 0)
			return 1;
		
		/* copy out the shortest path data, if we don't do this, it will get overwritten*/
		for (j = 0; j < NO_TERMINALS; j++) 
			if (i != j)
				copy_sPath(&tempPaths[i], &(sPaths[i][j]), (CoordData*)((PathVertex*)terminals[j])->data);
	}
			
	
			


	/*--------------------------------------------------------------------------------------------------*/
	/*                Generate complete distance network ND												*/
	/*--------------------------------------------------------------------------------------------------*/

	/* initialize the graph */
	graph_init(&ND, match_coord, (void*)mst_vertex_free);
	
	/* insert the verticies.  Verticies consist of all the terminals */
	for (i = 0; i < NO_TERMINALS; i++) {
		
		/* allocate space for a MST vertex */
		if ((mst_vertex = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) {
			printf("Error allocating space for mst_vertex\n");
			printf("Terminating..\n");
			return 1;
		}
		
		/* if it's the first, make it the start.  It doesn't matter which one is the start */
		if (i == 1)
			mst_start = mst_vertex;
		
		/* set the data */
		if ((coord = (CoordData*) malloc(sizeof(CoordData)))==NULL) {
			printf("gsFH.h : coord mem allocation error\n");
			fflush(stdout);
			exit(1);
		}

		coord->x = ((CoordData*)(((PathVertex*)terminals[i])->data))->x;
		coord->y = ((CoordData*)(((PathVertex*)terminals[i])->data))->y;
		coord->z = ((CoordData*)(((PathVertex*)terminals[i])->data))->z;
		mst_vertex->data = coord;
		
		/* insert */
		if (graph_ins_vertex(&ND, mst_vertex) != 0) {
			printf("Error inserting vertex into mst_graph\n");
			printf("Terminating...\n");
			return 1;
		}
	}

	/*	now we must insert the edges into the distance network graph ND.  We do this by accessing the
		shortest path lists (sPath) computed in the previous step */
	for (i = 0; i < NO_TERMINALS; i++) {
		int ux,uy,uz;
		
		ux = ((CoordData*)((PathVertex*)terminals[i])->data)->x;
		uy = ((CoordData*)((PathVertex*)terminals[i])->data)->y;		
		uz = ((CoordData*)((PathVertex*)terminals[i])->data)->z;
				
		for (j = 0; j < NO_TERMINALS; j++) {
			int vx,vy,vz;
			
			/* shouldn't be an edge from a terminal to itself */
			if (i != j) {
				double weight;
				CoordData *v1,*v2;
				int eCode;
			
				vx = ((CoordData*)((PathVertex*)terminals[j])->data)->x;
				vy = ((CoordData*)((PathVertex*)terminals[j])->data)->y;
				vz = ((CoordData*)((PathVertex*)terminals[j])->data)->z;
				
			
				/* now we must find how far away vx is from vy.   we do this by looking
					for at the head element in sPath[i][j] */
				
				element = list_head(&(sPaths[i][j]));
				sPath_vertex = list_data(element);
				weight = ((sPathData*)sPath_vertex)->d;
				
				/* allocate an edge */				
				if ((v1 = (CoordData*) malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : v1 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				if ((v2 = (CoordData*) malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : v2 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				
				v1->x = ux;
				v1->y = uy;
				v1->z = uz;
				
				v2->x = vx;
				v2->y = vy;
				v2->z = vz;
				
				if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_vertex1 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
								
				if ((mst_vertex2 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_vertex2 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				mst_vertex1->data =v1;
				mst_vertex2->data = v2;
				mst_vertex2->weight = weight;
				
				if ((eCode = graph_ins_edge(&ND, mst_vertex1, mst_vertex2)) != 0) {
					printf("Error inserting edge into ND\n");
					printf("graph_ins_edge returned the value %d\n",eCode);
					return 1;
				}
				
				free(mst_vertex1->data);
				free(mst_vertex1);
				
			}/* endif i!=j */
		}/* endfor j */
	}/* endfor i */

/*--------------------------------------------------------------------------------------------------*/
/*		Copmute TD (Min Span Tree of ND)						    */
/*--------------------------------------------------------------------------------------------------*/

	if (mst(&ND, mst_start,&TD, match_coord) != 0) {
		printf("Error computing minimum spanning tree\n");
		return 1;
	}	
	
	/* set leaves */
	
	/* initialize */
	for ( element = list_head(&TD); element != NULL; element = list_next(element))
	{
	   mst_vertex = list_data(element);
	   mst_vertex->is_leaf = 1;
    }
    
    /* for each node, set the parent is_leaf to 0.   Then, all leaves will remain */
    for (element = list_head(&TD); element != NULL; element = list_next(element))
    {
        mst_vertex = list_data(element);
        
        if (mst_vertex->parent != NULL)
            mst_vertex->parent->is_leaf = 0;
    }
	

/*--------------------------------------------------------------------------------------------------*/
/*	         Find N[TD]									    */
/*--------------------------------------------------------------------------------------------------*/
	
	graph_init(&NTD,match_coord,(void*)mst_vertex_free);


    /* for each edge in TD */
	for (element = list_head(&TD); element != NULL; element = list_next(element)) {
		MstVertex	*nextVertex;
		int			v,p;

		p = -1;
		v = -1;

		nextVertex = list_data(element);
		
		/* if it is not the root */
		if (nextVertex->parent != NULL) {
			int vx,vy,vz,px,py,pz;
			ListElmt	*currentV, *nextV;
			int			done;
			
			
			vx = ((CoordData*)((MstVertex*)nextVertex)->data)->x;
			vy = ((CoordData*)((MstVertex*)nextVertex)->data)->y;
			vz = ((CoordData*)((MstVertex*)nextVertex)->data)->z;
			
			px = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->x;
			py = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->y;			
			pz = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->z;
			
			/* find terminal index of nextVertex and nextVertex->parent */
			for (i = 0; i < NO_TERMINALS; i++) {
				int tx,ty,tz;
				
				tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x;
				ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y;
				tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z;
				
				if ((tx == vx)&&(ty == vy)&&(tz == vz))
					v = i;
				
				if ((tx == px)&&(ty == py)&&(tz == pz))
					p = i;
			}
			
			/* now, we must step through the list of sPathData elements found in sPaths[p][v].
			   For each element in the list, we must insert vertices for the vertex and parent, 
				then make an edge with the appropriate weight and insert it */
			
			currentV = list_head(&(sPaths[p][v]));
			nextV = list_next(currentV);
			done = 0;
			while ( !done ) {
				MstVertex	*u,*v, *mst_vertex1, *mst_vertex2;
				CoordData	*uc,*vc;
				sPathData	*currentVData, *nextVData;
				int			cvx,cvy,cvz,nvx,nvy,nvz;
				double		weight;

				/*---------------------------------------*/
				/* insert vertices u and v into NTD      */
				/*---------------------------------------*/
				
				/* make a vertex for currentV and nextV */
				u = (MstVertex*) malloc(sizeof(MstVertex));
				v = (MstVertex*) malloc(sizeof(MstVertex));
				uc = (CoordData*) malloc(sizeof(CoordData));
				vc = (CoordData*) malloc(sizeof(CoordData));
				
				if ((u == NULL)||(uc==NULL)||(v==NULL)||(vc==NULL)) {
					printf("gsFH.h : error allocating vertex for NTD\n");
					fflush(stdout);
					exit(1);
				}
				
				/* get vertices from the sPaths list */
				currentVData = list_data(currentV);
				nextVData = list_data(nextV);
				
				/* get vertex data */
				cvx = ((CoordData*)((sPathData*)currentVData)->vertex)->x;
				cvy = ((CoordData*)((sPathData*)currentVData)->vertex)->y;
				cvz = ((CoordData*)((sPathData*)currentVData)->vertex)->z;
				
				nvx = ((CoordData*)((sPathData*)nextVData)->vertex)->x;
				nvy = ((CoordData*)((sPathData*)nextVData)->vertex)->y;
				nvz = ((CoordData*)((sPathData*)nextVData)->vertex)->z;

								
				/* set vertex data */
				uc->x = cvx;
				uc->y = cvy;
				uc->z = cvz;
				
				vc->x = nvx;
				vc->y = nvy;
				vc->z = nvz;
				
				u->data = uc;
				v->data = vc;
				
				/* calculate weight between u and v */
				weight = currentVData->d - nextVData->d;

				
				/* try and insert u, if it exists, then delete the memory we allocated for it */
				if ( graph_ins_vertex(&NTD, u) == 1 ) {
					free(uc);
					free(u);
				}
				else {
					/* doesnt' matter which one is the start */
					mst_start = u;
				}

				/* try and insert v, if it exists, then delete the memorr we allocated for it */
				if ( graph_ins_vertex(&NTD, v) == 1) {
					free(vc);
					free(v);
				}
				
				/* now the vertices u and v are in the graph.   we now have to make an edge for uv */
				
				/* make edge going forward */				
				if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : uc mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : vc mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				uc->x = cvx;
				uc->y = cvy;
				uc->z = cvz;

				vc->x = nvx;
				vc->y = nvy;
				vc->z = nvz;
				
				if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_Vertex1 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_vertex2 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				mst_vertex1->data = uc;
				mst_vertex2->data = vc;
				mst_vertex2->weight = weight;
				
				/* try and insert, if it exists, free previously allocated mem */
				if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) {
					free(vc);
					free(mst_vertex2);
				}
				
				/* free the label */
				free(mst_vertex1->data);
				free(mst_vertex1);
				
				
				/* make edge going backward */				
				if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : uc mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) {
					printf("gsFH.h : vc mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				uc->x = cvx;
				uc->y = cvy;
				uc->z = cvz;
				
				vc->x = nvx;
				vc->y = nvy;
				vc->z = nvz;
				
				if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_Vertex1 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}

				if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) {
					printf("gsFH.h : mst_Vertex2 mem allocation error\n");
					fflush(stdout);
					exit(1);
				}
				
				mst_vertex1->data = vc;
				mst_vertex2->data = uc;
				mst_vertex2->weight = weight;
				
				/* try and insert, if it exists, free previously allocated mem */
				if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) {
					free(uc);
					free(mst_vertex2);
				}

				/* free the label */
				free(mst_vertex1->data);
				free(mst_vertex1);
								
				
				/* follow pointers */
				currentV = list_next(currentV);
				nextV = list_next(nextV);
				
				/* check to see if we're finished */
				if (nextV == NULL)
					done = 1;
			
			}
				
		 }
	}


/*----------------------------------------------------------------------------------------------------------*/
/*	Compute T (minimum spanning tree of NTD)							    */
/*----------------------------------------------------------------------------------------------------------*/

	/* call minimum spanning tree subroutine */
	if (mst(&NTD, mst_start,&T, match_coord) != 0) {
		printf("Error computing minimum spanning tree\n");
		return 1;
	}

	/* set leaves */	
	for ( element = list_head(&T); element != NULL; element = list_next(element))
	{
		mst_vertex = list_data(element);
		mst_vertex->is_leaf = 1;
    }
    
    /* for each node, set the parent is_leaf to 0.   Then, all leaves will remain */
    for (element = list_head(&T); element != NULL; element = list_next(element))
    {
        mst_vertex = list_data(element);
        
        if (mst_vertex->parent != NULL)
            mst_vertex->parent->is_leaf = 0;
    }
    
	
	
/*--------------------------------------------------------------------------------------*/
/*		Compute Steiner Tree Sk						 	*/
/*--------------------------------------------------------------------------------------*/

	isSteiner = 0;
	/* we remove all leaves that arent' terminals, when all leaves are terminals then we have a Steiner Tree */
	while (!isSteiner) {
		ListElmt	*prev;
		
		/* assume we have it */
		isSteiner = 1;
		
		/* check if each leaf is a terminal */
		prev = list_head(&T);
		element = list_next(prev);
		while (element != NULL) {
			int mx,my,mz;
			
			mst_vertex = list_data(element);
			mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x;
			my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y;		
			mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z;					
			
			if (mst_vertex->is_leaf) {
				int found;
				
				found = 0;
				for (i = 0; i < NO_TERMINALS; i++) {
					int	tx,ty,tz;
					
					tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x;
					ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y;
					tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z;
					
					if ( (tx==mx)&&(ty==my)&&(tz==mz))
						found = 1;
				}
				
				/* remove it if we can't find it */
				if (!found) {
					MstVertex	*junk;
					ListElmt *e;
					
					isSteiner = 0;		/* not done yet */
					
					list_rem_next(&T, prev, (void**)(&junk));
					
					/*reset leaves */
					/* initialize */
					for ( e = list_head(&T); e != NULL; e = list_next(e))
					{
						mst_vertex = list_data(e);
						mst_vertex->is_leaf = 1;
					}
					
					/* for each node, set the parent is_leaf to 0.   Then, all leaves will remain */
					for (e = list_head(&T); e != NULL; e = list_next(e))
					{
						mst_vertex = list_data(e);
						
						if (mst_vertex->parent != NULL)
							mst_vertex->parent->is_leaf = 0;
					}
					
					/* start over at beginning of list */
					prev = list_head(&T);
					element = list_next(prev);
					
					
				}
				else {
					prev = list_next(prev);
					element = list_next(element);
				}
			}
			else {
				prev = list_next(prev);
				element = list_next(element);
			}
		}
	}



	/* we can further eliminate vias that connect to a terminal leaf.   These are not neccessary*/
	isSteiner = 0;
	while (!isSteiner) {
		ListElmt	*prev;
		
		/* assume we have it */
		isSteiner = 1;
		
		/* check if each leaf is a terminal */
		prev = list_head(&T);
		element = list_next(prev);
		while (element != NULL) {
			int mx,my,mz;
			
			mst_vertex = list_data(element);
			mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x;
			my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y;		
			mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z;					
			
			if (mst_vertex->is_leaf) {
				int remove;
				int	px,py;
				
				remove = 0;
				px = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->x;
				py = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->y;				
				
				if ((px == mx)&&(py == my))
					remove = 1;
				
				
				/* remove it if neccessary */
				if (remove) {
					MstVertex	*junk;
					ListElmt *e;
					
					isSteiner = 0;		/* not done yet */
					
					list_rem_next(&T, prev, (void**)(&junk));
					
					/*reset leaves */
					/* initialize */
					for ( e = list_head(&T); e != NULL; e = list_next(e))
					{
						mst_vertex = list_data(e);
						mst_vertex->is_leaf = 1;
					}
					
					/* for each node, set the parent is_leaf to 0.   Then, all leaves will remain */
					for (e = list_head(&T); e != NULL; e = list_next(e))
					{
						mst_vertex = list_data(e);
						
						if (mst_vertex->parent != NULL)
							mst_vertex->parent->is_leaf = 0;
					}
					
					/* start over at beginning of list */
					prev = list_head(&T);
					element = list_next(prev);
					
					
				}
				else {
					prev = list_next(prev);
					element = list_next(element);
				}
			}
			else {
				prev = list_next(prev);
				element = list_next(element);
			}
		}
	}



	/* get the total cost of the tree */
	tree_cost = 0;
	for (element = list_head(&T); element != NULL; element = list_next(element)) {
		
		CoordData *u, *v;
		
		mst_vertex = list_data(element);
		
		if (( mst_vertex->parent == NULL))
			continue;
		else {
			double temp;
			
			u = (CoordData*)mst_vertex->data;
			v = (CoordData*)mst_vertex->parent->data;
			
			/* look up cost of edge uv */
			temp = find_edge_weight(grid_graph,u,v);
			tree_cost += temp;
				
		}
	}
	
	

	*edge_count_OUT = list_size(&T)-1;
	if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T)-1)))==NULL) {
		printf("gsFH.h : SteinerTree_OUT mem allocation error\n");
		fflush(stdout);
		exit(1);
	}


	i = 0;
	for ( element = list_head(&T); element != NULL; element = list_next(element))
	{
		int vx,vy,vz,px,py,pz;
		int tx,ty,tz;
		AdjList *a;
		ListElmt *e;
		int		edge_index;
		double	edge_weight;
		
		mst_vertex = list_data(element);
		
		vx = ((CoordData*)mst_vertex->data)->x;
		vy = ((CoordData*)mst_vertex->data)->y;
		vz = ((CoordData*)mst_vertex->data)->z;
		if (mst_vertex->parent != NULL) {
			px = ((CoordData*)mst_vertex->parent->data)->x;
			py = ((CoordData*)mst_vertex->parent->data)->y;		
			pz = ((CoordData*)mst_vertex->parent->data)->z;		
			edge_weight = mst_vertex->weight;
		}
		else {
			px = -1;
			py = -1;
			pz = -1;
		}
		

			
		a = (AdjList*)Edge2Adj[vx][vy][vz];
		
		tx = ((CoordData*)((PathVertex*)(a->vertex))->data)->x;
		ty = ((CoordData*)((PathVertex*)(a->vertex))->data)->y;
		tz = ((CoordData*)((PathVertex*)(a->vertex))->data)->z;
		
		for ( e = list_head(&(a->adjacent)); e != NULL; e = list_next(e) ) {
			PathVertex *p;
		
			p = (PathVertex*)list_data(e);
			
			tx = ((CoordData*)p->data)->x;
			ty = ((CoordData*)p->data)->y;
			tz = ((CoordData*)p->data)->z;
			
			if ((tx == px)&&(ty == py)&&(tz == pz)) {	/*found*/
				edge_index = p->index;
				(*SteinerTree_OUT)[i] = edge_index;
				i++;
			}
		}
	}


	

	/*-------------------------------------------------------------------------------------*/
	/*			Clean Up						       */
	/*-------------------------------------------------------------------------------------*/
	
	

	/* free our list of temporary paths*/
	for (i = 0; i < NO_TERMINALS; i++) 
		list_destroy(&tempPaths[i]);
	free(tempPaths);

	/* destroy distance network*/
	graph_destroy(&ND);
	
	/* deystroy all the shortest path lists*/
	for (i = 0; i < NO_TERMINALS; i++) 
	   for (j = 0; j < NO_TERMINALS; j++)
		   if ( i != j ) 
			   list_destroy(&sPaths[i][j]);
	
	/* destroy the pointers to the shortest path lists*/
	for (i = 0; i < NO_TERMINALS; i++) 
		free(sPaths[i]);
	free(sPaths);

	/* destroy the minimum spanning tree*/
	list_destroy(&TD);

	/* destroy grid spanning tree*/
	graph_destroy(&NTD);

	/* destroy the terminal list*/
	for (i = 0; i < NO_TERMINALS; i++) {
		path_vertex_free(terminals[i]);
	}
	free(terminals);
	
	/*destroy the steiner tree*/
	list_destroy(&T);

	return 0;
}
コード例 #21
0
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n = ptr;
  struct rdc_buf_list *q = list_head(n->queued_packet_list);
  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_transmissions;

  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions++;
    break;
  case MAC_TX_COLLISION:
    n->collisions++;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals++;
    break;
  }

  sent = metadata->sent;
  cptr = metadata->cptr;
  num_tx = n->transmissions;

  if(status == MAC_TX_COLLISION ||
     status == MAC_TX_NOACK) {

    /* If the transmission was not performed because of a collision or
       noack, we must retransmit the packet. */
    
    switch(status) {
    case MAC_TX_COLLISION:
      PRINTF("csma: rexmit collision %d\n", n->transmissions);
      break;
    case MAC_TX_NOACK:
      PRINTF("csma: rexmit noack %d\n", n->transmissions);
      break;
    default:
      PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
    }

    /* The retransmission time must be proportional to the channel
       check interval of the underlying radio duty cycling layer. */
    time = default_timebase();

    /* The retransmission time uses a linear backoff so that the
       interval between the transmissions increase with each
       retransmit. */
    backoff_transmissions = n->transmissions + 1;

    /* Clamp the number of backoffs so that we don't get a too long
       timeout here, since that will delay all packets in the
       queue. */
    if(backoff_transmissions > 3) {
      backoff_transmissions = 3;
    }

    time = time + (random_rand() % (backoff_transmissions * time));

    if(n->transmissions < metadata->max_transmissions) {
      PRINTF("csma: retransmitting with time %lu %p\n", time, q);
      ctimer_set(&n->transmit_timer, time,
                 transmit_packet_list, n);
      /* This is needed to correctly attribute energy that we spent
         transmitting this packet. */
      queuebuf_update_attr_from_packetbuf(q->buf);
    } else {
      PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
             status, n->transmissions, n->collisions);
      free_first_packet(n);
      mac_call_sent_callback(sent, cptr, status, num_tx);
    }
  } else {
    if(status == MAC_TX_OK) {
      PRINTF("csma: rexmit ok %d\n", n->transmissions);
    } else {
      PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
    }
    free_first_packet(n);
    mac_call_sent_callback(sent, cptr, status, num_tx);
  }
}
コード例 #22
0
ファイル: spa_config.c プロジェクト: sriramnrn/zfs-port
/*
 * Synchronize pool configuration to disk.  This must be called with the
 * namespace lock held.
 */
void
spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
{
    spa_t *spa = NULL;
    spa_config_dirent_t *dp, *tdp;
    nvlist_t *nvl;

    ASSERT(MUTEX_HELD(&spa_namespace_lock));

    /*
     * Iterate over all cachefiles for the pool, past or present.  When the
     * cachefile is changed, the new one is pushed onto this list, allowing
     * us to update previous cachefiles that no longer contain this pool.
     */
    for (dp = list_head(&target->spa_config_list); dp != NULL;
            dp = list_next(&target->spa_config_list, dp)) {
        spa = NULL;
        if (dp->scd_path == NULL)
            continue;

        /*
         * Iterate over all pools, adding any matching pools to 'nvl'.
         */
        nvl = NULL;
        while ((spa = spa_next(spa)) != NULL) {
#ifdef DEBUG
            if ( spa->spa_config ) {
                printf("spa_config_sync::spa->spa_config=0x%x\n", spa->spa_config);
            }
#endif
            if (spa->spa_config == NULL || spa->spa_name == NULL)
                continue;

            if (spa == target && removing)
                continue;

            tdp = list_head(&spa->spa_config_list);
            ASSERT(tdp != NULL);
            if (tdp->scd_path == NULL ||
                    strcmp(tdp->scd_path, dp->scd_path) != 0)
                continue;

            if (nvl == NULL)
                VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME,
                                    KM_SLEEP) == 0);

            VERIFY(nvlist_add_nvlist(nvl, spa->spa_name,
                                     spa->spa_config) == 0);
        }

        spa_config_write(dp, nvl);
        nvlist_free(nvl);
    }

    /*
     * Remove any config entries older than the current one.
     */
    dp = list_head(&target->spa_config_list);
    while ((tdp = list_next(&target->spa_config_list, dp)) != NULL) {
        list_remove(&target->spa_config_list, tdp);
        if (tdp->scd_path != NULL)
            spa_strfree(tdp->scd_path);
        kmem_free(tdp, sizeof (spa_config_dirent_t));
    }

    spa_config_generation++;

    if (postsysevent)
        spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC);
}
コード例 #23
0
ファイル: spa_config.c プロジェクト: rchander/freebsd
/*
 * Synchronize pool configuration to disk.  This must be called with the
 * namespace lock held.
 */
void
spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
{
	spa_config_dirent_t *dp, *tdp;
	nvlist_t *nvl;

	ASSERT(MUTEX_HELD(&spa_namespace_lock));

	if (rootdir == NULL || !(spa_mode_global & FWRITE))
		return;

	/*
	 * Iterate over all cachefiles for the pool, past or present.  When the
	 * cachefile is changed, the new one is pushed onto this list, allowing
	 * us to update previous cachefiles that no longer contain this pool.
	 */
	for (dp = list_head(&target->spa_config_list); dp != NULL;
	    dp = list_next(&target->spa_config_list, dp)) {
		spa_t *spa = NULL;
		if (dp->scd_path == NULL)
			continue;

		/*
		 * Iterate over all pools, adding any matching pools to 'nvl'.
		 */
		nvl = NULL;
		while ((spa = spa_next(spa)) != NULL) {
			/*
			 * Skip over our own pool if we're about to remove
			 * ourselves from the spa namespace or any pool that
			 * is readonly. Since we cannot guarantee that a
			 * readonly pool would successfully import upon reboot,
			 * we don't allow them to be written to the cache file.
			 */
			if ((spa == target && removing) ||
			    !spa_writeable(spa))
				continue;

			mutex_enter(&spa->spa_props_lock);
			tdp = list_head(&spa->spa_config_list);
			if (spa->spa_config == NULL ||
			    tdp->scd_path == NULL ||
			    strcmp(tdp->scd_path, dp->scd_path) != 0) {
				mutex_exit(&spa->spa_props_lock);
				continue;
			}

			if (nvl == NULL)
				VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME,
				    KM_SLEEP) == 0);

			VERIFY(nvlist_add_nvlist(nvl, spa->spa_name,
			    spa->spa_config) == 0);
			mutex_exit(&spa->spa_props_lock);
		}

		spa_config_write(dp, nvl);
		nvlist_free(nvl);
	}

	/*
	 * Remove any config entries older than the current one.
	 */
	dp = list_head(&target->spa_config_list);
	while ((tdp = list_next(&target->spa_config_list, dp)) != NULL) {
		list_remove(&target->spa_config_list, tdp);
		if (tdp->scd_path != NULL)
			spa_strfree(tdp->scd_path);
		kmem_free(tdp, sizeof (spa_config_dirent_t));
	}

	spa_config_generation++;

	if (postsysevent)
		spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC);
}
コード例 #24
0
    printf("add student success.\n");
}

/**
 * 从列表中删除一个学生信息
 * @param list  列表
 */
void delete(List *list){
    query(list);    //遍历列表,显示所有学生信息

    printf("please enter the number of student which one you want to delete\n");
    int number;
    scanf("%d", &number);

    Student *item;
    ListElmt *previous = list_head(list);  //将上一个元素指向列表头部
    ListElmt *current = list_head(list);   //将当前元素指向列表头部
    int flag = 0;

    int size = list_size(list);            //获取列表元素数量
    printf("list size = %d\n", size);

    if (size > 0) {
        while(current != NULL){
            item = list_data(current);      //获取当前元素中的数据,这个数据就是Student
            if(item->_id == number){        //将Student的id和用户输入的id比对, 相同
                flag = 1;
                if(current != previous){                        //这种情况表示移除的不是头部元素
                    list_rem_next(list, previous, (void **)item);
                }else {
                    list_rem_next(list, NULL, (void **)item);
コード例 #25
0
ファイル: listtest.c プロジェクト: rojkov/swupd-client
int main(int argc, char **argv)
{
	struct list *list = NULL;
	struct list *list1, *list2;
	struct list *item, *item2, *item3, *head, *tail;
	unsigned int i;
	struct timeval tod;
	unsigned int seed;
	unsigned int len = TEST_LIST_LEN;
	clock_t t;
	unsigned int *data;

	/* List length must be greater than 3 for all tests to work */
	if (argc > 1) {
		len = atoi(argv[1]);
	}
	if (len < 4) {
		printf("List length must be at least 4 for tests.\n");
		return EXIT_FAILURE;
	}

	/* seed the random generator so that we get different lists each time */
	gettimeofday(&tod, NULL);
	seed = (unsigned int) tod.tv_sec;
	srand(seed);

	/* create a list with random data between 0 and len */
	for (i = 1; i <= len; i++) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) rand() % len;
		list = list_append_data(list, data);
	}
	printf("List constructed, seed = %d, len = %d\n", seed, list_len(list));

	t = clock();
	list = list_sort(list, data_compare);
	t = clock() - t;

	/* check list elements are in right order */
	if (check_list_order(list, 1) != 0) {
		printf ("Sorted (1) List is in wrong order\n");
		return EXIT_FAILURE;
	}

	/* check sorted list has the expected len */
	if (list_len(list) != len) {
		printf("Wrong sorted (1) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("List sorted in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* sort again on sorted list to check special case */

	t = clock();
	list = list_sort(list, data_compare);
	t = clock() - t;

	if (check_list_order(list, 1) != 0) {
		printf ("Sorted (2) List is in wrong order\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len) {
		printf("Wrong sorted (2) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("Sorted list sorted again in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* reverse sort from sorted state */

	t = clock();
	list = list_sort(list, data_compare_reverse);
	t = clock() - t;

	if (check_list_order(list, -1) != 0) {
		printf ("Sorted (3) List is in wrong order\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len) {
		printf("Wrong sorted (3) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("Sorted list sorted reverse in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* Check freeing the head item.
	 * This must return the 2nd item, which must be the new head */
	head = list_head(list);
	item2 = head->next;
	list = list_free_item(head, free);
	if (list != item2) {
		printf("removing head item did not return 2nd item\n");
		return EXIT_FAILURE;
	}
	if (item2->prev) {
		printf("item returned after removing head is not new head\n");
		return EXIT_FAILURE;
	}
	if (list_len(item2) != len - 1) {
		printf("removing head item did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing head correctly returned 2nd item as new head\n");

	/* Check freeing middle item, must return previous item */
	head = list_head(list);
	item2 = head->next;
	item3 = item2->next;
	list = list_free_item(item2, free);
	if (list != head) {
		printf("removing 2nd item did not return head item\n");
		return EXIT_FAILURE;
	}
	if ((head != item3->prev) || (head->next != item3)) {
		printf("removing 2nd item did not link 3rd item to head\n");
		return EXIT_FAILURE;
	}

	if (list_len(list) != len - 2) {
		printf("removing 2nd item did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing middle item correctly returned previous item\n");

	/* Check freeing tail, must return new tail */
	tail = list_tail(list);
	item = tail->prev;
	list = list_free_item(tail, free);
	if (list != item) {
		printf("removing tail did not return prev item\n");
		return EXIT_FAILURE;
	}
	tail = list_tail(list);
	if (list != tail) {
		printf("removing tail did not return new tail\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len - 3) {
		printf("removing tail did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing tail correctly returned previous item as new tail\n");

	list_free_list_and_data(list, free);
	list = NULL;

	/* Check list_concat */
	list1 = NULL;
	list2 = NULL;

	for (i = 3; i > 0; i--) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) i;
		list1 = list_prepend_data(list1, data);
	}

	for (i = 6; i > 3; i--) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) i;
		list2 = list_prepend_data(list2, data);
	}

	/* Check concat one list with empty list */
	list = list_concat(list1, NULL);
	if (list_len(list) != 3) {
		printf("concat(list1, NULL) did not result in a list len of 3\n");
		return EXIT_FAILURE;
	}
	if (list != list1) {
		printf("concat(list1, NULL) did not return list1\n");
		return EXIT_FAILURE;
	}
	if (list_head(list) != list) {
		printf("concat(list1, NULL) did not return list1 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 1) {
		printf("concat(list1, NULL) head is wrong\n");
		return EXIT_FAILURE;
	}
	printf ("concat(list1, NULL) is OK\n");
	// dump_list(list);

	/* Check concat empty list with one list*/
	list = list_concat(NULL, list2);
	if (list_len(list) != 3) {
		printf("concat(NULL, list2) did not result in a list len of 3\n");
		return EXIT_FAILURE;
	}
	if (list != list2) {
		printf("concat(NULL, list2) did not return list2\n");
		return EXIT_FAILURE;
	}
	if (list_head(list) != list) {
		printf("concat(NULL, list2) did not return list2 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 4) {
		printf("concat(NULL, list2) head is wrong\n");
		return EXIT_FAILURE;
	}
	printf ("concat(NULL, list2) is OK\n");
	// dump_list(list);

	/* Check concat two lists */
	list = list_concat(list1->next, list2->next->next);
	if (list_len(list) != 6) {
		printf("concat(list1, list2) did not result in a list len of 6\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 1) {
		printf("concat(list1, list2) did not return list1 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->next->next->next->data)) != 4) {
		printf("concat(list1, list2) 4th item is not 4\n");
		return EXIT_FAILURE;
	}
	printf ("concat(list1, list2) is OK\n");
	// dump_list(list);

	list_free_list_and_data(list, free);

	printf ("*** ALL LIST TESTS COMPLETED OK***\n");

    return EXIT_SUCCESS;
}
コード例 #26
0
ファイル: csma.c プロジェクト: Noradila/multichannel-RPL
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint16_t seqno;
  const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  if(seqno == 0) {
    /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
       in framer-802154.c. */
    seqno++;
  }
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);

  /* Look for the neighbor entry */
  n = neighbor_queue_from_addr(addr);
  if(n == NULL) {
    /* Allocate a new neighbor entry */
    n = memb_alloc(&neighbor_memb);
    if(n != NULL) {
      /* Init neighbor entry */
      rimeaddr_copy(&n->addr, addr);
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Init packet list for this neighbor */
      LIST_STRUCT_INIT(n, queued_packet_list);
      /* Add neighbor to the list */
      list_add(neighbor_list, n);
    }
  }

  if(n != NULL) {
    /* Add packet to the neighbor's queue */
    q = memb_alloc(&packet_memb);
    if(q != NULL) {
      q->ptr = memb_alloc(&metadata_memb);
      if(q->ptr != NULL) {
	q->buf = queuebuf_new_from_packetbuf();
	if(q->buf != NULL) {
	  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
	  /* Neighbor and packet successfully allocated */
	  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
	    /* Use default configuration for max transmissions */
	    metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
	  } else {
	    metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
	  }
	  metadata->sent = sent;
	  metadata->cptr = ptr;

	  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
	    list_push(n->queued_packet_list, q);
	  } else {
	    list_add(n->queued_packet_list, q);
	  }

//ADILA EDIT
printf("Q %d\n\n", list_length(n->queued_packet_list));
//----------

	  /* If q is the first packet in the neighbor's queue, send asap */
	  if(list_head(n->queued_packet_list) == q) {
	    ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
	  }
	  return;
	}
	memb_free(&metadata_memb, q->ptr);
	PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      memb_free(&packet_memb, q);
      PRINTF("csma: could not allocate queuebuf, dropping packet\n");
    }
    /* The packet allocation failed. Remove and free neighbor entry if empty. */
    if(list_length(n->queued_packet_list) == 0) {
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
}
コード例 #27
0
ファイル: uip-mcast6-route.c プロジェクト: kamejoko80/emb6
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_list_head(void)
{
  return list_head(mcast_route_list);
}
コード例 #28
0
ファイル: helpers.c プロジェクト: pdxjohnny/swupd-client
/* This function is meant to be called while staging file to fix any missing/incorrect paths.
 * While staging a file, if its parent directory is missing, this would try to create the path
 * by breaking it into sub-paths and fixing them top down.
 * Here, target_MoM is the consolidated manifest for the version you are trying to update/verify.
 */
int verify_fix_path(char *targetpath, struct manifest *target_MoM)
{
	struct list *path_list = NULL; /* path_list contains the subparts in the path */
	char *path;
	char *tmp = NULL, *target = NULL;
	char *url = NULL;
	struct stat sb;
	int ret = 0;
	struct file *file;
	char *tar_dotfile = NULL;
	struct list *list1 = NULL;

	/* This shouldn't happen */
	if (strcmp(targetpath, "/") == 0) {
		return ret;
	}

	/* Removing trailing '/' from the path */
	path = strdup(targetpath);
	if (path[strlen(path) - 1] == '/') {
		path[strlen(path) - 1] = '\0';
	}

	/* Breaking down the path into parts.
	 * eg. Path /usr/bin/foo will be broken into /usr,/usr/bin and /usr/bin/foo
	 */
	while (strcmp(path, "/") != 0) {
		path_list = list_prepend_data(path_list, strdup(path));
		tmp = strdup(dirname(path));
		free(path);
		path = tmp;
	}
	free(path);

	list1 = list_head(path_list);
	while (list1) {
		path = list1->data;
		list1 = list1->next;

		target = mk_full_filename(path_prefix, path);

		/* Search for the file in the manifest, to get the hash for the file */
		file = search_file_in_manifest(target_MoM, path);
		if (file == NULL) {
			printf("Error: Path %s not found in any of the subscribed manifests"
			       "in verify_fix_path for path_prefix %s\n",
			       path, path_prefix);
			ret = -1;
			goto end;
		}

		if (file->is_deleted) {
			printf("Error: Path %s found deleted in verify_fix_path\n", path);
			ret = -1;
			goto end;
		}

		ret = stat(target, &sb);
		if (ret == 0) {
			if (verify_file(file, target)) {
				continue;
			}
			printf("Hash did not match for path : %s\n", path);
		} else if (ret == -1 && errno == ENOENT) {
			printf("Path %s is missing on the file system\n", path);
		} else {
			goto end;
		}

		string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash);

		// clean up in case any prior download failed in a partial state
		unlink(tar_dotfile);

		string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash);
		ret = swupd_curl_get_file(url, tar_dotfile, NULL, NULL, false);

		if (ret != 0) {
			printf("Error: Failed to download file %s in verify_fix_path\n", file->filename);
			unlink(tar_dotfile);
			goto end;
		}
		if (untar_full_download(file) != 0) {
			printf("Error: Failed to untar file %s\n", file->filename);
			ret = -1;
			goto end;
		}

		ret = do_staging(file, target_MoM);
		if (ret != 0) {
			printf("Error: Path %s failed to stage in verify_fix_path\n", path);
			goto end;
		}
	}
end:
	if (target) {
		free(target);
	}
	if (tar_dotfile) {
		free(tar_dotfile);
	}
	if (url) {
		free(url);
	}
	list_free_list_and_data(path_list, free_path_data);
	return ret;
}
コード例 #29
0
ファイル: nfs4_srv_deleg.c プロジェクト: pcd1193182/openzfs
/*
 * Check if the file is delegated via the provided file struct.
 * Return TRUE if it is delegated.  This is intended for use by
 * the v4 server.  The v2/v3 server code should use rfs4_check_delegated().
 *
 * Note that if the file is found to have a delegation, it is
 * recalled, unless the clientid of the caller matches the clientid of the
 * delegation. If the caller has specified, there is a slight delay
 * inserted in the hopes that the delegation will be returned quickly.
 */
bool_t
rfs4_check_delegated_byfp(int mode, rfs4_file_t *fp,
    bool_t trunc, bool_t do_delay, bool_t is_rm, clientid4 *cp)
{
	rfs4_deleg_state_t *dsp;

	/* Is delegation enabled? */
	if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
		return (FALSE);

	/* do we have a delegation on this file? */
	rfs4_dbe_lock(fp->rf_dbe);
	if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
		if (is_rm)
			fp->rf_dinfo.rd_hold_grant++;
		rfs4_dbe_unlock(fp->rf_dbe);
		return (FALSE);
	}
	/*
	 * do we have a write delegation on this file or are we
	 * requesting write access to a file with any type of existing
	 * delegation?
	 */
	if (mode == FWRITE || fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE) {
		if (cp != NULL) {
			dsp = list_head(&fp->rf_delegstatelist);
			if (dsp == NULL) {
				rfs4_dbe_unlock(fp->rf_dbe);
				return (FALSE);
			}
			/*
			 * Does the requestor already own the delegation?
			 */
			if (dsp->rds_client->rc_clientid == *(cp)) {
				rfs4_dbe_unlock(fp->rf_dbe);
				return (FALSE);
			}
		}

		rfs4_dbe_unlock(fp->rf_dbe);
		rfs4_recall_deleg(fp, trunc, NULL);

		if (!do_delay) {
			rfs4_dbe_lock(fp->rf_dbe);
			fp->rf_dinfo.rd_time_rm_delayed = gethrestime_sec();
			rfs4_dbe_unlock(fp->rf_dbe);
			return (TRUE);
		}

		delay(NFS4_DELEGATION_CONFLICT_DELAY);

		rfs4_dbe_lock(fp->rf_dbe);
		if (fp->rf_dinfo.rd_dtype != OPEN_DELEGATE_NONE) {
			fp->rf_dinfo.rd_time_rm_delayed = gethrestime_sec();
			rfs4_dbe_unlock(fp->rf_dbe);
			return (TRUE);
		}
	}
	if (is_rm)
		fp->rf_dinfo.rd_hold_grant++;
	rfs4_dbe_unlock(fp->rf_dbe);
	return (FALSE);
}
コード例 #30
0
ファイル: lpp.c プロジェクト: soohyunc/contiki-2.x
/**
 * Read a packet from the underlying radio driver. If the incoming
 * packet is a probe packet and the sender of the probe matches the
 * destination address of the queued packet (if any), the queued packet
 * is sent.
 */
static int
read_packet(void)
{
  int len;
  struct lpp_hdr *hdr;
  clock_time_t reception_time;

  reception_time = clock_time();
  
  packetbuf_clear();
  len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
  if(len > sizeof(struct lpp_hdr)) {
    packetbuf_set_datalen(len);
    hdr = packetbuf_dataptr();
    packetbuf_hdrreduce(sizeof(struct lpp_hdr));
    /*    PRINTF("got packet type %d\n", hdr->type);*/

    if(hdr->type == TYPE_PROBE) {
      /* Parse incoming announcements */
      struct announcement_msg *adata = packetbuf_dataptr();
      int i;
	
      /*	PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
		rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		hdr->sender.u8[0], hdr->sender.u8[1], adata->num);*/
	
      for(i = 0; i < adata->num; ++i) {
	/*	  PRINTF("%d.%d: announcement %d: %d\n",
		  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		  adata->data[i].id,
		  adata->data[i].value);*/

	announcement_heard(&hdr->sender,
			   adata->data[i].id,
			   adata->data[i].value);
      }

      /* Register the encounter with the sending node. We now know the
	 neighbor's phase. */
      register_encounter(&hdr->sender, reception_time);

      /* Go through the list of packets to be sent to see if any of
	 them match the sender of the probe, or if they are a
	 broadcast packet that should be sent. */
      if(list_length(queued_packets_list) > 0) {
	struct queue_list_item *i;
	for(i = list_head(queued_packets_list); i != NULL; i = i->next) {
	  struct lpp_hdr *qhdr;
	  
	  qhdr = queuebuf_dataptr(i->packet);
	  if(rimeaddr_cmp(&qhdr->receiver, &hdr->sender) ||
	      rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) {
	    queuebuf_to_packetbuf(i->packet);

#if WITH_PENDING_BROADCAST
	    if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
	       i->broadcast_flag == BROADCAST_FLAG_SEND) {
	      radio->send(queuebuf_dataptr(i->packet),
			  queuebuf_datalen(i->packet));
	      PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		     hdr->sender.u8[0], hdr->sender.u8[1],
		     qhdr->receiver.u8[0], qhdr->receiver.u8[1]);
	      
	    } else {
	      PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
		     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		     hdr->sender.u8[0], hdr->sender.u8[1]);
	    }
#else /* WITH_PENDING_BROADCAST */
	    radio->send(queuebuf_dataptr(i->packet),
			queuebuf_datalen(i->packet));
	    PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		   hdr->sender.u8[0], hdr->sender.u8[1],
		   qhdr->receiver.u8[0], qhdr->receiver.u8[1]);
#endif /* WITH_PENDING_BROADCAST */



	    /* Attribute the energy spent on listening for the probe
	       to this packet transmission. */
	    compower_accumulate(&i->compower);
	    
	    /* If the packet was not a broadcast packet, we dequeue it
	       now. Broadcast packets should be transmitted to all
	       neighbors, and are dequeued by the dutycycling function
	       instead, after the appropriate time. */
	    if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) {
	      remove_queued_packet(i);

#if WITH_PROBE_AFTER_TRANSMISSION
	      /* Send a probe packet to catch any reply from the other node. */
	      restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
#endif /* WITH_PROBE_AFTER_TRANSMISSION */

#if WITH_STREAMING
	      if(is_streaming) {
		ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
			   send_stream_probe, NULL);
	      }
#endif /* WITH_STREAMING */
	    }

#if WITH_ACK_OPTIMIZATION
	    if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
	       packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
	      /* We're sending a packet that needs an ACK, so we keep
		 the radio on in anticipation of the ACK. */
	      turn_radio_on();
	    }
#endif /* WITH_ACK_OPTIMIZATION */

	  }
	}
      }

    } else if(hdr->type == TYPE_DATA) {
      if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
        if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) {
          /* Not broadcast or for us */
          PRINTF("%d.%d: data not for us from %d.%d\n",
                 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                 hdr->sender.u8[0], hdr->sender.u8[1]);
          return 0;
        }
        packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver);
      }
      packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender);

      PRINTF("%d.%d: got data from %d.%d\n",
	     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	     hdr->sender.u8[0], hdr->sender.u8[1]);

      /* Accumulate the power consumption for the packet reception. */
      compower_accumulate(&current_packet);
      /* Convert the accumulated power consumption for the received
	 packet to packet attributes so that the higher levels can
	 keep track of the amount of energy spent on receiving the
	 packet. */
      compower_attrconv(&current_packet);
      
      /* Clear the accumulated power consumption so that it is ready
	 for the next packet. */
      compower_clear(&current_packet);

#if WITH_PENDING_BROADCAST
      if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
	/* This is a broadcast packet. Check the list of pending
	   packets to see if we are currently sending a broadcast. If
	   so, we refrain from sending our broadcast until one sleep
	   cycle period, so that the other broadcaster will have
	   finished sending. */
	
	struct queue_list_item *i;
	for(i = list_head(queued_packets_list); i != NULL; i = i->next) {
	  /* If the packet is a broadcast packet that is not yet
	     ready to be sent, we do not send it. */
	  if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
	    PRINTF("Someone else is sending, pending -> waiting\n");
	    set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
	  }
	}
      }
#endif /* WITH_PENDING_BROADCAST */
	    
      
#if WITH_PROBE_AFTER_RECEPTION
      /* XXX send probe after receiving a packet to facilitate data
        streaming. We must first copy the contents of the packetbuf into
        a queuebuf to avoid overwriting the data with the probe packet. */
      if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) {
        struct queuebuf *q;
        q = queuebuf_new_from_packetbuf();
        if(q != NULL) {
	  send_probe();
	  queuebuf_to_packetbuf(q);
          queuebuf_free(q);
        }
      }
#endif /* WITH_PROBE_AFTER_RECEPTION */

#if WITH_ADAPTIVE_OFF_TIME
      off_time = LOWEST_OFF_TIME;
      restart_dutycycle(off_time);
#endif /* WITH_ADAPTIVE_OFF_TIME */
      
    }

    len = packetbuf_datalen();
  }
  return len;
}