-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver_example.c
More file actions
116 lines (94 loc) · 3.37 KB
/
server_example.c
File metadata and controls
116 lines (94 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
// --- CTML Configuration ---
#define CTML_PRETTY
#define CTML_CUSTOM_ATTRIBUTES X(onclick);
#define CTML_IMPLEMENTATION
#include "ctml.h"
#include "ctml_short.h"
// --- The Sink Function ---
// Receives the HTML chunk and the client socket FD via userData
void socket_sink(char* data, void* userData) {
int client_fd = *(int*)userData;
send(client_fd, data, strlen(data), MSG_NOSIGNAL);
}
// --- HTML Page Generator ---
void render_homepage(int client_fd, int visitor_count) {
// Pass the client_fd address as userData to the context
ctml(.sink = socket_sink, .userData = &client_fd) {
ctml_raw("<!DOCTYPE html>");
html(.lang="en") {
head() {
title() {ctml_raw("CTML Server"); }
h(style) {
ctml_raw("body { font-family: sans-serif; text-align: center; padding: 50px; }");
ctml_raw(".box { border: 2px solid #333; padding: 20px; display: inline-block; }");
}
}
body() {
div(.class="box") {
h1() {ctml_raw("Hello from C!"); }
p() {ctml_raw("This HTML was generated directly by the CTML library."); }
hr();
div() {
p() {ctml_rawf("You are visitor number: <strong>%d</strong>", visitor_count);}
p() {ctml_text("You are visitor number: '' \" <> & <strong>X</strong>");}
}
br();
button(.onclick="location.reload()") {
ctml_raw("Refresh Page");
}
}
}
}
}
}
// --- Main Server Loop ---
int main() {
int server_fd;
struct sockaddr_in address;
int addrlen = sizeof(address);
int visitor_count = 0;
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) {
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen failed");
exit(EXIT_FAILURE);
}
printf("Server listening on http://localhost:8080\n");
while (1) {
int client_fd;
if ((client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept failed");
continue;
}
visitor_count++;
// Read request (ignored)
char buffer[1024] = {0};
read(client_fd, buffer, 1024);
// Send Header
char *header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n";
send(client_fd, header, strlen(header), 0);
// Render Body using CTML with local client_fd
render_homepage(client_fd, visitor_count);
close(client_fd);
}
return 0;
}