Changeset c76e926 in mainline for uspace/srv/tcp/tcp.c


Ignore:
Timestamp:
2012-02-01T21:18:27Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ecff3d9
Parents:
c8916d15
Message:

Sketch inet client API, inet server. Use inet client API for TCP, make TCP
compile again.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/tcp/tcp.c

    rc8916d15 rc76e926  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2012 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <byteorder.h>
    4040#include <errno.h>
     41#include <inet/inet.h>
    4142#include <io/log.h>
    4243#include <stdio.h>
    4344#include <task.h>
    44 
    45 #include <icmp_remote.h>
    46 #include <ip_client.h>
    47 #include <ip_interface.h>
    48 #include <ipc/services.h>
    49 #include <ipc/tl.h>
    50 #include <tl_common.h>
    51 #include <tl_skel.h>
    52 #include <packet_client.h>
    53 #include <packet_remote.h>
    5445
    5546#include "ncsim.h"
     
    6354#define NAME       "tcp"
    6455
    65 async_sess_t *net_sess;
    66 static async_sess_t *icmp_sess;
    67 async_sess_t *ip_sess;
    68 packet_dimensions_t pkt_dims;
    69 
     56static int tcp_inet_ev_recv(inet_dgram_t *dgram);
    7057static void tcp_received_pdu(tcp_pdu_t *pdu);
    7158
    72 /* Pull up packets into a single memory block. */
    73 static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
    74 {
    75         packet_t *npacket;
    76         size_t tot_len;
    77         int length;
    78 
    79         npacket = packet;
    80         tot_len = 0;
    81         do {
    82                 length = packet_get_data_length(packet);
    83                 if (length <= 0)
    84                         return EINVAL;
    85 
    86                 tot_len += length;
    87         } while ((npacket = pq_next(npacket)) != NULL);
    88 
    89         uint8_t *buf;
    90         uint8_t *dp;
    91 
    92         buf = calloc(tot_len, 1);
    93         if (buf == NULL) {
    94                 free(buf);
    95                 return ENOMEM;
    96         }
    97 
    98         npacket = packet;
    99         dp = buf;
    100         do {
    101                 length = packet_get_data_length(packet);
    102                 if (length <= 0) {
    103                         free(buf);
    104                         return EINVAL;
    105                 }
    106 
    107                 memcpy(dp, packet_get_data(packet), length);
    108                 dp += length;
    109         } while ((npacket = pq_next(npacket)) != NULL);
    110 
    111         *data = buf;
    112         *dsize = tot_len;
    113         return EOK;
    114 }
    115 
    116 /** Process packet received from network layer. */
    117 static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
    118     services_t error)
    119 {
    120         int rc;
    121         size_t offset;
    122         int length;
    123         struct sockaddr_in *src_addr;
    124         struct sockaddr_in *dest_addr;
    125         size_t addr_len;
    126 
    127         log_msg(LVL_DEBUG, "tcp_received_msg()");
    128 
    129         switch (error) {
    130         case SERVICE_NONE:
    131                 break;
    132         case SERVICE_ICMP:
    133         default:
    134                 log_msg(LVL_WARN, "Unsupported service number %u",
    135                     (unsigned)error);
    136                 pq_release_remote(net_sess, packet_get_id(packet));
    137                 return ENOTSUP;
    138         }
    139 
    140         /* Process and trim off IP header */
    141         log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
    142 
    143         rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    144         if (rc < 0) {
    145                 log_msg(LVL_WARN, "ip_client_process_packet() failed");
    146                 pq_release_remote(net_sess, packet_get_id(packet));
    147                 return rc;
    148         }
    149 
    150         offset = (size_t)rc;
    151         length = packet_get_data_length(packet);
    152 
    153         if (length < 0 || (size_t)length < offset) {
    154                 log_msg(LVL_WARN, "length=%d, dropping.", length);
    155                 pq_release_remote(net_sess, packet_get_id(packet));
    156                 return EINVAL;
    157         }
    158 
    159         addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
    160             (uint8_t **)&dest_addr);
    161         if (addr_len <= 0) {
    162                 log_msg(LVL_WARN, "Failed to get packet address.");
    163                 pq_release_remote(net_sess, packet_get_id(packet));
    164                 return EINVAL;
    165         }
    166 
    167         if (addr_len != sizeof(struct sockaddr_in)) {
    168                 log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
    169                     addr_len, sizeof(struct sockaddr_in));
    170                 pq_release_remote(net_sess, packet_get_id(packet));
    171                 return EINVAL;
    172         }
    173 
    174         rc = packet_trim(packet, offset, 0);
    175         if (rc != EOK) {
    176                 log_msg(LVL_WARN, "Failed to trim packet.");
    177                 pq_release_remote(net_sess, packet_get_id(packet));
    178                 return rc;
    179         }
    180 
    181         /* Pull up packets into a single memory block, pdu_raw. */
    182         log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
     59static inet_ev_ops_t tcp_inet_ev_ops = {
     60        .recv = tcp_inet_ev_recv
     61};
     62
     63/** Received datagram callback */
     64static int tcp_inet_ev_recv(inet_dgram_t *dgram)
     65{
    18366        uint8_t *pdu_raw;
    184         size_t pdu_raw_size = 0;
    185 
    186         pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
     67        size_t pdu_raw_size;
     68
     69        log_msg(LVL_DEBUG, "tcp_inet_ev_recv()");
     70
     71        pdu_raw = dgram->data;
     72        pdu_raw_size = dgram->size;
    18773
    18874        /* Split into header and payload. */
    18975
    190         log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
     76        log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
    19177
    19278        tcp_pdu_t *pdu;
     
    19884                log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
    19985                    pdu_raw_size, sizeof(tcp_header_t));
    200                 pq_release_remote(net_sess, packet_get_id(packet));
    20186                return EINVAL;
    20287        }
     
    21196                log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
    21297                    pdu_raw_size, hdr_size);
    213                 pq_release_remote(net_sess, packet_get_id(packet));
    21498                return EINVAL;
    21599        }
     
    217101        if (hdr_size < sizeof(tcp_header_t)) {
    218102                log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
    219                     hdr_size, sizeof(tcp_header_t));
    220                 pq_release_remote(net_sess, packet_get_id(packet));
    221                 return EINVAL;
     103                    hdr_size, sizeof(tcp_header_t));            return EINVAL;
    222104        }
    223105
     
    231113        }
    232114
    233         free(pdu_raw);
    234 
    235         pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
    236         pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
     115        pdu->src_addr.ipv4 = dgram->src.ipv4;
     116        pdu->dest_addr.ipv4 = dgram->dest.ipv4;
    237117        log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
    238118            pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
     
    244124}
    245125
    246 /** Receive packets from network layer. */
    247 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    248 {
    249         packet_t *packet;
    250         int rc;
    251 
    252         log_msg(LVL_DEBUG, "tcp_receiver()");
    253 
    254         while (true) {
    255                 switch (IPC_GET_IMETHOD(*icall)) {
    256                 case NET_TL_RECEIVED:
    257                         log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
    258                         rc = packet_translate_remote(net_sess, &packet,
    259                             IPC_GET_PACKET(*icall));
    260                         if (rc != EOK) {
    261                                 log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
    262                                 async_answer_0(iid, (sysarg_t)rc);
    263                                 break;
    264                         }
    265                         rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
    266                             IPC_GET_ERROR(*icall));
    267                         async_answer_0(iid, (sysarg_t)rc);
    268                         break;
    269                 default:
    270                         log_msg(LVL_DEBUG, "method = %u",
    271                             (unsigned)IPC_GET_IMETHOD(*icall));
    272                         async_answer_0(iid, ENOTSUP);
    273                         break;
    274                 }
    275 
    276                 iid = async_get_call(icall);
    277         }
    278 }
    279 
    280126/** Transmit PDU over network layer. */
    281127void tcp_transmit_pdu(tcp_pdu_t *pdu)
    282128{
    283         struct sockaddr_in dest;
    284         nic_device_id_t dev_id;
    285         void *phdr;
    286         size_t phdr_len;
    287         packet_dimension_t *pkt_dim;
    288129        int rc;
    289         packet_t *packet;
    290         void *pkt_data;
    291         size_t pdu_size;
    292 
    293         dest.sin_family = AF_INET;
    294         dest.sin_port = 0; /* not needed */
    295         dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
    296 
    297         /* Find route. Obtained pseudo-header is not used. */
    298         rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
    299             sizeof(dest), &dev_id, &phdr, &phdr_len);
    300         if (rc != EOK) {
    301                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
     130        uint8_t *pdu_raw;
     131        size_t pdu_raw_size;
     132        inet_dgram_t dgram;
     133
     134        pdu_raw_size = pdu->header_size + pdu->text_size;
     135        pdu_raw = malloc(pdu_raw_size);
     136        if (pdu_raw == NULL) {
     137                log_msg(LVL_ERROR, "Failed to transmit PDU. Out of memory.");
    302138                return;
    303139        }
    304140
    305         rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
    306         if (rc != EOK) {
    307                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
    308                 return;
    309         }
    310 
    311         pdu_size = pdu->header_size + pdu->text_size;
    312 
    313         packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
    314             pkt_dim->prefix, pkt_dim->suffix);
    315         if (!packet) {
    316                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
    317                 return;
    318         }
    319 
    320         pkt_data = packet_suffix(packet, pdu_size);
    321         if (!pkt_data) {
    322                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
    323                 pq_release_remote(net_sess, packet_get_id(packet));
    324                 return;
    325         }
    326 
    327         rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
    328         if (rc != EOK) {
    329                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
    330                 pq_release_remote(net_sess, packet_get_id(packet));
    331                 return;
    332         }
    333 
    334         rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
    335         if (rc != EOK) {
    336                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
    337                 pq_release_remote(net_sess, packet_get_id(packet));
    338                 return;
    339         }
    340 
    341         /* Copy PDU data to packet */
    342         memcpy(pkt_data, pdu->header, pdu->header_size);
    343         memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
     141        memcpy(pdu_raw, pdu->header, pdu->header_size);
     142        memcpy(pdu_raw + pdu->header_size, pdu->text,
    344143            pdu->text_size);
    345144
    346         /* Transmit packet. XXX Transfers packet ownership to IP? */
    347         ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
     145        dgram.src.ipv4 = pdu->src_addr.ipv4;
     146        dgram.dest.ipv4 = pdu->dest_addr.ipv4;
     147        dgram.tos = 0;
     148        dgram.data = pdu_raw;
     149        dgram.size = pdu_raw_size;
     150
     151        rc = inet_send(&dgram, INET_TTL_MAX, 0);
     152        if (rc != EOK)
     153                log_msg(LVL_ERROR, "Failed to transmit PDU.");
    348154}
    349155
     
    365171}
    366172
    367 /* Called from libnet */
    368 void tl_connection(void)
    369 {
    370         log_msg(LVL_DEBUG, "tl_connection()");
    371 }
    372 
    373 /* Called from libnet */
    374 int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    375     size_t *answer_count)
    376 {
    377         async_sess_t *callback;
    378 
    379         log_msg(LVL_DEBUG, "tl_message()");
    380 
    381         *answer_count = 0;
    382         callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
    383         if (callback)
    384                 return tcp_sock_connection(callback, callid, *call);
    385 
    386         return ENOTSUP;
    387 }
    388 
    389 /* Called from libnet */
    390 int tl_initialize(async_sess_t *sess)
     173static int tcp_init(void)
    391174{
    392175        int rc;
    393176
    394         net_sess = sess;
    395         icmp_sess = icmp_connect_module();
    396 
    397         log_msg(LVL_DEBUG, "tl_initialize()");
    398 
    399         tcp_sock_init();
    400 
    401         ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
    402             tcp_receiver);
    403         if (ip_sess == NULL)
     177        log_msg(LVL_DEBUG, "tcp_init()");
     178
     179        tcp_rqueue_init();
     180        tcp_rqueue_thread_start();
     181
     182        tcp_ncsim_init();
     183        tcp_ncsim_thread_start();
     184
     185        if (0) tcp_test();
     186
     187        rc = inet_init(42, &tcp_inet_ev_ops);
     188        if (rc != EOK)
    404189                return ENOENT;
    405190
    406         rc = packet_dimensions_initialize(&pkt_dims);
     191        rc = tcp_sock_init();
    407192        if (rc != EOK)
    408                 return rc;
     193                return ENOENT;
    409194
    410195        return EOK;
     
    423208        }
    424209
    425 //      printf(NAME ": Accepting connections\n");
    426 //      task_retval(0);
    427 
    428         tcp_rqueue_init();
    429         tcp_rqueue_thread_start();
    430 
    431         tcp_ncsim_init();
    432         tcp_ncsim_thread_start();
    433 
    434         if (0) tcp_test();
    435 /*
     210        tcp_init();
     211        task_retval(0);
    436212        async_manager();
    437 */
    438         tl_module_start(SERVICE_TCP);
    439213
    440214        /* Not reached */
Note: See TracChangeset for help on using the changeset viewer.