diff options
-rw-r--r-- | Makefile | 40 | ||||
-rw-r--r-- | README.md | 35 | ||||
-rw-r--r-- | ROADMAP.md | 3 | ||||
-rw-r--r-- | go.mod (renamed from go/go.mod) | 0 | ||||
-rw-r--r-- | go.sum (renamed from go/go.sum) | 0 | ||||
-rw-r--r-- | gui.c | 115 | ||||
-rw-r--r-- | gui.h | 20 | ||||
-rw-r--r-- | main.c | 85 | ||||
-rw-r--r-- | main.go (renamed from go/main.go) | 0 | ||||
-rw-r--r-- | tests/get_domainpart.c | 40 | ||||
-rwxr-xr-x | tools/lint.sh | 10 | ||||
-rw-r--r-- | xmpp.c | 200 | ||||
-rw-r--r-- | xmpp.h | 21 |
13 files changed, 2 insertions, 567 deletions
diff --git a/Makefile b/Makefile deleted file mode 100644 index 2ffa1b8..0000000 --- a/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -CC=gcc -CFLAGS=-g -I. -lSDL2 -SRC:=$(shell find ./ -maxdepth 1 -type f -regex ".*\.c" -not -name "main.c") -OBJ:=$(patsubst ./%.c,build/%.o,$(SRC)) -_TESTS:=$(shell find ./tests/ -maxdepth 1 -type f -regex ".*\.c") -TESTS:=$(patsubst ./%.c,build/%,$(_TESTS)) - -LIMOX=build/limox -GRAPHICS=build/icon.png build/icon.pdf -DOCS=build/docs/README.pdf build/docs/ROADMAP.pdf - -all: build $(OBJ) $(TESTS) $(LIMOX) $(DOCS) $(GRAPHICS) - -build: - mkdir -p build/tests - mkdir -p build/docs - -$(LIMOX): $(OBJ) build/main.o - $(CC) -o $@ $^ $(CFLAGS) - -build/%.o: %.c - $(CC) -c -o $@ $< $(CFLAGS) - -build/%.png: %.svg - inkscape $< -o $@ -w 256 -h 256 - -build/%.pdf: %.svg - inkscape $< -o $@ -w 256 -h 256 - -build/docs/%.pdf: %.md $(GRAPHICS) - pandoc -o $@ $< - -build/tests/%: tests/%.c $(OBJ) - $(CC) -o $@ $< $(OBJ) $(CFLAGS) - $@ - -.PHONY: clean - -clean: - rm -rf build @@ -7,40 +7,7 @@ usable on mobile linux devices like smartphones or tablets. ![LimoX icon](build/icon.pdf) -Also mind the `ROADMAP` file, the [project page][1] and my [packaging -repository][2] for Arch Linux with support for LimoX. A nice reference which -helps me a lot is [Beej's Guide to Network Programming][3] aswell as [Gigi's -SDL2 tutorial][5] and the [SDL2 documentation][4]. - - -## Building and dependencies - -Install these build dependencies: - -- GNU coreutils -- GNU make -- gcc -- pandoc -- texlive-core -- inkscape - -Install these runtime dependencies: - -- sdl2 - -Just run these commands to build, test and run: - -``` -make all -./build/limox -``` - -Run `make clean` to clean the build folder. You can get a help page by running -`./build/limox -h`. +Also mind the `ROADMAP` file and the [project page][1]. [1]: https://xengineering.eu/git/limox -[2]: https://xengineering.eu/git/pkgbuilds -[3]: https://www.beej.us/guide/bgnet/html/ -[4]: https://wiki.libsdl.org/SDL2/FrontPage -[5]: https://gigi.nullneuron.net/gigilabs/writing/sdl2-tutorials/ @@ -2,8 +2,7 @@ # Roadmap -- [x] develop minimal viable product with GTK4 (branch `legacy/gtk4-libstrophe`) -- [ ] develop minimal viable product with SDL2 +- [ ] develop minimal viable product - [ ] implement XMPP core client ([compliance suite 2022][1]) - [ ] RFC 6120: XMPP Core - [ ] RFC 7590: TLS for XMPP @@ -1,115 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -#include <SDL2/SDL.h> -#include <stdbool.h> -#include <stdlib.h> -#include <unistd.h> - -#include "xmpp.h" - - -struct GuiContext { - bool quit; - SDL_Event event; - SDL_Window* window; - SDL_Renderer* renderer; - SDL_Texture* texture; - uint32_t* pixels; - int xmpp_fd; -}; - - -struct GuiContext *init() { - struct GuiContext *ctx = malloc(sizeof(struct GuiContext)); - - ctx->quit = false; - ctx->xmpp_fd = -1; - - ctx->pixels = malloc(sizeof(uint32_t) * 640 * 480); - memset(ctx->pixels, 255, 640 * 480 * sizeof(uint32_t)); - - SDL_Init(SDL_INIT_VIDEO); - - return ctx; -} - -void deinit(struct GuiContext *ctx) { - - // TODO this seems to end in memory access errors but ... why? - //SDL_DestroyTexture(texture); - //SDL_DestroyRenderer(renderer); - - SDL_Quit(); - - free(ctx->pixels); - free(ctx); -} - -bool create_window(struct GuiContext *ctx) { - - ctx->window = SDL_CreateWindow("LimoX", - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, - SDL_WINDOW_RESIZABLE - ); - - ctx->renderer = SDL_CreateRenderer(ctx->window, -1, 0); - ctx->texture = SDL_CreateTexture(ctx->renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STATIC, 640, 480); - - return ctx->window != NULL; -} - -void gui_run(void) { - - struct GuiContext *ctx = init(); - - fprintf(stderr, "SDL2 video driver: %s\n", SDL_GetCurrentVideoDriver()); - - if (!create_window(ctx)) { - fprintf(stderr, "Failed to create SDL2 window!\n"); - return; - } - - while (!ctx->quit) { - SDL_UpdateTexture(ctx->texture, NULL, ctx->pixels, 640 * sizeof(uint32_t)); - SDL_WaitEvent(&ctx->event); - switch (ctx->event.type) { - case SDL_QUIT: - ctx->quit = true; - break; - case SDL_MOUSEBUTTONDOWN: - if (ctx->xmpp_fd == -1) { - ctx->xmpp_fd = xmpp_connect(); - } else { - close(ctx->xmpp_fd); - ctx->xmpp_fd = -1; - printf("Closed XMPP connection.\n"); - } - break; - } - SDL_RenderClear(ctx->renderer); - SDL_RenderCopy(ctx->renderer, ctx->texture, NULL, NULL); - SDL_RenderPresent(ctx->renderer); - } - - SDL_DestroyWindow(ctx->window); - deinit(ctx); - -} @@ -1,20 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -void gui_run(void); @@ -1,85 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -#include <stdbool.h> -#include <stdio.h> -#include <getopt.h> - -#include "gui.h" - - -/* - * Configuration struct for all options - */ -struct Options { - bool unknown; - bool help; -}; - - -/* - * Parse command line arguments - */ -static void get_opts(struct Options *opts, int argc, char* argv[]) -{ - opts->unknown = false; - opts->help = false; - - int c; - while ((c=getopt(argc, argv, "h")) != -1) { - - switch (c) { - case 'h': - opts->help = true; - break; - default: - opts->unknown = true; - } - } -} - -/* - * Print help page to command line - */ -static void print_help(void) -{ - printf( - "The Linux on mobile XMPP (LimoX) client.\n" - "\n" - "Usage: limox [-h]\n" - "\n" - "Options:\n" - " -h print help page\n" - ); -} - -/* - * Run control flow of the application - */ -int main(int argc, char* argv[]) -{ - struct Options opts; - get_opts(&opts, argc, argv); - - if (opts.unknown || opts.help) { - print_help(); - } else { - gui_run(); - } -} diff --git a/tests/get_domainpart.c b/tests/get_domainpart.c deleted file mode 100644 index 6601330..0000000 --- a/tests/get_domainpart.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -#include <string.h> -#include <stdio.h> - -#include "xmpp.h" - - -int main(void) -{ - char *input = "test@example.org/3f"; - const char *expected = "example.org"; - - char *result = get_domainpart(input); - - if (strcmp(result, expected) == 0) { - printf("Unit test passed - \033[;32mok\033[0m\n"); - return 0; - } else { - printf("'%s' != '%s' - \033[;31mfailed\033[0m\n", result, expected); - return 1; - } -} diff --git a/tools/lint.sh b/tools/lint.sh deleted file mode 100755 index 5264112..0000000 --- a/tools/lint.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - - -if ! command -v splint 2> /dev/null -then - echo "Please install splint (http://splint.org/)!" - exit 1 -fi - -find . -type f -iname '*.c' | xargs splint @@ -1,200 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -#define _GNU_SOURCE -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <stdbool.h> - - -/* - * Get the domainpart of the Jabber ID (JID) - * - * See https://datatracker.ietf.org/doc/html/rfc7622#section-3.2 for details. - */ -char *get_domainpart(char *jid) -{ - int start = 0; // inclusive index - int stop = strlen(jid); // exclusive index - - for(int i=0; i<strlen(jid); i++) { - if (jid[i] == '/') { - stop = i; - break; - } - } - - for(int i=0; i<strlen(jid); i++) { - if (jid[i] == '@') { - start = i + 1; - break; - } - } - - char *retval = (char *)malloc((stop-start+1) * sizeof(char)); - memcpy(retval, jid+start, (stop-start) * sizeof(char)); - retval[stop] = '\0'; - - return retval; -} - -/* - * Return the preferred struct addrinfo * or NULL - * - * This handles DNS resolution. It returns the first valid addrinfo which is - * returned by getaddrinfo. Mind that the addrinfo could use IPv6 instead of - * IPv4. - * - * FIXME this just takes the first received IPv4 address (by far not compliant - * to RFC 6120!) - * FIXME This function contains a memory leak! Free the linked list servinfo! - */ -struct addrinfo *resolve_dns(char *domain) -{ - struct addrinfo hints; - struct addrinfo *servinfo; - void *addr; - char ipstr[INET6_ADDRSTRLEN]; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo(domain, "xmpp-client", &hints, &servinfo) != 0) { - printf("Failed to resolve hostname '%s'.\n", domain); - return NULL; - } - struct addrinfo *p; - for(p=servinfo; p!=NULL; p=p->ai_next) { - if (p->ai_family == AF_INET) { - struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; - addr = &(ipv4->sin_addr); - inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); - printf("Got compatible IPv4 address %s from DNS.\n", ipstr); - return p; - } else if (p->ai_family == AF_INET6) { - printf("Ignored IPv6 DNS entry which is not supported.\n"); - } else { - printf("Ignored unknown addrinfo address type.\n"); - } - } - printf("No suitable IP address found via DNS!\n"); - return NULL; -} - -/* - * Start XMPP stream via the given socket filedescriptor - * - * Returns 0 in case of success and -1 otherwise. - */ -int start_stream(int sock_fd, char *jid, char *domainpart) -{ - const char *tmpl = "<stream:stream\ - from='%s'\ - to='%s'\ - version='1.0'\ - xml:lang='en'\ - xmlns='jabber:client'\ - xmlns:stream='http://etherx.jabber.org/streams'>"; - - char *msg; - asprintf(&msg, tmpl, jid, domainpart); - int len = strlen(msg); - - int sent = send(sock_fd, msg, len, 0); - if (sent == len) { - printf(">>> %s\n", msg); - return 0; - } else if (sent == 0) { - printf("Failed to send any bytes to server!\n"); - return -1; - } else { - printf("Could just send %d bytes of %d bytes to server!\n", sent, len); - return -1; - } -} - -/* - * Get JID and password and return true on success - */ -bool get_credentials(char **jid, char **pwd) -{ - if (getenv("LIMOX_USER") == NULL || getenv("LIMOX_PWD") == NULL) { - printf("Failed to connect.\n"); - printf("Please set the LIMOX_USER and LIMOX_PWD shell variables.\n"); - return false; - } - - *jid = getenv("LIMOX_USER"); - *pwd = getenv("LIMOX_PWD"); - - return true; -} - -/* - * Initialize the network connection to the XMPP server and return socket fd - * - * TODO: Error handling is missing. - */ -int xmpp_connect(void) -{ - printf("net_init()\n"); - - int sock = -1; - - char *jid; - char *pwd; - if (!get_credentials(&jid, &pwd)) { - return sock; - } - printf("Trying to connect as '%s' with '%s'.\n", jid, pwd); - - char *domain = get_domainpart(jid); - printf("Domainpart is '%s'.\n", domain); - - struct addrinfo *addr = resolve_dns(domain); - - sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (sock == -1) { - printf("Failed to get socket from OS!."); - return sock; - } else { - printf("Got socket number %d from OS.\n", sock); - } - - if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) { - printf("Failed to connect!\n"); - return sock; - } else { - printf("Successfully connected.\n"); - } - - if (start_stream(sock, jid, domain) == -1) { - printf("Failed to init stream!\n"); - return sock; - } - printf("Stream init sent.\n"); - - return sock; -} @@ -1,21 +0,0 @@ -/* - * LimoX - The Linux on mobile XMPP chat client - * Copyright (C) 2022 xengineering - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - - -int xmpp_connect(void); -char *get_domainpart(char *jid); |