/** * Delete the pcb inside a netconn. * Called from netconn_delete. * * @param msg the api_msg_msg pointing to the connection */ void lwip_netconn_do_delconn(struct api_msg_msg *msg) { /* @todo TCP: abort running write/connect? */ if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN) && (msg->conn->state != NETCONN_CONNECT)) { /* this only happens for TCP netconns */ LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP", NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP); msg->err = ERR_INPROGRESS; } else { LWIP_ASSERT("blocking connect in progress", (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); /* Drain and delete mboxes */ netconn_drain(msg->conn); if (msg->conn->pcb.tcp != NULL) { switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: raw_remove(msg->conn->pcb.raw); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp->recv_arg = NULL; udp_remove(msg->conn->pcb.udp); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && msg->conn->write_offset == 0); msg->conn->state = NETCONN_CLOSE; msg->msg.sd.shut = NETCONN_SHUT_RDWR; msg->conn->current_msg = msg; lwip_netconn_do_close_internal(msg->conn); /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing the application thread, so we can return at this point! */ return; #endif /* LWIP_TCP */ default: break; } msg->conn->pcb.tcp = NULL; } /* tcp netconns don't come here! */ /* @todo: this lets select make the socket readable and writable, which is wrong! errfd instead? */ API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); } if (sys_sem_valid(&msg->conn->op_completed)) { sys_sem_signal(&msg->conn->op_completed); } }
static void do_delconn(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: raw_remove(msg->conn->pcb.raw); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: msg->conn->pcb.udp->recv_arg = NULL; udp_remove(msg->conn->pcb.udp); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: if (msg->conn->pcb.tcp->state == LISTEN) { tcp_arg(msg->conn->pcb.tcp, NULL); tcp_accept(msg->conn->pcb.tcp, NULL); tcp_close(msg->conn->pcb.tcp); } else { tcp_arg(msg->conn->pcb.tcp, NULL); tcp_sent(msg->conn->pcb.tcp, NULL); tcp_recv(msg->conn->pcb.tcp, NULL); tcp_poll(msg->conn->pcb.tcp, NULL, 0); tcp_err(msg->conn->pcb.tcp, NULL); if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) { tcp_abort(msg->conn->pcb.tcp); } } #endif default: break; } } /* Trigger select() in socket layer */ if (msg->conn->callback) { (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0); (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0); } if (msg->conn->mbox != SYS_MBOX_NULL) { sys_mbox_post(msg->conn->mbox, NULL); } }
static void raw_ip_close(struct socket * sock) { /* deque and free all enqueued data before closing */ sock_dequeue_data_all(sock, raw_ip_recv_free); if (sock->pcb) raw_remove(sock->pcb); if (sock->buf) sock_free_buf(sock->buf); /* mark it as unused */ sock->ops = NULL; }
static void ping_thread(void *arg) { struct raw_pcb *raw; if (!(raw = raw_new(IP_PROTO_ICMP))) return; raw_recv(raw,ping_recv,NULL); while (1) { printf("ping send\n"); ping_send(raw,&ping_addr); sleep(1); } /* Never reaches this */ raw_remove(raw); }
static void ICACHE_FLASH_ATTR ping_coarse_tmr(void *arg) { // struct ping_msg *pingmsg = (struct ping_msg*)arg; struct ping_option *ping_opt= NULL; struct ping_resp pingresp; ip_addr_t ping_target; LWIP_ASSERT("ping_timeout: no pcb given!", pingmsg != NULL); ping_target.addr = pingmsg->ping_opt->ip; ping_opt = pingmsg->ping_opt; if (--pingmsg->sent_count != 0){ pingmsg ->ping_sent = system_get_time(); ping_send(pingmsg->ping_pcb, &ping_target); sys_timeout(PING_TIMEOUT_MS, ping_timeout, pingmsg); sys_timeout(pingmsg->coarse_time, ping_coarse_tmr, pingmsg); } else { uint32 delay = system_relative_time(pingmsg->ping_start); delay /= PING_COARSE; //ping_seq_num = 0; if (ping_opt->sent_function == NULL){ os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n", pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay); } else { os_bzero(&pingresp, sizeof(struct ping_resp)); pingresp.total_count = pingmsg->max_count; pingresp.timeout_count = pingmsg->timeout_count; pingresp.total_bytes = PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count); pingresp.total_time = delay; pingresp.ping_err = 0; } sys_untimeout(ping_coarse_tmr, pingmsg); raw_remove(pingmsg->ping_pcb); // os_free(pingmsg); if (ping_opt->sent_function != NULL) ping_opt->sent_function(ping_opt,(uint8*)&pingresp); } }
/** * Delete the pcb inside a netconn. * Called from netconn_delete. * * @param msg the api_msg_msg pointing to the connection */ void do_delconn(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: raw_remove(msg->conn->pcb.raw); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp->recv_arg = NULL; udp_remove(msg->conn->pcb.udp); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->state = NETCONN_CLOSE; do_close_internal(msg->conn); /* API_EVENT is called inside do_close_internal, before releasing the application thread, so we can return at this point! */ return; #endif /* LWIP_TCP */ default: break; } } /* tcp netconns don't come here! */ /* Trigger select() in socket layer. This send should something else so the errorfd is set, not the read and write fd! */ API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); if (msg->conn->op_completed != SYS_SEM_NULL) { sys_sem_signal(msg->conn->op_completed); } }
int32_t MTD_FLASHMEM ICMP::ping(IPAddress const& dest) { static uint32_t const TIMEOUT = 4000; static int32_t const TIMEOUT_RESULT = -1; uint32_t result = TIMEOUT_RESULT; // generate seq m_waitingSeq++; // prepare packet to send pbuf* hdrbuf = pbuf_alloc(PBUF_IP, sizeof(icmp_echo_hdr), PBUF_RAM); icmp_echo_hdr* hdr = (icmp_echo_hdr*)hdrbuf->payload; hdr->type = ICMP_ECHO; hdr->code = 0; hdr->chksum = 0; hdr->id = htons(m_waitingID); hdr->seqno = htons(m_waitingSeq); hdr->chksum = inet_chksum((uint16_t*)hdr, sizeof(icmp_echo_hdr)); // send Echo request raw_pcb* pcb = raw_new(IP_PROTO_ICMP); raw_recv(pcb, ICMP::raw_recv_fn, this); raw_bind(pcb, IP_ADDR_ANY); ip_addr_t addr = dest.get_ip_addr_t(); raw_sendto(pcb, hdrbuf, &addr); pbuf_free(hdrbuf); uint32_t t1 = micros(); if (m_queue.receive(TIMEOUT)) result = (micros() - t1); raw_remove(pcb); return result; }
void remove(const E elem) { raw_remove((const void*) elem); }
cmd_state_t cmd_ping(int argc, char* argv[], void* ctx) { static enum { INIT, PING, WAIT_REPLY } state = INIT; struct ping_info_t *ping_info = &INFO; static struct raw_pcb *pcb; switch (state) { case INIT: if (init_ping_info(argc, argv, ping_info) != 0) { printk("Usage: ping [-c count] [-i interval] " \ "[-s packetsize]\n " \ "[-w deadline] [-q] destination\n"); return CMD_DONE; } if (!(pcb = raw_new(IP_PROTO_ICMP))) { printk("could not allocate pcb\n"); state = INIT; return CMD_DONE; } raw_recv(pcb, ping_recv, ping_info); raw_bind(pcb, IP_ADDR_ANY); printk("PING %s %d(%d) bytes of data\n", ip2str(ping_info->destination), ping_info->data_size, ping_info->size); state = PING; /* fall through */ case PING: if (!netif_is_up(netif_default)) { printk("netif is down\n"); raw_remove(pcb); state = INIT; return CMD_DONE; } if (ping_info->count && ping_info->num_tx == ping_info->count) { ping_finalize(ping_info); raw_remove(pcb); state = INIT; return CMD_DONE; } if (timer_get_ms() < ping_info->last_rx_tm + ping_info->interval) { return CMD_INPROGRESS; } ping_send(pcb, ping_info); state = WAIT_REPLY; return CMD_INPROGRESS; case WAIT_REPLY: if (ping_info->flags & PING_REPLY) { ping_info->flags &= (~PING_REPLY); state = PING; return CMD_INPROGRESS; } if (timer_get_ms() > ping_info->last_tx_tm + ping_info->timeout) { if (!ping_info->quiet) printk("timeout from %s\n", ip2str(ping_info->destination)); state = PING; return CMD_INPROGRESS; } if (ping_info->deadline && timer_get_ms() > ping_info->first_tx_tm + ping_info->deadline * 1000) { ping_finalize(ping_info); raw_remove(pcb); state = INIT; return CMD_DONE; } return CMD_INPROGRESS; } /* unreachable */ assert(0); return CMD_DONE; }