int gnrc_conn_recvfrom(conn_t *conn, void *data, size_t max_len, void *addr, size_t *addr_len, uint16_t *port) { msg_t msg; int timeout = 3; while ((timeout--) > 0) { gnrc_pktsnip_t *pkt, *l3hdr; size_t size = 0; msg_receive(&msg); switch (msg.type) { case GNRC_NETAPI_MSG_TYPE_RCV: pkt = (gnrc_pktsnip_t *)msg.content.ptr; if (pkt->size > max_len) { return -ENOMEM; } LL_SEARCH_SCALAR(pkt, l3hdr, type, conn->l3_type); if (l3hdr == NULL) { msg_send_to_self(&msg); /* requeue invalid messages */ continue; } #if defined(MODULE_CONN_UDP) || defined(MODULE_CONN_TCP) if ((conn->l4_type != GNRC_NETTYPE_UNDEF) && (port != NULL)) { gnrc_pktsnip_t *l4hdr; LL_SEARCH_SCALAR(pkt, l4hdr, type, conn->l4_type); if (l4hdr == NULL) { msg_send_to_self(&msg); /* requeue invalid messages */ continue; } *port = byteorder_ntohs(((udp_hdr_t *)l4hdr->data)->src_port); } #endif /* defined(MODULE_CONN_UDP) */ if (addr != NULL) { memcpy(addr, &((ipv6_hdr_t *)l3hdr->data)->src, sizeof(ipv6_addr_t)); *addr_len = sizeof(ipv6_addr_t); } memcpy(data, pkt->data, pkt->size); size = pkt->size; gnrc_pktbuf_release(pkt); return (int)size; default: (void)port; msg_send_to_self(&msg); /* requeue invalid messages */ break; } } return -ETIMEDOUT; }
int msg_try_send(msg_t *m, kernel_pid_t target_pid) { if (irq_is_in()) { return msg_send_int(m, target_pid); } if (sched_active_pid == target_pid) { return msg_send_to_self(m); } return _msg_send(m, target_pid, false, irq_disable()); }
int msg_send(msg_t *m, kernel_pid_t target_pid) { if (inISR()) { return msg_send_int(m, target_pid); } if (sched_active_pid == target_pid) { return msg_send_to_self(m); } return _msg_send(m, target_pid, true, disableIRQ()); }
int msg_send(msg_t *m, unsigned int target_pid, bool block) { if (inISR()) { return msg_send_int(m, target_pid); } if ((unsigned int)sched_active_pid == target_pid) { return msg_send_to_self(m); } dINT(); tcb_t *target = (tcb_t*) sched_threads[target_pid]; m->sender_pid = sched_active_pid; if (target == NULL) { DEBUG("msg_send(): target thread does not exist\n"); eINT(); return -1; } DEBUG("msg_send() %s:%i: Sending from %i to %i. block=%i src->state=%i target->state=%i\n", __FILE__, __LINE__, sched_active_pid, target_pid, block, sched_active_thread->status, target->status); if (target->status != STATUS_RECEIVE_BLOCKED) { DEBUG("msg_send() %s:%i: Target %i is not RECEIVE_BLOCKED.\n", __FILE__, __LINE__, target_pid); if (target->msg_array && queue_msg(target, m)) { DEBUG("msg_send() %s:%i: Target %i has a msg_queue. Queueing message.\n", __FILE__, __LINE__, target_pid); eINT(); if (sched_active_thread->status == STATUS_REPLY_BLOCKED) { thread_yield(); } return 1; } if (!block) { DEBUG("msg_send: %s: Receiver not waiting, block=%u\n", sched_active_thread->name, block); eINT(); return 0; } DEBUG("msg_send: %s: send_blocked.\n", sched_active_thread->name); queue_node_t n; n.priority = sched_active_thread->priority; n.data = (unsigned int) sched_active_thread; n.next = NULL; DEBUG("msg_send: %s: Adding node to msg_waiters:\n", sched_active_thread->name); queue_priority_add(&(target->msg_waiters), &n); sched_active_thread->wait_data = (void*) m; int newstatus; if (sched_active_thread->status == STATUS_REPLY_BLOCKED) { newstatus = STATUS_REPLY_BLOCKED; } else { newstatus = STATUS_SEND_BLOCKED; } sched_set_status((tcb_t*) sched_active_thread, newstatus); DEBUG("msg_send: %s: Back from send block.\n", sched_active_thread->name); } else { DEBUG("msg_send: %s: Direct msg copy from %i to %i.\n", sched_active_thread->name, thread_getpid(), target_pid); /* copy msg to target */ msg_t *target_message = (msg_t*) target->wait_data; *target_message = *m; sched_set_status(target, STATUS_PENDING); } eINT(); thread_yield(); return 1; }
void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) { assert(ctx != NULL); gnrc_sixlowpan_msg_frag_t *fragment_msg = ctx; gnrc_netif_t *iface = gnrc_netif_get_by_pid(fragment_msg->pid); uint16_t res; /* payload_len: actual size of the packet vs * datagram_size: size of the uncompressed IPv6 packet */ size_t payload_len = gnrc_pkt_len(fragment_msg->pkt->next); msg_t msg; assert((fragment_msg->pkt == pkt) || (pkt == NULL)); (void)page; (void)pkt; #if defined(DEVELHELP) && ENABLE_DEBUG if (iface == NULL) { DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n"); /* remove original packet from packet buffer */ gnrc_pktbuf_release(fragment_msg->pkt); /* 6LoWPAN free for next fragmentation */ fragment_msg->pkt = NULL; return; } #endif /* Check whether to send the first or an Nth fragment */ if (fragment_msg->offset == 0) { /* increment tag for successive, fragmented datagrams */ _tag++; if ((res = _send_1st_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size)) == 0) { /* error sending first fragment */ DEBUG("6lo frag: error sending 1st fragment\n"); gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; return; } fragment_msg->offset += res; /* send message to self*/ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = (void *)fragment_msg; msg_send_to_self(&msg); thread_yield(); } else { /* (offset + (datagram_size - payload_len) < datagram_size) simplified */ if (fragment_msg->offset < payload_len) { if ((res = _send_nth_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size, fragment_msg->offset)) == 0) { /* error sending subsequent fragment */ DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16 ")\n", fragment_msg->offset); gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; return; } fragment_msg->offset += res; /* send message to self*/ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = (void *)fragment_msg; msg_send_to_self(&msg); thread_yield(); } else { gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; } } }
static void _send(gnrc_pktsnip_t *pkt) { gnrc_netif_hdr_t *hdr; gnrc_pktsnip_t *pkt2; gnrc_netif_t *iface; /* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */ size_t datagram_size; if ((pkt == NULL) || (pkt->size < sizeof(gnrc_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); gnrc_pktbuf_release(pkt); return; } if ((pkt->next == NULL) || (pkt->next->type != GNRC_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); gnrc_pktbuf_release(pkt); return; } pkt2 = gnrc_pktbuf_start_write(pkt); if (pkt2 == NULL) { DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return; } hdr = pkt2->data; iface = gnrc_netif_get_by_pid(hdr->if_pid); datagram_size = gnrc_pkt_len(pkt2->next); if (iface == NULL) { DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n"); gnrc_pktbuf_release(pkt); return; } #ifdef MODULE_GNRC_SIXLOWPAN_IPHC if (iface->flags & GNRC_NETIF_FLAGS_6LO_HC) { if (!gnrc_sixlowpan_iphc_encode(pkt2)) { DEBUG("6lo: error on IPHC encoding\n"); gnrc_pktbuf_release(pkt2); return; } /* IPHC dispatch does not count on dispatch length since it _shortens_ * the datagram */ } else { if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt2); return; } } #else /* suppress clang-analyzer report about iface being not read */ (void) iface; if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt2); return; } #endif DEBUG("6lo: iface->sixlo.max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", iface->sixlo.max_frag_size, hdr->if_pid); /* IP should not send anything here if it is not a 6LoWPAN interface, * so we don't need to check for NULL pointers. * Note, that datagram_size cannot be used here, because the header size * might be changed by IPHC. */ if (gnrc_pkt_len(pkt2->next) <= iface->sixlo.max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt2, hdr->if_pid); if (gnrc_netapi_send(hdr->if_pid, pkt2) < 1) { DEBUG("6lo: unable to send %p over %" PRIu16 "\n", (void *)pkt, hdr->if_pid); gnrc_pktbuf_release(pkt2); } return; } #ifdef MODULE_GNRC_SIXLOWPAN_FRAG else if (fragment_msg.pkt != NULL) { DEBUG("6lo: Fragmentation already ongoing. Dropping packet\n"); gnrc_pktbuf_release(pkt2); return; } else if (datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); msg_t msg; fragment_msg.pid = hdr->if_pid; fragment_msg.pkt = pkt2; fragment_msg.datagram_size = datagram_size; /* Sending the first fragment has an offset==0 */ fragment_msg.offset = 0; /* set the outgoing message's fields */ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = &fragment_msg; /* send message to self */ msg_send_to_self(&msg); } else { DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, (uint16_t)SIXLOWPAN_FRAG_MAX_LEN); gnrc_pktbuf_release(pkt2); } #else (void) datagram_size; DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); gnrc_pktbuf_release(pkt2); #endif }