mirror of
https://github.com/Mercantec-GHC/h5-projekt-mst.git
synced 2026-08-26 21:27:38 +02:00
impl tcp.cpp
This commit is contained in:
parent
ac8d2f2013
commit
fca446d8e9
@ -1,54 +1,54 @@
|
||||
|
||||
MAKEFLAGS += -j16
|
||||
|
||||
CC=gcc
|
||||
LD=gcc
|
||||
CXX=g++
|
||||
LD=g++
|
||||
CLANG_FORMAT=clang-format
|
||||
|
||||
CFLAGS = -std=c23 -pedantic-errors -Wall -Wextra -Wconversion
|
||||
CXXFLAGS = -std=c++23 -pedantic-errors -Wall -Wextra -Wconversion
|
||||
LDFLAGS =
|
||||
|
||||
libraries = libmicrohttpd
|
||||
# libraries = ""
|
||||
|
||||
CFLAGS += $(shell pkg-config $(libraries) --cflags)
|
||||
LDFLAGS += $(shell pkg-config $(libraries) --libs)
|
||||
# CXXFLAGS += $(shell pkg-config $(libraries) --cflags)
|
||||
# LDFLAGS += $(shell pkg-config $(libraries) --libs)
|
||||
|
||||
RELEASE = 0
|
||||
GDB = 0
|
||||
|
||||
ifeq ($(RELEASE),1)
|
||||
CFLAGS += -O3
|
||||
CXXFLAGS += -O3
|
||||
else
|
||||
CFLAGS += -g -Wno-unused
|
||||
CXXFLAGS += -g -Wno-unused
|
||||
|
||||
ifeq ($(GDB),1)
|
||||
CFLAGS += -ggdb
|
||||
CXXFLAGS += -ggdb
|
||||
else
|
||||
CFLAGS += -fsanitize=address
|
||||
CXXFLAGS += -fsanitize=address
|
||||
endif
|
||||
endif
|
||||
|
||||
NO_MAIN = 0
|
||||
ifeq ($(NO_MAIN),1)
|
||||
CFLAGS += -Dmain="not_main"
|
||||
CXXFLAGS += -Dmain="not_main"
|
||||
endif
|
||||
|
||||
build_dir = build
|
||||
obj_dir = $(build_dir)/obj
|
||||
|
||||
sources = \
|
||||
src/main.c
|
||||
src/main.cpp
|
||||
|
||||
target=$(build_dir)/backend
|
||||
|
||||
all: $(target)
|
||||
|
||||
$(target): $(sources:%.c=$(obj_dir)/%.o)
|
||||
$(LD) -o $@ $(CFLAGS) $(LDFLAGS) $^
|
||||
$(target): $(sources:%.cpp=$(obj_dir)/%.o)
|
||||
$(LD) -o $@ $(CXXFLAGS) $(LDFLAGS) $^
|
||||
|
||||
$(obj_dir)/%.o: %.c
|
||||
$(obj_dir)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $< -c -o $@ -MMD -MP $(CFLAGS)
|
||||
$(CXX) $< -c -o $@ -MMD -MP $(CXXFLAGS)
|
||||
|
||||
format:
|
||||
$(CLANG_FORMAT) -style=file -i src/*
|
||||
@ -59,5 +59,5 @@ check:
|
||||
clean:
|
||||
rm -rf $(build_dir)
|
||||
|
||||
-include $(sources:%.c=$(obj_dir)/%.d)
|
||||
-include $(sources:%.cpp=$(obj_dir)/%.d)
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
-xc
|
||||
-std=c23
|
||||
-xc++
|
||||
-std=c++23
|
||||
-pedantic-errors
|
||||
-Wall
|
||||
-Wextra
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
#include <microhttpd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PORT 8888
|
||||
|
||||
int print_out_key(
|
||||
void* cls, enum MHD_ValueKind kind, const char* key, const char* value)
|
||||
{
|
||||
printf("%s: %s\n", key, value);
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
int answer_to_connection(void* cls, struct MHD_Connection* connection,
|
||||
const char* url, const char* method, const char* version,
|
||||
const char* upload_data, size_t* upload_data_size, void** req_cls)
|
||||
{
|
||||
const char* page = "<html><body>Hello, browser!</body></html>";
|
||||
struct MHD_Response* response;
|
||||
int ret;
|
||||
|
||||
MHD_get_connection_values(connection,
|
||||
MHD_HEADER_KIND,
|
||||
(MHD_KeyValueIterator)&print_out_key,
|
||||
NULL);
|
||||
|
||||
printf("New %s request for %s using version %s\n", method, url, version);
|
||||
|
||||
response = MHD_create_response_from_buffer(
|
||||
strlen(page), (void*)page, MHD_RESPMEM_PERSISTENT);
|
||||
|
||||
ret = (int)MHD_queue_response(connection, MHD_HTTP_OK, response);
|
||||
MHD_destroy_response(response);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("hello\n");
|
||||
struct MHD_Daemon* daemon;
|
||||
|
||||
daemon = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD,
|
||||
PORT,
|
||||
NULL,
|
||||
NULL,
|
||||
(MHD_AccessHandlerCallback)&answer_to_connection,
|
||||
NULL,
|
||||
MHD_OPTION_END);
|
||||
|
||||
if (NULL == daemon)
|
||||
return 1;
|
||||
getchar();
|
||||
|
||||
MHD_stop_daemon(daemon);
|
||||
return 0;
|
||||
}
|
||||
12
backend/src/main.cpp
Normal file
12
backend/src/main.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PORT 8888
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("hello\n");
|
||||
return 0;
|
||||
}
|
||||
78
backend/src/tcp.cpp
Normal file
78
backend/src/tcp.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "tcp.hpp"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <expected>
|
||||
#include <format>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mst {
|
||||
auto errno_shim(std::string_view message) -> std::string
|
||||
{
|
||||
auto x = strerror(errno);
|
||||
return std::format("{} ({})", message, x);
|
||||
}
|
||||
|
||||
auto TcpConnection::write(uint8_t* buffer, size_t len) -> Result<size_t>
|
||||
{
|
||||
ssize_t bytes_written = ::write(this->fd, buffer, len);
|
||||
if (bytes_written < 0) {
|
||||
return std::unexpected(errno_shim("could not write bytes"));
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
auto TcpConnection::read(uint8_t* buffer, size_t len) -> Result<size_t>
|
||||
{
|
||||
ssize_t bytes_read = ::recv(this->fd, buffer, len, 0);
|
||||
if (bytes_read < 0) {
|
||||
return std::unexpected(errno_shim("could not read bytes"));
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
auto TcpListener::bind(const std::string& host, uint16_t port)
|
||||
-> Result<TcpListener>
|
||||
{
|
||||
int socket_fd = 0;
|
||||
if ((socket_fd = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
return std::unexpected(errno_shim("could not get socket"));
|
||||
}
|
||||
|
||||
struct sockaddr_in address = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(port),
|
||||
.sin_addr = in_addr { .s_addr = inet_addr(host.c_str()) },
|
||||
.sin_zero = { },
|
||||
};
|
||||
|
||||
if (::bind(socket_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
|
||||
return std::unexpected(errno_shim("could not bind"));
|
||||
}
|
||||
|
||||
if (::listen(socket_fd, 0) < 0) {
|
||||
return std::unexpected(errno_shim("could not listen"));
|
||||
}
|
||||
|
||||
return TcpListener(socket_fd, address);
|
||||
}
|
||||
|
||||
auto TcpListener::accept() -> Result<TcpConnection>
|
||||
{
|
||||
socklen_t size = sizeof(address);
|
||||
|
||||
int socket = ::accept(this->fd, (struct sockaddr*)&address, &size);
|
||||
if (socket < 0) {
|
||||
return std::unexpected(errno_shim("could not accept"));
|
||||
}
|
||||
return TcpConnection(*this, socket);
|
||||
}
|
||||
|
||||
}
|
||||
38
backend/src/tcp.hpp
Normal file
38
backend/src/tcp.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <netinet/in.h>
|
||||
#include <string>
|
||||
|
||||
namespace mst {
|
||||
template <typename T> using Result = std::expected<T, std::string>;
|
||||
|
||||
class TcpListener;
|
||||
|
||||
class TcpConnection {
|
||||
public:
|
||||
auto write(uint8_t* buffer, size_t len) -> Result<size_t>;
|
||||
auto read(uint8_t* buffer, size_t len) -> Result<size_t>;
|
||||
TcpConnection(TcpListener&, int fd)
|
||||
: fd(fd) { };
|
||||
|
||||
private:
|
||||
int fd;
|
||||
};
|
||||
|
||||
class TcpListener {
|
||||
|
||||
public:
|
||||
static auto bind(const std::string& host, uint16_t port)
|
||||
-> Result<TcpListener>;
|
||||
auto accept() -> Result<TcpConnection>;
|
||||
|
||||
private:
|
||||
TcpListener(int fd, sockaddr_in address)
|
||||
: fd(fd)
|
||||
, address(address) { };
|
||||
int fd;
|
||||
sockaddr_in address;
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user