⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dymopacketm.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin@gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "dymo_packet.h"

/**
 * DymoPacketM - Implementation of the DYMO packets format.
 *
 * @author Romain Thouvenin
 */

module DymoPacketM {
  provides {
    interface DymoPacket;
    interface PacketMaker; //For tests and debugging
  }
  uses interface Packet;
}
//TODO generalize size values
implementation {
  message_t * currentMsg;
  message_t * processedMsg;

  /* Local functions */
  void    create_block(nx_uint8_t * payload, const rt_info_t * info);
  uint8_t block_size(nx_uint8_t * block);
  uint8_t block_info_size(nx_uint8_t * block);
  uint8_t block_header_size(nx_uint8_t * block);
  uint8_t block_num_addr(nx_uint8_t * block);
  void    block_get_info(nx_uint8_t * block, uint8_t pos, rt_info_t * info, bool update);
  nx_uint8_t * block_get_pointer(nx_uint8_t * block, uint8_t pos, uint8_t * size);
  bool block_can_contain(nx_uint8_t * block, const rt_info_t * info);
  void block_add_info(nx_uint8_t * block, const rt_info_t * info);
  void move_data(nx_uint8_t * data, uint8_t amount, uint8_t offset);


  /*****************
   * Packet header *
   *****************/

  command dymo_msg_t DymoPacket.getType(message_t * msg){
    nx_uint8_t * p = call Packet.getPayload(msg, 1);
    return *p;
  }

  command uint16_t DymoPacket.getSize(message_t * msg){
    nx_uint8_t * p = call Packet.getPayload(msg, 3);
    return *(nx_uint16_t *)(p + 1);
  }


  /*********************
   * Creating a packet *
   *********************/

  command void DymoPacket.createRM(message_t * msg, dymo_msg_t msg_type, 
			const rt_info_t * origin, const rt_info_t * target){
    nx_uint8_t * payload = call Packet.getPayload(msg, call Packet.maxPayloadLength());
    nx_uint16_t * size_p;
    *(payload++) = msg_type;
    size_p = (nx_uint16_t *) payload;
    payload += 2;
    *(payload++) = DYMO_HOPLIMIT;
    *(payload++) = 0;

    create_block(payload, target);
   
    if(origin){
      if(block_can_contain(payload, origin)){
	block_add_info(payload, origin);
	*size_p = block_size(payload);
      } else {
	*size_p = block_size(payload);
	payload += *size_p;
	create_block(payload, origin);
	*size_p += block_size(payload);
      }
    } else {
      *size_p = block_size(payload);
    }

    //size of msg header
    //it is here to save a few instructions or a byte
    *size_p += 5; 
  }

  command error_t DymoPacket.addInfo(message_t * msg, const rt_info_t * info){
    nx_uint8_t * payload = call Packet.getPayload(msg, call Packet.maxPayloadLength());
    nx_uint16_t * size_p = (nx_uint16_t *)(payload + 1);
    nx_uint8_t * block = payload + 5;
    uint8_t bsize;

    while(block < payload + *size_p){
      //We don't want to add something before the origin
      if ( ((block > payload + 5) && block_can_contain(block, info))
	   || ((block == payload + 5) && (block_num_addr(block) > 1)) ) {

	uint8_t isize = block_info_size(block);
	if(*size_p + isize > call Packet.maxPayloadLength()){
	  return ESIZE;
	} else {
	  bsize = block_size(block);
	  move_data(block + bsize, payload + *size_p - (block + bsize), isize);
	  block_add_info(block, info);
	  *size_p += isize;
	  return SUCCESS;
	}

      } else {
	block += block_size(block);
      }
    }

    create_block(block, info);
    bsize = block_size(block);
    if(*size_p +  bsize > call Packet.maxPayloadLength()){
      return ESIZE;
    } else {
      *size_p += bsize;
      return SUCCESS;
    }
  }


  /***********************
   * Processing a packet *
   ***********************/

  task void processMessage(){
    nx_uint8_t * payload = call Packet.getPayload(currentMsg, call Packet.maxPayloadLength());
    nx_uint8_t * end = payload + *(nx_uint16_t *)(payload+1);
    nx_uint8_t * fw_payload = NULL;
    nx_uint16_t * fw_size = NULL;
    nx_uint8_t *fw_block, *info_p;
    rt_info_t info;
    uint8_t i,n,s;
    bool first_block = 1;
    proc_action_t action;

    payload += 3;
    *(payload++) -= 1; //decr hopL
    *(payload++) += 1; //incr hopC
    action = signal DymoPacket.hopsProcessed(currentMsg, *(payload-2), *(payload-1));
    if(processedMsg){
      if(action != ACTION_DISCARD_MSG){
	fw_payload = call Packet.getPayload(processedMsg, call Packet.maxPayloadLength());
	memcpy(fw_payload, payload - 5, 5);
	fw_size = (nx_uint16_t *)(fw_payload + 1);
	*fw_size = 5;
	fw_payload += 5;
      } else {
	processedMsg = NULL;
      }
    }

    while(payload < end){
      fw_block = NULL;
      n = block_num_addr(payload);

      for(i=0;i<n;i++){
	block_get_info(payload, i, &info, !first_block || i);
	action = signal DymoPacket.infoProcessed(currentMsg, &info);

	if(processedMsg){
	  switch(action){
	  case ACTION_KEEP:
	    if(!fw_block){
	      s = block_header_size(payload);
	      memcpy(fw_payload, payload, s);
	      fw_block = fw_payload;
	      *(fw_block+1) = 0;
	      fw_payload += s;
	    }
	    info_p = block_get_pointer(payload, i, &s);
	    memcpy(fw_payload, info_p, s);
	    fw_payload += s;
	    *(fw_block+1) += 1; //increments NumAddr
	    break;

	  case ACTION_DISCARD_MSG:
	    processedMsg = NULL;
	  default:
	  }
	}//if

      }//for
      payload += block_size(payload);
      first_block = 0;
      if(fw_block)
	*fw_size += block_size(fw_block);
    }
    
    signal DymoPacket.messageProcessed(currentMsg);
  }

  command void DymoPacket.startProcessing(message_t * msg, message_t * newmsg){
    currentMsg = msg;
    processedMsg = newmsg;
    post processMessage();
  }



  //TODO return block_size, it is always needed after a block creation
  void create_block(nx_uint8_t * payload, const rt_info_t * info){
    uint8_t semantics;

    semantics = BLOCK_HEAD;
    if(info->seqnum)
      semantics |= BLOCK_SEQNUM;
    if(info->has_hopcnt)
      semantics |= BLOCK_HOPCNT;

    *(payload++) = semantics;
    *(payload++) = 1;
    *(nx_addr_t *)payload = info->address;
    payload += sizeof(addr_t);
    if(info->seqnum){
      *(nx_seqnum_t *)payload = info->seqnum;
      payload += 2;
    }
    if(info->has_hopcnt){
      *(payload++) = info->hopcnt;
    }
  }

  void block_add_info(nx_uint8_t * block, const rt_info_t * info){
    uint8_t semantics = *block;
    nx_uint8_t * size_p = block + 1;
    block += block_size(block);
    *size_p += 1;
    if(semantics & BLOCK_HEAD){
      *block = info->address % 256;
      block++;
    } else {
      *(nx_addr_t *)block = info->address;
      block += sizeof(addr_t);
    }

    if(semantics & BLOCK_SEQNUM){
      *(nx_seqnum_t *)block = info->seqnum;
      block += sizeof(seqnum_t);
    }

    if(semantics & BLOCK_HOPCNT){
      *block = info->hopcnt;
    }
  }

  bool block_can_contain(nx_uint8_t * block, const rt_info_t * info){
    if( (*block & BLOCK_SEQNUM) && !info->seqnum )
      return 0;
    if( !(*block & BLOCK_SEQNUM) && info->seqnum )
      return 0;

    if( (*block & BLOCK_HOPCNT) && !info->has_hopcnt )
      return 0;
    if( !(*block & BLOCK_HOPCNT) && info->has_hopcnt )
      return 0;

    if( (*block & BLOCK_HEAD) && (*(block + 2) != (info->address / 256)) )
      return 0;

    return 1;
  }

  uint8_t block_info_size(nx_uint8_t * block){
    uint8_t result = 1;
    if(!(*block & BLOCK_HEAD))
      result++;
    if(*block & BLOCK_SEQNUM)
      result += 2;
    if(*block & BLOCK_HOPCNT)
      result++;
    //TODO add max age
    return result;
  }

  uint8_t block_header_size(nx_uint8_t * block){
    if(*block & BLOCK_HEAD)
      return 3;
    else
      return 2;
  }

  uint8_t block_num_addr(nx_uint8_t * block){
    return *(block + 1);
  }

  uint8_t block_size(nx_uint8_t * block){
    uint8_t result = 2;
    if(*block & BLOCK_HEAD){
      result++;
    }
    return result + block_num_addr(block) * block_info_size(block);
  }

  nx_uint8_t * block_get_pointer(nx_uint8_t * block, uint8_t pos, uint8_t * size){
    if(size){
      *size = block_info_size(block);
      return block + block_header_size(block) + pos * (*size);
    } else {
      return block + block_header_size(block) + pos * block_info_size(block);
    }
  }

  void block_get_info(nx_uint8_t * block, uint8_t pos, rt_info_t * info, bool update){
    nx_uint8_t * semantics = block;
    block = block_get_pointer(block, pos, NULL);
    
    if(*semantics & BLOCK_HEAD){
      info->address = *(semantics + 2) * 256 + *block;
      block++;
    } else {
      info->address = *(nx_addr_t *)block;
      block += sizeof(addr_t);
    }

    if(*semantics & BLOCK_SEQNUM){
      info->seqnum = *(nx_seqnum_t *)block;
      block += sizeof(seqnum_t);
    } else {
      info->seqnum = 0;
    }

    if(*semantics & BLOCK_HOPCNT){
      info->has_hopcnt = 1;
      if(update)
	*block += 1;
      info->hopcnt = *block;
      block++;
    } else {
      info->has_hopcnt = 0;
    }
  }

  void move_data(nx_uint8_t * data, uint8_t amount, uint8_t offset){
    nx_uint8_t * newdata = data + amount + offset;
    data += amount;
    for(; amount > 0; amount--)
      *--newdata = *--data;
  }


  /**************
   * PakerMaker *
   **************/

  command uint16_t PacketMaker.getSize(message_t * msg){
    return call DymoPacket.getSize(msg);
  }

  command void PacketMaker.createRM(message_t * msg, dymo_msg_t msg_type, 
				   const rt_info_t * origin, const rt_info_t * target){
    call DymoPacket.createRM(msg, msg_type, origin, target);
  }

  command error_t PacketMaker.addInfo(message_t * msg, const rt_info_t * info){
    return call DymoPacket.addInfo(msg, info);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -