Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc_tcp: align with sock tcp #16493

Merged
merged 1 commit into from Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions sys/include/net/gnrc/tcp.h
Expand Up @@ -101,6 +101,14 @@ int gnrc_tcp_init(void);
*/
void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb);

/**
* @brief Initialize Transmission Control Block (TCB) queue
* @pre @p queue must not be NULL.
*
* @param[in,out] queue TCB queue to initialize.
*/
void gnrc_tcp_tcb_queue_init(gnrc_tcp_tcb_queue_t *queue);

/**
* @brief Opens a connection.
*
Expand Down Expand Up @@ -168,6 +176,7 @@ int gnrc_tcp_listen(gnrc_tcp_tcb_queue_t *queue, gnrc_tcp_tcb_t *tcbs, size_t tc
*
* @return 0 on success.
* @return -ENOMEM if all connection in @p queue were already accepted.
* @return -EINVAL if listen was never called on queue.
* @return -EAGAIN if @p user_timeout_duration_ms was 0 and no connection is ready to accept.
* @return -ETIMEDOUT if @p user_timeout_duration_ms was not 0 and no connection
* could be established.
Expand Down Expand Up @@ -263,6 +272,48 @@ void gnrc_tcp_abort(gnrc_tcp_tcb_t *tcb);
*/
void gnrc_tcp_stop_listen(gnrc_tcp_tcb_queue_t *queue);

/**
* @brief Get the local end point of a connected TCB
*
* @pre tcb must not be NULL
* @pre ep must not be NULL
*
* @param[in] tcb TCB holding the connection information.
* @param[out] ep The local end point.
*
* @return 0 on success.
* @return -EADDRNOTAVAIL, when @p tcb in not in a connected state.
*/
int gnrc_tcp_get_local(gnrc_tcp_tcb_t *tcb, gnrc_tcp_ep_t *ep);

/**
* @brief Get the remote end point of a connected TCB
*
* @pre tcb must not be NULL
* @pre ep must not be NULL
*
* @param[in] tcb TCB holding the connection information.
* @param[out] ep The remote end point.
*
* @return 0 on success.
* @return -ENOTCONN, when @p tcb in not in a connected state.
*/
int gnrc_tcp_get_remote(gnrc_tcp_tcb_t *tcb, gnrc_tcp_ep_t *ep);

/**
* @brief Gets the local end point of a TCB queue
*
* @pre queue must not be NULL
* @pre ep must not be NULL
*
* @param[in] queue TCB queue to stop listening
* @param[out] ep The local end point.
*
* @return 0 on success.
* @return -EADDRNOTAVAIL, when @p queue has no local end point.
*/
int gnrc_tcp_queue_get_local(gnrc_tcp_tcb_queue_t *queue, gnrc_tcp_ep_t *ep);

/**
* @brief Calculate and set checksum in TCP header.
*
Expand Down
130 changes: 127 additions & 3 deletions sys/net/gnrc/transport_layer/tcp/gnrc_tcp.c
Expand Up @@ -310,6 +310,8 @@ int gnrc_tcp_init(void)
void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb)
{
TCP_DEBUG_ENTER;
assert(tcb != NULL);

memset(tcb, 0, sizeof(gnrc_tcp_tcb_t));
#ifdef MODULE_GNRC_IPV6
tcb->address_family = AF_INET6;
Expand All @@ -324,6 +326,16 @@ void gnrc_tcp_tcb_init(gnrc_tcp_tcb_t *tcb)
TCP_DEBUG_LEAVE;
}

void gnrc_tcp_tcb_queue_init(gnrc_tcp_tcb_queue_t *queue)
{
TCP_DEBUG_ENTER;
assert(queue != NULL);

mutex_init(&queue->lock);
queue->tcbs = NULL;
queue->tcbs_len = 0;
TCP_DEBUG_LEAVE;
}

int gnrc_tcp_open(gnrc_tcp_tcb_t *tcb, const gnrc_tcp_ep_t *remote, uint16_t local_port)
{
Expand Down Expand Up @@ -561,14 +573,19 @@ int gnrc_tcp_accept(gnrc_tcp_tcb_queue_t *queue, gnrc_tcp_tcb_t **tcb,
++avail_tcbs;
}

/* Return if a connection was found, accept was called as non-blocking or all
* TCBs were already accepted.
/* Return if a connection was found, queue is not listening, accept was called as non-blocking
* or all TCBs were already accepted.
*/
if ((*tcb) || (user_timeout_duration_ms == 0) || (avail_tcbs == 0)) {
if ((*tcb) || (queue->tcbs == NULL) || (user_timeout_duration_ms == 0) ||
(avail_tcbs == 0)) {
if (*tcb) {
TCP_DEBUG_INFO("Accepting connection.");
ret = 0;
}
else if (queue->tcbs == NULL) {
TCP_DEBUG_ERROR("-EINVAL: Queue is not listening.");
ret = -EINVAL;
}
else if (avail_tcbs == 0) {
TCP_DEBUG_ERROR("-ENOMEM: All TCBs are currently accepted.");
ret = -ENOMEM;
Expand Down Expand Up @@ -933,6 +950,113 @@ void gnrc_tcp_stop_listen(gnrc_tcp_tcb_queue_t *queue)
TCP_DEBUG_LEAVE;
}

int gnrc_tcp_get_local(gnrc_tcp_tcb_t *tcb, gnrc_tcp_ep_t *ep)
{
TCP_DEBUG_ENTER;
assert(tcb != NULL);
assert(ep != NULL);

int ret = 0;

/* Lock the TCB for this function call */
mutex_lock(&(tcb->function_lock));
_gnrc_tcp_fsm_state_t state =_gnrc_tcp_fsm_get_state(tcb);

/* Check if connection is established */
if ((state == FSM_STATE_ESTABLISHED) || (state == FSM_STATE_CLOSE_WAIT)) {
/* Construct endpoint from connection parameters */
ep->family = tcb->address_family;
ep->port = tcb->local_port;
ep->netif = tcb->ll_iface;
#ifdef MODULE_GNRC_IPV6
if (ep->family == AF_INET6) {
memcpy(ep->addr.ipv6, tcb->local_addr, sizeof(ep->addr.ipv6));
}
#endif
} else {
TCP_DEBUG_ERROR("-EADDRNOTAVAIL: TCB is not connected.");
ret = -EADDRNOTAVAIL;
}

mutex_unlock(&(tcb->function_lock));
TCP_DEBUG_LEAVE;
return ret;
}

int gnrc_tcp_get_remote(gnrc_tcp_tcb_t *tcb, gnrc_tcp_ep_t *ep)
{
TCP_DEBUG_ENTER;
assert(tcb != NULL);
assert(ep != NULL);

int ret = 0;

/* Lock the TCB for this function call */
mutex_lock(&(tcb->function_lock));
_gnrc_tcp_fsm_state_t state =_gnrc_tcp_fsm_get_state(tcb);

/* Check if connection is established */
if ((state == FSM_STATE_ESTABLISHED) || (state == FSM_STATE_CLOSE_WAIT)) {
/* Construct endpoint from connection parameters */
ep->family = tcb->address_family;
ep->port = tcb->peer_port;
ep->netif = 0;
#ifdef MODULE_GNRC_IPV6
if (ep->family == AF_INET6) {
memcpy(ep->addr.ipv6, tcb->peer_addr, sizeof(ep->addr.ipv6));
}
#endif
} else {
TCP_DEBUG_ERROR("-ENOTCONN: TCB is not connected.");
ret = -ENOTCONN;
}

mutex_unlock(&(tcb->function_lock));
TCP_DEBUG_LEAVE;
return ret;
}

int gnrc_tcp_queue_get_local(gnrc_tcp_tcb_queue_t *queue, gnrc_tcp_ep_t *ep)
{
TCP_DEBUG_ENTER;
assert(queue != NULL);
assert(ep != NULL);

int ret = 0;

/* Lock the TCB queue for this function call */
mutex_lock(&(queue->lock));

/* Check if queue has associated TCBs */
if (queue->tcbs) {
/* There are listening TCBs: Construct ep from first TCB. */
gnrc_tcp_tcb_t *tcb = queue->tcbs;
mutex_lock(&(tcb->function_lock));

/* Construct endpoint from tcbs connection parameters */
ep->family = tcb->address_family;
ep->port = tcb->local_port;
ep->netif = 0;
#ifdef MODULE_GNRC_IPV6
if (ep->family == AF_INET6) {
if (tcb->status & STATUS_ALLOW_ANY_ADDR) {
ipv6_addr_set_unspecified((ipv6_addr_t *) ep->addr.ipv6);
} else {
memcpy(ep->addr.ipv6, tcb->local_addr, sizeof(ep->addr.ipv6));
}
}
#endif
mutex_unlock(&(tcb->function_lock));
} else {
TCP_DEBUG_ERROR("-EADDRNOTAVAIL: queue was never listening.");
ret = -EADDRNOTAVAIL;
}

mutex_unlock(&(queue->lock));
TCP_DEBUG_LEAVE;
return ret;
}

int gnrc_tcp_calc_csum(const gnrc_pktsnip_t *hdr, const gnrc_pktsnip_t *pseudo_hdr)
{
TCP_DEBUG_ENTER;
Expand Down
82 changes: 82 additions & 0 deletions tests/gnrc_tcp/main.c
Expand Up @@ -217,6 +217,10 @@ int gnrc_tcp_accept_cmd(int argc, char **argv)
int timeout = atol(argv[1]);
int err = gnrc_tcp_accept(&queue, &tmp, timeout);
switch (err) {
case -EINVAL:
printf("%s: returns -EINVAL\n", argv[0]);
break;

case -EAGAIN:
printf("%s: returns -EAGAIN\n", argv[0]);
break;
Expand Down Expand Up @@ -341,6 +345,78 @@ int gnrc_tcp_stop_listen_cmd(int argc, char **argv)
return 0;
}

int gnrc_tcp_get_local_cmd(int argc, char **argv)
{
dump_args(argc, argv);
gnrc_tcp_ep_t ep;

int err = gnrc_tcp_get_local(tcb, &ep);
switch (err) {
case 0:
printf("%s: returns 0\n", argv[0]);
printf("Endpoint: addr.ipv6=");
ipv6_addr_print((ipv6_addr_t *) ep.addr.ipv6);
printf(" netif=%u port=%u\n", ep.netif, ep.port);
break;

case -EADDRNOTAVAIL:
printf("%s: returns -EADDRNOTAVAIL\n", argv[0]);
break;

default:
printf("%s: returns %d\n", argv[0], err);
}
return 0;
}

int gnrc_tcp_get_remote_cmd(int argc, char **argv)
{
dump_args(argc, argv);
gnrc_tcp_ep_t ep;

int err = gnrc_tcp_get_remote(tcb, &ep);
switch (err) {
case 0:
printf("%s: returns 0\n", argv[0]);
printf("Endpoint: addr.ipv6=");
ipv6_addr_print((ipv6_addr_t *) ep.addr.ipv6);
printf(" netif=%u port=%u\n", ep.netif, ep.port);
break;

case -ENOTCONN:
printf("%s: returns -ENOTCONN\n", argv[0]);
break;

default:
printf("%s: returns %d\n", argv[0], err);
}
return 0;
}

int gnrc_tcp_queue_get_local_cmd(int argc, char **argv)
{
dump_args(argc, argv);
gnrc_tcp_ep_t ep;

int err = gnrc_tcp_queue_get_local(&queue, &ep);
switch (err) {
case 0:
printf("%s: returns 0\n", argv[0]);
printf("Endpoint: addr.ipv6=");
ipv6_addr_print((ipv6_addr_t *) ep.addr.ipv6);
printf(" netif=%u port=%u\n", ep.netif, ep.port);
break;

case -EADDRNOTAVAIL:
printf("%s: returns -EADDRNOTAVAIL\n", argv[0]);
break;

default:
printf("%s: returns %d\n", argv[0], err);
}
return 0;
}

/* Exporting GNRC TCP Api to for shell usage */
static const shell_command_t shell_commands[] = {
{ "gnrc_tcp_ep_from_str", "Build endpoint from string",
Expand All @@ -363,6 +439,12 @@ static const shell_command_t shell_commands[] = {
gnrc_tcp_abort_cmd },
{ "gnrc_tcp_stop_listen", "gnrc_tcp: stop listening",
gnrc_tcp_stop_listen_cmd },
{ "gnrc_tcp_get_local", "gnrc_tcp: get local",
gnrc_tcp_get_local_cmd },
{ "gnrc_tcp_get_remote", "gnrc_tcp: get remote",
gnrc_tcp_get_remote_cmd },
{ "gnrc_tcp_queue_get_local", "gnrc_tcp: get queue local",
gnrc_tcp_queue_get_local_cmd },
{ "buffer_init", "init internal buffer",
buffer_init_cmd },
{ "buffer_get_max_size", "get max size of internal buffer",
Expand Down