📄 dymopacketm.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 valuesimplementation { 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 + -