Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d493830e in mainline


Ignore:
Timestamp:
2010-12-27T19:16:47Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
727f04f
Parents:
58fe0aa
Message:

Fix incoming TCP FIN handling. Signal end of data on the socket. Do not ACK if no new data arrived.

Location:
uspace
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/net/socket_client.c

    r58fe0aa rd493830e  
    10061006        // wait for a received packet
    10071007        ++socket->blocked;
    1008         while ((result = dyn_fifo_value(&socket->received)) <= 0) {
     1008        while ((result = dyn_fifo_value(&socket->received)) < 0) {
    10091009                fibril_rwlock_read_unlock(&socket_globals.lock);
    10101010                fibril_condvar_wait(&socket->receive_signal,
     
    10181018        --socket->blocked;
    10191019        fragments = (size_t) result;
     1020
     1021        if (fragments == 0) {
     1022                /* No more data, other side has closed the connection. */
     1023                return 0;
     1024        }
    10201025
    10211026        // prepare lengths if more fragments
     
    10571062
    10581063                free(lengths);
    1059         } else {
     1064        } else { /* fragments == 1 */
    10601065                // request packet data
    10611066                message_id = async_send_4(socket->phone, message,
  • uspace/srv/net/tl/tcp/tcp.c

    r58fe0aa rd493830e  
    205205static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
    206206    packet_t *, int, size_t);
     207static void tcp_queue_received_end_of_data(socket_core_t *socket);
    207208
    208209static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
     
    504505        size_t offset;
    505506        uint32_t new_sequence_number;
     507        bool forced_ack;
    506508        int rc;
    507509
     
    512514        assert(packet);
    513515
     516        forced_ack = false;
     517
    514518        new_sequence_number = ntohl(header->sequence_number);
    515519        old_incoming = socket_data->next_incoming;
    516520
    517         if (header->finalize)
    518                 socket_data->fin_incoming = new_sequence_number;
     521        if (header->finalize) {
     522                socket_data->fin_incoming = new_sequence_number +
     523                    total_length - TCP_HEADER_LENGTH(header);
     524        }
    519525
    520526        /* Trim begining if containing expected data */
     
    760766                /* Release duplicite or restricted */
    761767                pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
    762         }
    763 
    764         /* Change state according to the acknowledging incoming fin */
    765         if (IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming,
    766             socket_data->next_incoming)) {
     768                forced_ack = true;
     769        }
     770
     771        if (header->finalize)
     772                socket_data->next_incoming += 1;
     773
     774        /* If next in sequence is an incoming FIN */
     775        if (socket_data->next_incoming == socket_data->fin_incoming) {
     776                /* Advance sequence number */
     777                socket_data->next_incoming += 1;
     778
     779                /* Handle FIN */
    767780                switch (socket_data->state) {
    768781                case TCP_SOCKET_FIN_WAIT_1:
     
    771784                        socket_data->state = TCP_SOCKET_CLOSING;
    772785                        break;
    773                 /*case TCP_ESTABLISHED:*/
     786                case TCP_SOCKET_ESTABLISHED:
     787                        /* Queue end-of-data marker on the socket. */
     788                        tcp_queue_received_end_of_data(socket);
     789                        socket_data->state = TCP_SOCKET_CLOSE_WAIT;
     790                        break;
    774791                default:
    775792                        socket_data->state = TCP_SOCKET_CLOSE_WAIT;
     
    779796
    780797        packet = tcp_get_packets_to_send(socket, socket_data);
    781         if (!packet) {
     798        if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) {
    782799                /* Create the notification packet */
    783800                rc = tcp_create_notification_packet(&packet, socket,
     
    835852
    836853        return EOK;
     854}
     855
     856/** Queue end-of-data marker on the socket.
     857 *
     858 * Next element in the sequence space is FIN. Queue end-of-data marker
     859 * on the socket.
     860 *
     861 * @param socket        Socket
     862 */
     863static void tcp_queue_received_end_of_data(socket_core_t *socket)
     864{
     865        assert(socket != NULL);
     866
     867        /* Notify the destination socket */
     868        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
     869            (sysarg_t) socket->socket_id,
     870            0, 0, 0,
     871            (sysarg_t) 0 /* 0 fragments == no more data */);
    837872}
    838873
Note: See TracChangeset for help on using the changeset viewer.