-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.hpp
136 lines (118 loc) · 4 KB
/
server.hpp
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <vector>
#include <format>
#include "scheduler.hpp"
#include "co_syscall.hpp"
#define MAX_CLIENTS 1024
#define BUFFER_SIZE 1024
class server {
protected:
int serverSocket, clientSockets[MAX_CLIENTS], maxClients = MAX_CLIENTS;
struct sockaddr_in serverAddr, clientAddr;
socklen_t addrLen = sizeof(clientAddr);
char buffer[BUFFER_SIZE];
public:
server(int port) {
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// Set up server address struct
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(port); // Change this port as needed
// Bind socket
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
perror("Bind failed");
close(serverSocket);
exit(EXIT_FAILURE);
}
// Listen for incoming connections
if (listen(serverSocket, MAX_CLIENTS) == -1) {
perror("Listen failed");
close(serverSocket);
exit(EXIT_FAILURE);
}
std::cout << std::format("Server listening on port {}...\n", port);
// Initialize client sockets array
for (int i = 0; i < MAX_CLIENTS; ++i) {
clientSockets[i] = 0;
}
}
scheduler::task_t co_listen(scheduler &sche)
{
co_yield std::format("listen");
while(1) {
// If a new connection is available, accept it
int newSocket = co_await co_syscall::accept(sche, serverSocket, (struct sockaddr *)&clientAddr, &addrLen);
if (newSocket == -1)
{
perror("Accept failed");
exit(EXIT_FAILURE);
}
// printf("New connection, socket fd is %d, ip is: %s, port: %d\n",
// newSocket, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
// Add the new socket to the array of sockets
for (int i = 0; i < MAX_CLIENTS; ++i)
{
if (clientSockets[i] == 0)
{
clientSockets[i] = newSocket;
sche.schedule(co_handle_client(sche, i), await_state::schedule_now);
break;
}
}
}
}
virtual scheduler::task_t co_handle_client(scheduler &sche, int clientSockets_i)
{
co_yield std::format("co_handle_client {}", clientSockets_i);
char package[MAX_PACKAGE_SIZE+1];
while(1) {
int sd = clientSockets[clientSockets_i];
// Read the incoming message
// std::cout << "co_handle_client awaiting" << std::endl;
int32_t package_size = co_await co_syscall::read_package(sche, sd, buffer);
if (package_size <= 0)
{
// Client disconnected
// printf("Host disconnected, socket fd is %d\n", sd);
close(sd);
clientSockets[clientSockets_i] = 0;
co_return 0;
}
else
{
co_await process_request(sche, sd, buffer, package_size);
}
}
}
virtual scheduler::task_t process_request(scheduler &sche, int fd, void *request, int32_t sz) {
co_return 0;
}
std::vector<int> list_of_client_fds() {
std::vector<int> res;
for(int i = 0; i < MAX_CLIENTS; i++) {
if (clientSockets[i] != 0) {
res.push_back(clientSockets[i]);
}
}
return res;
}
int32_t rpc_add_number_impl(void *buffer) {
int *ib = (int*)buffer;
return ib[1] + ib[2];
}
~server()
{
close(serverSocket);
}
};