void callback_dhcpclient(void*cli, int code) { struct pico_ip4 gateway; char gw_txt_addr[30]; if(code == PICO_DHCP_SUCCESS) { gateway = pico_dhcp_get_gateway(&dhcp_client_ptr); pico_ipv4_to_string(gw_txt_addr, gateway.addr); } printf("callback happened with code %d!\n", code); }
/* * TCP code. For TCP, a socket is created and listens. * A callback occurs when the packet is received. The callback handles the different types of TCP events, * including the handshake protocol. * Based off the sample tcpecho app provided in the picotcp library. */ void cb_tcpecho(uint16_t ev, struct pico_socket *s) { int r = 0; ZF_LOGD("tcpecho> wakeup ev=%u\n", ev); if (ev & PICO_SOCK_EV_RD) { char buf[100]; r = pico_socket_read(s, buf, 100); pico_socket_write(s, buf, r); // Immediately echo back a response } if (ev & PICO_SOCK_EV_CONN) { uint32_t ka_val = 0; struct pico_socket *sock_peer; struct pico_ip4 orig = {0}; uint16_t port = 0; char peer[30] = {0}; int yes = 1; sock_peer = pico_socket_accept(s, &orig, &port); pico_ipv4_to_string(peer, orig.addr); ZF_LOGD("Connection established with %s:%d.\n", peer, short_be(port)); pico_socket_setoption(sock_peer, PICO_TCP_NODELAY, &yes); /* Set keepalive options - from picoTCP documentation */ ka_val = 5; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPCNT, &ka_val); ka_val = 30000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPIDLE, &ka_val); ka_val = 5000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPINTVL, &ka_val); } if (ev & PICO_SOCK_EV_FIN) { ZF_LOGD("Socket closed. Exit normally. \n"); } if (ev & PICO_SOCK_EV_ERR) { ZF_LOGD("Socket error received: %s. Bailing out.\n", strerror(pico_err)); } if (ev & PICO_SOCK_EV_CLOSE) { ZF_LOGD("Socket received close from peer.\n"); pico_socket_shutdown(s, PICO_SHUT_WR); } if (ev & PICO_SOCK_EV_WR) { ZF_LOGD("TCP Write ack\n"); } }
static int pico_dns_client_user_callback(struct pico_dns_answer_suffix *asuffix, struct pico_dns_query *q) { uint32_t ip = 0; char *str = NULL; char *rdata = (char *) asuffix + sizeof(struct pico_dns_answer_suffix); switch (q->qtype) { case PICO_DNS_TYPE_A: ip = long_from(rdata); str = PICO_ZALLOC(PICO_DNS_IPV4_ADDR_LEN); pico_ipv4_to_string(str, ip); break; #ifdef PICO_SUPPORT_IPV6 case PICO_DNS_TYPE_AAAA: { struct pico_ip6 ip6; memcpy(&ip6.addr, rdata, sizeof(struct pico_ip6)); str = PICO_ZALLOC(PICO_DNS_IPV6_ADDR_LEN); pico_ipv6_to_string(str, ip6.addr); break; } #endif case PICO_DNS_TYPE_PTR: pico_dns_client_answer_domain(rdata); str = PICO_ZALLOC((size_t)(asuffix->rdlength - PICO_DNS_LABEL_INITIAL)); if (!str) { pico_err = PICO_ERR_ENOMEM; return -1; } memcpy(str, rdata + PICO_DNS_LABEL_INITIAL, short_be(asuffix->rdlength) - PICO_DNS_LABEL_INITIAL); break; default: dns_dbg("DNS ERROR: incorrect qtype (%u)\n", q->qtype); break; } if (q->retrans) { q->callback(str, q->arg); q->retrans = 0; PICO_FREE(str); pico_dns_client_del_query(q->id); } return 0; }
void cb_ping(struct pico_icmp4_stats *s) { char host[30]; pico_ipv4_to_string(host, s->dst.addr); if (s->err == 0) { dbg("%lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host, s->seq, s->time); if (s->seq == NUM_PING) { ping_test_var++; } fail_if (s->seq > NUM_PING); } else { dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err); exit(1); } }
void handle_picoserver_notification(void) { picoserver_event_t server_event = echo_control_event_poll(); int ret = 0; int socket = 0; uint16_t events = 0; char ip_string[16] = {0}; while (server_event.num_events_left > 0 || server_event.events) { socket = server_event.socket_fd; events = server_event.events; if (events & PICOSERVER_CONN) { if (socket != listener_socket) { picoserver_peer_t peer = echo_control_accept(socket); if (peer.result == -1) { assert(!"Failed to accept a peer"); } pico_ipv4_to_string(ip_string, peer.peer_addr); printf("%s: Connection established with %s on socket %d\n", get_instance_name(), ip_string, socket); } } if (events & PICOSERVER_READ) { printf("%s: Received a message on socket %d, going to echo to Listener\n", get_instance_name(), socket); ret = echo_recv_recv(socket, 4096, 0); strncpy(echo_send_buf, echo_recv_buf, ret); ret = echo_send_send(listener_socket, strlen(echo_send_buf), 0); memset(echo_recv_buf, 0, 4096); memset(echo_send_buf, 0, 4096); } if (events & PICOSERVER_CLOSE) { ret = echo_control_shutdown(socket, PICOSERVER_SHUT_RDWR); printf("%s: Connection closing on socket %d\n", get_instance_name(), socket); } if (events & PICOSERVER_FIN) { printf("%s: Connection closed on socket %d\n", get_instance_name(), socket); } if (events & PICOSERVER_ERR) { printf("%s: Error with socket %d, going to die\n", get_instance_name(), socket); assert(0); } server_event = echo_control_event_poll(); } }
void ping_callback_dhcpclient(struct pico_icmp4_stats *s) { char host[30] = { }; pico_ipv4_to_string(host, s->dst.addr); if (s->err == 0) { dbg("DHCP client: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host, s->seq, (long unsigned int)s->time); if (s->seq >= 3) { dbg("DHCP client: TEST SUCCESS!\n"); if (--dhcpclient_devices <= 0) exit(0); } } else { dbg("DHCP client: ping %lu to %s error %d\n", s->seq, host, s->err); dbg("DHCP client: TEST FAILED!\n"); exit(1); } }
static void pico_dns_client_callback(uint16_t ev, struct pico_socket *s) { char *q_qname, *q_suf, *a_hdr, *a_qname, *a_suf, *a_rdata; struct dns_message_hdr *hdr; struct dns_query_suffix query_suf; struct dns_answer_suffix answer_suf; struct pico_dns_key test, *key; char *answer; char dns_answer[PICO_DNS_MAX_RESPONSE_LEN] = {0}; uint8_t valid_suffix = 0; uint16_t compression = 0; int i = 0, r = 0; if (ev & PICO_SOCK_EV_RD) { r = pico_socket_read(s, dns_answer, PICO_DNS_MAX_RESPONSE_LEN); pico_socket_close(s); if (r == PICO_DNS_MAX_RESPONSE_LEN || r < (int)sizeof(struct dns_message_hdr)) { dns_dbg("DNS ERROR: received incorrect number(%d) of bytes\n", r); return; } /* Check header validity */ a_hdr = dns_answer; hdr = (struct dns_message_hdr *) a_hdr; pico_dns_client_hdr_ntoh(hdr); if (GET_FLAG_QR(hdr) != PICO_DNS_QR_RESPONSE || GET_FLAG_OPCODE(hdr) != PICO_DNS_OPCODE_QUERY || GET_FLAG_TC(hdr) == PICO_DNS_TC_IS_TRUNCATED || GET_FLAG_RCODE(hdr) != PICO_DNS_RCODE_NO_ERROR) { dns_dbg("DNS ERROR: OPCODE %d | TC %d | RCODE %d\n", GET_FLAG_OPCODE(hdr), GET_FLAG_TC(hdr), GET_FLAG_RCODE(hdr)); return; } if (hdr->ancount < 1 || r < (int)(sizeof(struct dns_message_hdr) + hdr->qdcount * sizeof(struct dns_query_suffix) + hdr->ancount * sizeof(struct dns_answer_suffix))) { dns_dbg("DNS ERROR: ancount < 1 OR received number(%d) of bytes too low\n", r); return; } /* Find DNS key */ test.id = hdr->id; key = pico_tree_findKey(&DNSTable,&test); if (!key) { dns_dbg("DNS WARNING: key with id %u not found\n", hdr->id); return; } key->retrans = 0; /* Check query suffix validity */ q_qname = a_hdr + sizeof(struct dns_message_hdr); q_suf = pico_dns_client_seek(q_qname); query_suf = *(struct dns_query_suffix *) q_suf; if (short_be(query_suf.qtype) != key->qtype || short_be(query_suf.qclass) != key->qclass) { dns_dbg("DNS ERROR: received qtype (%u) or qclass (%u) incorrect\n", short_be(query_suf.qtype), short_be(query_suf.qclass)); return; } /* Seek answer suffix */ a_qname = q_suf + sizeof(struct dns_query_suffix); a_suf = a_qname; while(i++ < hdr->ancount) { uint16_t comp_h = short_from(a_suf); compression = short_be(comp_h); switch (compression >> 14) { case PICO_DNS_POINTER: while (compression >> 14 == PICO_DNS_POINTER) { dns_dbg("DNS: pointer\n"); a_suf += sizeof(uint16_t); comp_h = short_from(a_suf); compression = short_be(comp_h); } break; case PICO_DNS_LABEL: dns_dbg("DNS: label\n"); a_suf = pico_dns_client_seek(a_qname); break; default: dns_dbg("DNS ERROR: incorrect compression (%u) value\n", compression); return; } /* Check answer suffix validity */ answer_suf = *(struct dns_answer_suffix *)a_suf; if (short_be(answer_suf.qtype) != key->qtype || short_be(answer_suf.qclass) != key->qclass) { dns_dbg("DNS WARNING: received qtype (%u) or qclass (%u) incorrect\n", short_be(answer_suf.qtype), short_be(answer_suf.qclass)); a_suf = a_suf + sizeof(struct dns_answer_suffix) + short_be(answer_suf.rdlength); continue; } if (short_be(answer_suf.ttl) > PICO_DNS_MAX_TTL) { dns_dbg("DNS WARNING: received TTL (%u) > MAX (%u)\n", short_be(answer_suf.ttl), PICO_DNS_MAX_TTL); a_suf = a_suf + sizeof(struct dns_answer_suffix) + short_be(answer_suf.rdlength); continue; } valid_suffix = 1; break; } if (!valid_suffix) { dns_dbg("DNS ERROR: invalid dns answer suffix\n"); return; } a_rdata = a_suf + sizeof(struct dns_answer_suffix); if (key->qtype == PICO_DNS_TYPE_A) { uint32_t ip_h = long_from(a_rdata); dns_dbg("DNS: length %u | ip %08X\n", short_be(answer_suf.rdlength), long_be(ip_h)); answer = pico_zalloc(16); pico_ipv4_to_string(answer, ip_h); key->callback(answer, key->arg); } else if (key->qtype == PICO_DNS_TYPE_PTR) { pico_dns_client_reverse_label((char *) a_rdata); dns_dbg("DNS: length %u | name %s\n", short_be(answer_suf.rdlength), (char *)a_rdata + 1); answer = pico_zalloc(answer_suf.rdlength - 1); memcpy(answer, (char *)a_rdata + 1, short_be(answer_suf.rdlength) - 1); key->callback(answer, key->arg); } else { dns_dbg("DNS ERROR: incorrect qtype (%u)\n", key->qtype); return; } }
void serverWakeup(uint16_t ev, uint16_t conn) { char * body; uint32_t read = 0; if(ev & EV_HTTPS_CON) { printf("New connection received\n"); pico_https_server_accept(); } if(ev & EV_HTTPS_REQ) /* new header received */ { char *resource; int method; printf("Header request received\n"); resource = pico_https_getResource(conn); if(strcmp(resource, "/") == 0) { resource = "/stm32f4.html"; } method = pico_https_getMethod(conn); if(strcmp(resource, "/board_info") == 0) { pico_https_respond(conn, HTTPS_RESOURCE_FOUND); strcpy(http_buffer, "{\"uptime\":"); pico_itoa(PICO_TIME(), http_buffer + strlen(http_buffer)); strcat(http_buffer, ", \"l1\":\""); strcat(http_buffer, "on"); strcat(http_buffer, "\", \"l2\":\""); strcat(http_buffer, "off"); strcat(http_buffer, "\", \"l3\":\""); strcat(http_buffer, "on"); strcat(http_buffer, "\", \"l4\":\""); strcat(http_buffer, "on"); strcat(http_buffer, "\", \"button\":\""); strcat(http_buffer, "up"); strcat(http_buffer, "\"}"); pico_https_submitData(conn, http_buffer, strlen(http_buffer)); } else if(strcmp(resource, "/ip") == 0) { pico_https_respond(conn, HTTPS_RESOURCE_FOUND); struct pico_ipv4_link * link; link = pico_ipv4_link_by_dev(pico_dev_eth); if (link) pico_ipv4_to_string(http_buffer, link->address.addr); else strcpy(http_buffer, "0.0.0.0"); pico_https_submitData(conn, http_buffer, strlen(http_buffer)); } else if(strcmp(resource,"/led1") == 0){ pico_https_respond(conn, HTTPS_RESOURCE_FOUND); pico_https_submitData(conn, toggledString, sizeof(toggledString)); } else if(strcmp(resource,"/led2") == 0){ pico_https_respond(conn, HTTPS_RESOURCE_FOUND); pico_https_submitData(conn, toggledString, sizeof(toggledString)); } else if(strcmp(resource,"/led3") == 0){ pico_https_respond(conn, HTTPS_RESOURCE_FOUND); pico_https_submitData(conn, toggledString, sizeof(toggledString)); } else if(strcmp(resource,"/led4") == 0){ pico_https_respond(conn, HTTPS_RESOURCE_FOUND); pico_https_submitData(conn, toggledString, sizeof(toggledString)); } else /* search in flash resources */ { struct Www_file * www_file; www_file = find_www_file(resource + 1); if(www_file != NULL) { uint16_t flags; flags = HTTPS_RESOURCE_FOUND | HTTPS_STATIC_RESOURCE; if(www_file->cacheable) { flags = flags | HTTPS_CACHEABLE_RESOURCE; } pico_https_respond(conn, flags); pico_https_submitData(conn, www_file->content, (int) *www_file->filesize); } else { /* not found */ /* reject */ printf("Rejected connection...\n"); pico_https_respond(conn, HTTPS_RESOURCE_NOT_FOUND); } } } if(ev & EV_HTTPS_PROGRESS) /* submitted data was sent */ { uint16_t sent, total; pico_https_getProgress(conn, &sent, &total); printf("Chunk statistics : %d/%d sent\n", sent, total); } if(ev & EV_HTTPS_SENT) /* submitted data was fully sent */ { printf("Last chunk post !\n"); pico_https_submitData(conn, NULL, 0); /* send the final chunk */ } if(ev & EV_HTTPS_CLOSE) { printf("Close request: %p\n", conn); if (conn) pico_https_close(conn); else printf(">>>>>>>> Close request w/ conn=NULL!!\n"); } if(ev & EV_HTTPS_ERROR) { printf("Error on server: %p\n", conn); //TODO: what to do? //pico_http_close(conn); } }
void cb_tcpecho(uint16_t ev, struct pico_socket *s) { int r = 0; picoapp_dbg("tcpecho> wakeup ev=%u\n", ev); if (ev & PICO_SOCK_EV_RD) { if (flag & PICO_SOCK_EV_CLOSE) printf("SOCKET> EV_RD, FIN RECEIVED\n"); while (len < BSIZE) { r = pico_socket_read(s, recvbuf + len, BSIZE - len); if (r > 0) { len += r; flag &= ~(PICO_SOCK_EV_RD); } else { flag |= PICO_SOCK_EV_RD; break; } } if (flag & PICO_SOCK_EV_WR) { flag &= ~PICO_SOCK_EV_WR; send_tcpecho(s); } } if (ev & PICO_SOCK_EV_CONN) { uint32_t ka_val = 0; struct pico_socket *sock_a = { 0 }; struct pico_ip4 orig = { 0 }; uint16_t port = 0; char peer[30] = { 0 }; int yes = 1; sock_a = pico_socket_accept(s, &orig, &port); pico_ipv4_to_string(peer, orig.addr); printf("Connection established with %s:%d.\n", peer, short_be(port)); pico_socket_setoption(sock_a, PICO_TCP_NODELAY, &yes); /* Set keepalive options */ ka_val = 5; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPCNT, &ka_val); ka_val = 30000; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPIDLE, &ka_val); ka_val = 5000; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPINTVL, &ka_val); } if (ev & PICO_SOCK_EV_FIN) { printf("Socket closed. Exit normally. \n"); if (!pico_timer_add(2000, deferred_exit, NULL)) { printf("Failed to start exit timer, exiting now\n"); exit(1); } } if (ev & PICO_SOCK_EV_ERR) { printf("Socket error received: %s. Bailing out.\n", strerror(pico_err)); exit(1); } if (ev & PICO_SOCK_EV_CLOSE) { printf("Socket received close from peer.\n"); if (flag & PICO_SOCK_EV_RD) { pico_socket_shutdown(s, PICO_SHUT_WR); printf("SOCKET> Called shutdown write, ev = %d\n", ev); } } if (ev & PICO_SOCK_EV_WR) { r = send_tcpecho(s); if (r == 0) flag |= PICO_SOCK_EV_WR; else flag &= (~PICO_SOCK_EV_WR); } }