1#include <unistd.h>
2#include <netinet/in.h>
3#include <sys/socket.h>
4
5#include "server.h"
6#include "socket.h"
7
8#define CTEST_MAIN
9#include "ctest.h"
10
11#include "common.h"
12
13cstr server_host = "127.0.0.1";
14int server_port = 8181;
15cstr content = "Lorem ipsum dolor sit amet";
16
17void process_data(vws_svr_data* req, void* thread_ctx)
18{
19 vws_tcp_svr* server = req->server;
20
21 vws.trace(VL_INFO, "process_data (%p)", req);
22
23 //> Prepare the response: echo the data back
24
25 // Allocate memory for the data to be sent in response
26 char* data = (char*)vws.malloc(req->size);
27
28 // Copy the request's data to the response data
29 strncpy(data, req->data, req->size);
30
31 // Create response
32 vws_svr_data* reply = vws_svr_data_own( req->server,
33 req->cid,
34 (ucstr)data,
35 req->size );
36
37 // Free request
38 vws_svr_data_free(req);
39
40 if (vws.tracelevel >= VT_APPLICATION)
41 {
42 vws.trace( VL_INFO,
43 "process_data(%lu): %i bytes",
44 reply->cid,
45 reply->size);
46 }
47
48 // Send reply. This will wakeup network thread.
49 vws_tcp_svr_send(reply);
50}
51
52void server_thread(void* arg)
53{
54 // Create a listening socket
55 int listenfd = socket(AF_INET, SOCK_STREAM, 0);
56
57 ASSERT_TRUE(listenfd >= 0);
58
59 // setsockopt: Handy debugging trick that lets us rerun the server
60 // immediately after we kill it; otherwise we have to wait about 20 secs.
61 // Eliminates "ERROR on binding: Address already in use" error.
62 int optval = 1;
63 setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,
64 (const void*)&optval, sizeof(int) );
65
66 struct sockaddr_in serveraddr;
67 memset((char*)&serveraddr, 0, sizeof(serveraddr));
68 serveraddr.sin_family = AF_INET;
69 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
70 serveraddr.sin_port = htons((unsigned short)server_port);
71
72 struct sockaddr* bindaddr = (struct sockaddr*)&serveraddr;
73 ASSERT_TRUE(bind(listenfd, bindaddr, sizeof(serveraddr)) >= 0);
74
75 vws_tcp_svr* server = (vws_tcp_svr*)arg;
76 server->state = VS_RUNNING;
77 server->on_data_in = process_data;
78 vws.tracelevel = VT_ALL;
79 server->trace = vws.tracelevel;
80
81 ASSERT_TRUE(listen(listenfd, 10) >= 0);
82
83 struct sockaddr_in clientaddr;
84 socklen_t clientlen = sizeof(clientaddr);
85 int connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &clientlen);
86 ASSERT_TRUE(connfd >= 0);
87
88 vws_tcp_svr_inetd_run(server, connfd);
89}
90
91void client_thread(void* arg)
92{
93 // Connect
94 vws.trace(VL_INFO, "[CLIENT] Connecting");
95 vws_socket* s = vws_socket_new();
96 ASSERT_TRUE(vws_socket_connect(s, server_host, server_port, false));
97 vws.trace(VL_INFO, "[CLIENT] Connected");
98
99 // Send request
100 vws.trace(VL_INFO, "[CLIENT] Send: %s", content);
101 vws_socket_write(s, (ucstr)content, strlen(content));
102
103 // Get reply
104 ssize_t n = vws_socket_read(s);
105 ASSERT_TRUE(n > 0);
106 vws.trace(VL_INFO, "[CLIENT] Receive: %s", s->buffer->data);
107
108 // Disconnect and cleanup.
109 vws_socket_free(s);
110}
111
112CTEST(test_server, echo)
113{
114 vws_tcp_svr* server = vws_tcp_svr_new(10, 0, 0);
115 vws.tracelevel = VT_THREAD;
116 server->on_data_in = process_data;
117
118 vws.trace(VL_INFO, "[CLIENT] Starting server");
119
120 uv_thread_t server_tid;
121 uv_thread_create(&server_tid, server_thread, server);
122
123 // Wait for server to start up
124 while (server->state != VS_RUNNING)
125 {
126 vws_msleep(100);
127 }
128
129 int nc = 1;
130 uv_thread_t* threads = vws.malloc(sizeof(uv_thread_t) * nc);
131
132 for (int i = 0; i < nc; i++)
133 {
134 uv_thread_create(&threads[i], client_thread, NULL);
135 vws.trace(VL_INFO, "started client thread %p", threads[i]);
136 }
137
138 for (int i = 0; i < nc; i++)
139 {
140 uv_thread_join(&threads[i]);
141 vws.trace(VL_INFO, "stopped client thread %p", threads[i]);
142 }
143
144 free(threads);
145
146 // Server auto-shutdown on client disconnect. Wait for thread.
147 uv_thread_join(&server_tid);
148
149 // Cleanup
150 vws_tcp_svr_free(server);
151}
152
153int main(int argc, const char* argv[])
154{
155 return ctest_main(argc, argv);
156}
157