HelenOS sources
This source file includes following definitions.
- tcp_inet_ev_recv
- tcp_transmit_pdu
- tcp_received_pdu
- tcp_inet_init
#include <bitops.h>
#include <byteorder.h>
#include <errno.h>
#include <inet/inet.h>
#include <mem.h>
#include <io/log.h>
#include <stdlib.h>
#include "inet.h"
#include "pdu.h"
#include "rqueue.h"
#include "std.h"
#define NAME "tcp"
static errno_t tcp_inet_ev_recv(inet_dgram_t *dgram);
static void tcp_received_pdu(tcp_pdu_t *pdu);
static inet_ev_ops_t tcp_inet_ev_ops = {
.recv = tcp_inet_ev_recv
};
static errno_t tcp_inet_ev_recv(inet_dgram_t *dgram)
{
uint8_t *pdu_raw;
size_t pdu_raw_size;
log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_inet_ev_recv()");
pdu_raw = dgram->data;
pdu_raw_size = dgram->size;
log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
tcp_pdu_t *pdu;
size_t hdr_size;
tcp_header_t *hdr;
uint32_t data_offset;
if (pdu_raw_size < sizeof(tcp_header_t)) {
log_msg(LOG_DEFAULT, LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
pdu_raw_size, sizeof(tcp_header_t));
return EINVAL;
}
hdr = (tcp_header_t *)pdu_raw;
data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
uint16_t_be2host(hdr->doff_flags));
hdr_size = sizeof(uint32_t) * data_offset;
if (pdu_raw_size < hdr_size) {
log_msg(LOG_DEFAULT, LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
pdu_raw_size, hdr_size);
return EINVAL;
}
if (hdr_size < sizeof(tcp_header_t)) {
log_msg(LOG_DEFAULT, LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
hdr_size, sizeof(tcp_header_t));
return EINVAL;
}
log_msg(LOG_DEFAULT, LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
pdu_raw_size, hdr_size);
pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
pdu_raw_size - hdr_size);
if (pdu == NULL) {
log_msg(LOG_DEFAULT, LVL_WARN, "Failed creating PDU. Dropped.");
return ENOMEM;
}
pdu->src = dgram->src;
pdu->dest = dgram->dest;
tcp_received_pdu(pdu);
tcp_pdu_delete(pdu);
return EOK;
}
void tcp_transmit_pdu(tcp_pdu_t *pdu)
{
errno_t rc;
uint8_t *pdu_raw;
size_t pdu_raw_size;
inet_dgram_t dgram;
pdu_raw_size = pdu->header_size + pdu->text_size;
pdu_raw = malloc(pdu_raw_size);
if (pdu_raw == NULL) {
log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to transmit PDU. Out of memory.");
return;
}
memcpy(pdu_raw, pdu->header, pdu->header_size);
memcpy(pdu_raw + pdu->header_size, pdu->text,
pdu->text_size);
dgram.iplink = 0;
dgram.src = pdu->src;
dgram.dest = pdu->dest;
dgram.tos = 0;
dgram.data = pdu_raw;
dgram.size = pdu_raw_size;
rc = inet_send(&dgram, INET_TTL_MAX, 0);
if (rc != EOK)
log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to transmit PDU.");
free(pdu_raw);
}
static void tcp_received_pdu(tcp_pdu_t *pdu)
{
tcp_segment_t *dseg;
inet_ep2_t rident;
log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_received_pdu()");
if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. PDU dropped.");
return;
}
tcp_rqueue_insert_seg(&rident, dseg);
}
errno_t tcp_inet_init(void)
{
errno_t rc;
log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_inet_init()");
rc = inet_init(IP_PROTO_TCP, &tcp_inet_ev_ops);
if (rc != EOK) {
log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting to internet service.");
return ENOENT;
}
return EOK;
}
HelenOS homepage, sources at GitHub