static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, reason, tcp->refcount.count, tcp->refcount.count - 1); if (gpr_unref(&tcp->refcount)) { tcp_free(tcp); } }
void transport_free(rdpTransport* transport) { if (transport) { if (transport->async) { assert(!transport->thread); assert(!transport->stopEvent); } if (transport->ReceiveBuffer) Stream_Release(transport->ReceiveBuffer); StreamPool_Free(transport->ReceivePool); CloseHandle(transport->ReceiveEvent); CloseHandle(transport->connectedEvent); if (transport->TlsIn) tls_free(transport->TlsIn); if (transport->TlsOut != transport->TlsIn) tls_free(transport->TlsOut); transport->TlsIn = NULL; transport->TlsOut = NULL; if (transport->TcpIn) tcp_free(transport->TcpIn); if (transport->TcpOut != transport->TcpIn) tcp_free(transport->TcpOut); transport->TcpIn = NULL; transport->TcpOut = NULL; tsg_free(transport->tsg); transport->tsg = NULL; CloseHandle(transport->ReadMutex); CloseHandle(transport->WriteMutex); free(transport); } }
int main(int argc, char **argv) { struct sigaction sig_stop; struct sigaction sig_time; _main = main_init(argc, argv); _log = log_init(); _main->conf = conf_init(argc, argv); _main->work = work_init(); _main->tcp = tcp_init(); _main->node = node_init(); _main->mime = mime_init(); /* Check configuration */ conf_print(); /* Catch SIG INT */ unix_signal(&sig_stop, &sig_time); /* Fork daemon */ unix_fork(log_console(_log)); /* Increase limits */ unix_limits(_main->conf->cores, CONF_EPOLL_MAX_EVENTS); /* Load mime types */ mime_load(); mime_hash(); /* Prepare TCP daemon */ tcp_start(); /* Drop privileges */ unix_dropuid0(); /* Start worker threads */ work_start(); /* Stop worker threads */ work_stop(); /* Stop TCP daemon */ tcp_stop(); mime_free(); node_free(); tcp_free(); work_free(); conf_free(); log_free(_log); main_free(); return 0; }
void transport_free(rdpTransport* transport) { if (transport != NULL) { stream_free(transport->recv_buffer); stream_free(transport->recv_stream); stream_free(transport->send_stream); wait_obj_free(transport->recv_event); if (transport->tls) tls_free(transport->tls); tcp_free(transport->tcp); tcp_free(transport->tcp_in); tsg_free(transport->tsg); xfree(transport); } }
void transport_free(rdpTransport* transport) { if (transport != NULL) { stream_free(transport->recv_buffer); stream_free(transport->recv_stream); stream_free(transport->send_stream); tcp_free(transport->tcp); xfree(transport); } }
void iso_free(rdpIso * iso) { if (iso != NULL) { tcp_free(iso->tcp); if (iso->nego != NULL) nego_free(iso->nego); xfree(iso); } }
void transport_free(rdpTransport* transport) { if (!transport) return; transport_stop(transport); if (transport->ReceiveBuffer) Stream_Release(transport->ReceiveBuffer); StreamPool_Free(transport->ReceivePool); CloseHandle(transport->ReceiveEvent); CloseHandle(transport->connectedEvent); if (transport->TlsIn) tls_free(transport->TlsIn); if (transport->TlsOut != transport->TlsIn) tls_free(transport->TlsOut); transport->TlsIn = NULL; transport->TlsOut = NULL; if (transport->TcpIn) tcp_free(transport->TcpIn); if (transport->TcpOut != transport->TcpIn) tcp_free(transport->TcpOut); transport->TcpIn = NULL; transport->TcpOut = NULL; tsg_free(transport->tsg); transport->tsg = NULL; DeleteCriticalSection(&(transport->ReadLock)); DeleteCriticalSection(&(transport->WriteLock)); free(transport); }
static int search_n_handoff(int parent) { int fd; struct file *filp; struct tcp_socket_data *sock; struct tcb *tcb_tmp; extern struct tcb *tcp_handoff(struct tcb *parent); extern void tcp_free(struct tcb *tcb); printf("start search_n_handoff: %d\n",parent); for(fd = 0; fd < NR_OPEN ; fd++) { if (__current->fd[fd] != NULL) { filp = __current->fd[fd]; if (filp->op_type == TCP_SOCKET_TYPE) { if (parent) { printf("SENDING fd: %d\n",fd); pr_filp(filp,"SENDING FILP"); /* put the tcb in our shared table */ sock = (struct tcp_socket_data *) &filp->data; printf("SOCK addr %p\n",sock); /* now sock->tcb will point to a shared location */ demand(sock->tcb, bogus tcb); printf("\ntcb before\n"); tcb_print(sock->tcb); tcb_tmp = sock->tcb; sock->tcb = puttcb(sock->tcb); printf("\ntcb after\n"); tcb_print(sock->tcb); tcp_free(tcb_tmp); printf("--\n"); } else { printf("RECEIVING fd: %d\n",fd); pr_filp(filp,"RECEIVING FILP"); /* grab the tcb from the shared table */ sock = (struct tcp_socket_data *) &filp->data; printf("SOCK addr %p\n",sock); /* now sock->tcb will point to a local structure */ printf("\ntcb before\n"); tcb_print(sock->tcb); printf("\ntcb handoff\n"); sock->tcb = tcp_handoff(sock->tcb); printf("\ntcb after\n"); tcb_print(sock->tcb); printf("--\n"); } } } } printf("done search_n_handoff %d\n",parent); return 0; }
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val, val - 1); } if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } }
static void test(int scope) { struct tcpcb tcb1, tcb2, tcb3, tcb4; int i; tcpc_init(scope); printf("\nScope: %s\n", scope == TESLA_SCOPE_GLOBAL ? "global" : "per-thread"); tcpc_setaction_debug(); /* Use printf(), not assert(). */ printf("Sending valid sequence..."); for (i = 0; i < test1_len; i++) { tcb1.t_state = test1[i]; } tcp_free(&tcb1); printf(" OK\n"); printf("Sending invalid sequence...error follows:\n"); for (i = 0; i < test2_len; i++) { tcb2.t_state = test2[i]; } tcp_free(&tcb2); printf(" OK\n"); printf("Initial closed to closed:\n"); for (i = 0; i < test3_len; i++) { tcb3.t_state = test3[i]; } tcp_free(&tcb3); printf(" OK\n"); printf("Free directly from TCPS_LAST_ACK\n"); for (i = 0; i < test4_len; i++) { tcb4.t_state = test4[i]; } tcp_free(&tcb4); printf(" OK\n"); }
rdpTransport* transport_new(rdpSettings* settings) { rdpTransport* transport; transport = (rdpTransport *)calloc(1, sizeof(rdpTransport)); if (!transport) return NULL; WLog_Init(); transport->log = WLog_Get("com.freerdp.core.transport"); if (!transport->log) goto out_free; transport->TcpIn = tcp_new(settings); if (!transport->TcpIn) goto out_free; transport->settings = settings; /* a small 0.1ms delay when transport is blocking. */ transport->SleepInterval = 100; transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE); if (!transport->ReceivePool) goto out_free_tcpin; /* receive buffer for non-blocking read. */ transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); if (!transport->ReceiveBuffer) goto out_free_receivepool; transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!transport->ReceiveEvent || transport->ReceiveEvent == INVALID_HANDLE_VALUE) goto out_free_receivebuffer; transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE) goto out_free_receiveEvent; transport->blocking = TRUE; transport->GatewayEnabled = FALSE; transport->layer = TRANSPORT_LAYER_TCP; if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000)) goto out_free_connectedEvent; if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000)) goto out_free_readlock; return transport; out_free_readlock: DeleteCriticalSection(&(transport->ReadLock)); out_free_connectedEvent: CloseHandle(transport->connectedEvent); out_free_receiveEvent: CloseHandle(transport->ReceiveEvent); out_free_receivebuffer: StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer); out_free_receivepool: StreamPool_Free(transport->ReceivePool); out_free_tcpin: tcp_free(transport->TcpIn); out_free: free(transport); return NULL; }
static void tcp_unref(grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { tcp_free(tcp); } }
FAR struct tcp_conn_s *tcp_alloc(void) { FAR struct tcp_conn_s *conn; net_lock_t flags; /* Because this routine is called from both interrupt level and * and from user level, we have not option but to disable interrupts * while accessing g_free_tcp_connections[]; */ flags = net_lock(); /* Return the entry from the head of the free list */ conn = (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); #ifndef CONFIG_NET_SOLINGER /* Is the free list empty? */ if (!conn) { /* As a fall-back, check for connection structures which can be stalled. * * Search the active connection list for the oldest connection * that is about to be closed anyway. */ FAR struct tcp_conn_s *tmp = (FAR struct tcp_conn_s *)g_active_tcp_connections.head; while (tmp) { nllvdbg("conn: %p state: %02x\n", tmp, tmp->tcpstateflags); /* Is this connection in a state we can sacrifice. */ /* REVISIT: maybe we could check for SO_LINGER but it's buried * in the socket layer. */ if (tmp->tcpstateflags == TCP_CLOSING || tmp->tcpstateflags == TCP_FIN_WAIT_1 || tmp->tcpstateflags == TCP_FIN_WAIT_2 || tmp->tcpstateflags == TCP_TIME_WAIT || tmp->tcpstateflags == TCP_LAST_ACK) { /* Yes.. Is it the oldest one we have seen so far? */ if (!conn || tmp->timer > conn->timer) { /* Yes.. remember it */ conn = tmp; } } /* Look at the next active connection */ tmp = (FAR struct tcp_conn_s *)tmp->node.flink; } /* Did we find a connection that we can re-use? */ if (conn != NULL) { nlldbg("Closing unestablished connection: %p\n", conn); /* Yes... free it. This will remove the connection from the list * of active connections and release all resources held by the * connection. * * REVISIT: Could there be any higher level, socket interface * that needs to be informed that we did this to them? * * Actually yes. When CONFIG_NET_SOLINGER is enabled there is a * pending callback in netclose_disconnect waiting for getting * woken up. Otherwise there's the callback too, but no one is * waiting for it. */ tcp_free(conn); /* Now there is guaranteed to be one free connection. Get it! */ conn = (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); } } #endif net_unlock(flags); /* Mark the connection allocated */ if (conn) { memset(conn, 0, sizeof(struct tcp_conn_s)); conn->tcpstateflags = TCP_ALLOCATED; } return conn; }
static inline int netclose_disconnect(FAR struct socket *psock) { struct tcp_close_s state; FAR struct tcp_conn_s *conn; net_lock_t flags; #ifdef CONFIG_NET_SOLINGER bool linger; #endif int ret = OK; /* Interrupts are disabled here to avoid race conditions */ flags = net_lock(); conn = (FAR struct tcp_conn_s *)psock->s_conn; /* If we have a semi-permanent write buffer callback in place, then * release it now. */ #ifdef CONFIG_NET_TCP_WRITE_BUFFERS if (psock->s_sndcb) { tcp_callback_free(conn, psock->s_sndcb); psock->s_sndcb = NULL; } #endif /* There shouldn't be any callbacks registered. */ DEBUGASSERT(conn && conn->list == NULL); /* Check for the case where the host beat us and disconnected first */ if (conn->tcpstateflags == TCP_ESTABLISHED && (state.cl_cb = tcp_callback_alloc(conn)) != NULL) { /* Set up to receive TCP data event callbacks */ state.cl_cb->flags = (TCP_NEWDATA | TCP_POLL | TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT); state.cl_cb->event = netclose_interrupt; #ifdef CONFIG_NET_SOLINGER /* Check for a lingering close */ linger = _SO_GETOPT(psock->s_options, SO_LINGER); /* Has a lingering close been requested */ if (linger) { /* A non-NULL value of the priv field means that lingering is * enabled. */ state.cl_cb->priv = (FAR void *)&state; /* Set up for the lingering wait */ state.cl_psock = psock; state.cl_result = -EBUSY; sem_init(&state.cl_sem, 0, 0); /* Record the time that we started the wait (in ticks) */ state.cl_start = clock_systimer(); } else #endif /* CONFIG_NET_SOLINGER */ { /* We will close immediately. The NULL priv field signals this */ state.cl_cb->priv = NULL; /* No further references on the connection */ conn->crefs = 0; } /* Notify the device driver of the availability of TX data */ netdev_txnotify(conn->ripaddr); #ifdef CONFIG_NET_SOLINGER /* Wait only if we are lingering */ if (linger) { /* Wait for the disconnect event */ (void)net_lockedwait(&state.cl_sem); /* We are now disconnected */ sem_destroy(&state.cl_sem); tcp_callback_free(conn, state.cl_cb); /* Free the connection */ conn->crefs = 0; /* No more references on the connection */ tcp_free(conn); /* Free uIP resources */ /* Get the result of the close */ ret = state.cl_result; } #endif /* CONFIG_NET_SOLINGER */ } else { tcp_free(conn); } net_unlock(flags); return ret; }
static uint16_t netclose_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { #ifdef CONFIG_NET_SOLINGER FAR struct tcp_close_s *pstate = (FAR struct tcp_close_s *)pvpriv; #endif FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; DEBUGASSERT(conn != NULL); nllvdbg("conn: %p flags: %04x\n", conn, flags); /* TCP_CLOSE: The remote host has closed the connection * TCP_ABORT: The remote host has aborted the connection * TCP_TIMEDOUT: The remote did not respond, the connection timed out */ if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { /* The disconnection is complete */ #ifdef CONFIG_NET_SOLINGER /* pstate non-NULL means that we are performing a LINGERing close.*/ if (pstate) { /* Wake up the waiting thread with a successful result */ pstate->cl_result = OK; goto end_wait; } /* Otherwise, nothing is waiting on the close event and we can perform * the completion actions here. */ else #endif { /* Free connection resources */ tcp_free(conn); /* Stop further callbacks */ flags = 0; } } #ifdef CONFIG_NET_SOLINGER /* Check for a timeout. */ else if (pstate && close_timeout(pstate)) { /* Yes.. Wake up the waiting thread and report the timeout */ nlldbg("CLOSE timeout\n"); pstate->cl_result = -ETIMEDOUT; goto end_wait; } #endif /* CONFIG_NET_SOLINGER */ #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Check if all outstanding bytes have been ACKed */ else if (conn->unacked != 0) { /* No... we are still waiting for ACKs. Drop any received data, but * do not yet report TCP_CLOSE in the response. */ dev->d_len = 0; flags = (flags & ~TCP_NEWDATA); } #endif /* CONFIG_NET_TCP_WRITE_BUFFERS */ else { /* Drop data received in this state and make sure that TCP_CLOSE * is set in the response */ dev->d_len = 0; flags = (flags & ~TCP_NEWDATA) | TCP_CLOSE; } return flags; #ifdef CONFIG_NET_SOLINGER end_wait: pstate->cl_cb->flags = 0; pstate->cl_cb->priv = NULL; pstate->cl_cb->event = NULL; sem_post(&pstate->cl_sem); nllvdbg("Resuming\n"); return 0; #endif }
void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, int hsec) { uint16_t result; uint8_t hdrlen; /* Set up for the callback. We can't know in advance if the application * is going to send a IPv4 or an IPv6 packet, so this setup may not * actually be used. Furthermore, the TCP logic is required to call * tcp_ipv4_select() or tcp_ipv6_select() prior to sending any packets. * We will try to set the correct value here basic on the binding of * the connection. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET) #endif { hdrlen = IPv4TCP_HDRLEN; tcp_ipv4_select(dev); } #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif { hdrlen = IPv6TCP_HDRLEN; tcp_ipv6_select(dev); } #endif /* CONFIG_NET_IPv6 */ /* Increase the TCP sequence number */ tcp_nextsequence(); /* Reset the length variables. */ dev->d_len = 0; dev->d_sndlen = 0; /* Check if the connection is in a state in which we simply wait * for the connection to time out. If so, we increase the * connection's timer and remove the connection if it times * out. */ if (conn->tcpstateflags == TCP_TIME_WAIT || conn->tcpstateflags == TCP_FIN_WAIT_2) { unsigned int newtimer; /* Increment the connection timer */ newtimer = (unsigned int)conn->timer + hsec; /* Check if the timer exceeds the timeout value */ if (newtimer >= TCP_TIME_WAIT_TIMEOUT) { /* Set the timer to the maximum value */ conn->timer = TCP_TIME_WAIT_TIMEOUT; /* The TCP connection was established and, hence, should be bound * to a device. Make sure that the polling device is the one that * we are bound to. * * If not, then we will catch the timeout on the next poll from * the correct device. */ DEBUGASSERT(conn->dev != NULL); if (dev != conn->dev) { ninfo("TCP: TCP_CLOSED pending\n"); } else { conn->tcpstateflags = TCP_CLOSED; /* Notify upper layers about the timeout */ result = tcp_callback(dev, conn, TCP_TIMEDOUT); ninfo("TCP state: TCP_CLOSED\n"); } } else { /* No timeout. Just update the incremented timer */ conn->timer = newtimer; } } else if (conn->tcpstateflags != TCP_CLOSED) { /* If the connection has outstanding data, we increase the connection's * timer and see if it has reached the RTO value in which case we * retransmit. */ if (conn->unacked > 0) { /* The connection has outstanding data */ if (conn->timer > hsec) { /* Will not yet decrement to zero */ conn->timer -= hsec; } else { /* Will decrement to zero */ conn->timer = 0; /* The TCP is connected and, hence, should be bound to a * device. Make sure that the polling device is the one that * we are bound to. * * If not, then we will catch the timeout on the next poll * from the correct device. */ DEBUGASSERT(conn->dev != NULL); if (dev != conn->dev) { ninfo("TCP: TCP_CLOSED pending\n"); goto done; } /* Check for a timeout on connection in the TCP_SYN_RCVD state. * On such timeouts, we would normally resend the SYNACK until * the ACK is received, completing the 3-way handshake. But if * the retry count elapsed, then we must assume that no ACK is * forthcoming and terminate the attempted connection. */ if (conn->tcpstateflags == TCP_SYN_RCVD && conn->nrtx >= TCP_MAXSYNRTX) { FAR struct tcp_conn_s *listener; conn->tcpstateflags = TCP_CLOSED; ninfo("TCP state: TCP_SYN_RCVD->TCP_CLOSED\n"); /* Find the listener for this connection. */ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) listener = tcp_findlistener(conn->lport, conn->domain); #else listener = tcp_findlistener(conn->lport); #endif if (listener != NULL) { /* We call tcp_callback() for the connection with * TCP_TIMEDOUT to inform the listener that the * connection has timed out. */ result = tcp_callback(dev, listener, TCP_TIMEDOUT); } /* We also send a reset packet to the remote host. */ tcp_send(dev, conn, TCP_RST | TCP_ACK, hdrlen); /* Finally, we must free this TCP connection structure */ tcp_free(conn); goto done; } /* Otherwise, check for a timeout on an established connection. * If the retry count is exceeded in this case, we should * close the connection. */ else if ( #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired > 0 || #else conn->nrtx >= TCP_MAXRTX || #endif (conn->tcpstateflags == TCP_SYN_SENT && conn->nrtx >= TCP_MAXSYNRTX) ) { conn->tcpstateflags = TCP_CLOSED; ninfo("TCP state: TCP_CLOSED\n"); /* We call tcp_callback() with TCP_TIMEDOUT to * inform the application that the connection has * timed out. */ result = tcp_callback(dev, conn, TCP_TIMEDOUT); /* We also send a reset packet to the remote host. */ tcp_send(dev, conn, TCP_RST | TCP_ACK, hdrlen); goto done; } /* Exponential backoff. */ conn->timer = TCP_RTO << (conn->nrtx > 4 ? 4: conn->nrtx); (conn->nrtx)++; /* Ok, so we need to retransmit. We do this differently * depending on which state we are in. In ESTABLISHED, we * call upon the application so that it may prepare the * data for the retransmit. In SYN_RCVD, we resend the * SYNACK that we sent earlier and in LAST_ACK we have to * retransmit our FINACK. */ #ifdef CONFIG_NET_STATISTICS g_netstats.tcp.rexmit++; #endif switch (conn->tcpstateflags & TCP_STATE_MASK) { case TCP_SYN_RCVD: /* In the SYN_RCVD state, we should retransmit our * SYNACK. */ tcp_ack(dev, conn, TCP_ACK | TCP_SYN); goto done; case TCP_SYN_SENT: /* In the SYN_SENT state, we retransmit out SYN. */ tcp_ack(dev, conn, TCP_SYN); goto done; case TCP_ESTABLISHED: /* In the ESTABLISHED state, we call upon the application * to do the actual retransmit after which we jump into * the code for sending out the packet. */ result = tcp_callback(dev, conn, TCP_REXMIT); tcp_rexmit(dev, conn, result); goto done; case TCP_FIN_WAIT_1: case TCP_CLOSING: case TCP_LAST_ACK: /* In all these states we should retransmit a FINACK. */ tcp_send(dev, conn, TCP_FIN | TCP_ACK, hdrlen); goto done; } } } /* The connection does not have outstanding data. Check if the TCP * connection has been established. */ else if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED) { /* The TCP connection is established and, hence, should be bound * to a device. Make sure that the polling device is the one that * we are bound to. */ DEBUGASSERT(conn->dev != NULL); if (dev == conn->dev) { #ifdef CONFIG_NET_TCP_KEEPALIVE /* Is this an established connected with KeepAlive enabled? */ if (conn->keepalive) { socktimeo_t timeo; uint32_t saveseq; /* If this is the first probe, then the keepstart time is * the time that the last ACK or data was received from the * remote. * * On subsequent retries, keepstart is the time that the * last probe was sent. */ if (conn->keepretries > 0) { timeo = (socktimeo_t)conn->keepintvl; } else { timeo = (socktimeo_t)conn->keepidle; } /* Yes... has the idle period elapsed with no data or ACK * received from the remote peer? */ if (net_timeo(conn->keeptime, timeo)) { /* Yes.. Has the retry count expired? */ if (conn->keepretries >= conn->keepcnt) { /* Yes... stop the network monitor, closing the connection and all sockets * associated with the connection. */ tcp_stop_monitor(conn, TCP_ABORT); } else { unsigned int tcpiplen; /* No.. we need to send another probe. * * Get the size of the IP header and the TCP header. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET) #endif { tcpiplen = IPv4_HDRLEN + TCP_HDRLEN; } #endif #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif { tcpiplen = IPv6_HDRLEN + TCP_HDRLEN; } #endif /* And send the probe (along with a garbage byte). * The packet we sned must have these properties: * * - TCP_ACK flag (only) is set. * - Sequence number is the sequence number of * previously ACKed data, i.e., the expected * sequence number minus one. * - The data payload is one or two bytes. * * tcp_send() will send the TCP sequence number as * conn->sndseq. Rather than creating a new * interface, we spoof tcp_end() here: */ saveseq = tcp_getsequence(conn->sndseq); tcp_setsequence(conn->sndseq, saveseq - 1); tcp_send(dev, conn, TCP_ACK, tcpiplen + 1); tcp_setsequence(conn->sndseq, saveseq); /* Increment the number of un-ACKed bytes due to the dummy * byte that we just sent. */ conn->unacked++; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Increment the un-ACKed sequence number */ conn->sndseq_max++; #endif /* Update for the next probe */ conn->keeptime = clock_systimer(); conn->keepretries++; } goto done; } } #endif /* There was no need for a retransmission and there was no * need to probe the remote peer. We poll the application for * new outgoing data. */ result = tcp_callback(dev, conn, TCP_POLL); tcp_appsend(dev, conn, result); goto done; } } } /* Nothing to be done */ dev->d_len = 0; done: return; }
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } }
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp) { FAR struct tcp_conn_s *conn; uint8_t domain; int ret; /* Get the appropriate IP domain */ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv4) bool ipv6 = IFF_IS_IPv6(dev->d_flags); domain = ipv6 ? PF_INET6 : PF_INET; #elif defined(CONFIG_NET_IPv4) domain = PF_INET; #else /* defined(CONFIG_NET_IPv6) */ domain = PF_INET6; #endif /* Allocate the connection structure */ conn = tcp_alloc(domain); if (conn) { /* Set up the local address (laddr) and the remote address (raddr) * that describes the TCP connection. */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (ipv6) #endif { FAR struct ipv6_hdr_s *ip = IPv6BUF; /* Set the IPv6 specific MSS and the IPv6 locally bound address */ conn->mss = TCP_IPv6_INITIAL_MSS(dev); net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr); #ifdef CONFIG_NETDEV_MULTINIC net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr); /* We now have to filter all outgoing transfers so that they use * only the MSS of this device. */ DEBUGASSERT(conn->dev == NULL || conn->dev == dev); conn->dev = dev; #endif /* Find the device that can receive packets on the network * associated with this local address. */ ret = tcp_remote_ipv6_device(conn); } #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 else #endif { FAR struct ipv4_hdr_s *ip = IPv4BUF; /* Set the IPv6 specific MSS and the IPv4 bound remote address. */ conn->mss = TCP_IPv4_INITIAL_MSS(dev); net_ipv4addr_copy(conn->u.ipv4.raddr, net_ip4addr_conv32(ip->srcipaddr)); #ifdef CONFIG_NETDEV_MULTINIC /* Set the local address as well */ net_ipv4addr_copy(conn->u.ipv4.laddr, net_ip4addr_conv32(ip->destipaddr)); /* We now have to filter all outgoing transfers so that they use * only the MSS of this device. */ DEBUGASSERT(conn->dev == NULL || conn->dev == dev); conn->dev = dev; #endif /* Find the device that can receive packets on the network * associated with this local address. */ ret = tcp_remote_ipv4_device(conn); } #endif /* CONFIG_NET_IPv4 */ /* Verify that a network device that can provide packets to this * local address was found. */ if (ret < 0) { /* If no device is found, then the address is not reachable. * That should be impossible in this context and we should * probably really just assert here. */ nerr("ERROR: Failed to find network device: %d\n", ret); tcp_free(conn); return NULL; } /* Fill in the necessary fields for the new connection. */ conn->rto = TCP_RTO; conn->timer = TCP_RTO; conn->sa = 0; conn->sv = 4; conn->nrtx = 0; conn->lport = tcp->destport; conn->rport = tcp->srcport; conn->tcpstateflags = TCP_SYN_RCVD; tcp_initsequence(conn->sndseq); conn->unacked = 1; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->expired = 0; conn->isn = 0; conn->sent = 0; conn->sndseq_max = 0; #endif /* rcvseq should be the seqno from the incoming packet + 1. */ memcpy(conn->rcvseq, tcp->seqno, 4); #ifdef CONFIG_NET_TCP_READAHEAD /* Initialize the list of TCP read-ahead buffers */ IOB_QINIT(&conn->readahead); #endif #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Initialize the write buffer lists */ sq_init(&conn->write_q); sq_init(&conn->unacked_q); #endif /* And, finally, put the connection structure into the active list. * Interrupts should already be disabled in this context. */ dq_addlast(&conn->node, &g_active_tcp_connections); } return conn; }