void udprand_task(){ OpenQueueEntry_t* pkt; // don't run if not synch if (ieee154e_isSynch() == FALSE) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(udprand_vars.timerId); return; } //prepare packet pkt = openqueue_getFreePacketBuffer(COMPONENT_UDPRAND); if (pkt==NULL) { openserial_printError(COMPONENT_UDPRAND,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } pkt->creator = COMPONENT_UDPRAND; pkt->owner = COMPONENT_UDPRAND; pkt->l4_protocol = IANA_UDP; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_RAND; pkt->l4_destination_port = WKP_UDP_RAND; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],&ipAddr_motedata,16); packetfunctions_reserveHeaderSize(pkt,2); ((uint8_t*)pkt->payload)[0] = openrandom_get16b()%0xff; ((uint8_t*)pkt->payload)[1] = openrandom_get16b()%0xff; //send packet if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
void udpecho_receive(OpenQueueEntry_t* msg) { uint16_t temp_l4_destination_port; OpenQueueEntry_t * pkt = openqueue_getFreePacketBuffer(COMPONENT_UDPECHO); if (pkt==NULL) { openserial_printError(COMPONENT_UDPLATENCY,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } pkt->owner = COMPONENT_UDPECHO; //reply with the same OpenQueueEntry_t pkt->creator = COMPONENT_UDPECHO; pkt->l4_protocol = IANA_UDP; temp_l4_destination_port = msg->l4_destination_port; pkt->l4_destination_port = msg->l4_sourcePortORicmpv6Type; pkt->l4_sourcePortORicmpv6Type = temp_l4_destination_port; pkt->l3_destinationAdd.type = ADDR_128B; //copy source to destination to echo. memcpy(&pkt->l3_destinationAdd.addr_128b[0],&msg->l3_sourceAdd.addr_128b[0],16); packetfunctions_reserveHeaderSize(pkt,msg->length); memcpy(&pkt->payload[0],&msg->payload[0],msg->length); openqueue_freePacketBuffer(msg); if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
/** \brief Send a CoAP request. This function is called by a CoAP resource when it wants to send some data. This function is NOT called for a response. \param[in] msg The message to be sent. This messages should not contain the CoAP header. \param[in] type The CoAP type of the message. \param[in] code The CoAP code of the message. \param[in] TKL The Token Length of the message. \param[out] descSender A pointer to the description of the calling CoAP resource. \post After returning, this function will have written the messageID and TOKEN used in the descSender parameter. \return The outcome of sending the packet. */ owerror_t opencoap_send( OpenQueueEntry_t* msg, coap_type_t type, coap_code_t code, uint8_t TKL, coap_resource_desc_t* descSender ) { // pick a new (global) messageID opencoap_vars.messageID = openrandom_get16b(); // take ownership over the packet msg->owner = COMPONENT_OPENCOAP; // fill in packet metadata msg->l4_sourcePortORicmpv6Type = WKP_UDP_COAP; // pre-pend CoAP header (version,type,TKL,code,messageID,Token) packetfunctions_reserveHeaderSize(msg,5); msg->payload[0] = (COAP_VERSION << 6) | (type << 4) | (TKL << 0); msg->payload[1] = code; msg->payload[2] = (opencoap_vars.messageID>>8) & 0xff; msg->payload[3] = (opencoap_vars.messageID>>0) & 0xff; msg->payload[4] = COAP_TOKEN; // indicate the messageID used to the sender descSender->messageID = opencoap_vars.messageID; descSender->token = COAP_TOKEN; return openudp_send(msg); }
void udplatency_task(){ OpenQueueEntry_t* pkt; open_addr_t * p; open_addr_t q; //prepare packet pkt = openqueue_getFreePacketBuffer(COMPONENT_UDPLATENCY); if (pkt==NULL) { openserial_printError(COMPONENT_UDPLATENCY,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } pkt->creator = COMPONENT_UDPLATENCY; pkt->owner = COMPONENT_UDPLATENCY; pkt->l4_protocol = IANA_UDP; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_LATENCY; pkt->l4_destination_port = WKP_UDP_LATENCY; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],&ipAddr_motedata,16); //the payload contains the 64bit address of the sender + the ASN packetfunctions_reserveHeaderSize(pkt,sizeof(asn_t)); asnWriteToPkt(pkt);//gets asn from mac layer. packetfunctions_reserveHeaderSize(pkt,8); p=idmanager_getMyID(ADDR_64B); pkt->payload[0]=p->addr_64b[0]; pkt->payload[1]=p->addr_64b[1]; pkt->payload[2]=p->addr_64b[2]; pkt->payload[3]=p->addr_64b[3]; pkt->payload[4]=p->addr_64b[4]; pkt->payload[5]=p->addr_64b[5]; pkt->payload[6]=p->addr_64b[6]; pkt->payload[7]=p->addr_64b[7]; neighbors_getPreferredParent(&q,ADDR_64B); if (q.type==ADDR_64B){ packetfunctions_reserveHeaderSize(pkt,8); //copy my preferred parent so we can build the topology pkt->payload[0]=q.addr_64b[0]; pkt->payload[1]=q.addr_64b[1]; pkt->payload[2]=q.addr_64b[2]; pkt->payload[3]=q.addr_64b[3]; pkt->payload[4]=q.addr_64b[4]; pkt->payload[5]=q.addr_64b[5]; pkt->payload[6]=q.addr_64b[6]; pkt->payload[7]=q.addr_64b[7]; } //send packet if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
/** \brief Send a CoAP request. This function is called by a CoAP resource when it wants to send some data. This function is NOT called for a response. \param[in] msg The message to be sent. This messages should not contain the CoAP header. \param[in] type The CoAP type of the message. \param[in] code The CoAP code of the message. \param[in] TKL The Token Length of the message, sanitized to a max of COAP_MAX_TKL (8). \param[out] descSender A pointer to the description of the calling CoAP resource. \post After returning, this function will have written the messageID and TOKEN used in the descSender parameter. \return The outcome of sending the packet. */ owerror_t opencoap_send( OpenQueueEntry_t* msg, coap_type_t type, coap_code_t code, uint8_t TKL, coap_resource_desc_t* descSender ) { uint16_t token; uint8_t tokenPos=0; coap_header_iht* request; // increment the (global) messageID if (opencoap_vars.messageID++ == 0xffff) { opencoap_vars.messageID = 0; } // take ownership over the packet msg->owner = COMPONENT_OPENCOAP; // fill in packet metadata msg->l4_sourcePortORicmpv6Type = WKP_UDP_COAP; // update the last_request header request = &descSender->last_request; request->T = type; request->Code = code; request->messageID = opencoap_vars.messageID; request->TKL = TKL<COAP_MAX_TKL ? TKL : COAP_MAX_TKL; while (tokenPos<request->TKL) { token = openrandom_get16b(); memcpy(&request->token[tokenPos],&token,2); tokenPos+=2; } // pre-pend CoAP header (version,type,TKL,code,messageID,Token) packetfunctions_reserveHeaderSize(msg,4+request->TKL); msg->payload[0] = (COAP_VERSION << 6) | (type << 4) | (request->TKL << 0); msg->payload[1] = code; msg->payload[2] = (request->messageID>>8) & 0xff; msg->payload[3] = (request->messageID>>0) & 0xff; memcpy(&msg->payload[4],&token,request->TKL); return openudp_send(msg); }
void uinject_task_cb() { OpenQueueEntry_t* pkt; // don't run if not synch if (ieee154e_isSynch() == FALSE) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(uinject_vars.timerId); return; } // if you get here, send a packet // get a free packet buffer pkt = openqueue_getFreePacketBuffer(COMPONENT_UINJECT); if (pkt==NULL) { openserial_printError( COMPONENT_UINJECT, ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0 ); return; } pkt->owner = COMPONENT_UINJECT; pkt->creator = COMPONENT_UINJECT; pkt->l4_protocol = IANA_UDP; pkt->l4_destination_port = WKP_UDP_INJECT; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_INJECT; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],uinject_dst_addr,16); packetfunctions_reserveHeaderSize(pkt,sizeof(uint16_t)); *((uint16_t*)&pkt->payload[0]) = uinject_vars.counter++; if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
void udpinject_trigger() { OpenQueueEntry_t* pkt; uint8_t number_bytes_from_input_buffer; uint8_t input_buffer[18]; //get command from OpenSerial (16B IPv6 destination address, 2B destination port) number_bytes_from_input_buffer = openserial_getInputBuffer(&(input_buffer[0]),sizeof(input_buffer)); if (number_bytes_from_input_buffer!=sizeof(input_buffer)) { openserial_printError(COMPONENT_UDPINJECT,ERR_INPUTBUFFER_LENGTH, (errorparameter_t)number_bytes_from_input_buffer, (errorparameter_t)0); return; }; //prepare packet pkt = openqueue_getFreePacketBuffer(COMPONENT_UDPINJECT); if (pkt==NULL) { openserial_printError(COMPONENT_UDPINJECT,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } pkt->creator = COMPONENT_UDPINJECT; pkt->owner = COMPONENT_UDPINJECT; pkt->l4_protocol = IANA_UDP; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_INJECT; pkt->l4_destination_port = packetfunctions_ntohs(&(input_buffer[16])); pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&(pkt->l3_destinationAdd.addr_128b[0]),&(input_buffer[0]),16); packetfunctions_reserveHeaderSize(pkt,6); ((uint8_t*)pkt->payload)[0] = 'p'; ((uint8_t*)pkt->payload)[1] = 'o'; ((uint8_t*)pkt->payload)[2] = 'i'; ((uint8_t*)pkt->payload)[3] = 'p'; ((uint8_t*)pkt->payload)[4] = 'o'; ((uint8_t*)pkt->payload)[5] = 'i'; //send packet if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
void uecho_receive(OpenMote* self, OpenQueueEntry_t* request) { uint16_t temp_l4_destination_port; OpenQueueEntry_t* reply; reply = openqueue_getFreePacketBuffer(self, COMPONENT_UECHO); if (reply==NULL) { openserial_printError(self, COMPONENT_UECHO, ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0 ); openqueue_freePacketBuffer(self, request); //clear the request packet as well return; } reply->owner = COMPONENT_UECHO; // reply with the same OpenQueueEntry_t reply->creator = COMPONENT_UECHO; reply->l4_protocol = IANA_UDP; temp_l4_destination_port = request->l4_destination_port; reply->l4_destination_port = request->l4_sourcePortORicmpv6Type; reply->l4_sourcePortORicmpv6Type = temp_l4_destination_port; reply->l3_destinationAdd.type = ADDR_128B; // copy source to destination to echo. memcpy(&reply->l3_destinationAdd.addr_128b[0],&request->l3_sourceAdd.addr_128b[0],16); packetfunctions_reserveHeaderSize(self, reply,request->length); memcpy(&reply->payload[0],&request->payload[0],request->length); openqueue_freePacketBuffer(self, request); if (( openudp_send(self, reply))==E_FAIL) { openqueue_freePacketBuffer(self, reply); } }
/** \brief Indicate a CoAP messages was received. A "CoAP message" is simply a UDP datagram received on the CoAP UDP port. This function will call the appropriate resource, and send back its answer. The received packetbuffer is reused to contain the response (or error code). \param[in] msg The received CoAP message. */ void opencoap_receive(OpenQueueEntry_t* msg) { uint16_t temp_l4_destination_port; uint8_t i; uint8_t index; coap_option_t last_option; coap_resource_desc_t* temp_desc; bool found; owerror_t outcome; // local variables passed to the handlers (with msg) coap_header_iht coap_header; coap_option_iht coap_options[MAX_COAP_OPTIONS]; // take ownership over the received packet msg->owner = COMPONENT_OPENCOAP; //=== step 1. parse the packet // parse the CoAP header and remove from packet index = 0; coap_header.Ver = (msg->payload[index] & 0xc0) >> 6; coap_header.T = (coap_type_t)((msg->payload[index] & 0x30) >> 4); coap_header.TKL = (msg->payload[index] & 0x0f); index++; coap_header.Code = (coap_code_t)(msg->payload[index]); index++; coap_header.messageID = msg->payload[index]*256+msg->payload[index+1]; index+=2; // reject unsupported header if (coap_header.Ver!=COAP_VERSION || coap_header.TKL>COAP_MAX_TKL) { openserial_printError( COMPONENT_OPENCOAP,ERR_WRONG_TRAN_PROTOCOL, (errorparameter_t)0, (errorparameter_t)coap_header.Ver ); openqueue_freePacketBuffer(msg); return; } // record the token memcpy(&coap_header.token[0], &msg->payload[index], coap_header.TKL); index += coap_header.TKL; // initialize the coap_options for (i=0;i<MAX_COAP_OPTIONS;i++) { coap_options[i].type = COAP_OPTION_NONE; } // fill in the coap_options last_option = COAP_OPTION_NONE; for (i=0;i<MAX_COAP_OPTIONS;i++) { // detect when done parsing options if (msg->payload[index]==COAP_PAYLOAD_MARKER){ // found the payload marker, done parsing options. index++; // skip marker and stop parsing options break; } // parse this option coap_options[i].type = (coap_option_t)((uint8_t)last_option+(uint8_t)((msg->payload[index] & 0xf0) >> 4)); last_option = coap_options[i].type; coap_options[i].length = (msg->payload[index] & 0x0f); index++; coap_options[i].pValue = &(msg->payload[index]); index += coap_options[i].length; //includes length as well } // remove the CoAP header+options packetfunctions_tossHeader(msg,index); //=== step 2. find the resource to handle the packet // find the resource this applies to found = FALSE; if ( coap_header.Code>=COAP_CODE_REQ_GET && coap_header.Code<=COAP_CODE_REQ_DELETE ) { // this is a request: target resource is indicated as COAP_OPTION_LOCATIONPATH option(s) // find the resource which matches // start with the first resource in the linked list temp_desc = opencoap_vars.resources; // iterate until matching resource found, or no match while (found==FALSE) { if ( coap_options[0].type==COAP_OPTION_NUM_URIPATH && coap_options[1].type==COAP_OPTION_NUM_URIPATH && temp_desc->path0len>0 && temp_desc->path0val!=NULL && temp_desc->path1len>0 && temp_desc->path1val!=NULL ) { // resource has a path of form path0/path1 if ( coap_options[0].length==temp_desc->path0len && memcmp(coap_options[0].pValue,temp_desc->path0val,temp_desc->path0len)==0 && coap_options[1].length==temp_desc->path1len && memcmp(coap_options[1].pValue,temp_desc->path1val,temp_desc->path1len)==0 ) { found = TRUE; }; } else if ( coap_options[0].type==COAP_OPTION_NUM_URIPATH && temp_desc->path0len>0 && temp_desc->path0val!=NULL ) { // resource has a path of form path0 if ( coap_options[0].length==temp_desc->path0len && memcmp(coap_options[0].pValue,temp_desc->path0val,temp_desc->path0len)==0 ) { found = TRUE; }; }; // iterate to next resource, if not found if (found==FALSE) { if (temp_desc->next!=NULL) { temp_desc = temp_desc->next; } else { break; } } } } else { // this is a response: target resource is indicated by message ID // find the resource which matches // start with the first resource in the linked list temp_desc = opencoap_vars.resources; // iterate until matching resource found, or no match while (found==FALSE) { if (coap_header.messageID==temp_desc->messageID) { found=TRUE; // call the resource's callback if (temp_desc->callbackRx!=NULL) { temp_desc->callbackRx(msg,&coap_header,&coap_options[0]); } } // iterate to next resource, if not found if (found==FALSE) { if (temp_desc->next!=NULL) { temp_desc = temp_desc->next; } else { break; } } }; // free the received packet openqueue_freePacketBuffer(msg); // stop here: will will not respond to a response return; } //=== step 3. ask the resource to prepare response if (found==TRUE) { // call the resource's callback outcome = temp_desc->callbackRx(msg,&coap_header,&coap_options[0]); } else { // reset packet payload (DO NOT DELETE, we will reuse same buffer for response) msg->payload = &(msg->packet[127]); msg->length = 0; // set the CoAP header coap_header.TKL = 0; coap_header.Code = COAP_CODE_RESP_NOTFOUND; } if (outcome==E_FAIL) { // reset packet payload (DO NOT DELETE, we will reuse same buffer for response) msg->payload = &(msg->packet[127]); msg->length = 0; // set the CoAP header coap_header.TKL = 0; coap_header.Code = COAP_CODE_RESP_METHODNOTALLOWED; } //=== step 4. send that packet back // fill in packet metadata if (found==TRUE) { msg->creator = temp_desc->componentID; } else { msg->creator = COMPONENT_OPENCOAP; } msg->l4_protocol = IANA_UDP; temp_l4_destination_port = msg->l4_destination_port; msg->l4_destination_port = msg->l4_sourcePortORicmpv6Type; msg->l4_sourcePortORicmpv6Type = temp_l4_destination_port; // set destination address as the current source msg->l3_destinationAdd.type = ADDR_128B; memcpy(&msg->l3_destinationAdd.addr_128b[0],&msg->l3_sourceAdd.addr_128b[0],LENGTH_ADDR128b); // fill in CoAP header packetfunctions_reserveHeaderSize(msg,4+coap_header.TKL); msg->payload[0] = (COAP_VERSION << 6) | (COAP_TYPE_ACK << 4) | (coap_header.TKL << 0); msg->payload[1] = coap_header.Code; msg->payload[2] = coap_header.messageID/256; msg->payload[3] = coap_header.messageID%256; memcpy(&msg->payload[4], &coap_header.token[0], coap_header.TKL); if ((openudp_send(msg))==E_FAIL) { openqueue_freePacketBuffer(msg); } }
void bbk_task_cb() { OpenQueueEntry_t* pkt; error_t outcome; uint8_t numOptions; demo_t demoPayload; // create a CoAP RD packet pkt = openqueue_getFreePacketBuffer(0xcc); if (pkt==NULL) { openserial_printError(0xcc,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); openqueue_freePacketBuffer(pkt); return; } // take ownership over that packet pkt->creator = COMPONENT_BBK; //just a number randomly picked for this temp app pkt->owner = COMPONENT_BBK; // CoAP payload packetfunctions_reserveHeaderSize(pkt,sizeof(demo_t)); construct_demo(&demoPayload); memcpy((pkt->payload),&demoPayload,sizeof(demo_t)); numOptions = 0; // location-path option packetfunctions_reserveHeaderSize(pkt,sizeof(bbk_path0)-1); memcpy(&pkt->payload[0],&bbk_path0,sizeof(bbk_path0)-1); packetfunctions_reserveHeaderSize(pkt,1); pkt->payload[0] = (COAP_OPTION_LOCATIONPATH-COAP_OPTION_CONTENTTYPE) << 4 | sizeof(bbk_path0)-1; numOptions++; // content-type option packetfunctions_reserveHeaderSize(pkt,2); pkt->payload[0] = COAP_OPTION_CONTENTTYPE << 4 | 1; pkt->payload[1] = COAP_MEDTYPE_APPOCTETSTREAM; numOptions++; // metadata //pkt->l4_destination_port = WKP_UDP_COAP; pkt->l4_destination_port = WKP_UDP_HDL; pkt->l3_destinationORsource.type = ADDR_128B; memcpy(&pkt->l3_destinationORsource.addr_128b[0],&ipAddr_local,16); // send if(bbk_vars.sequence<SAMPLE){ bbk_vars.sequence++; /*outcome = opencoap_send(pkt, COAP_TYPE_NON, COAP_CODE_REQ_PUT, numOptions, &bbk_vars.desc);*/ outcome = openudp_send(pkt); //call UDP directly bypassing CoAP } else{ opentimers_stop(bbk_vars.timerId); bbk_vars.sequence=0; openqueue_freePacketBuffer(pkt); } // avoid overflowing the queue if fails if (outcome==E_FAIL) { openqueue_freePacketBuffer(pkt); } return; }