diff options
Diffstat (limited to 'xmpp.c')
-rw-r--r-- | xmpp.c | 200 |
1 files changed, 0 insertions, 200 deletions
@@ -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; -} |