list * list_distinct2(list *l, void *data, fcmp2 cmp, fdup dup) { list *res = list_new_(l); node *n = NULL; for (n = l->h; n; n = n->next) { if (!list_find2(res, data, n->data, cmp)) { list_append(res, dup?dup(n->data):n->data); } } return res; }
void udp_error(struct fins_module *module, struct finsFrame *ff) { PRINT_DEBUG("Entered: module=%p, ff=%p, meta=%p", module, ff, ff->metaData); struct udp_data *md = (struct udp_data *) module->data; //uint32_t src_ip; //uint32_t src_port; //uint32_t dst_ip; //uint32_t dst_port; //uint32_t udp_len; //uint32_t checksum; switch (ff->ctrlFrame.param_id) { case UDP_ERROR_TTL: PRINT_DEBUG("param_id=UDP_ERROR_TTL (%d)", ff->ctrlFrame.param_id); /* struct udp_packet *udp_hdr = (struct udp_packet *) ff->ctrlFrame.data; struct udp_header hdr; hdr.u_src = ntohs(udp_hdr->u_src); hdr.u_dst = ntohs(udp_hdr->u_dst); hdr.u_len = ntohs(udp_hdr->u_len); hdr.u_cksum = ntohs(udp_hdr->u_cksum); */ //if recv_dst_ip==send_src_ip, recv_dst_port==send_src_port, recv_udp_len==, recv_checksum==, \\should be unique! if (list_is_empty(md->sent_packet_list)) { PRINT_WARN("todo error"); //TODO drop freeFinsFrame(ff); } else { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { //TODO make func!! struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { metadata_copy(sent->ff->metaData, ff->metaData); ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_TTL; //TODO error msg code //ERROR_UDP_TTL? ff->ctrlFrame.data_len = sent->ff->dataFrame.pduLength; ff->ctrlFrame.data = sent->ff->dataFrame.pdu; sent->ff->dataFrame.pdu = NULL; if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } list_remove(md->sent_packet_list, sent); udp_sent_free(sent); PRINT_DEBUG("Freeing: pdu=%p", pdu); free(pdu); } else { PRINT_WARN("todo error"); freeFinsFrame(ff); //TODO drop? } } else { PRINT_WARN("todo"); freeFinsFrame(ff); } } break; case UDP_ERROR_DEST_UNREACH: PRINT_DEBUG("param_id=UDP_ERROR_DEST_UNREACH (%d)", ff->ctrlFrame.param_id); if (list_is_empty(md->sent_packet_list)) { PRINT_WARN("todo error"); //TODO drop freeFinsFrame(ff); } else { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { metadata_copy(sent->ff->metaData, ff->metaData); ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_DEST_UNREACH; //TODO error msg code //ERROR_UDP_TTL? ff->ctrlFrame.data_len = sent->ff->dataFrame.pduLength; ff->ctrlFrame.data = sent->ff->dataFrame.pdu; sent->ff->dataFrame.pdu = NULL; if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } list_remove(md->sent_packet_list, sent); udp_sent_free(sent); PRINT_DEBUG("Freeing: pdu=%p", pdu); free(pdu); } else { PRINT_WARN("todo error"); //TODO drop? freeFinsFrame(ff); } } else { PRINT_WARN("todo"); freeFinsFrame(ff); } } break; case UDP_ERROR_GET_ADDR: PRINT_DEBUG("param_id=UDP_ERROR_GET_ADDR (%d)", ff->ctrlFrame.param_id); if (!list_is_empty(md->sent_packet_list)) { uint8_t *pdu = ff->ctrlFrame.data; if (pdu != NULL) { //TODO make func!! struct udp_sent *sent = (struct udp_sent *) list_find2(md->sent_packet_list, udp_sent_match_test, &ff->ctrlFrame.data_len, pdu); if (sent != NULL) { list_remove(md->sent_packet_list, sent); udp_sent_free(sent); } } } ff->ctrlFrame.sender_id = module->index; //ff->ctrlFrame.param_id = UDP_ERROR_GET_ADDR; //TODO error msg code //ERROR_UDP_TTL? if (!module_send_flow(module, ff, UDP_FLOW_DAEMON)) { PRINT_WARN("todo error"); freeFinsFrame(ff); } break; default: PRINT_ERROR("Error unknown param_id=%d", ff->ctrlFrame.param_id); PRINT_WARN("todo error"); freeFinsFrame(ff); break; } }