Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions Examples/simple_chat_room.alusus
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import "Srl/Console.alusus";
import "Srl/String.alusus";
import "Apm.alusus";
Apm.importFile("Alusus/Http");

module WebSocketChat {
use Srl;

class Client {
def conn: ptr[Http.Connection];
};

def clients: array[Client, 32];
def clientCount: Int = 0;



func onWebSocketConnect(conn: ptr[Http.Connection], _: ptr[Void]): Int {
clients(clientCount).conn = conn;
clientCount += 1;

Console.print("Client connected\n");
return 0;
};

func onWebSocketReady(conn: ptr[Http.Connection], _: ptr[Void]): Void {
Http.writeWebSocketText(
conn,
"Connected to broadcast chat",
27
);
};

func onWebSocketData(
conn: ptr[Http.Connection],
bits: Int,
data: CharsPtr,
len: Int,
_: ptr[Void]
): Int {
if ((bits & 1) == 0) return 1;

def i: Int = 0;
def full_data : String ="";
while i < clientCount {
if (clients(i).conn == conn)
full_data = full_data + String.format("user : %i ",i+1) ;
i +=1;
}
full_data.append(data);
i=0;
len = full_data.getLength();
while i < clientCount {
Http.writeWebSocketText(
clients(i).conn,
full_data.buf,
len
);
i += 1;
}

return 1;
};

func onWebSocketClose(conn: ptr[Http.Connection], _: ptr[Void]): Void {
def i: Int = 0;
while i < clientCount {
if (clients(i).conn == conn) {

def j: Int = i;
while j < clientCount - 1 {
clients(j).conn = clients(j + 1).conn;
j += 1;
}

clientCount -= 1;
break;
}
i += 1;
}

Console.print("Client disconnected\n");
};



func handleHttpRequest(conn: ptr[Http.Connection]): Int {
def req : ptr[Http.RequestInfo] = Http.getRequestInfo(conn);

if String.isEqual(req~cnt.localUri, "/websocket") return 0;

if String.isEqual(req~cnt.localUri, "/") {
def html: CharsPtr =
"<!DOCTYPE html><html><body>"
"<h2>Broadcast Chat</h2>"
"<input id='msg' placeholder='Message'>"
"<button onclick='send()'>Send</button>"
"<div id='box'></div>"
"<script>"
"const ws=new WebSocket('ws://'+location.host+'/websocket');"
"function send(){"
"ws.send(msg.value);"
"msg.value='';"
"}"
"ws.onmessage=e=>{"
"let d=document.createElement('div');"
"d.textContent=e.data;"
"box.appendChild(d);};"
"</script></body></html>";

Http.print(conn, "HTTP/1.1 200 OK\r\n");
Http.print(conn, "Content-Length: %d\r\n\r\n",
String.getLength(html));
Http.print(conn, html);
return 1;
}

return 1;
};

func start() {
def ctx : ptr[Http.Context] = Http.startServer(handleHttpRequest~ptr, {
"listening_ports", "8080"
});

Http.setWebSocketHandler(
ctx,
"/websocket",
onWebSocketConnect~ptr,
onWebSocketReady~ptr,
onWebSocketData~ptr,
onWebSocketClose~ptr
);

Console.print("Server running on 8080\n");
Console.getChar();
Http.stopServer(ctx);
};
};

WebSocketChat.start();
207 changes: 117 additions & 90 deletions Examples/websocket_server.alusus
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ module WebSocketExample {
use Srl;

func start() {
def context: ptr[Http.Context] = Http.startServer(handleHttpRequest~ptr, {
"document_root", ".", // Set document root
"listening_ports", "8080", // Listen on port 8080
"websocket_timeout_ms", "3600000"
});
def context: ptr[Http.Context] =
Http.startServer(handleHttpRequest~ptr, {
"document_root", ".",
"listening_ports", "8080",
"websocket_timeout_ms", "3600000"
});

Http.setWebSocketHandler(
context,
Expand All @@ -23,110 +24,136 @@ module WebSocketExample {
onWebSocketClose~ptr
);

Console.print("Server with WebSocket support listening on port 8080\n");
Console.print("HTTP: http://localhost:8080/\n");
Console.print("WebSocket: ws://localhost:8080/websocket\n");
Console.print("Press enter to close server.");
Console.print("Server running on port 8080\n");
Console.print("HTTP : http://localhost:8080/\n");
Console.print("WS : ws://localhost:8080/websocket\n");
Console.print("Press ENTER to stop server...\n");
Console.getChar();

Http.stopServer(context);
Console.print("Server closed.\nPress enter to exit.");
Console.print("Server stopped. Press ENTER to exit.\n");
Console.getChar();
};

func handleHttpRequest(connection: ptr[Http.Connection]): Int {
def requestInfo: ptr[Http.RequestInfo] = Http.getRequestInfo(connection);

if String.isEqual(requestInfo~cnt.localUri, "/") {
def htmlContent: CharsPtr =
"<!DOCTYPE html>\n"
"<html>\n"
"<head><title>WebSocket Test</title></head>\n"
"<body>\n"
" <h1>WebSocket Test Page</h1>\n"
" <div id=\"messages\"></div>\n"
" <input type=\"text\" id=\"messageInput\" placeholder=\"Type a message...\">\n"
" <button onclick=\"sendMessage()\">Send</button>\n"
" <script>\n"
" const ws = new WebSocket('ws://' + window.location.host + '/websocket');\n"
" const messages = document.getElementById('messages');\n"
" const input = document.getElementById('messageInput');\n"
"\n"
" ws.onopen = function(event) {\n"
" addMessage('Connected to WebSocket server');\n"
" };\n"
"\n"
" ws.onmessage = function(event) {\n"
" addMessage('Server: ' + event.data);\n"
" };\n"
"\n"
" ws.onclose = function(event) {\n"
" addMessage('Connection closed');\n"
" };\n"
"\n"
" function sendMessage() {\n"
" const message = input.value;\n"
" if (message) {\n"
" ws.send(message);\n"
" addMessage('You: ' + message);\n"
" input.value = '';\n"
" }\n"
" }\n"
"\n"
" function addMessage(message) {\n"
" const div = document.createElement('div');\n"
" div.textContent = message;\n"
" messages.appendChild(div);\n"
" }\n"
"\n"
" input.addEventListener('keypress', function(e) {\n"
" if (e.key === 'Enter') {\n"
" sendMessage();\n"
" }\n"
" });\n"
" </script>\n"
"</body>\n"
"</html>";

Http.print(connection, "HTTP/1.1 200 OK\r\n");
Http.print(connection, "Content-Type: text/html\r\n");
Http.print(connection, "Content-Length: %d\r\n\r\n", String.getLength(htmlContent));
Http.print(connection, htmlContent);
} else {
Http.print(connection, "HTTP/1.1 404 Not Found\r\n");
Http.print(connection, "Content-Type: text/plain\r\n");
Http.print(connection, "Content-Length: 9\r\n\r\n");
Http.print(connection, "Not Found");
}
def req: ptr[Http.RequestInfo] = Http.getRequestInfo(connection);


if String.isEqual(req~cnt.localUri, "/websocket") {
return 0;
}


if String.isEqual(req~cnt.localUri, "/") {

def page: CharsPtr =
"<!DOCTYPE html>\n"
"<html>\n"
"<head><meta charset=\"utf-8\"><title>WebSocket Test</title></head>\n"
"<body>\n"
"<h1>WebSocket Test</h1>\n"
"<div id=\"messages\"></div>\n"
"<input id=\"msg\" placeholder=\"Type message...\">\n"
"<button onclick=\"send()\">Send</button>\n"
"<script>\n"
"const ws = new WebSocket('ws://' + location.host + '/websocket');\n"
"const box = document.getElementById('messages');\n"
"const inp = document.getElementById('msg');\n"
"ws.onopen = () => add('Connected');\n"
"ws.onmessage = e => add('Server: ' + e.data);\n"
"ws.onclose = () => add('Connection closed');\n"
"function send(){\n"
" if(inp.value){\n"
" ws.send(inp.value);\n"
" add('You: ' + inp.value);\n"
" inp.value='';\n"
" }\n"
"}\n"
"function add(t){\n"
" let d=document.createElement('div');\n"
" d.textContent=t;\n"
" box.appendChild(d);\n"
"}\n"
"</script>\n"
"</body>\n"
"</html>";

Http.print(connection, "HTTP/1.1 200 OK\r\n");
Http.print(connection, "Content-Type: text/html\r\n");
Http.print(
connection,
"Content-Length: %d\r\n\r\n",
String.getLength(page)
);
Http.print(connection, page);

return 1;
};
}


Http.print(connection, "HTTP/1.1 404 Not Found\r\n");
Http.print(connection, "Content-Length: 9\r\n\r\nNot Found");

func onWebSocketConnect(connection: ptr[Http.Connection], userData: ptr[Void]): Int {
return 1;
};

func onWebSocketConnect(
connection: ptr[Http.Connection],
userData: ptr[Void]
): Int {
Console.print("WebSocket client connected\n");
return 0;
};

func onWebSocketReady(connection: ptr[Http.Connection], userData: ptr[Void]): Void {
Console.print("WebSocket connection ready\n");
Http.writeWebSocketText(connection, "Welcome to the WebSocket server!", 33);
};
func onWebSocketReady(
connection: ptr[Http.Connection],
userData: ptr[Void]
): Void {
Console.print("WebSocket ready\n");

func onWebSocketData(connection: ptr[Http.Connection], bits: Int, data: CharsPtr, dataLen: Int, userData: ptr[Void]): Int {
Console.print("Received WebSocket message: ");
Console.print(data, dataLen);
Console.print("\n");
def msg: CharsPtr = "Welcome to the WebSocket server!";
Http.writeWebSocketText(
connection,
msg,
String.getLength(msg)
);
};

def response: array[Char, 256];
String.assign(response~ptr, "Echo: ");
String.concat(response~ptr, data, dataLen);
func onWebSocketData(
connection: ptr[Http.Connection],
bits: Int,
data: CharsPtr,
dataLen: Int,
userData: ptr[Void]
): Int {

Http.writeWebSocketText(connection, response~ptr, String.getLength(response~ptr));
if ((bits & 0x1) == 0) {
return 1;
};
}

Console.print("Received: ");
Console.print(data, dataLen);
Console.print("\n");

def buffer: array[Char, 512];
String.assign(buffer~ptr, "Echo: ");
String.concat(buffer~ptr, data, dataLen);

Http.writeWebSocketText(
connection,
buffer~ptr,
String.getLength(buffer~ptr)
);

return 1;
};

func onWebSocketClose(connection: ptr[Http.Connection], userData: ptr[Void]): Void {
func onWebSocketClose(
connection: ptr[Http.Connection],
userData: ptr[Void]
): Void {
Console.print("WebSocket client disconnected\n");
};
};

WebSocketExample.start();
WebSocketExample.start();
2 changes: 1 addition & 1 deletion Http.alusus
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Http {
}

class Context{
def stopFlag: int; // Should we stop event loop

};

def RequestCallback: alias ptr[func (connection: ptr[Connection]): Int];
Expand Down