--- /dev/null
+/*
+ * Copyright (C) 2013 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "friend.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+static int connect_friend(struct sockaddr *saddr, char *address, char *port, int *c)
+{
+ struct addrinfo *addresses;
+ struct addrinfo *addr;
+ struct addrinfo hint;
+ int r;
+ int fd = *c = -1;
+ int i;
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ hint.ai_flags = AI_ADDRCONFIG;
+ r = getaddrinfo(address, port, &hint, &addresses);
+ if (r) {
+ return r;
+ }
+ for (addr = addresses; addr != NULL; addr = addr->ai_next) {
+ fd = socket(addr->ai_family, addr->ai_socktype,
+ addr->ai_protocol);
+ if (fd >= 0)
+ break;
+ close(fd);
+ fd = -1;
+ }
+ freeaddrinfo(addresses);
+ *c = fd;
+ if (fd == -1)
+ return EAI_SYSTEM;
+ return 0;
+}
+
+struct friend {
+ char *name;
+ char *address;
+ char *port;
+ struct sockaddr *saddr;
+};
+
+struct cache {
+ int nfriends;
+ struct friend *friends;
+};
+
+int create_cache(struct cache **cache)
+{
+ *cache = malloc(sizeof(*cache));
+ if (!*cache)
+ return -errno;
+ (*cache)->nfriends = 0;
+ (*cache)->friends = NULL;
+ return 0;
+}
+
+int destroy_cache(struct cache *cache)
+{
+ if (cache->friends)
+ free(cache->friends);
+ free(cache);
+}
+
+int cache_add_friend(struct cache *cache, char *friend, char *address, char *port)
+{
+ struct friend *tfriend;
+ if (!cache->friends) {
+ cache->friends = malloc(sizeof(struct friend));
+ cache->nfriends = 1;
+ } else {
+ struct friend *new_friends;
+ cache->nfriends++;
+ new_friends = realloc(cache->friends, cache->nfriends * sizeof(struct friend));
+ if (!new_friends) {
+ cache->nfriends--;
+ return -errno;
+ }
+ cache->friends = new_friends;
+ }
+ tfriend = &cache->friends[cache->nfriends - 1];
+ tfriend->name = friend;
+ tfriend->address = address;
+ tfriend->port = port;
+ tfriend->saddr = NULL;
+ return 0;
+}
+
+int load_cache(struct cache *cache, char *fname)
+{
+ FILE *file;
+ int err = 0;
+ char *buffer = NULL;
+ size_t len = 0;
+ int r;
+ file = fopen(fname, "r");
+ if (!file)
+ return -errno;
+ while ((r = getline(&buffer, &len, file)) > 0) {
+ char *name;
+ char *address;
+ char *port;
+ char *end;
+ name = buffer;
+ address = name;
+ while (*++address != '\t');
+ *address++ = '\0';
+ port = address;
+ while (*++port != '\t');
+ *port++ = '\0';
+ end = port;
+ while (*++end != '\n');
+ *end = '\0';
+ fprintf(file, "%s\t%s\t%s\n", name, address, port);
+ cache_add_friend(cache, strdup(name), strdup(address), strdup(port));
+ }
+out:
+ fclose(file);
+ return err;
+}
+
+int store_cache(struct cache *cache, char *fname)
+{
+ FILE *file;
+ int err = 0;
+ int i;
+ file = fopen(fname, "w");
+ if (!file)
+ return -errno;
+ for (i = 0; i < cache->nfriends; i++) {
+ struct friend *friend = &cache->friends[i];
+ fprintf(file, "%s\t%s\t%s\n", friend->name, friend->address, friend->port);
+ }
+out:
+ fclose(file);
+ return err;
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _FRIEND_H
+#define _FRIEND_H
+
+struct friend;
+struct cache;
+int create_cache(struct cache **cache);
+int destroy_cache(struct cache *cache);
+int cache_add_friend(struct cache *cache, char *friend, char *address, char *port);
+int load_cache(struct cache *cache, char *fname);
+int store_cache(struct cache *cache, char *fname);
+
+#endif