static void test_sock_udp_create__EADDRINUSE(void) { static const sock_udp_ep_t local = { .family = AF_INET6, .port = _TEST_PORT_LOCAL }; assert(0 == sock_udp_create(&_sock, &local, NULL, 0)); assert(-EADDRINUSE == sock_udp_create(&_sock2, &local, NULL, 0)); }
static void test_sock_udp_create__EAFNOSUPPORT(void) { /* port may not be NULL according to doc */ static const sock_udp_ep_t local = { .family = AF_UNSPEC, .port = _TEST_PORT_LOCAL }; /* port may not be NULL according to doc */ static const sock_udp_ep_t remote = { .family = AF_UNSPEC, .port = _TEST_PORT_REMOTE }; assert(-EAFNOSUPPORT == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); assert(-EAFNOSUPPORT == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); }
/** * @brief Request prefix from uhcp server * * Never returns. * Calls @c uhcp_handle_prefix() when a prefix or prefix change is received. * * @param[in] iface interface to request prefix on */ void uhcp_client(uhcp_iface_t iface) { sock_udp_t sock; sock_udp_ep_t local = { .family=AF_INET6, .port=UHCP_PORT, .netif=iface }; sock_udp_ep_t req_target = { .family=AF_INET6, .port=UHCP_PORT, .netif=iface }; sock_udp_ep_t remote; inet_pton(AF_INET6, "ff15::abcd", req_target.addr.ipv6); /* prepare UHCP header */ uhcp_req_t req; uhcp_hdr_set(&req.hdr, UHCP_REQ); req.prefix_len = 64; /* create listening socket */ int res = sock_udp_create(&sock, &local, NULL, 0); uint8_t buf[sizeof(uhcp_push_t) + 16]; while(1) { puts("uhcp_client(): sending REQ..."); sock_udp_send(&sock, &req, sizeof(uhcp_req_t), &req_target); res = sock_udp_recv(&sock, buf, sizeof(buf), 10U*US_PER_SEC, &remote); if (res > 0) { uhcp_handle_udp(buf, res, remote.addr.ipv6, remote.port, iface); xtimer_sleep(60); } else { puts("uhcp_client(): no reply received"); } } }
/* * Starts a blocking and never-returning loop dispatching CoAP requests. * * When using gnrc, make sure the calling thread has an initialized msg queue. */ void microcoap_server_loop(void) { static const sock_udp_ep_t local = { .family = AF_INET6, .port = COAP_SERVER_PORT }; sock_udp_ep_t remote; sock_udp_t sock; int rc = sock_udp_create(&sock, &local, NULL, 0); while (1) { DEBUG("Waiting for incoming UDP packet...\n"); rc = sock_udp_recv(&sock, (char *)_udp_buf, sizeof(_udp_buf), SOCK_NO_TIMEOUT, &remote); if (rc < 0) { DEBUG("Error in sock_udp_recv(). rc=%u\n", rc); continue; } size_t n = rc; coap_packet_t pkt; DEBUG("Received packet: "); coap_dump(_udp_buf, n, true); DEBUG("\n"); /* parse UDP packet to CoAP */ if (0 != (rc = coap_parse(&pkt, _udp_buf, n))) { DEBUG("Bad packet rc=%d\n", rc); } else { coap_packet_t rsppkt; DEBUG("content:\n"); coap_dumpPacket(&pkt); /* handle CoAP request */ coap_handle_req(&scratch_buf, &pkt, &rsppkt); /* build reply */ size_t rsplen = sizeof(_udp_buf); if ((rc = coap_build(_udp_buf, &rsplen, &rsppkt)) != 0) { DEBUG("coap_build failed rc=%d\n", rc); } else { DEBUG("Sending packet: "); coap_dump(_udp_buf, rsplen, true); DEBUG("\n"); DEBUG("content:\n"); coap_dumpPacket(&rsppkt); /* send reply via UDP */ rc = sock_udp_send(&sock, _udp_buf, rsplen, &remote); if (rc < 0) { DEBUG("Error sending CoAP reply via udp; %u\n", rc); } } } } }
static void test_sock_udp_recv__EADDRNOTAVAIL(void) { assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); assert(-EADDRNOTAVAIL == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT, NULL)); }
static void test_sock_udp_create__no_endpoints(void) { sock_udp_ep_t ep; assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep)); assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep)); }
ssize_t nanocoap_request(coap_pkt_t *pkt, sock_udp_ep_t *local, sock_udp_ep_t *remote, size_t len) { ssize_t res; size_t pdu_len = (pkt->payload - (uint8_t *)pkt->hdr) + pkt->payload_len; uint8_t *buf = (uint8_t*)pkt->hdr; sock_udp_t sock; if (!remote->port) { remote->port = COAP_PORT; } res = sock_udp_create(&sock, local, remote, 0); if (res < 0) { return res; } /* TODO: timeout random between between ACK_TIMEOUT and (ACK_TIMEOUT * * ACK_RANDOM_FACTOR) */ uint32_t timeout = COAP_ACK_TIMEOUT * US_PER_SEC; unsigned tries_left = COAP_MAX_RETRANSMIT + 1; /* add 1 for initial transmit */ while (tries_left) { res = sock_udp_send(&sock, buf, pdu_len, NULL); if (res <= 0) { DEBUG("nanocoap: error sending coap request, %d\n", (int)res); break; } res = sock_udp_recv(&sock, buf, len, timeout, NULL); if (res <= 0) { if (res == -ETIMEDOUT) { DEBUG("nanocoap: timeout\n"); timeout *= 2; tries_left--; if (!tries_left) { DEBUG("nanocoap: maximum retries reached\n"); } continue; } DEBUG("nanocoap: error receiving coap response, %d\n", (int)res); break; } else { if (coap_parse(pkt, (uint8_t *)buf, res) < 0) { DEBUG("nanocoap: error parsing packet\n"); res = -EBADMSG; } break; } } sock_udp_close(&sock); return res; }
static void test_sock_udp_recv__EAGAIN(void) { static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, .port = _TEST_PORT_LOCAL }; assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); assert(-EAGAIN == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), 0, NULL)); }
static void test_sock_udp_create__EINVAL_addr(void) { /* port may not be NULL according to doc */ static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, .port = _TEST_PORT_LOCAL }; /* port may not be NULL according to doc */ static const sock_udp_ep_t remote = { .family = AF_INET6, .netif = _TEST_NETIF, .port = _TEST_PORT_REMOTE }; assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); }
static void test_sock_udp_recv__ENOBUFS(void) { static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; static const sock_udp_ep_t local = { .family = AF_INET6, .port = _TEST_PORT_LOCAL }; assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), _TEST_NETIF)); assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT, NULL)); assert(_check_net()); }
static void test_sock_udp_create__only_local_reuse_ep(void) { static const sock_udp_ep_t local = { .family = AF_INET6, .port = _TEST_PORT_LOCAL }; sock_udp_ep_t ep, ep2; assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); assert(0 == sock_udp_create(&_sock2, &local, NULL, SOCK_FLAGS_REUSE_EP)); assert(0 == sock_udp_get_local(&_sock, &ep)); assert(0 == sock_udp_get_local(&_sock2, &ep2)); assert(AF_INET6 == ep.family); assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); assert(SOCK_ADDR_ANY_NETIF == ep.netif); assert(_TEST_PORT_LOCAL == ep.port); assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep)); assert(AF_INET6 == ep2.family); assert(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6, sizeof(ipv6_addr_t)) == 0); assert(SOCK_ADDR_ANY_NETIF == ep2.netif); assert(_TEST_PORT_LOCAL == ep2.port); assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep2)); sock_udp_close(&_sock2); }
static void test_sock_udp_create__only_remote(void) { static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; static const sock_udp_ep_t remote = { .family = AF_INET6, .port = _TEST_PORT_REMOTE, .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; sock_udp_ep_t ep; assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep)); assert(0 == sock_udp_get_remote(&_sock, &ep)); assert(AF_INET6 == ep.family); assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); assert(SOCK_ADDR_ANY_NETIF == ep.netif); assert(_TEST_PORT_REMOTE == ep.port); }
int sntp_sync(sock_udp_ep_t *server, uint32_t timeout) { int result; mutex_lock(&_sntp_mutex); if ((result = sock_udp_create(&_sntp_sock, NULL, server, 0)) < 0) { DEBUG("Error creating UDP sock\n"); mutex_unlock(&_sntp_mutex); return result; } memset(&_sntp_packet, 0, sizeof(_sntp_packet)); ntp_packet_set_vn(&_sntp_packet); ntp_packet_set_mode(&_sntp_packet, NTP_MODE_CLIENT); if ((result = (int)sock_udp_send(&_sntp_sock, &_sntp_packet, sizeof(_sntp_packet), NULL)) < 0) { DEBUG("Error sending message\n"); sock_udp_close(&_sntp_sock); mutex_unlock(&_sntp_mutex); return result; } if ((result = (int)sock_udp_recv(&_sntp_sock, &_sntp_packet, sizeof(_sntp_packet), timeout, NULL)) < 0) { DEBUG("Error receiving message\n"); sock_udp_close(&_sntp_sock); mutex_unlock(&_sntp_mutex); return result; } sock_udp_close(&_sntp_sock); _sntp_offset = (byteorder_ntohl(_sntp_packet.transmit.seconds) * US_PER_SEC) + ((byteorder_ntohl(_sntp_packet.transmit.fraction) * 232) / 1000000) - xtimer_now64(); mutex_unlock(&_sntp_mutex); return 0; }
static int sock_send_payload (long dest, int port, char *packet, int packet_len) { int sock; /* create udp socket */ sock = sock_udp_create (); if (sock_connect (sock, dest, PROTO_3G_A11_PORT) < 0) return -1; /* send packet */ send (sock, packet, packet_len, 0); printf ("[-] UDP packet sent (%d bytes).\n", packet_len); fflush (stdout); /* disconnect socket */ sock_disconnect (sock); return 0; }
/* Event/Message loop for gcoap _pid thread. */ static void *_event_loop(void *arg) { msg_t msg_rcvd, msg_queue[GCOAP_MSG_QUEUE_SIZE]; (void)arg; msg_init_queue(msg_queue, GCOAP_MSG_QUEUE_SIZE); sock_udp_ep_t local; memset(&local, 0, sizeof(sock_udp_ep_t)); local.family = AF_INET6; local.netif = SOCK_ADDR_ANY_NETIF; local.port = GCOAP_PORT; int res = sock_udp_create(&_sock, &local, NULL, 0); if (res < 0) { DEBUG("gcoap: cannot create sock: %d\n", res); return 0; } while(1) { res = msg_try_receive(&msg_rcvd); if (res > 0) { switch (msg_rcvd.type) { case GCOAP_MSG_TYPE_TIMEOUT: _expire_request((gcoap_request_memo_t *)msg_rcvd.content.ptr); break; case GCOAP_MSG_TYPE_INTR: /* next _listen() timeout will account for open requests */ break; default: break; } } _listen(&_sock); } return 0; }
static void *_server_thread(void *args) { sock_udp_ep_t server_addr = SOCK_IPV6_EP_ANY; int res; msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); /* parse port */ server_addr.port = atoi(args); if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) { printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n", server_addr.port, -res); return NULL; } server_running = true; printf("Success: started UDP server on port %" PRIu16 "\n", server_addr.port); while (1) { sock_udp_ep_t src; int res; if ((res = sock_udp_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf), SOCK_NO_TIMEOUT, &src)) < 0) { puts("Error on receive"); } else if (res == 0) { puts("No data received"); } else { char addrstr[IPV6_ADDR_MAX_STR_LEN]; printf("Received UDP data from [%s]:%" PRIu16 ":\n", ipv6_addr_to_str(addrstr, (ipv6_addr_t *)&src.addr.ipv6, sizeof(addrstr)), src.port); od_hex_dump(sock_inbuf, res, 0); } } return NULL; }
static void test_sock_udp_create__full(void) { static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, .port = _TEST_PORT_LOCAL }; static const sock_udp_ep_t remote = { .family = AF_INET6, .port = _TEST_PORT_REMOTE, .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; sock_udp_ep_t ep; assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); assert(0 == sock_udp_get_local(&_sock, &ep)); assert(AF_INET6 == ep.family); assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); assert(_TEST_NETIF == ep.netif); assert(_TEST_PORT_LOCAL == ep.port); assert(0 == sock_udp_get_remote(&_sock, &ep)); assert(AF_INET6 == ep.family); assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); assert(SOCK_ADDR_ANY_NETIF == ep.netif); assert(_TEST_PORT_REMOTE == ep.port); }
int nanocoap_server(sock_udp_ep_t *local, uint8_t *buf, size_t bufsize) { sock_udp_t sock; sock_udp_ep_t remote; if (!local->port) { local->port = COAP_PORT; } ssize_t res = sock_udp_create(&sock, local, NULL, 0); if (res != 0) { return -1; } while (1) { res = sock_udp_recv(&sock, buf, bufsize, -1, &remote); if (res < 0) { DEBUG("error receiving UDP packet %d\n", (int)res); } else if (res > 0) { coap_pkt_t pkt; if (coap_parse(&pkt, (uint8_t *)buf, res) < 0) { DEBUG("error parsing packet\n"); continue; } if ((res = coap_handle_req(&pkt, buf, bufsize)) > 0) { res = sock_udp_send(&sock, buf, res, &remote); } else { DEBUG("error handling request %d\n", (int)res); } } } return 0; }
assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT, NULL)); assert(_check_net()); } static void test_sock_udp_recv__EPROTO(void) { static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG }; static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; static const sock_udp_ep_t local = { .family = AF_INET6, .port = _TEST_PORT_LOCAL }; static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, .family = AF_INET6, .port = _TEST_PORT_REMOTE }; assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), _TEST_NETIF)); assert(-EPROTO == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT, NULL)); assert(_check_net()); } static void test_sock_udp_recv__ETIMEDOUT(void) { static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, .port = _TEST_PORT_LOCAL }; assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
void emcute_run(uint16_t port, const char *id) { assert(strlen(id) < EMCUTE_ID_MAXLEN); sock_udp_ep_t local = SOCK_IPV6_EP_ANY; sock_udp_ep_t remote; local.port = port; cli_id = id; timer.callback = time_evt; timer.arg = NULL; mutex_init(&txlock); if (sock_udp_create(&sock, &local, NULL, 0) < 0) { LOG_ERROR("[emcute] unable to open UDP socket on port %i\n", (int)port); return; } uint32_t start = xtimer_now_usec(); uint32_t t_out = (EMCUTE_KEEPALIVE * US_PER_SEC); while (1) { ssize_t len = sock_udp_recv(&sock, rbuf, sizeof(rbuf), t_out, &remote); if ((len < 0) && (len != -ETIMEDOUT)) { LOG_ERROR("[emcute] error while receiving UDP packet\n"); return; } if (len >= 2) { /* handle the packet */ uint16_t pkt_len; /* catch invalid length field */ if ((len == 2) && (rbuf[0] == 0x01)) { continue; } /* parse length field */ size_t pos = get_len(rbuf, &pkt_len); /* verify length to prevent overflows */ if (((size_t)pkt_len > (size_t)len) || (pos >= (size_t)len)) { continue; } /* get packet type */ uint8_t type = rbuf[pos]; switch (type) { case CONNACK: on_ack(type, 0, 2, 0); break; case WILLTOPICREQ: on_ack(type, 0, 0, 0); break; case WILLMSGREQ: on_ack(type, 0, 0, 0); break; case REGACK: on_ack(type, 4, 6, 2); break; case PUBLISH: on_publish((size_t)pkt_len, pos); break; case PUBACK: on_ack(type, 4, 6, 0); break; case SUBACK: on_ack(type, 5, 7, 3); break; case UNSUBACK: on_ack(type, 2, 0, 0); break; case PINGREQ: on_pingreq(&remote); break; case PINGRESP: on_pingresp(); break; case DISCONNECT: on_disconnect(); break; case WILLTOPICRESP: on_ack(type, 0, 0, 0); break; case WILLMSGRESP: on_ack(type, 0, 0, 0); break; default: LOG_DEBUG("[emcute] received unexpected type [%s]\n", emcute_type_str(type)); } } uint32_t now = xtimer_now_usec(); if ((now - start) >= (EMCUTE_KEEPALIVE * US_PER_SEC)) { send_ping(); start = now; t_out = (EMCUTE_KEEPALIVE * US_PER_SEC); } else { t_out = (EMCUTE_KEEPALIVE * US_PER_SEC) - (now - start); } } }
/* Event/Message loop for gcoap _pid thread. */ static void *_event_loop(void *arg) { msg_t msg_rcvd; (void)arg; msg_init_queue(_msg_queue, GCOAP_MSG_QUEUE_SIZE); sock_udp_ep_t local; memset(&local, 0, sizeof(sock_udp_ep_t)); local.family = AF_INET6; local.netif = SOCK_ADDR_ANY_NETIF; local.port = GCOAP_PORT; int res = sock_udp_create(&_sock, &local, NULL, 0); if (res < 0) { DEBUG("gcoap: cannot create sock: %d\n", res); return 0; } while(1) { res = msg_try_receive(&msg_rcvd); if (res > 0) { switch (msg_rcvd.type) { case GCOAP_MSG_TYPE_TIMEOUT: { gcoap_request_memo_t *memo = (gcoap_request_memo_t *)msg_rcvd.content.ptr; /* no retries remaining */ if ((memo->send_limit == GCOAP_SEND_LIMIT_NON) || (memo->send_limit == 0)) { _expire_request(memo); } /* reduce retries remaining, double timeout and resend */ else { memo->send_limit--; unsigned i = COAP_MAX_RETRANSMIT - memo->send_limit; uint32_t timeout = ((uint32_t)COAP_ACK_TIMEOUT << i) * US_PER_SEC; uint32_t variance = ((uint32_t)COAP_ACK_VARIANCE << i) * US_PER_SEC; timeout = random_uint32_range(timeout, timeout + variance); ssize_t bytes = sock_udp_send(&_sock, memo->msg.data.pdu_buf, memo->msg.data.pdu_len, &memo->remote_ep); if (bytes > 0) { xtimer_set_msg(&memo->response_timer, timeout, &memo->timeout_msg, _pid); } else { DEBUG("gcoap: sock resend failed: %d\n", (int)bytes); _expire_request(memo); } } break; } default: break; } } _listen(&_sock); } return 0; }