Line 48... |
Line 48... |
#include "timer.h"
|
#include "timer.h"
|
#include "utilities.h"
|
#include "utilities.h"
|
#include "packet.h"
|
#include "packet.h"
|
#include "tcp.h"
|
#include "tcp.h"
|
#include "telnet.h"
|
#include "telnet.h"
|
|
#include "serial.h"
|
|
|
|
|
/* Global variables */
|
/* Global variables */
|
int tcp_checksum_errors_g = 0;
|
int tcp_checksum_errors_g = 0;
|
socket_t* first_socket_g;
|
socket_t* first_socket_g = NULL;
|
socket_t* socket1_g;
|
|
|
|
/* input argument is a pointer to the previous socket,
|
/* input argument is a pointer to the previous socket,
|
if this is the first socket object, then it is NULL */
|
if this is the first socket object, then it is NULL */
|
socket_t* new_socket(socket_t* prev)
|
socket_t* new_socket(socket_t* prev)
|
{
|
{
|
Line 78... |
Line 79... |
socket->tcp_buf[i]->ending_seq = 0;
|
socket->tcp_buf[i]->ending_seq = 0;
|
socket->tcp_buf[i]->len_bytes = 0;
|
socket->tcp_buf[i]->len_bytes = 0;
|
socket->tcp_buf[i]->ack_received = 0;
|
socket->tcp_buf[i]->ack_received = 0;
|
}
|
}
|
|
|
socket->telnet_txbuf = init_line_buffer(0x80000);
|
|
socket->telnet_rxbuf = init_line_buffer(0x1000);
|
|
|
|
socket->packets_sent = 0;
|
socket->packets_sent = 0;
|
socket->packets_received = 0;
|
socket->packets_received = 0;
|
socket->packets_resent = 0;
|
socket->packets_resent = 0;
|
|
|
socket->telnet_sent_opening_message = 0;
|
|
socket->telnet_echo_mode = 0;
|
|
socket->telnet_connection_state = TELNET_CLOSED;
|
|
socket->telnet_options_sent = 0;
|
|
|
|
socket->tcp_current_buf = 0;
|
socket->tcp_current_buf = 0;
|
socket->tcp_reset = 0;
|
socket->tcp_reset = 0;
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->tcp_disconnect = 0;
|
socket->tcp_disconnect = 0;
|
socket->tcp_seq = 0x100; /* should be random initial seq number for tcp */
|
socket->tcp_tx_seq = 0x100; /* should be random initial seq number for tcp */
|
socket->tcp_last_seq = socket->tcp_seq;
|
socket->tcp_rx_ack = 0;
|
socket->tcp_last_ack = 0;
|
socket->tcp_bytes_received = 0;
|
|
socket->tcp_bytes_acked = 0;
|
|
|
/* Chain the socket objects together */
|
/* Chain the socket objects together */
|
if (prev == NULL){
|
if (prev == NULL){
|
socket->first = socket;
|
socket->first = socket;
|
socket->id = 0;
|
socket->id = 0;
|
Line 115... |
Line 108... |
|
|
return socket;
|
return socket;
|
}
|
}
|
|
|
|
|
|
|
|
/* returns the socket id */
|
|
int listen_socket (unsigned int listen_port, app_t* app)
|
|
{
|
|
socket_t* socket;
|
|
|
|
/* Add a new socket to the end of the list */
|
|
if (first_socket_g == NULL) {
|
|
trace("first_socket_g == NULL");
|
|
first_socket_g = new_socket(NULL);
|
|
socket = first_socket_g;
|
|
}
|
|
else {
|
|
socket = first_socket_g;
|
|
for(;;){
|
|
if (socket->next!=NULL)
|
|
socket=socket->next;
|
|
else
|
|
break;
|
|
}
|
|
socket = new_socket(socket);
|
|
}
|
|
|
|
socket->listen_port = listen_port;
|
|
socket->tcp_connection_state = TCP_LISTENING;
|
|
|
|
/* Assign the telnet object */
|
|
socket->app = app;
|
|
/* cross link, so can find the socket object when have pointer to the telnet object */
|
|
socket->app->socket = socket;
|
|
|
|
trace("new socket %d listening", socket->id);
|
|
|
|
return socket->id;
|
|
}
|
|
|
|
|
|
|
/* All received tcp packets with dset ip == me arrive here */
|
/* All received tcp packets with dset ip == me arrive here */
|
void parse_tcp_packet(char * buf, packet_t* rx_packet)
|
void parse_tcp_packet(char * buf, packet_t* rx_packet)
|
{
|
{
|
int i;
|
int i;
|
int ptr;
|
int ptr;
|
Line 147... |
Line 178... |
rx_packet->tcp_seq = buf[4]<<24|buf[5]<<16|buf[6]<<8|buf[7];
|
rx_packet->tcp_seq = buf[4]<<24|buf[5]<<16|buf[6]<<8|buf[7];
|
rx_packet->tcp_ack = buf[8]<<24|buf[9]<<16|buf[10]<<8|buf[11];
|
rx_packet->tcp_ack = buf[8]<<24|buf[9]<<16|buf[10]<<8|buf[11];
|
rx_packet->tcp_flags = buf[13];
|
rx_packet->tcp_flags = buf[13];
|
rx_packet->tcp_window_size = buf[14]<<8|buf[15];
|
rx_packet->tcp_window_size = buf[14]<<8|buf[15];
|
|
|
|
// trace("client tcp rx window %d bytes",
|
|
// (rx_packet->tcp_window_size)<<rx_packet->tcp_window_scale);
|
|
|
/* only interested in telnet packet to dest port xx */
|
|
if (rx_packet->tcp_dst_port != 23) {
|
|
return;
|
|
}
|
|
|
|
if (rx_packet->tcp_hdr_len > 20) {
|
if (rx_packet->tcp_hdr_len > 20) {
|
/* Get the source time stamp */
|
/* Get the source time stamp */
|
parse_tcp_options(buf, rx_packet);
|
parse_tcp_options(buf, rx_packet);
|
}
|
}
|
|
|
|
|
|
/* only interested in telnet packet to dest port xx */
|
|
//if (rx_packet->tcp_dst_port != 23) {
|
|
// return;
|
|
//}
|
|
|
|
|
/* --------------------------------------------------
|
/* --------------------------------------------------
|
Assign the received packet to a socket
|
Assign the received packet to a socket
|
-------------------------------------------------- */
|
-------------------------------------------------- */
|
/* seach for an open socket that matches the tcp connection */
|
/* seach for an open socket that matches the tcp connection */
|
socket = first_socket_g;
|
socket = first_socket_g;
|
|
if (socket == NULL) {
|
|
trace("first socket is null");
|
|
return;
|
|
}
|
|
|
|
|
|
/* Search for an already open socket */
|
for(;;){
|
for(;;){
|
if (socket->tcp_connection_state != TCP_CLOSED &&
|
if ((socket->tcp_connection_state == TCP_PENDING ||
|
|
socket->tcp_connection_state == TCP_OPEN) &&
|
socket->rx_packet->tcp_src_port == rx_packet->tcp_src_port) {
|
socket->rx_packet->tcp_src_port == rx_packet->tcp_src_port) {
|
found=1;
|
found=1;
|
break;
|
break;
|
}
|
}
|
if (socket->next!=NULL)
|
if (socket->next!=NULL)
|
Line 177... |
Line 220... |
else
|
else
|
break;
|
break;
|
}
|
}
|
|
|
|
|
/* Search for an available closed soeckt to reuse */
|
/* Search for a listening socket */
|
if (!found){
|
if (!found){
|
socket = first_socket_g;
|
socket = first_socket_g;
|
|
trace("search for listening socket");
|
|
|
for(;;){
|
for(;;){
|
if (socket->tcp_connection_state == TCP_CLOSED) {
|
if (socket->tcp_connection_state == TCP_LISTENING) {
|
|
if (socket->listen_port == rx_packet->tcp_dst_port) {
|
found=1;
|
found=1;
|
break;
|
break;
|
}
|
}
|
|
}
|
if (socket->next!=NULL)
|
if (socket->next!=NULL)
|
socket=socket->next;
|
socket=socket->next;
|
else
|
else
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
|
|
/* All available sockets being used. Add a new one to the end of the chain */
|
/* All available sockets being used. Add a new one to the end of the chain */
|
if (!found) {
|
if (!found) {
|
socket = new_socket(socket);
|
trace("not found");
|
|
return;
|
}
|
}
|
|
|
|
|
/* Copy the rx_packet structure into the socket */
|
/* Copy the rx_packet structure into the socket */
|
memcpy(socket->rx_packet, rx_packet, sizeof(packet_t));
|
memcpy(socket->rx_packet, rx_packet, sizeof(packet_t));
|
|
|
tcp_response(buf, socket);
|
tcp_response(buf, socket);
|
}
|
}
|
Line 217... |
Line 264... |
while (ptr < rx_packet->tcp_hdr_len-1) {
|
while (ptr < rx_packet->tcp_hdr_len-1) {
|
switch (buf[ptr]) {
|
switch (buf[ptr]) {
|
case 0: ptr=rx_packet->tcp_hdr_len; break; // end of options
|
case 0: ptr=rx_packet->tcp_hdr_len; break; // end of options
|
case 1: ptr++; break;
|
case 1: ptr++; break;
|
case 2: ptr = ptr + buf[ptr+1]; break; // max segment size
|
case 2: ptr = ptr + buf[ptr+1]; break; // max segment size
|
case 3: ptr = ptr + buf[ptr+1]; break; // Window Scale
|
case 3:
|
|
// Window Scale
|
|
trace("%s:L%d window scale bytes %d, 0x%x", buf[ptr+1], buf[ptr+2]);
|
|
rx_packet->tcp_window_scale = buf[ptr+2];
|
|
ptr = ptr + buf[ptr+1];
|
|
break;
|
|
|
case 4: ptr = ptr + buf[ptr+1]; break; // SACK Permitted
|
case 4: ptr = ptr + buf[ptr+1]; break; // SACK Permitted
|
case 5: ptr = ptr + buf[ptr+1]; break; // SACK
|
case 5: ptr = ptr + buf[ptr+1]; break; // SACK
|
case 8:
|
case 8:
|
// Time Stamp Option
|
// Time Stamp Option
|
rx_packet->tcp_src_time_stamp = buf[ptr+2]<<24|buf[ptr+3]<<16|buf[ptr+4]<<8|buf[ptr+5];
|
rx_packet->tcp_src_time_stamp = buf[ptr+2]<<24|buf[ptr+3]<<16|buf[ptr+4]<<8|buf[ptr+5];
|
Line 239... |
Line 292... |
|
|
|
|
void tcp_response(char * buf, socket_t* socket)
|
void tcp_response(char * buf, socket_t* socket)
|
{
|
{
|
socket->packets_received++;
|
socket->packets_received++;
|
|
trace("tcp_response");
|
|
|
/* Mark the ack in the tcp tx packet buffer so the tx packet does not get resent */
|
/* Mark the ack in the tcp tx packet buffer so the tx packet does not get resent */
|
if (socket->rx_packet->tcp_flags & 0x10) // ack flag set ?
|
if (socket->rx_packet->tcp_flags & 0x10) // ack flag set ?
|
tcp_ack(socket);
|
tcp_ack(socket);
|
|
|
Line 252... |
Line 306... |
// Reset the connection
|
// Reset the connection
|
socket->tcp_disconnect = 1;
|
socket->tcp_disconnect = 1;
|
}
|
}
|
|
|
// open a connection
|
// open a connection
|
else if (socket->tcp_connection_state == TCP_CLOSED) {
|
else if (socket->tcp_connection_state == TCP_LISTENING) {
|
|
|
if (socket->rx_packet->tcp_flags & 0x02) { // SYN
|
if (socket->rx_packet->tcp_flags & 0x02) { // SYN
|
|
trace("tcp_open");
|
// Open connection
|
// Open connection
|
tcp_open(socket);
|
tcp_open(socket);
|
socket->tcp_connection_state = TCP_PENDING;
|
socket->tcp_connection_state = TCP_PENDING;
|
}
|
}
|
|
|
Line 271... |
Line 326... |
// Sent the first ack packet to establish a connection.
|
// Sent the first ack packet to establish a connection.
|
// Have just received the second packet from the server
|
// Have just received the second packet from the server
|
else if (socket->tcp_connection_state == TCP_PENDING) {
|
else if (socket->tcp_connection_state == TCP_PENDING) {
|
/* Add 1 to the sequence number as a special case to open
|
/* Add 1 to the sequence number as a special case to open
|
the connection */
|
the connection */
|
socket->tcp_seq++;
|
socket->tcp_tx_seq++;
|
socket->tcp_connection_state = TCP_OPEN;
|
socket->tcp_connection_state = TCP_OPEN;
|
}
|
}
|
|
|
|
|
// connection is already open
|
// connection is already open
|
else {
|
else {
|
|
|
/* contains tcp payload */
|
/* contains tcp payload */
|
if (socket->rx_packet->tcp_payload_len != 0) {
|
if (socket->rx_packet->tcp_payload_len != 0) {
|
|
|
|
socket->tcp_bytes_received += socket->rx_packet->tcp_payload_len;
|
|
trace("socket %d received total %d bytes", socket->id, socket->tcp_bytes_received);
|
|
|
/* Ack the packet only if the payload length is non-zero */
|
/* Ack the packet only if the payload length is non-zero */
|
tcp_reply(socket, NULL, 0);
|
tcp_reply(socket, NULL, 0);
|
|
|
/* Process the tcp contents */
|
/* Process the tcp contents */
|
if (socket->rx_packet->tcp_dst_port == TELNET_PORT)
|
if (socket->rx_packet->tcp_dst_port == TELNET_PORT)
|
Line 295... |
Line 354... |
}
|
}
|
|
|
|
|
void tcp_disconnect(socket_t * socket)
|
void tcp_disconnect(socket_t * socket)
|
{
|
{
|
|
telnet_t* telnet;
|
|
|
if (socket->tcp_connection_state != TCP_CLOSED) {
|
if (socket->tcp_connection_state != TCP_CLOSED) {
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->telnet_connection_state = TELNET_CLOSED;
|
|
socket->telnet_options_sent = 0;
|
|
socket->telnet_sent_opening_message = 0;
|
|
tcp_reply(socket, NULL, 0);
|
tcp_reply(socket, NULL, 0);
|
|
|
|
/* app level disconnect function */
|
|
switch(socket->app->type) {
|
|
case APP_TELNET: telnet_disconnect(socket->app);
|
|
break;
|
|
default:
|
|
trace("Unknown app type");
|
|
}
|
socket->tcp_disconnect = 0;
|
socket->tcp_disconnect = 0;
|
socket->telnet_echo_mode = 0; // reset this setting
|
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
Line 329... |
Line 394... |
void tcp_open(socket_t* socket)
|
void tcp_open(socket_t* socket)
|
{
|
{
|
|
|
int i, j;
|
int i, j;
|
unsigned short header_checksum;
|
unsigned short header_checksum;
|
mac_ip_t target;
|
|
int ip_length;
|
int ip_length;
|
char * buf;
|
char * buf;
|
|
|
|
|
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
|
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
|
|
|
|
strncpy(&socket->dest_ip, socket->rx_packet->src_ip, 4);
|
target.mac[0] = socket->rx_packet->src_mac[0];
|
strncpy(&socket->dest_mac, socket->rx_packet->src_mac, 6);
|
target.mac[1] = socket->rx_packet->src_mac[1];
|
|
target.mac[2] = socket->rx_packet->src_mac[2];
|
|
target.mac[3] = socket->rx_packet->src_mac[3];
|
|
target.mac[4] = socket->rx_packet->src_mac[4];
|
|
target.mac[5] = socket->rx_packet->src_mac[5];
|
|
target.ip[0] = socket->rx_packet->src_ip[0];
|
|
target.ip[1] = socket->rx_packet->src_ip[1];
|
|
target.ip[2] = socket->rx_packet->src_ip[2];
|
|
target.ip[3] = socket->rx_packet->src_ip[3];
|
|
|
|
|
|
/* Include 20 bytes of tcp options */
|
/* Include 20 bytes of tcp options */
|
ip_length = 20+20+20; /* 20 bytes ip header, 20 bytes tcp header, 20 bytes tcp options */
|
ip_length = 20+20+20; /* 20 bytes ip header, 20 bytes tcp header, 20 bytes tcp options */
|
|
|
|
/* fill in the information about the packet about to be sent */
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
|
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
|
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
|
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, 0, TCP_NEW);
|
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, 0, TCP_NEW);
|
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + 1;
|
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + 1;
|
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
|
|
|
|
ip_header(&buf[14], &target, ip_length, 6); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
|
|
ethernet_header(buf, &target, 0x0800); /* bytes 0 to 13*/
|
|
|
|
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
|
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
|
|
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
|
|
|
strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
|
ip_header(&buf[14], &socket->dest_ip, ip_length, 6); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
|
|
ethernet_header(buf, &socket->dest_mac, 0x0800); /* bytes 0 to 13*/
|
|
|
tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes); // MAC header, IP header, TCP header, TCP options
|
/* transmit an ethernet frame */
|
|
//trace("tx_packet buf 0x%d, len %d",
|
|
// (unsigned int)buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
|
|
ethmac_tx_packet(buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
|
socket->packets_sent++;
|
socket->packets_sent++;
|
|
|
|
|
/* Pick the next tx buffer to use */
|
/* Pick the next tx buffer to use */
|
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
|
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
|
Line 382... |
Line 436... |
|
|
void tcp_reply(socket_t* socket, char* telnet_payload, int telnet_payload_length)
|
void tcp_reply(socket_t* socket, char* telnet_payload, int telnet_payload_length)
|
{
|
{
|
|
|
int i, j;
|
int i, j;
|
mac_ip_t target;
|
|
int ip_length;
|
int ip_length;
|
char * buf;
|
char * buf;
|
|
|
|
|
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
|
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
|
|
|
target.mac[0] = socket->rx_packet->src_mac[0];
|
|
target.mac[1] = socket->rx_packet->src_mac[1];
|
|
target.mac[2] = socket->rx_packet->src_mac[2];
|
|
target.mac[3] = socket->rx_packet->src_mac[3];
|
|
target.mac[4] = socket->rx_packet->src_mac[4];
|
|
target.mac[5] = socket->rx_packet->src_mac[5];
|
|
target.ip[0] = socket->rx_packet->src_ip[0];
|
|
target.ip[1] = socket->rx_packet->src_ip[1];
|
|
target.ip[2] = socket->rx_packet->src_ip[2];
|
|
target.ip[3] = socket->rx_packet->src_ip[3];
|
|
|
|
ip_length = 20+20 + telnet_payload_length;
|
ip_length = 20+20 + telnet_payload_length;
|
|
|
/* Copy the payload into the transmit buffer */
|
/* Copy the payload into the transmit buffer */
|
if (telnet_payload_length != 0) {
|
if (telnet_payload_length != 0) {
|
for (i=14+ip_length-telnet_payload_length, j=0; i<14+ip_length;i++,j++) {
|
for (i=14+ip_length-telnet_payload_length, j=0; i<14+ip_length;i++,j++) {
|
Line 414... |
Line 455... |
if (telnet_payload_length)
|
if (telnet_payload_length)
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
|
else
|
else
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 0;
|
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 0;
|
|
|
|
/* fill in the information about the packet about to be sent */
|
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
|
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
|
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, telnet_payload_length, TCP_NORMAL);
|
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, telnet_payload_length, TCP_NORMAL);
|
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + telnet_payload_length;
|
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + telnet_payload_length;
|
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
|
|
|
|
ip_header(&buf[14], &target, ip_length, 6); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
|
|
ethernet_header(buf, &target, 0x0800); /*bytes 0 to 13*/
|
|
|
|
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
|
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
|
|
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
|
|
|
strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
|
/* Create the IP header */
|
|
/* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
|
|
ip_header(&buf[14], &socket->dest_ip, ip_length, 6); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
|
|
ethernet_header(buf, &socket->dest_mac, 0x0800); /* bytes 0 to 13*/
|
|
|
tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes); // MAC header, IP header, TCP header, TCP options
|
/* transmit an ethernet frame */
|
|
ethmac_tx_packet(buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
|
socket->packets_sent++;
|
socket->packets_sent++;
|
|
|
|
|
/* Pick the next tx buffer to use */
|
/* Pick the next tx buffer to use */
|
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
|
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
|
Line 439... |
Line 481... |
socket->tcp_current_buf++;
|
socket->tcp_current_buf++;
|
}
|
}
|
|
|
|
|
|
|
|
|
/* Find the packets lower than or equal to seq and mark them as acked */
|
/* Find the packets lower than or equal to seq and mark them as acked */
|
void tcp_ack(socket_t* socket)
|
void tcp_ack(socket_t* socket)
|
{
|
{
|
int i, ack_valid;
|
int i, ack_valid;
|
unsigned int ack = socket->rx_packet->tcp_ack;
|
unsigned int ack = socket->rx_packet->tcp_ack;
|
unsigned int last_ack = socket->tcp_last_ack;
|
unsigned int last_ack = socket->tcp_rx_ack;
|
|
|
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
|
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
|
if (socket->tcp_buf[i]->payload_valid) {
|
if (socket->tcp_buf[i]->payload_valid) {
|
|
|
if (ack > last_ack) {
|
if (ack > last_ack) {
|
Line 469... |
Line 510... |
if (socket->tcp_buf[i]->ending_seq == ack) break;
|
if (socket->tcp_buf[i]->ending_seq == ack) break;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
socket->tcp_last_ack = ack;
|
socket->tcp_rx_ack = ack;
|
}
|
}
|
|
|
|
|
/* Check if any tcp packets need to be re-transmitted */
|
/* Check if any tcp packets need to be re-transmitted */
|
void tcp_retransmit(socket_t* socket)
|
void tcp_retransmit(socket_t* socket)
|
Line 491... |
Line 532... |
socket->packets_resent++;
|
socket->packets_resent++;
|
|
|
/* Disable ethmac_int interrupt */
|
/* Disable ethmac_int interrupt */
|
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
|
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
|
|
|
strncpy((char*)ETHMAC_TX_BUFFER, socket->tcp_buf[i]->buf, socket->tcp_buf[i]->len_bytes);
|
/* transmit an ethernet frame */
|
tx_packet(socket->tcp_buf[i]->len_bytes); // MAC header, IP header, TCP header, TCP options
|
ethmac_tx_packet(socket->tcp_buf[i]->buf, socket->tcp_buf[i]->len_bytes);
|
socket->packets_sent++;
|
socket->packets_sent++;
|
|
|
|
|
/* Enable ethmac_int interrupt */
|
/* Enable ethmac_int interrupt */
|
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
|
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
|
Line 525... |
Line 566... |
buf[2] = socket->rx_packet->tcp_src_port >>8;
|
buf[2] = socket->rx_packet->tcp_src_port >>8;
|
buf[3] = socket->rx_packet->tcp_src_port &0xff;
|
buf[3] = socket->rx_packet->tcp_src_port &0xff;
|
|
|
/* Sequence Number */
|
/* Sequence Number */
|
/* Increment the sequence number for the next packet */
|
/* Increment the sequence number for the next packet */
|
starting_seq = socket->tcp_seq;
|
starting_seq = socket->tcp_tx_seq;
|
socket->tcp_last_seq = socket->tcp_seq;
|
socket->tcp_tx_seq += payload_length;
|
socket->tcp_seq += payload_length;
|
|
|
|
|
|
buf[4] = starting_seq>>24;
|
buf[4] = starting_seq>>24;
|
buf[5] = (starting_seq>>16)&0xff;
|
buf[5] = (starting_seq>>16)&0xff;
|
buf[6] = (starting_seq>>8)&0xff;
|
buf[6] = (starting_seq>>8)&0xff;
|
buf[7] = starting_seq&0xff;
|
buf[7] = starting_seq&0xff;
|
|
|
|
|
/* Ack Number */
|
/* Ack Number */
|
if (options == TCP_NEW)
|
if (options == TCP_NEW) {
|
ack_num = socket->rx_packet->tcp_seq + 1;
|
ack_num = socket->rx_packet->tcp_seq + 1;
|
|
socket->tcp_rx_init_seq = socket->rx_packet->tcp_seq;
|
|
}
|
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
|
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
|
// +1 to the final ack
|
// +1 to the final ack
|
ack_num = socket->rx_packet->tcp_seq + 1;
|
ack_num = socket->rx_packet->tcp_seq + 1;
|
else
|
else
|
ack_num = socket->rx_packet->tcp_seq + socket->rx_packet->tcp_payload_len;
|
ack_num = socket->rx_packet->tcp_seq + socket->rx_packet->tcp_payload_len;
|
|
|
|
socket->tcp_rx_seq= ack_num;
|
|
//trace("socket %d received seq %d",
|
|
// socket->id, socket->tcp_rx_seq - socket->tcp_rx_init_seq);
|
|
|
|
|
buf[8] = ack_num>>24;
|
buf[8] = ack_num>>24;
|
buf[9] = (ack_num>>16)&0xff;
|
buf[9] = (ack_num>>16)&0xff;
|
buf[10] = (ack_num>>8)&0xff;
|
buf[10] = (ack_num>>8)&0xff;
|
buf[11] = ack_num&0xff;
|
buf[11] = ack_num&0xff;
|
|
|
Line 665... |
Line 712... |
|
|
/* handle tcp connections and process buffers
|
/* handle tcp connections and process buffers
|
Poll all sockets in turn for activity */
|
Poll all sockets in turn for activity */
|
void process_tcp(socket_t* socket)
|
void process_tcp(socket_t* socket)
|
{
|
{
|
|
telnet_t* telnet;
|
|
|
/* Check if any tcp packets need to be re-transmitted */
|
/* Check if any tcp packets need to be re-transmitted */
|
tcp_retransmit(socket);
|
tcp_retransmit(socket);
|
|
|
/* Handle exit command */
|
/* Handle exit command */
|
if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
|
if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
|
|
trace("calling tcp disconnect %d",
|
|
socket->tcp_rx_seq - socket->tcp_rx_init_seq);
|
tcp_disconnect(socket);
|
tcp_disconnect(socket);
|
}
|
}
|
|
|
/* Reset connection */
|
/* Reset connection */
|
else if (socket->tcp_reset) {
|
else if (socket->tcp_reset) {
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->tcp_connection_state = TCP_CLOSED;
|
socket->telnet_connection_state = TELNET_CLOSED;
|
|
socket->telnet_options_sent = 0;
|
telnet = (telnet_t*) socket->app->telnet;
|
|
telnet->connection_state = TELNET_CLOSED;
|
|
telnet->options_sent = 0;
|
|
|
tcp_reply(socket, NULL, 0);
|
tcp_reply(socket, NULL, 0);
|
socket->tcp_reset = 0;
|
socket->tcp_reset = 0;
|
}
|
}
|
|
|
/* handle telnet messages */
|
/* handle telnet messages */
|
else if (socket->tcp_connection_state == TCP_OPEN){
|
else if (socket->tcp_connection_state == TCP_OPEN){
|
process_telnet(socket);
|
|
|
/* app level process function */
|
|
switch(socket->app->type) {
|
|
case APP_TELNET: process_telnet(socket);
|
|
break;
|
|
default:
|
|
trace("Unknown app type");
|
}
|
}
|
}
|
}
|
|
}
|
|
|
|
|
|
|
|
void process_sockets()
|
|
{
|
|
socket_t* socket;
|
|
|
|
/* handle tcp connections and process buffers */
|
|
/* Poll all sockets in turn for activity */
|
|
socket = first_socket_g;
|
|
for(;;){
|
|
process_tcp(socket);
|
|
if (socket->next!=NULL)
|
|
socket=socket->next;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|