314 lines
7.0 KiB
C
314 lines
7.0 KiB
C
#include "ipv4.h"
|
|
#include "tcp.h"
|
|
#include "socket.h"
|
|
#include "memory.h"
|
|
#include "string.h"
|
|
#include "console.h"
|
|
|
|
struct socket_t **sockets;
|
|
unsigned int socket_count;
|
|
|
|
extern void tcp_send(struct ether_t *ether, struct socket_t *sock, unsigned short flags, unsigned char *packet, unsigned int len);
|
|
|
|
struct socket_t *socket_find(unsigned int dport, unsigned int sport, unsigned int src_ip, unsigned int seq) {
|
|
int i;
|
|
struct socket_t *new_socket;
|
|
|
|
for (i=0;i<socket_count;i++) {
|
|
if (sockets[i]->port_recv == dport && sockets[i]->port_dest == sport && sockets[i]->addr == src_ip) {
|
|
if (sockets[i]->status == 0 || sockets[i]->status == 2) {
|
|
return sockets[i];
|
|
} else {
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0;i<socket_count;i++) {
|
|
if (sockets[i]->port_recv == dport && sockets[i]->addr == 0) {
|
|
if (sockets[i]->status == 3) {
|
|
struct task_t *task = (struct task_t *)sockets[i]->data;
|
|
|
|
if (task->waiting_socket_count < 4) {
|
|
|
|
|
|
new_socket = (struct socket_t *)malloc(sizeof(struct socket_t));
|
|
if (new_socket) {
|
|
memset(new_socket, 0, sizeof(struct socket_t));
|
|
new_socket->socket_type = 1;
|
|
|
|
new_socket->port_recv = dport;
|
|
new_socket->tcp_sock.seq_number = 0;
|
|
new_socket->tcp_sock.ack_number = seq + 1;
|
|
|
|
new_socket->tcp_packets = (void *)0;
|
|
new_socket->tcp_packet_count = 0;
|
|
|
|
new_socket->addr = src_ip;
|
|
new_socket->bytes_available = 0;
|
|
new_socket->bytes_read = 0;
|
|
new_socket->port_dest = sport;
|
|
new_socket->offset = 0;
|
|
new_socket->ether = sockets[i]->ether;
|
|
|
|
new_socket->status = 0;
|
|
task->waiting_sockets[task->waiting_socket_count++] = new_socket;
|
|
}
|
|
}
|
|
} else {
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (void *)0;
|
|
}
|
|
|
|
|
|
struct tcp_data_t *socket_get_packet(struct socket_t *sock) {
|
|
struct tcp_data_t *packet;
|
|
int i;
|
|
|
|
|
|
if (sock->tcp_packet_count == 0) {
|
|
return (void *)0;
|
|
}
|
|
|
|
packet = sock->tcp_packets[0];
|
|
|
|
for (i=0;i<sock->tcp_packet_count-1;i++) {
|
|
sock->tcp_packets[i] = sock->tcp_packets[i+1];
|
|
}
|
|
|
|
sock->tcp_packet_count--;
|
|
if (sock->tcp_packet_count == 0) {
|
|
free(sock->tcp_packets);
|
|
sock->tcp_packets = (void *)0;
|
|
} else {
|
|
sock->tcp_packets = (struct tcp_data_t **)realloc(sock->tcp_packets, sizeof(struct tcp_data_t *) * sock->tcp_packet_count);
|
|
}
|
|
|
|
return packet;
|
|
}
|
|
|
|
int socket_status(struct socket_t *sock) {
|
|
return sock->status;
|
|
}
|
|
|
|
int socket_read(struct socket_t *sock, char *buffer, int len) {
|
|
struct tcp_data_t *data = (void *)0;
|
|
|
|
int size_to_read = 0;
|
|
int offset = sock->offset;
|
|
do {
|
|
if (sock->bytes_available) {
|
|
data = sock->tcp_curr_packet;
|
|
} else {
|
|
if (sock->tcp_packet_count > 0) {
|
|
data = socket_get_packet(sock);
|
|
} else {
|
|
if (sock->status == 1) {
|
|
return 0;
|
|
}
|
|
sock->offset = offset;
|
|
return -1; // return -1 to signal retry.
|
|
}
|
|
|
|
sock->bytes_available = data->len;
|
|
sock->bytes_read = 0;
|
|
}
|
|
|
|
if (len < offset + sock->bytes_available) {
|
|
size_to_read = len;
|
|
} else {
|
|
size_to_read = offset + sock->bytes_available;
|
|
}
|
|
|
|
if (data->len > 0) {
|
|
memcpy(buffer + offset, data->data + sock->bytes_read, size_to_read);
|
|
}
|
|
|
|
offset += size_to_read;
|
|
|
|
if (size_to_read < sock->bytes_available) {
|
|
sock->bytes_available = sock->bytes_available - size_to_read;
|
|
sock->bytes_read += size_to_read;
|
|
sock->tcp_curr_packet = data;
|
|
} else {
|
|
sock->bytes_available = 0;
|
|
sock->tcp_curr_packet = (void *)0;
|
|
free(data);
|
|
}
|
|
} while (!size_to_read);
|
|
|
|
sock->offset = 0;
|
|
return size_to_read;
|
|
}
|
|
|
|
unsigned socket_get_port(void) {
|
|
static unsigned short next = 49152;
|
|
|
|
unsigned short out = next;
|
|
next++;
|
|
|
|
return out;
|
|
}
|
|
|
|
int socket_connect(struct socket_t* sock, unsigned int dest_ip, unsigned short dest_port) {
|
|
if (sock->socket_type != 1) {
|
|
return -1;
|
|
}
|
|
|
|
sock->port_recv = socket_get_port();
|
|
sock->tcp_sock.seq_number = 0;
|
|
sock->tcp_sock.ack_number = 0;
|
|
|
|
sock->tcp_packets = (void *)0;
|
|
sock->tcp_packet_count = 0;
|
|
|
|
sock->addr = dest_ip;
|
|
sock->port_dest = dest_port;
|
|
|
|
sock->ether = ether_find_from_ipv4(dest_ip);
|
|
|
|
if (!sock->ether) {
|
|
return -1;
|
|
}
|
|
|
|
tcp_send(sock->ether, sock, (1<<1), (void *)0, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void socket_close(struct socket_t *sock) {
|
|
sock->status = 1;
|
|
tcp_send(sock->ether, sock, TCP_FLAGS_FIN, (void *)0, 0);
|
|
}
|
|
|
|
void socket_doclose(struct socket_t *sock) {
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0;i<socket_count;i++) {
|
|
if (sockets[i] == sock) {
|
|
for (j=0;j<sock->tcp_packet_count;j++) {
|
|
free(sock->tcp_packets[j]->data);
|
|
free(sock->tcp_packets[j]);
|
|
}
|
|
free(sock->tcp_packets);
|
|
free(sock);
|
|
|
|
for (j=i+1;j<socket_count;j++) {
|
|
sockets[j-1] = sockets[j];
|
|
}
|
|
socket_count--;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
struct socket_t *socket_open(unsigned char type) {
|
|
struct socket_t *sock;
|
|
if (type == 1) {
|
|
sock = (struct socket_t *)malloc(sizeof(struct socket_t));
|
|
memset(sock, 0, sizeof(struct socket_t));
|
|
|
|
if (socket_count == 0) {
|
|
sockets = (struct socket_t **)malloc(sizeof(struct socket_t *));
|
|
} else {
|
|
sockets = (struct socket_t **)realloc(sockets, sizeof(struct socket_t *) * (socket_count + 1));
|
|
}
|
|
sock->status = 0;
|
|
sock->socket_type = type;
|
|
sock->bytes_available = 0;
|
|
sock->bytes_read = 0;
|
|
sockets[socket_count] = sock;
|
|
socket_count++;
|
|
} else {
|
|
kprintf("Unsupported Socket type!\n");
|
|
return (void *)0;
|
|
}
|
|
return sock;
|
|
}
|
|
|
|
extern void *current_task;
|
|
|
|
int socket_listen(struct socket_t *sock, unsigned int listenip, unsigned short port) {
|
|
if (sock->socket_type != 1) {
|
|
kprintf("Wrong socket Type\n");
|
|
return -1;
|
|
}
|
|
|
|
sock->port_recv = port;
|
|
sock->tcp_sock.seq_number = 0;
|
|
sock->tcp_sock.ack_number = 0;
|
|
|
|
sock->tcp_packets = (void *)0;
|
|
sock->tcp_packet_count = 0;
|
|
|
|
sock->addr = 0;
|
|
sock->port_dest = 0;
|
|
|
|
sock->ether = ether_find_from_ipv4(listenip);
|
|
|
|
sock->status = 3;
|
|
|
|
sock->data = (void *)current_task;
|
|
|
|
if (!sock->ether) {
|
|
kprintf("Cant find ether\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct socket_t *socket_accept(struct socket_t *socket, struct inet_addr *client_addr) {
|
|
struct task_t *task = (struct task_t *)socket->data;
|
|
struct socket_t *new_socket;
|
|
int i;
|
|
|
|
if (task->waiting_socket_count > 0) {
|
|
new_socket = task->waiting_sockets[0];
|
|
|
|
for (i=1;i<task->waiting_socket_count;i++) {
|
|
task->waiting_sockets[i-1] = task->waiting_sockets[i];
|
|
}
|
|
task->waiting_socket_count--;
|
|
|
|
if (socket_count == 0) {
|
|
sockets = (struct socket_t **)malloc(sizeof(struct socket_t *));
|
|
} else {
|
|
sockets = (struct socket_t **)realloc(sockets, sizeof(struct socket_t *) * (socket_count + 1));
|
|
}
|
|
|
|
sockets[socket_count] = new_socket;
|
|
|
|
socket_count++;
|
|
|
|
// send SYN ACK
|
|
if (new_socket->socket_type == 1) {
|
|
|
|
tcp_send(new_socket->ether, new_socket, TCP_FLAGS_SYN | TCP_FLAGS_ACK, (void *)0, 0);
|
|
}
|
|
|
|
if (client_addr != (void *)0) {
|
|
client_addr->type = new_socket->socket_type;
|
|
client_addr->addr = new_socket->addr;
|
|
}
|
|
return new_socket;
|
|
}
|
|
|
|
return (void *)0;
|
|
}
|
|
|
|
int socket_write(struct socket_t* sock, unsigned char* payload, unsigned int len) {
|
|
tcp_send(sock->ether, sock, (1 << 4) | (1 << 3), payload, len);
|
|
return 0;
|
|
}
|
|
|
|
void init_sockets() {
|
|
socket_count = 0;
|
|
}
|