aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2020-12-03 22:26:46 +0100
committerMarvin Borner2020-12-03 22:26:46 +0100
commitcd2dbb2e146562c9e37c614bb09a24f7fbf135e0 (patch)
tree12605be6b6dfe837f1a2ebefef3cfbc1ed8536e5
parentd525526f52c76156c4b9ee5ee4f14ed0d06547bc (diff)
Quite important network stuff
-rw-r--r--apps/browser.c13
-rw-r--r--apps/server.c1
-rw-r--r--kernel/features/net.c17
-rw-r--r--kernel/features/syscall.c4
-rw-r--r--libc/inc/socket.h2
-rw-r--r--libnet/http.c46
-rw-r--r--libnet/inc/http.h4
-rw-r--r--libnet/inc/net.h5
8 files changed, 73 insertions, 19 deletions
diff --git a/apps/browser.c b/apps/browser.c
index c7c303f..6ed83b2 100644
--- a/apps/browser.c
+++ b/apps/browser.c
@@ -5,6 +5,7 @@
#include <gfx.h>
#include <gui.h>
#include <html.h>
+#include <http.h>
#include <input.h>
#include <mem.h>
#include <net.h>
@@ -88,13 +89,13 @@ void on_submit(void *event, struct element *box)
struct socket *socket = net_open(S_TCP);
if (socket && net_connect(socket, ip, port, NET_TIMEOUT)) {
net_send(socket, query, strlen(query));
- char buf[4096] = { 0 };
- if (!net_receive(socket, buf, 4096, NET_TIMEOUT) ||
- !html_render(output, http_data(buf), 4096))
+ char *buf = NULL;
+ if (!(buf = http_receive(socket)) || !html_render(output, http_data(buf), 4096)) {
print_error("HTML parsing failed.\n");
-
- c->text = http_code(buf);
- c->color_fg = status_color(c->text);
+ } else {
+ c->text = http_code(buf);
+ c->color_fg = status_color(c->text);
+ }
} else {
print_error("Can't connect to server.\n");
c->text = strdup("000");
diff --git a/apps/server.c b/apps/server.c
index 6aca617..3d3bb77 100644
--- a/apps/server.c
+++ b/apps/server.c
@@ -1,6 +1,7 @@
// MIT License, Copyright (c) 2020 Marvin Borner
#include <assert.h>
+#include <http.h>
#include <mem.h>
#include <net.h>
#include <print.h>
diff --git a/kernel/features/net.c b/kernel/features/net.c
index 26bdc0f..ab747e4 100644
--- a/kernel/features/net.c
+++ b/kernel/features/net.c
@@ -521,12 +521,7 @@ static void tcp_handle_packet(struct tcp_packet *packet, u32 dst, int len)
tcp->ack_no += data_length;
tcp->seq_no = recv_ack;
- // TODO: How many segments are going to be sent?!
- if ((flags & 0xff) == (TCP_FLAG_ACK | TCP_FLAG_PSH)) {
- tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0);
- tcp_send_packet(socket, TCP_FLAG_FIN | TCP_FLAG_ACK, NULL, 0);
- tcp->state++;
- }
+ tcp_send_packet(socket, TCP_FLAG_ACK, NULL, 0);
socket->state = S_CONNECTED;
return;
@@ -740,6 +735,16 @@ int net_close(struct socket *socket)
if (!net_installed())
return 1;
+ if (socket->state == S_CLOSING)
+ return 0;
+
+ if (socket->type == S_TCP && socket->state != S_CLOSED) {
+ tcp_send_packet(socket, TCP_FLAG_FIN | TCP_FLAG_ACK, NULL, 0);
+ socket->state = S_CLOSING;
+ socket->prot.tcp.state++;
+ return 0;
+ }
+
return socket_close(socket);
}
diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c
index 01720c5..9eb9f4b 100644
--- a/kernel/features/syscall.c
+++ b/kernel/features/syscall.c
@@ -102,8 +102,8 @@ void syscall_handler(struct regs *r)
}
case SYS_NET_CLOSE: {
struct socket *s = (void *)r->ebx;
- if (s->type == S_TCP && s->state == S_CONNECTED) {
- proc_current()->state = PROC_SLEEPING;
+ int status = net_close(s);
+ if (!status) {
proc_yield(r);
return;
}
diff --git a/libc/inc/socket.h b/libc/inc/socket.h
index e5e23ad..18bc316 100644
--- a/libc/inc/socket.h
+++ b/libc/inc/socket.h
@@ -8,7 +8,7 @@
// TODO: Use actual socket types (stream etc)
enum socket_type { S_TCP, S_UDP };
-enum socket_state { S_CONNECTING, S_CONNECTED, S_OPEN, S_CLOSED, S_FAILED };
+enum socket_state { S_CONNECTING, S_CONNECTED, S_OPEN, S_CLOSING, S_CLOSED, S_FAILED };
struct tcp_socket {
u32 seq_no;
diff --git a/libnet/http.c b/libnet/http.c
index 96dcd4d..85ceefc 100644
--- a/libnet/http.c
+++ b/libnet/http.c
@@ -3,9 +3,10 @@
#include <assert.h>
#include <conv.h>
#include <def.h>
-#include <http.h>
#include <mem.h>
+#include <net.h>
#include <print.h>
+#include <socket.h>
#include <str.h>
char *http_data(char *r)
@@ -20,6 +21,33 @@ char *http_data(char *r)
return h;
}
+char *http_header_key(char *r, const char *key)
+{
+ char *res = NULL;
+ for (char *p = r; *p; p++) {
+ /* printf("'%c%c%c' vs '%c%c%c'\n", p[0], p[1], p[2], key[0], key[1], key[2]); */
+ if (strlen(p) >= strlen(key) && !memcmp(p, key, strlen(key))) {
+ char *start = p + strlen(key) + 2;
+ char *end = start;
+ for (; *end != '\n'; end++)
+ ;
+ res = malloc(end - start);
+ memcpy(res, start, end - start - 1);
+ res[end - start] = '\0';
+ break;
+ }
+ }
+ return res;
+}
+
+u32 http_content_length(char *r)
+{
+ char *value = http_header_key(r, "Content-Length");
+ int length = value ? atoi(value) : 0;
+ free(value);
+ return length;
+}
+
char *http_code(char *r)
{
char *code = malloc(4);
@@ -87,3 +115,19 @@ char *http_query_path(const char *query, char *path)
return path;
}
+
+char *http_receive(struct socket *socket)
+{
+ char buf[4096] = { 0 };
+ if (!net_receive(socket, buf, 4096, NET_TIMEOUT))
+ return NULL;
+
+ u32 length = http_content_length(buf);
+ char *data = malloc(strlen(buf) + length);
+ memcpy(data, buf, strlen(buf));
+ while (strlen(http_data(data)) != length) {
+ if (!net_receive(socket, data, length, NET_TIMEOUT))
+ break;
+ }
+ return data;
+}
diff --git a/libnet/inc/http.h b/libnet/inc/http.h
index 223bdfc..45709c6 100644
--- a/libnet/inc/http.h
+++ b/libnet/inc/http.h
@@ -4,12 +4,16 @@
#define HTTP_H
#include <def.h>
+#include <socket.h>
char *http_data(char *response);
+char *http_header_key(char *r, const char *key);
+u32 http_content_length(char *r);
char *http_code(char *r);
u32 http_response(const char *http_code, u32 content_length, const char *data, char *resp);
char *http_query_get(const char *url, const char *path);
char *http_query_path(const char *query, char *path);
+char *http_receive(struct socket *socket);
#define HTTP_100 "100 Continue"
#define HTTP_101 "101 Switching Protocol"
diff --git a/libnet/inc/net.h b/libnet/inc/net.h
index a897f1d..1b6a17d 100644
--- a/libnet/inc/net.h
+++ b/libnet/inc/net.h
@@ -4,7 +4,6 @@
#define NET_H
#include <dns.h>
-#include <http.h>
#include <ip.h>
#include <print.h>
#include <socket.h>
@@ -48,8 +47,8 @@ static inline int net_connect(struct socket *socket, u32 ip_addr, u16 dst_port,
static inline int net_close(struct socket *socket)
{
int res = 0;
- while (!(res = (int)sys1(SYS_NET_CLOSE, (int)(socket))))
- ;
+ while (socket->state == S_CLOSING || !(res = (int)sys1(SYS_NET_CLOSE, (int)(socket))))
+ yield();
return res;
}