1 /* This is a basic TCP/TLS echo server. */
2 
3 #include <libusockets.h>
4 const int SSL = 1;
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 /* Our socket extension */
11 struct echo_socket {
12 	char *backpressure;
13 	int length;
14 };
15 
16 /* Our socket context extension */
17 struct echo_context {
18 
19 };
20 
21 /* Loop wakeup handler */
on_wakeup(struct us_loop_t * loop)22 void on_wakeup(struct us_loop_t *loop) {
23 
24 }
25 
26 /* Loop pre iteration handler */
on_pre(struct us_loop_t * loop)27 void on_pre(struct us_loop_t *loop) {
28 
29 }
30 
31 /* Loop post iteration handler */
on_post(struct us_loop_t * loop)32 void on_post(struct us_loop_t *loop) {
33 
34 }
35 
36 /* Socket writable handler */
on_echo_socket_writable(struct us_socket_t * s)37 struct us_socket_t *on_echo_socket_writable(struct us_socket_t *s) {
38 	struct echo_socket *es = (struct echo_socket *) us_socket_ext(SSL, s);
39 
40 	/* Continue writing out our backpressure */
41 	int written = us_socket_write(SSL, s, es->backpressure, es->length, 0);
42 	if (written != es->length) {
43 		char *new_buffer = (char *) malloc(es->length - written);
44 		memcpy(new_buffer, es->backpressure, es->length - written);
45 		free(es->backpressure);
46 		es->backpressure = new_buffer;
47 		es->length -= written;
48 	} else {
49 		free(es->backpressure);
50 		es->length = 0;
51 	}
52 
53 	/* Client is not boring */
54 	us_socket_timeout(SSL, s, 30);
55 
56 	return s;
57 }
58 
59 /* Socket closed handler */
on_echo_socket_close(struct us_socket_t * s,int code,void * reason)60 struct us_socket_t *on_echo_socket_close(struct us_socket_t *s, int code, void *reason) {
61 	struct echo_socket *es = (struct echo_socket *) us_socket_ext(SSL, s);
62 
63 	printf("Client disconnected\n");
64 
65 	free(es->backpressure);
66 
67 	return s;
68 }
69 
70 /* Socket half-closed handler */
on_echo_socket_end(struct us_socket_t * s)71 struct us_socket_t *on_echo_socket_end(struct us_socket_t *s) {
72 	us_socket_shutdown(SSL, s);
73 	return us_socket_close(SSL, s, 0, NULL);
74 }
75 
76 /* Socket data handler */
on_echo_socket_data(struct us_socket_t * s,char * data,int length)77 struct us_socket_t *on_echo_socket_data(struct us_socket_t *s, char *data, int length) {
78 	struct echo_socket *es = (struct echo_socket *) us_socket_ext(SSL, s);
79 
80 	/* Print the data we received */
81 	printf("Client sent <%.*s>\n", length, data);
82 
83 	/* Send it back or buffer it up */
84 	int written = us_socket_write(SSL, s, data, length, 0);
85 	if (written != length) {
86 		char *new_buffer = (char *) malloc(es->length + length - written);
87 		memcpy(new_buffer, es->backpressure, es->length);
88 		memcpy(new_buffer + es->length, data + written, length - written);
89 		free(es->backpressure);
90 		es->backpressure = new_buffer;
91 		es->length += length - written;
92 	}
93 
94 	/* Client is not boring */
95 	us_socket_timeout(SSL, s, 30);
96 
97 	return s;
98 }
99 
100 /* Socket opened handler */
on_echo_socket_open(struct us_socket_t * s,int is_client,char * ip,int ip_length)101 struct us_socket_t *on_echo_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
102 	struct echo_socket *es = (struct echo_socket *) us_socket_ext(SSL, s);
103 
104 	/* Initialize the new socket's extension */
105 	es->backpressure = 0;
106 	es->length = 0;
107 
108 	/* Start a timeout to close the socekt if boring */
109 	us_socket_timeout(SSL, s, 30);
110 
111 	printf("Client connected\n");
112 
113 	return s;
114 }
115 
116 /* Socket timeout handler */
on_echo_socket_timeout(struct us_socket_t * s)117 struct us_socket_t *on_echo_socket_timeout(struct us_socket_t *s) {
118 	printf("Client was idle for too long\n");
119 	return us_socket_close(SSL, s, 0, NULL);
120 }
121 
main()122 int main() {
123 	/* The event loop */
124 	struct us_loop_t *loop = us_create_loop(0, on_wakeup, on_pre, on_post, 0);
125 
126 	/* Socket context */
127 	struct us_socket_context_options_t options = {};
128 	options.key_file_name = "/home/alexhultman/uWebSockets.js/misc/key.pem";
129 	options.cert_file_name = "/home/alexhultman/uWebSockets.js/misc/cert.pem";
130 	options.passphrase = "1234";
131 
132 	struct us_socket_context_t *echo_context = us_create_socket_context(SSL, loop, sizeof(struct echo_context), options);
133 
134 
135 	/* Registering event handlers */
136 	us_socket_context_on_open(SSL, echo_context, on_echo_socket_open);
137 	us_socket_context_on_data(SSL, echo_context, on_echo_socket_data);
138 	us_socket_context_on_writable(SSL, echo_context, on_echo_socket_writable);
139 	us_socket_context_on_close(SSL, echo_context, on_echo_socket_close);
140 	us_socket_context_on_timeout(SSL, echo_context, on_echo_socket_timeout);
141 	us_socket_context_on_end(SSL, echo_context, on_echo_socket_end);
142 
143 	/* Start accepting echo sockets */
144 	struct us_listen_socket_t *listen_socket = us_socket_context_listen(SSL, echo_context, 0, 3000, 0, sizeof(struct echo_socket));
145 
146 	if (listen_socket) {
147 		printf("Listening on port 3000...\n");
148 		us_loop_run(loop);
149 	} else {
150 		printf("Failed to listen!\n");
151 	}
152 }
153