From cf917927a53d227bf1fd5e228da93a1c00216c1e Mon Sep 17 00:00:00 2001
From: koniifer <koniifer@proton.me>
Date: Mon, 11 Nov 2024 01:03:01 +0000
Subject: [PATCH] incomplete sunset redesign

---
 kernel/src/holeybytes/ecah.rs                 |   2 +-
 sysdata/libraries/intouch/src/lib.hb          |   2 +-
 sysdata/libraries/stn/src/buffer.hb           |   2 +-
 sysdata/libraries/stn/src/memory.hb           |  11 +-
 sysdata/libraries/sunset_proto/src/client.hb  | 113 ++++++++++--------
 sysdata/libraries/sunset_proto/src/lib.hb     |  20 ++--
 sysdata/libraries/sunset_proto/src/message.hb |  10 +-
 sysdata/libraries/sunset_proto/src/server.hb  |  65 +++++++---
 sysdata/programs/horizon/src/main.hb          |   2 +-
 sysdata/programs/sunset_client/src/main.hb    |  20 +---
 sysdata/programs/sunset_server/src/main.hb    |  35 +-----
 11 files changed, 139 insertions(+), 143 deletions(-)

diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs
index ab45e64..8a03816 100644
--- a/kernel/src/holeybytes/ecah.rs
+++ b/kernel/src/holeybytes/ecah.rs
@@ -182,7 +182,7 @@ pub fn handler(vm: &mut Vm) {
             } else {
                 unsafe {
                     let ptr = map_ptr as *mut u8;
-                    ptr.copy_from(msg.as_ptr(), msg.len());
+                    ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
                 }
 
                 debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
diff --git a/sysdata/libraries/intouch/src/lib.hb b/sysdata/libraries/intouch/src/lib.hb
index dca49d4..a6c5a91 100644
--- a/sysdata/libraries/intouch/src/lib.hb
+++ b/sysdata/libraries/intouch/src/lib.hb
@@ -15,7 +15,7 @@ recieve_mouse_event := fn(): ?MouseEvent {
 	buf_id := buffer.search("PS/2 Mouse\0")
 
 	// Read out of the Mouse buffer here
-	buffer.recv(MouseEvent, buf_id, @bitcast(&mevent))
+	buffer.recv(MouseEvent, buf_id, &mevent)
 
 	if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
 		return mevent
diff --git a/sysdata/libraries/stn/src/buffer.hb b/sysdata/libraries/stn/src/buffer.hb
index 1912c59..aa16637 100644
--- a/sysdata/libraries/stn/src/buffer.hb
+++ b/sysdata/libraries/stn/src/buffer.hb
@@ -1,6 +1,6 @@
 string := @use("string.hb")
 
-recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^u8): void {
+recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
 	return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
 }
 
diff --git a/sysdata/libraries/stn/src/memory.hb b/sysdata/libraries/stn/src/memory.hb
index 821e46f..5bebd68 100644
--- a/sysdata/libraries/stn/src/memory.hb
+++ b/sysdata/libraries/stn/src/memory.hb
@@ -2,15 +2,8 @@ PAGE_SIZE := 4096
 MAX_ALLOC := 0xFF
 MAX_FREE := 0xFF
 
-is_uninit := fn($Expr: type, ptr: ^Expr): bool {
-	i := 0
-	loop if *(@as(^u8, @bitcast(ptr)) + i) != 0 return false else if i + 1 == @sizeof(Expr) return true else i += 1
-}
-
-uninit := fn($Expr: type): Expr {
-	empty := @as(Expr, idk)
-	@inline(set, u8, &0, @bitcast(&empty), @sizeof(Expr))
-	return empty
+uninit := fn($Expr: type): ?Expr {
+	return null
 }
 
 dangling := fn($Expr: type): ^Expr {
diff --git a/sysdata/libraries/sunset_proto/src/client.hb b/sysdata/libraries/sunset_proto/src/client.hb
index da1950c..bc23e0d 100644
--- a/sysdata/libraries/sunset_proto/src/client.hb
+++ b/sysdata/libraries/sunset_proto/src/client.hb
@@ -1,62 +1,79 @@
 .{math: .{Vec2}, buffer, log, memory} := @use("../../stn/src/lib.hb");
 .{Surface, new_surface} := @use("../../render/src/lib.hb");
-.{WindowWrapper, WindowID, WindowProps, WindowMessage, message, BUFFER} := @use("./lib.hb")
+.{Window, WindowData, WindowProps, MessageHeader, message, BUFFER} := @use("./lib.hb")
 
-buffer_id := @as(?uint, null)
-
-new_window := fn(props: WindowProps): ?WindowWrapper {
-	if buffer_id == null {
-		log.error("client: (request_new) buffer id is null. did you init the client?\0")
-		return null
-	}
-	buf := memory.uninit(?WindowWrapper)
-	buffer.write(WindowMessage, &.(message.new, 0, @sizeof(WindowProps), @bitcast(&props), @bitcast(&buf)), @unwrap(buffer_id))
-	loop if memory.is_uninit(?WindowWrapper, &buf) == false break else {
-	}
-	// loop until i write a better socket
-	i := 0
-	loop if i >= 1000 break else i += 1
-	return buf
-}
-
-update_window_props := fn(wrapper: WindowWrapper): ?WindowProps {
-	log.error("todo: sunset_proto/src/client/update_window_props.hb\0")
-	if buffer_id == null {
-		log.error("client: (request_update_properties) buffer id is null. did you init the client?\0")
-		return null
-	}
-	// TODO: buffer.write(WINDOWING_BUFFER, update properties) request
-	return null
-}
-
-request_shutdown := fn(): ?bool {
-	if buffer_id == null {
-		log.error("client: (request_shutdown) buffer id is null. did you init the client?\0")
-		return null
-	}
-	buf := memory.uninit(?u8)
-	buffer.write(WindowMessage, &.(message.shutdown, 0, 0, memory.dangling(u8), @bitcast(&buf)), @unwrap(buffer_id))
-	loop if memory.is_uninit(?u8, &buf) == false break else {
-	}
-	// loop until i write a better socket
-	i := 0
-	loop if i >= 1000 break else i += 1
-	// had to do ?u8 here, ?bool didnt work
-	if buf == null | @unwrap(buf) != 255 {
-		return false
-	} else {
-		return true
-	}
-}
+server_id := @as(?uint, null)
 
 init := fn(): void {
 	log.info("client: waiting for server\0")
 	id := 0
 	loop if id != 0 {
-		buffer_id = id
+		server_id = id
 		log.info("client: done waiting\0")
 		return
 	} else {
 		id = buffer.search(BUFFER)
 	}
+}
+
+// wait_for_message := fn($Expr: type, ptr: ^?Expr, buffer_id: uint): bool {
+// 	timer := 0
+// 	loop if timer < 1000 {
+// 		buffer.recv(?Expr, buffer_id, ptr)
+// 		if *ptr != null {
+// 			return true
+// 		}
+// 		timer -= 1
+// 	}
+// 	return false
+// }
+
+new := fn(props: WindowProps): ?Window {
+	if server_id == null {
+		init()
+	}
+	buffer.write(?MessageHeader, &@as(?MessageHeader, .(message.syn, @sizeof(WindowProps))), @unwrap(server_id))
+	log.info("client: sent syn\0")
+
+	timer := 0
+	response := memory.uninit(MessageHeader)
+	// if wait_for_message(MessageHeader, &response, @unwrap(server_id)) == false {
+	// 	return null
+	// }
+	loop if timer < 1000 {
+		buffer.recv(?MessageHeader, @unwrap(server_id), &response)
+		if response != null {
+			break
+		}
+		timer += 1
+	} else {
+		log.error("client: no response in timeout\0")
+		return null
+	}
+	if response.kind != message.ack {
+		log.error("client: refused\0")
+		return null
+	}
+	log.info("client: received ack\0")
+
+	buffer_id := response.data
+	buffer.write(?WindowProps, &@as(?WindowProps, props), buffer_id)
+	log.info("client: sent props\0")
+
+	timer = 0
+	response2 := memory.uninit(WindowData)
+	loop if timer < 1000 {
+		buffer.recv(?WindowData, buffer_id, &response2)
+
+		if response2 != null {
+			log.info("client: received window data\0")
+			surface := new_surface(
+				response2.props.dimensions.x,
+				response2.props.dimensions.y,
+			)
+			return .(@as(WindowData, response2), surface)
+		}
+		timer += 1
+	}
+	return null
 }
\ No newline at end of file
diff --git a/sysdata/libraries/sunset_proto/src/lib.hb b/sysdata/libraries/sunset_proto/src/lib.hb
index 7006f7d..b5f8a95 100644
--- a/sysdata/libraries/sunset_proto/src/lib.hb
+++ b/sysdata/libraries/sunset_proto/src/lib.hb
@@ -7,30 +7,24 @@ client := @use("./client.hb")
 server := @use("./server.hb")
 message := @use("./message.hb")
 
-WindowID := uint
-MessageKind := uint
-
-WindowMessage := packed struct {
-	kind: MessageKind,
-	id: WindowID,
-	length: uint,
-	data_ptr: ^u8,
-	// need to replace this with a buffer id
-	callback: ^u8,
+MessageHeader := packed struct {
+	kind: uint,
+	data: uint,
 }
 
 WindowProps := struct {
 	position: Vec2(uint),
 	dimensions: Vec2(uint),
+	// replace with owned string type later
 	title: ^u8,
 }
 
-WindowWrapper := struct {
-	id: WindowID,
+WindowData := struct {
 	props: WindowProps,
+	buffer_id: uint,
 }
 
 Window := struct {
+	data: WindowData,
 	surface: Surface,
-	props: WindowProps,
 }
\ No newline at end of file
diff --git a/sysdata/libraries/sunset_proto/src/message.hb b/sysdata/libraries/sunset_proto/src/message.hb
index 700ab52..9c69092 100644
--- a/sysdata/libraries/sunset_proto/src/message.hb
+++ b/sysdata/libraries/sunset_proto/src/message.hb
@@ -1,4 +1,6 @@
-$new := 0
-$destroy := 1
-$update_props := 2
-$shutdown := 3
\ No newline at end of file
+$syn := 1
+$ack := 2
+$refused := 3
+$quit := 4
+$update_props := 5
+$shutdown := 6
\ No newline at end of file
diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb
index 4581571..46d4617 100644
--- a/sysdata/libraries/sunset_proto/src/server.hb
+++ b/sysdata/libraries/sunset_proto/src/server.hb
@@ -1,32 +1,63 @@
 .{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
 .{Surface, new_surface} := @use("../../render/src/lib.hb");
-.{WindowWrapper, WindowID, WindowProps, WindowMessage, BUFFER} := @use("./lib.hb")
+.{Window, WindowProps, WindowData, MessageHeader, BUFFER, message} := @use("./lib.hb")
 
-WindowServer := struct {window_count: uint, buffer_id: uint}
+WindowServer := struct {
+	window_count: uint,
+	id: uint,
+	// replace this with an actual collection when we get an allocator
+	windows: ^WindowData,
+}
 
 server := @as(?WindowServer, null)
 
-new_window_id := fn(): WindowID {
-	return random.any(uint)
-}
-
-init := fn(): bool {
+init := fn(): void {
+	if server != null {
+		return
+	}
 	log.info("server: starting server\0")
-	server = .(0, buffer.create(BUFFER))
-	return true
+	windows := memory.alloc(WindowData, 10)
+	server = .(0, buffer.create(BUFFER), windows)
 }
 
-recieve := fn(): ?WindowMessage {
+handle_connections := fn(): bool {
 	if server == null {
-		log.error("server: (request_new) server is null. did you init the client?\0")
-		return null
+		return false
 	}
-	buf := memory.uninit(WindowMessage)
-	buffer.recv(WindowMessage, @unwrap(server).buffer_id, @bitcast(&buf))
-	if memory.is_uninit(WindowMessage, &buf) {
-		return null
+	recv := memory.uninit(MessageHeader)
+	buffer.recv(?MessageHeader, @unwrap(server).id, &recv)
+	if recv == null {
+		return true
+	} else if recv.kind == message.syn {
+		buffer_id := buffer.create("asdf\0")
+		buffer.write(?MessageHeader, &@as(?MessageHeader, .(message.ack, buffer_id)), @unwrap(server).id)
+		log.info("server: sent ack\0")
+
+		timer := 0
+		resp := memory.uninit(WindowProps)
+		loop if timer < 1000 {
+			buffer.recv(?WindowProps, buffer_id, &resp)
+			if resp != null {
+				break
+			}
+			timer += 1
+		} else {
+			log.error("server: no props in timeout\0")
+			return true
+		}
+		log.info("server: received props\0")
+		surface := new_surface(resp.dimensions.x, resp.dimensions.y)
+		data := WindowData.(@as(WindowProps, resp), buffer_id)
+		buffer.write(?WindowData, &@as(?WindowData, data), buffer_id)
+		log.info("server: sent window data\0");
+		*(@unwrap(server).windows + @unwrap(server).window_count) = data
+		@unwrap(server).window_count += 1
+	} else if recv.kind == message.quit {
+		// todo: quit
+	} else if recv.kind == message.shutdown {
+		return false
 	}
-	return buf
+	return true
 }
 
 should_shutdown := fn(): bool {
diff --git a/sysdata/programs/horizon/src/main.hb b/sysdata/programs/horizon/src/main.hb
index 0666373..9ead559 100644
--- a/sysdata/programs/horizon/src/main.hb
+++ b/sysdata/programs/horizon/src/main.hb
@@ -96,7 +96,7 @@ main := fn(): int {
 			//
 
 			if mouse_event != null {
-				// log.warn("Mouse event recieved\0")
+				// log.warn("Mouse event received\0")
 
 				change_x := @as(i16, mouse_event.x_change)
 				change_x = change_x << 8
diff --git a/sysdata/programs/sunset_client/src/main.hb b/sysdata/programs/sunset_client/src/main.hb
index a9def72..86b8ac7 100644
--- a/sysdata/programs/sunset_client/src/main.hb
+++ b/sysdata/programs/sunset_client/src/main.hb
@@ -2,23 +2,11 @@
 sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
 
 main := fn(): void {
-	sunset.client.init()
-	log.info("client: request new window\0")
-	window := sunset.client.new_window(.(.(100, 100), .(150, 150), "Hello, World!\0"))
+	window := sunset.client.new(.(.(100, 100), .(100, 100), "Hello, World!\0"))
 	if window == null {
-		log.error("Could not create window\0")
+		log.error("client: window was null\0")
 		return
 	}
-	log.info("client: window created. title:\0")
-	log.info(window.props.title)
-	window.props.position = .(500, 500)
-	props := @unwrap(sunset.client.update_window_props(window))
-	if props.position.x != window.props.position.x {
-		log.error("client: we did not update props\0")
-	}
-	log.info("client: sending shutdown request\0")
-	shutdown := sunset.client.request_shutdown()
-	if shutdown == null {
-		log.error("client: didnt shutdown the server\0")
-	}
+	log.info("client: window title:\0")
+	log.info(window.data.props.title)
 }
\ No newline at end of file
diff --git a/sysdata/programs/sunset_server/src/main.hb b/sysdata/programs/sunset_server/src/main.hb
index c3e2011..98f421b 100644
--- a/sysdata/programs/sunset_server/src/main.hb
+++ b/sysdata/programs/sunset_server/src/main.hb
@@ -1,36 +1,7 @@
-.{log} := @use("../../../libraries/stn/src/lib.hb")
-render := @use("../../../libraries/render/src/lib.hb");
-.{server, message, WindowWrapper, WindowProps} := @use("../../../libraries/sunset_proto/src/lib.hb")
-
-psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
+sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
 
 main := fn(): void {
-	screen := render.init(false)
-	font := render.text.font_from_psf2(@bitcast(&psf), false)
-	if font == null {
-		return
+	sunset.server.init()
+	loop if sunset.server.handle_connections() {
 	}
-	if server.init() == false {
-		log.error("Failed to create server\0")
-		return
-	}
-	loop if server.should_shutdown() break else {
-		recv := server.recieve()
-		if recv == null {
-			continue
-		} else if recv.kind == message.new {
-			props := *@as(^WindowProps, @bitcast(recv.data_ptr));
-			*@as(^?WindowWrapper, @bitcast(recv.callback)) = WindowWrapper.(0, props)
-			render.put_rect(screen, props.position, props.dimensions, render.white)
-			render.put_text(screen, font, props.position + .(1, 1), render.white, props.title)
-			render.put_hline(screen, props.position.y + font.height + 2, props.position.x, props.position.x + props.dimensions.x, render.white)
-			log.info("server: made a new window\0")
-		} else if recv.kind == message.shutdown {
-			*@as(^?u8, @bitcast(recv.callback)) = 255
-			break
-		}
-	}
-
-	render.put_text(screen, font, .(0, 0), render.white, "Shutdown triggered\0")
-	log.info("Server shutdown\0")
 }
\ No newline at end of file