static void pico_slaacv4_send_probe_timer(pico_time now, void *arg) { struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg; (void)now; if (tmp->probe_try_nb < PROBE_NB) { pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE); tmp->probe_try_nb++; tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp); if (!tmp->timer) { slaacv4_dbg("SLAACV4: Failed to start probe timer\n"); tmp->state = SLAACV4_ERROR; if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } } else { tmp->state = SLAACV4_ANNOUNCING; tmp->timer = pico_timer_add(ANNOUNCE_WAIT * 1000, pico_slaacv4_send_announce_timer, arg); if (!tmp->timer) { slaacv4_dbg("SLAACV4: Failed to start announce timer\n"); tmp->state = SLAACV4_ERROR; if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } } }
static void pico_slaacv4_receive_ipconflict(int reason) { struct slaacv4_cookie *tmp = &slaacv4_local; tmp->conflict_nb++; pico_slaacv4_cancel_timers(tmp); if(tmp->state == SLAACV4_CLAIMED) { if(reason == PICO_ARP_CONFLICT_REASON_CONFLICT) { pico_ipv4_link_del(tmp->device, tmp->ip); } } if (tmp->conflict_nb < MAX_CONFLICTS) { tmp->state = SLAACV4_CLAIMING; tmp->probe_try_nb = 0; tmp->announce_nb = 0; tmp->ip.addr = pico_slaacv4_getip(tmp->device, (uint8_t)1); pico_arp_register_ipconflict(&tmp->ip, &tmp->device->eth->mac, pico_slaacv4_receive_ipconflict); pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE); tmp->probe_try_nb++; tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp); if (!tmp->timer) { slaacv4_dbg("SLAACV4: Failed to start probe timer\n"); tmp->state = SLAACV4_ERROR; if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } } else if (tmp->conflict_nb < MAX_CONFLICTS_FAIL) { tmp->state = SLAACV4_CLAIMING; tmp->probe_try_nb = 0; tmp->announce_nb = 0; tmp->ip.addr = pico_slaacv4_getip(tmp->device, (uint8_t)1); pico_arp_register_ipconflict(&tmp->ip, &tmp->device->eth->mac, pico_slaacv4_receive_ipconflict); tmp->timer = pico_timer_add(RATE_LIMIT_INTERVAL * 1000, pico_slaacv4_send_probe_timer, tmp); if (!tmp->timer) { slaacv4_dbg("SLAACV4: Failed to start probe timer\n"); tmp->state = SLAACV4_ERROR; if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } } else { if (tmp->cb != NULL) { pico_hotplug_deregister(tmp->device, &pico_slaacv4_hotplug_cb); tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } tmp->state = SLAACV4_ERROR; } }
static inline void send_ping(struct pico_icmp4_ping_cookie *cookie) { pico_icmp4_send_echo(cookie); cookie->timestamp = pico_tick; pico_timer_add((uint32_t)cookie->timeout, ping_timeout, cookie); if (cookie->seq < cookie->count) pico_timer_add((uint32_t)cookie->interval, next_ping, cookie); }
static void pico_dns_client_retransmission(unsigned long now, void *arg) { struct pico_dns_key *key = (struct pico_dns_key *)arg; struct pico_dns_ns *q_ns = NULL; if (!key->retrans) { dns_dbg("DNS: no retransmission!\n"); pico_free(key->q_hdr); if(pico_tree_delete(&DNSTable,key)) pico_free(key); } else if (key->retrans <= PICO_DNS_CLIENT_MAX_RETRANS) { key->retrans++; dns_dbg("DNS: retransmission! (%u attempts)\n", key->retrans); // ugly hack q_ns = pico_tree_next(pico_tree_findNode(&NSTable,&key->q_ns))->keyValue; if (q_ns) key->q_ns = *q_ns; else key->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); pico_dns_client_send(key); pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, key); } else { dns_dbg("DNS ERROR: no reply from nameservers! (%u attempts)\n", key->retrans); pico_socket_close(key->s); pico_err = PICO_ERR_EIO; key->callback(NULL, key->arg); pico_free(key->q_hdr); /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ if(pico_tree_delete(&DNSTable,key)) pico_free(key); } }
int cb_tftp_rx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg) { struct note_t *note = (struct note_t *) arg; int ret; if (event != PICO_TFTP_EV_OK) { fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block); exit(1); } if (!note) return 0; note->filesize += len; if (write(note->fd, block, len) < 0) { perror("write"); fprintf(stderr, "Filesystem error writing file %s, cancelling current transfer\n", note->filename); pico_tftp_abort(session, TFTP_ERR_EACC, "Error on write"); del_note(note); } else { if (len != PICO_TFTP_PAYLOAD_SIZE) { printf("TFTP: file %s (%" PRId32 " bytes) RX transfer complete!\n", note->filename, note->filesize); close(note->fd); del_note(note); } } if (!clipboard) pico_timer_add(3000, deferred_exit, NULL); return len; }
int cb_tftp_tx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg) { struct note_t *note = (struct note_t *) arg; if (event != PICO_TFTP_EV_OK) { fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block); exit(1); } len = read(note->fd, tftp_txbuf, PICO_TFTP_PAYLOAD_SIZE); if (len >= 0) { note->filesize += len; pico_tftp_send(session, tftp_txbuf, len); if (len < PICO_TFTP_PAYLOAD_SIZE) { printf("TFTP: file %s (%" PRId32 " bytes) TX transfer complete!\n", note->filename, note->filesize); close(note->fd); del_note(note); } } else { perror("read"); fprintf(stderr, "Filesystem error reading file %s, cancelling current transfer\n", note->filename); pico_tftp_abort(session, TFTP_ERR_EACC, "Error on read"); del_note(note); } if (!clipboard) pico_timer_add(3000, deferred_exit, NULL); return len; }
int cb_tftp(uint16_t err, uint8_t *block, uint32_t len) { static int fd = -1; static int count = 1; if (fd == -1) { fd = open("/tmp/tftp_recv", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { perror("open"); exit(1); } } if (err != PICO_TFTP_ERR_OK) { printf("TFTP: Error %d: %s\n", err, block); exit(1); } if (len > 0) write(fd, block, len); if (len == PICO_TFTP_SIZE) { /* printf("Received block %d, size: %d\n", count++, len); */ } else { printf("Received last block, size:%d. Transfer complete.\n", len); close(fd); pico_timer_add(2000, deferred_exit, NULL); } return len; }
int cb_tftp_tx(uint16_t err, uint8_t *block, uint32_t len) { static int fd = -1; static int count = 1; (void)block; if (fd == -1) { fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { perror("open"); exit(1); } } if (err != PICO_TFTP_ERR_OK) { printf("TFTP: Error %d: %s\n", err, block); exit(1); } if (count++ == TFTP_TX_COUNT) { len = 0; close(fd); pico_timer_add(2000, deferred_exit, NULL); } else { len = read(fd, tftp_txbuf, PICO_TFTP_SIZE); } if (len >= 0) { pico_tftp_send(tftp_txbuf, len); } return len; }
static void pico_slaacv4_send_announce_timer(pico_time now, void *arg) { struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg; struct pico_ip4 netmask = { 0 }; netmask.addr = long_be(0xFFFF0000); (void)now; if (tmp->announce_nb < ANNOUNCE_NB) { pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_ANNOUNCE); tmp->announce_nb++; tmp->timer = pico_timer_add(ANNOUNCE_INTERVAL * 1000, pico_slaacv4_send_announce_timer, arg); if (!tmp->timer) { slaacv4_dbg("SLAACV4: Failed to start announce timer\n"); tmp->state = SLAACV4_ERROR; if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); } } else { tmp->state = SLAACV4_CLAIMED; pico_ipv4_link_add(tmp->device, tmp->ip, netmask); if (tmp->cb != NULL) tmp->cb(&tmp->ip, PICO_SLAACV4_SUCCESS); } }
static int pico_dns_client_send(struct pico_dns_query *q) { uint16_t *paramID = PICO_ZALLOC(sizeof(uint16_t)); if (!paramID) { pico_err = PICO_ERR_ENOMEM; return -1; } dns_dbg("DNS: sending query to %08X\n", q->q_ns.ns.addr); if (!q->s) goto failure; if (pico_socket_connect(q->s, &q->q_ns.ns, short_be(PICO_DNS_NS_PORT)) < 0) goto failure; pico_socket_send(q->s, q->query, q->len); *paramID = q->id; pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, paramID); return 0; failure: PICO_FREE(paramID); return -1; }
static void pico_slaacv4_send_probe_timer(pico_time now, void *arg) { struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg; (void)now; if (tmp->probe_try_nb < PROBE_NB) { pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE); tmp->probe_try_nb++; tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp); } else { tmp->state = SLAACV4_ANNOUNCING; tmp->timer = pico_timer_add(ANNOUNCE_WAIT * 1000, pico_slaacv4_send_announce_timer, arg); } }
static void pico_ipv6_frag_timer_on(void) { ipv6_fragments_timer = pico_timer_add(PICO_IPV6_FRAG_TIMEOUT, pico_frag_expire, &ipv6_fragments); if (!ipv6_fragments_timer) { frag_dbg("FRAG: Failed to start IPv6 expiration timer\n"); pico_fragments_empty_tree(&ipv6_fragments); } }
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); } }