Skip to content
Merged
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
4 changes: 2 additions & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
add_executable(echo-server echo-server.cpp)
target_link_libraries(echo-server PRIVATE condy uring)

add_executable(fast-cp fast-cp.cpp)
target_link_libraries(fast-cp PRIVATE condy uring)
add_executable(link-cp link-cp.cpp)
target_link_libraries(link-cp PRIVATE condy uring)

add_executable(custom-allocator custom-allocator.cpp)
target_link_libraries(custom-allocator PRIVATE condy uring)
107 changes: 55 additions & 52 deletions examples/echo-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,92 +7,95 @@
#include <sys/socket.h>
#include <unistd.h>

void prepare_address(const std::string &host, uint16_t port,
sockaddr_in &addr) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, host.c_str(), &addr.sin_addr);
}
constexpr size_t BACKLOG = 128;
constexpr size_t MAX_CONNECTIONS = 1024;
constexpr size_t MAX_MESSAGE_LEN = 2048;

condy::Coro<> handle_client(int client_fd) {
constexpr size_t BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
condy::Coro<void> session(int client_fd) {
char buffer[MAX_MESSAGE_LEN];

while (true) {
int n = co_await condy::async_read(
client_fd, condy::buffer(buffer, BUFFER_SIZE), 0);
int n = co_await condy::async_recv(condy::fixed(client_fd),
condy::buffer(buffer), 0);
if (n <= 0) {
if (n < 0) {
std::fprintf(stderr, "Read error: %s\n", std::strerror(-n));
std::fprintf(stderr, "Read error: %d\n", n);
}
break;
}

n = co_await condy::async_write(client_fd, condy::buffer(buffer, n), 0);
n = co_await condy::async_send(condy::fixed(client_fd),
condy::buffer(buffer, n), 0);
if (n < 0) {
std::fprintf(stderr, "Write error: %s\n", std::strerror(-n));
std::fprintf(stderr, "Write error: %d\n", n);
break;
}
}

co_await condy::async_close(client_fd);
std::printf("Connection closed, fd:%d\n", client_fd);
co_await condy::async_close(condy::fixed(client_fd));
}

condy::Coro<> co_main(const std::string &host, uint16_t port) {
condy::Coro<int> co_main(int server_fd) {
while (true) {
sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = co_await condy::async_accept_direct(
server_fd, (struct sockaddr *)&client_addr, &client_len, 0,
CONDY_FILE_INDEX_ALLOC);
if (client_fd < 0) {
std::fprintf(stderr, "Failed to accept connection: %d\n",
client_fd);
co_return 1;
}

condy::co_spawn(session(client_fd)).detach();
}
}
Comment on lines +38 to +53
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The co_main function has an infinite loop that never returns under normal circumstances. This means the return value of 1 on line 48 will only be reached if async_accept_direct fails. However, the function is declared to return int, but the infinite loop prevents reaching a normal return path. Consider either documenting that this is intentional behavior (the server runs indefinitely), or implement a shutdown mechanism.

Copilot uses AI. Check for mistakes.

void prepare_address(const std::string &host, uint16_t port,
sockaddr_in &addr) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, host.c_str(), &addr.sin_addr);
}

int main(int argc, char **argv) noexcept(false) {
if (argc < 3) {
std::fprintf(stderr, "Usage: %s <host> <port>\n", argv[0]);
return 1;
}

std::string host = argv[1];
uint16_t port = static_cast<uint16_t>(std::stoi(argv[2]));
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The port parsing using std::stoi doesn't handle invalid input gracefully. If the port argument is not a valid integer or is out of the valid port range (0-65535), std::stoi will throw an exception. While the function is marked noexcept(false), it would be better to validate the port number and provide a meaningful error message to the user.

Suggested change
uint16_t port = static_cast<uint16_t>(std::stoi(argv[2]));
uint16_t port;
try {
std::size_t pos = 0;
int parsed = std::stoi(argv[2], &pos);
// Ensure the whole argument was parsed and the value is within valid port range.
if (argv[2][pos] != '\0' || parsed < 0 || parsed > 65535) {
std::fprintf(stderr,
"Invalid port '%s'. Please provide a number between 0 and 65535.\n",
argv[2]);
return 1;
}
port = static_cast<uint16_t>(parsed);
} catch (const std::exception &) {
std::fprintf(stderr,
"Invalid port '%s'. Please provide a number between 0 and 65535.\n",
argv[2]);
return 1;
}

Copilot uses AI. Check for mistakes.

sockaddr_in server_addr;
prepare_address(host, port, server_addr);

int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
std::perror("Failed to create socket");
co_return;
return 1;
}

if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) <
0) {
std::perror("Failed to bind socket");
co_await condy::async_close(server_fd);
co_return;
close(server_fd);
return 1;
}

if (listen(server_fd, SOMAXCONN) < 0) {
if (listen(server_fd, BACKLOG) < 0) {
std::perror("Failed to listen on socket");
co_await condy::async_close(server_fd);
co_return;
close(server_fd);
return 1;
}

std::printf("Echo server listening on %s:%d\n", host.c_str(), port);

while (true) {
sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = co_await condy::async_accept(
server_fd, (struct sockaddr *)&client_addr, &client_len, 0);
if (client_fd < 0) {
std::fprintf(stderr, "Failed to accept connection: %s\n",
std::strerror(-client_fd));
co_return;
}

std::printf("Accept connection from %s:%d, fd:%d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port), client_fd);
condy::Runtime runtime(condy::RuntimeOptions().sq_size(MAX_CONNECTIONS));

condy::co_spawn(handle_client(client_fd)).detach();
}
}

int main(int argc, char **argv) noexcept(false) {
if (argc < 3) {
std::fprintf(stderr, "Usage: %s <host> <port>\n", argv[0]);
return 1;
}

std::string host = argv[1];
uint16_t port = static_cast<uint16_t>(std::stoi(argv[2]));
runtime.fd_table().init(MAX_CONNECTIONS);

condy::sync_wait(co_main(host, port));
return 0;
return condy::sync_wait(runtime, co_main(server_fd));
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server_fd socket is never closed before the program exits. If condy::sync_wait returns normally or if an error occurs in co_main, the socket file descriptor will leak. Consider closing the socket after sync_wait returns, or use RAII (e.g., a unique_ptr with a custom deleter) to ensure proper cleanup.

Suggested change
return condy::sync_wait(runtime, co_main(server_fd));
int result = condy::sync_wait(runtime, co_main(server_fd));
close(server_fd);
return result;

Copilot uses AI. Check for mistakes.
}
135 changes: 0 additions & 135 deletions examples/fast-cp.cpp

This file was deleted.

Loading
Loading