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.   -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); | 
