err_t echo_poll(void *arg, struct tcp_pcb *tpcb) { err_t ret_err; struct echo_state *es; es = arg; if (es != NULL) { if (es->p != NULL) { /* there is a remaining pbuf (chain) */ tcp_sent(tpcb, echo_sent); echo_send(tpcb, es); } else { /* no remaining pbuf (chain) */ if(es->state == ES_CLOSING) { echo_close(tpcb, es); } } ret_err = ERR_OK; } else { /* nothing to be done */ tcp_abort(tpcb); ret_err = ERR_ABRT; } return ret_err; }
err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { struct echo_state *es; LWIP_UNUSED_ARG(len); es = (struct echo_state *)arg; es->retries = 0; if(es->p != NULL) { /* still got pbufs to send */ tcp_sent(tpcb, echo_sent); echo_send(tpcb, es); } else { /* no more pbufs to send */ if(es->state == ES_CLOSING) { echo_close(tpcb, es); } } return ERR_OK; }
err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { struct echo_state *es; err_t ret_err; LWIP_ASSERT("arg != NULL",arg != NULL); es = arg; if (p == NULL) { /* remote host closed connection */ es->state = ES_CLOSING; if(es->p == NULL) { /* we're done sending, close it */ echo_close(tpcb, es); } else { /* we're not done yet */ tcp_sent(tpcb, echo_sent); echo_send(tpcb, es); } ret_err = ERR_OK; } else if(err != ERR_OK) { /* cleanup, for unkown reason */ if (p != NULL) { es->p = NULL; pbuf_free(p); } ret_err = err; } else if(es->state == ES_ACCEPTED) { /* first data chunk in p->payload */ es->state = ES_RECEIVED; /* store reference to incoming pbuf (chain) */ es->p = p; /* install send completion notifier */ tcp_sent(tpcb, echo_sent); echo_send(tpcb, es); ret_err = ERR_OK; } else if (es->state == ES_RECEIVED) { /* read some more data */ if(es->p == NULL) { es->p = p; tcp_sent(tpcb, echo_sent); echo_send(tpcb, es); } else { struct pbuf *ptr; /* chain pbufs to the end of what we recv'ed previously */ ptr = es->p; pbuf_chain(ptr,p); } ret_err = ERR_OK; } else if(es->state == ES_CLOSING) { /* odd case, remote side closing twice, trash data */ tcp_recved(tpcb, p->tot_len); es->p = NULL; pbuf_free(p); ret_err = ERR_OK; } else { /* unkown es->state, trash data */ tcp_recved(tpcb, p->tot_len); es->p = NULL; pbuf_free(p); ret_err = ERR_OK; } return ret_err; }
int main(int argc, char *argv[]) { NoiseHandshakeState *handshake = 0; NoiseCipherState *send_cipher = 0; NoiseCipherState *recv_cipher = 0; EchoProtocolId id; NoiseProtocolId nid; NoiseBuffer mbuf; size_t message_size; int fd; int err; int ok = 1; int action; /* Parse the command-line options */ if (!parse_options(argc, argv)) return 1; /* Change into the key directory and load all of the keys we'll need */ if (chdir(key_dir) < 0) { perror(key_dir); return 1; } if (!echo_load_private_key ("server_key_25519", server_key_25519, sizeof(server_key_25519))) { return 1; } if (!echo_load_private_key ("server_key_448", server_key_448, sizeof(server_key_448))) { return 1; } if (!echo_load_public_key ("client_key_25519.pub", client_key_25519, sizeof(client_key_25519))) { return 1; } if (!echo_load_public_key ("client_key_448.pub", client_key_448, sizeof(client_key_448))) { return 1; } if (!echo_load_public_key("psk", psk, sizeof(psk))) { return 1; } /* Accept an incoming connection */ fd = echo_accept(port); /* Read the echo protocol identifier sent by the client */ if (ok && !echo_recv_exact(fd, (uint8_t *)&id, sizeof(id))) { fprintf(stderr, "Did not receive the echo protocol identifier\n"); ok = 0; } /* Convert the echo protocol identifier into a Noise protocol identifier */ if (ok && !echo_to_noise_protocol_id(&nid, &id)) { fprintf(stderr, "Unknown echo protocol identifier\n"); ok = 0; } /* Create a HandshakeState object to manage the server's handshake */ if (ok) { err = noise_handshakestate_new_by_id (&handshake, &nid, NOISE_ROLE_RESPONDER); if (err != NOISE_ERROR_NONE) { noise_perror("create handshake", err); ok = 0; } } /* Set all keys that are needed by the client's requested echo protocol */ if (ok) { if (!initialize_handshake(handshake, &nid, &id, sizeof(id))) { ok = 0; } } /* Start the handshake */ if (ok) { err = noise_handshakestate_start(handshake); if (err != NOISE_ERROR_NONE) { noise_perror("start handshake", err); ok = 0; } } /* Run the handshake until we run out of things to read or write */ while (ok) { action = noise_handshakestate_get_action(handshake); if (action == NOISE_ACTION_WRITE_MESSAGE) { /* Write the next handshake message with a zero-length payload */ noise_buffer_set_output(mbuf, message + 2, sizeof(message) - 2); err = noise_handshakestate_write_message(handshake, &mbuf, NULL); if (err != NOISE_ERROR_NONE) { noise_perror("write handshake", err); ok = 0; break; } message[0] = (uint8_t)(mbuf.size >> 8); message[1] = (uint8_t)mbuf.size; if (!echo_send(fd, message, mbuf.size + 2)) { ok = 0; break; } } else if (action == NOISE_ACTION_READ_MESSAGE) {