From e0cd01eef6b8f2d83e2ca3f4d87b015f2305b7db Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 17 Sep 2014 19:50:59 +0100 Subject: Rename ratatox to ratox --- ratatox.c | 1188 ------------------------------------------------------------- 1 file changed, 1188 deletions(-) delete mode 100644 ratatox.c (limited to 'ratatox.c') diff --git a/ratatox.c b/ratatox.c deleted file mode 100644 index f86be84..0000000 --- a/ratatox.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "arg.h" -#include "queue.h" - -#define LEN(x) (sizeof (x) / sizeof *(x)) -#define DATAFILE ".ratatox.data" - -struct node { - const char *addr; - uint16_t port; - uint8_t key[TOX_CLIENT_ID_SIZE]; -}; - -#include "config.h" - -struct file { - int type; - const char *name; - int flags; - mode_t mode; -}; - -enum { - IN, - OUT, - ERR, - NR_GFILES -}; - -struct slot { - const char *name; - void (*cb)(void *); - int outtype; - int outmode; - int fd[NR_GFILES]; -}; - -enum { - NAME, - STATUS, - REQUEST, -}; - -enum { - FIFO, - OUT_F, - STATIC, - FOLDER -}; - -static void setname(void *); -static void setstatusmsg(void *); -static void sendfriendreq(void *); - -static struct slot gslots[] = { - [NAME] = { .name = "name", .cb = setname, .outtype = STATIC }, - [STATUS] = { .name = "status", .cb = setstatusmsg, .outtype = STATIC }, - [REQUEST] = { .name = "request", .cb = sendfriendreq, .outtype = FOLDER, .outmode = 0755 }, -}; - -static struct file gfiles[] = { - { .type = FIFO, .name = "in", .flags = O_RDWR | O_NONBLOCK, .mode = 0644}, - { .type = OUT_F, .name = "out", .flags = O_WRONLY | O_TRUNC | O_CREAT, .mode = 0644}, - { .type = OUT_F, .name = "err", .flags = O_WRONLY | O_TRUNC | O_CREAT, .mode = 0644}, -}; - -enum { - TEXT_IN_FIFO, - FILE_IN_FIFO, - NR_FFIFOS -}; - -/* Friend related FIFOs, they go in fid == fid) { - snprintf(path, sizeof(path), "%s/online", f->idstr); - writeline(path, "w", status == 0 ? "0\n" : "1\n"); - return; - } - } - - friendcreate(fid); -} - -static void -cbfriendmessage(Tox *m, int32_t fid, const uint8_t *data, uint16_t len, void *udata) -{ - struct friend *f; - uint8_t msg[len + 1]; - char buft[64]; - char path[PATH_MAX]; - time_t t; - - memcpy(msg, data, len); - msg[len] = '\0'; - - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid == fid) { - t = time(NULL); - strftime(buft, sizeof(buft), "%F %R", localtime(&t)); - snprintf(path, sizeof(path), "%s/text_out", f->idstr); - writeline(path, "a", "%s %s\n", buft, msg); - printout("%s %s\n", - f->namestr[0] == '\0' ? "Anonymous" : f->namestr, msg); - break; - } - } -} - -static void -cbfriendrequest(Tox *m, const uint8_t *id, const uint8_t *data, uint16_t len, void *udata) -{ - struct request *req; - - req = calloc(1, sizeof(*req)); - if (!req) { - perror("calloc"); - exit(EXIT_FAILURE); - } - memcpy(req->id, id, TOX_CLIENT_ID_SIZE); - id2str(req->id, req->idstr); - - if (len > 0) { - req->msgstr = malloc(len + 1); - if (!req->msgstr) { - perror("malloc"); - exit(EXIT_FAILURE); - } - memcpy(req->msgstr, data, len); - req->msgstr[len] = '\0'; - } - - TAILQ_INSERT_TAIL(&reqhead, req, entry); - - printout("Pending request from %s with message: %s\n", - req->idstr, req->msgstr); -} - -static void -cbnamechange(Tox *m, int32_t fid, const uint8_t *data, uint16_t len, void *user) -{ - struct friend *f; - uint8_t name[len + 1]; - char path[PATH_MAX]; - - memcpy(name, data, len); - name[len] = '\0'; - - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid == fid) { - snprintf(path, sizeof(path), "%s/name", f->idstr); - writeline(path, "w", "%s\n", name); - if (memcmp(f->namestr, name, len + 1) == 0) - break; - printout("%s -> %s\n", f->namestr[0] == '\0' ? - "Anonymous" : f->namestr, name); - memcpy(f->namestr, name, len + 1); - break; - } - } - datasave(); -} - -static void -cbstatusmessage(Tox *m, int32_t fid, const uint8_t *data, uint16_t len, void *udata) -{ - struct friend *f; - uint8_t statusmsg[len + 1]; - char path[PATH_MAX]; - - memcpy(statusmsg, data, len); - statusmsg[len] = '\0'; - - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid == fid) { - snprintf(path, sizeof(path), "%s/statusmsg", f->idstr); - writeline(path, "w", "%s\n", statusmsg); - printout("%s changed status: %s\n", - f->namestr[0] == '\0' ? "Anonymous" : f->namestr, statusmsg); - break; - } - } - datasave(); -} - -static void -cbuserstatus(Tox *m, int32_t fid, uint8_t status, void *udata) -{ - struct friend *f; - char *statusstr[] = { "none", "away", "busy" }; - - if (status >= LEN(statusstr)) { - fprintf(stderr, "received invalid user status: %d\n", status); - return; - } - - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid == fid) { - printout("%s changed user status: %s\n", - f->namestr[0] == '\0' ? "Anonymous" : f->namestr, - statusstr[status]); - break; - } - } -} - -static void -cbfilecontrol(Tox *m, int32_t fid, uint8_t rec_sen, uint8_t fnum, uint8_t ctrltype, - const uint8_t *data, uint16_t len, void *udata) -{ - struct friend *f; - - switch (ctrltype) { - case TOX_FILECONTROL_ACCEPT: - if (rec_sen == 1) { - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid != fid) - continue; - f->t.fnum = fnum; - f->t.chunksz = tox_file_data_size(tox, fnum); - f->t.buf = malloc(f->t.chunksz); - if (!f->t.buf) { - perror("malloc"); - exit(EXIT_FAILURE); - } - f->t.n = 0; - f->t.pending = 0; - f->t.state = TRANSFER_INPROGRESS; - break; - } - } - break; - case TOX_FILECONTROL_FINISHED: - if (rec_sen == 1) { - TAILQ_FOREACH(f, &friendhead, entry) { - if (f->fid != fid) - continue; - f->t.state = TRANSFER_DONE; - break; - } - } - break; - default: - fprintf(stderr, "Unhandled file control type: %d\n", ctrltype); - break; - }; -} - -static void -sendfriendfile(struct friend *f) -{ - ssize_t n; - - while (1) { - /* attempt to transmit the pending buffer */ - if (f->t.pending == 1) { - if (tox_file_send_data(tox, f->fid, f->t.fnum, f->t.buf, f->t.n) == -1) { - /* bad luck - we will try again later */ - break; - } - f->t.pending = 0; - } - /* grab another buffer from the FIFO */ - n = read(f->fd[FILE_IN_FIFO], f->t.buf, f->t.chunksz); - if (n < 0) { - if (errno == EINTR) - continue; - /* go back to select() until the fd is readable */ - if (errno == EWOULDBLOCK) - break; - perror("read"); - exit(EXIT_FAILURE); - } - /* we are done */ - if (n == 0) { - tox_file_send_control(tox, f->fid, 0, f->t.fnum, - TOX_FILECONTROL_FINISHED, NULL, 0); - f->t.state = TRANSFER_DONE; - break; - } - /* store transfer size in case we can't send it right now */ - f->t.n = n; - if (tox_file_send_data(tox, f->fid, f->t.fnum, f->t.buf, f->t.n) == -1) { - /* ok we will have to send it later, flip state */ - f->t.pending = 1; - return; - } - } -} - -static void -sendfriendtext(struct friend *f) -{ - uint8_t buf[TOX_MAX_MESSAGE_LENGTH]; - ssize_t n; - -again: - n = read(f->fd[TEXT_IN_FIFO], buf, sizeof(buf)); - if (n < 0) { - if (errno == EINTR) - goto again; - /* go back to select() until the fd is readable */ - if (errno == EWOULDBLOCK) - return; - perror("read"); - exit(EXIT_FAILURE); - } - if (buf[n - 1] == '\n') - n--; - tox_send_message(tox, f->fid, buf, n); -} - -static void -dataload(void) -{ - FILE *fp; - size_t sz; - uint8_t *data; - int r; - - fp = fopen(DATAFILE, "r"); - if (!fp) - return; - - fseek(fp, 0, SEEK_END); - sz = ftell(fp); - rewind(fp); - - data = malloc(sz); - if (!data) { - perror("malloc"); - exit(EXIT_FAILURE); - } - - if (fread(data, 1, sz, fp) != sz || ferror(fp)) { - fprintf(stderr, "failed to read %s\n", DATAFILE); - exit(EXIT_FAILURE); - } - r = tox_load(tox, data, sz); - if (r < 0) { - fprintf(stderr, "tox_load() failed\n"); - exit(EXIT_FAILURE); - } - if (r == 1) - printf("Found encrypted data in %s\n", DATAFILE); - - free(data); - fclose(fp); -} - -static void -datasave(void) -{ - FILE *fp; - size_t sz; - uint8_t *data; - - fp = fopen(DATAFILE, "w"); - if (!fp) { - fprintf(stderr, "can't open %s for writing\n", DATAFILE); - exit(EXIT_FAILURE); - } - - sz = tox_size(tox); - data = malloc(sz); - if (!data) { - perror("malloc"); - exit(EXIT_FAILURE); - } - - tox_save(tox, data); - if (fwrite(data, 1, sz, fp) != sz || ferror(fp)) { - fprintf(stderr, "failed to write %s\n", DATAFILE); - exit(EXIT_FAILURE); - } - - free(data); - fclose(fp); -} - -static int -localinit(void) -{ - uint8_t name[TOX_MAX_NAME_LENGTH + 1]; - uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; - uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; - FILE *fp; - int r; - size_t i, m; - - for (i = 0; i < LEN(gslots); i++) { - r = mkdir(gslots[i].name, 0755); - if (r < 0 && errno != EEXIST) { - perror("mkdir"); - exit(EXIT_FAILURE); - } - r = chdir(gslots[i].name); - if (r < 0) { - perror("chdir"); - exit(EXIT_FAILURE); - } - for (m = 0; m < LEN(gfiles); m++) { - if (gfiles[m].type == FIFO) { - r = mkfifo(gfiles[m].name, gfiles[m].mode); - if (r < 0 && errno != EEXIST) { - perror("mkfifo"); - exit(EXIT_FAILURE); - } - r = open(gfiles[m].name, gfiles[m].flags, 0); - if (r < 0) { - perror("open"); - exit(EXIT_FAILURE); - } - gslots[i].fd[m] = r; - } else if (gfiles[m].type == OUT_F) { - if (gslots[i].outtype == STATIC) { - r = open(gfiles[m].name, gfiles[m].flags, gfiles[m].mode); - if (r < 0) { - perror("open"); - exit(EXIT_FAILURE); - } - gslots[i].fd[m] = r; - } else if (gslots[i].outtype == FOLDER) { - r = mkdir(gfiles[m].name, gslots[i].outmode); - if (r < 0 && errno != EEXIST) { - perror("mkdir"); - exit(EXIT_FAILURE); - } - gslots[i].fd[m] = 0; - } - } - } - chdir(".."); - } - - /* Dump current name */ - r = tox_get_self_name(tox, name); - if (r > sizeof(name) - 1) - r = sizeof(name) - 1; - name[r] = '\0'; - ftruncate(gslots[NAME].fd[OUT], 0); - dprintf(gslots[NAME].fd[OUT], "%s\n", name); - - /* Dump status message */ - r = tox_get_self_status_message(tox, statusmsg, - sizeof(statusmsg) - 1); - if (r > sizeof(statusmsg) - 1) - r = sizeof(statusmsg) - 1; - statusmsg[r] = '\0'; - ftruncate(gslots[STATUS].fd[OUT], 0); - dprintf(gslots[STATUS].fd[OUT], "%s\n", name); - - /* Dump ID */ - fp = fopen("id", "w"); - if (!fp) { - perror("fopen"); - exit(EXIT_FAILURE); - } - tox_get_address(tox, address); - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) - fprintf(fp, "%02X", address[i]); - fputc('\n', fp); - fclose(fp); - - return 0; -} - -static int -toxinit(void) -{ - /* IPv4 only */ - tox = tox_new(0); - dataload(); - datasave(); - tox_callback_connection_status(tox, cbconnstatus, NULL); - tox_callback_friend_message(tox, cbfriendmessage, NULL); - tox_callback_friend_request(tox, cbfriendrequest, NULL); - tox_callback_name_change(tox, cbnamechange, NULL); - tox_callback_status_message(tox, cbstatusmessage, NULL); - tox_callback_user_status(tox, cbuserstatus, NULL); - tox_callback_file_control(tox, cbfilecontrol, NULL); - return 0; -} - -static int -toxconnect(void) -{ - struct node *bn; - size_t i; - - for (i = 0; i < LEN(nodes); i++) { - bn = &nodes[i]; - tox_bootstrap_from_address(tox, bn->addr, bn->port, bn->key); - } - return 0; -} - -static void -id2str(uint8_t *id, char *idstr) -{ - char hex[] = "0123456789ABCDEF"; - int i; - - for (i = 0; i < TOX_CLIENT_ID_SIZE; i++) { - *idstr++ = hex[(id[i] >> 4) & 0xf]; - *idstr++ = hex[id[i] & 0xf]; - } - *idstr = '\0'; -} - -static void -str2id(char *idstr, uint8_t *id) -{ - size_t i, len = strlen(idstr) / 2; - char *p = idstr; - - for (i = 0; i < len; ++i, p += 2) - sscanf(p, "%2hhx", &id[i]); -} - -static struct friend * -friendcreate(int32_t fid) -{ - char path[PATH_MAX]; - struct friend *f; - uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; - size_t i; - int r; - - f = calloc(1, sizeof(*f)); - if (!f) { - perror("calloc"); - exit(EXIT_FAILURE); - } - - r = tox_get_name(tox, fid, (uint8_t *)f->namestr); - if (r < 0) { - fprintf(stderr, "tox_get_name() on fid %d failed\n", fid); - exit(EXIT_FAILURE); - } - f->namestr[r] = '\0'; - - f->fid = fid; - tox_get_client_id(tox, f->fid, f->id); - id2str(f->id, f->idstr); - - r = mkdir(f->idstr, 0755); - if (r < 0 && errno != EEXIST) { - perror("mkdir"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < LEN(ffifos); i++) { - snprintf(path, sizeof(path), "%s/%s", f->idstr, - ffifos[i].name); - r = mkfifo(path, ffifos[i].mode); - if (r < 0 && errno != EEXIST) { - perror("mkfifo"); - exit(EXIT_FAILURE); - } - r = open(path, ffifos[i].flags, 0); - if (r < 0) { - perror("open"); - exit(EXIT_FAILURE); - } - f->fd[i] = r; - } - - snprintf(path, sizeof(path), "%s/name", f->idstr); - writeline(path, "w", "%s\n", f->namestr); - snprintf(path, sizeof(path), "%s/online", f->idstr); - writeline(path, "w", tox_get_friend_connection_status(tox, fid) == 0 ? "0\n" : "1\n"); - r = tox_get_status_message_size(tox, fid); - if (r > sizeof(statusmsg) - 1) - r = sizeof(statusmsg) - 1; - statusmsg[r] = '\0'; - snprintf(path, sizeof(path), "%s/statusmsg", f->idstr); - writeline(path, "w", "%s\n", statusmsg); - snprintf(path, sizeof(path), "%s/text_out", f->idstr); - writeline(path, "a", ""); - - TAILQ_INSERT_TAIL(&friendhead, f, entry); - - return f; -} - -static void -friendload(void) -{ - int32_t *fids; - uint32_t sz; - uint32_t i; - - sz = tox_count_friendlist(tox); - fids = malloc(sz); - if (!fids) { - perror("malloc"); - exit(EXIT_FAILURE); - } - - tox_get_friendlist(tox, fids, sz); - - for (i = 0; i < sz; i++) - friendcreate(fids[i]); - - free(fids); -} - -struct cmd { - const char *cmd; - int (*cb)(char *, size_t); - const char *usage; -} cmds[] = { - { .cmd = "a", .cb = cmdaccept, .usage = "usage: a [id]\tAccept or list pending requests\n" }, - { .cmd = "h", .cb = cmdhelp, .usage = NULL }, -}; - -static int -cmdaccept(char *cmd, size_t sz) -{ - struct request *req, *tmp; - char *args[2]; - int r; - int found = 0; - - r = tokenize(cmd, args, 2); - - if (r == 1) { - TAILQ_FOREACH(req, &reqhead, entry) { - printout("Pending request from %s with message: %s\n", - req->idstr, req->msgstr); - found = 1; - } - if (found == 0) - printf("No pending requests\n"); - } else { - for (req = TAILQ_FIRST(&reqhead); req; req = tmp) { - tmp = TAILQ_NEXT(req, entry); - if (strcmp(req->idstr, args[1]) == 0) { - tox_add_friend_norequest(tox, req->id); - printout("Accepted friend request for %s\n", req->idstr); - datasave(); - TAILQ_REMOVE(&reqhead, req, entry); - free(req->msgstr); - free(req); - break; - } - } - } - - return 0; -} - -static int -cmdhelp(char *cmd, size_t sz) -{ - size_t i; - - for (i = 0; i < LEN(cmds); i++) - if (cmds[i].usage) - fprintf(stderr, "%s", cmds[i].usage); - return 0; -} - -static int -cmdrun(void) -{ - char cmd[BUFSIZ]; - ssize_t n; - size_t i; - -again: - n = read(STDIN_FILENO, cmd, sizeof(cmd) - 1); - if (n < 0) { - if (errno == EINTR) - goto again; - perror("read"); - exit(EXIT_FAILURE); - } - if (n == 0) - return 0; - cmd[n] = '\0'; - if (cmd[strlen(cmd) - 1] == '\n') - cmd[strlen(cmd) - 1] = '\0'; - if (cmd[0] == '\0') - return 0; - - for (i = 0; i < LEN(cmds); i++) - if (cmd[0] == cmds[i].cmd[0]) - if (cmd[1] == '\0' || isspace((int)cmd[1])) - return (*cmds[i].cb)(cmd, strlen(cmd)); - - fprintf(stderr, "Unknown command '%s', type h for help\n", cmd); - return -1; -} - -static void -writeline(const char *path, const char *mode, - const char *fmt, ...) -{ - FILE *fp; - va_list ap; - - fp = fopen(path, mode); - if (!fp) { - perror("fopen"); - exit(EXIT_FAILURE); - } - va_start(ap, fmt); - vfprintf(fp, fmt, ap); - va_end(ap); - fclose(fp); -} - -static void -setname(void *data) -{ - uint8_t name[TOX_MAX_NAME_LENGTH + 1]; - int r; - -again: - r = read(gslots[NAME].fd[IN], name, sizeof(name) - 1); - if (r < 0) { - if (errno == EINTR) - goto again; - if (errno == EWOULDBLOCK) - return; - perror("read"); - return; - } - if (name[r - 1] == '\n') - r--; - name[r] = '\0'; - tox_set_name(tox, name, r); - datasave(); - printout("Changed name to %s\n", name); - ftruncate(gslots[NAME].fd[OUT], 0); - dprintf(gslots[NAME].fd[OUT], "%s\n", name); -} - -static void -setstatusmsg(void *data) -{ - uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; - int r; - -again: - r = read(gslots[STATUS].fd[IN], statusmsg, sizeof(statusmsg) - 1); - if (r < 0) { - if (errno == EINTR) - goto again; - if (errno == EWOULDBLOCK) - return; - perror("read"); - return; - } - if (statusmsg[r - 1] == '\n') - r--; - statusmsg[r] = '\0'; - tox_set_status_message(tox, statusmsg, r); - datasave(); - printout("Changed status message to %s\n", statusmsg); - ftruncate(gslots[STATUS].fd[OUT], 0); - dprintf(gslots[STATUS].fd[OUT], "%s\n", statusmsg); -} - -static void -sendfriendreq(void *data) -{ - char *p; - uint8_t id[TOX_FRIEND_ADDRESS_SIZE]; - uint8_t buf[BUFSIZ], *msg = "ratatox is awesome!"; - int r; - -again: - r = read(gslots[REQUEST].fd[IN], buf, sizeof(buf) - 1); - if (r < 0) { - if (errno == EINTR) - goto again; - if (errno == EWOULDBLOCK) - return; - perror("read"); - return; - } - buf[r] = '\0'; - - for (p = buf; *p && isspace(*p) == 0; p++) - ; - if (*p != '\0') { - *p = '\0'; - while (isspace(*p++) != 0) - ; - if (*p != '\0') - msg = p; - if (msg[strlen(msg) - 1] == '\n') - msg[strlen(msg) - 1] = '\0'; - } - str2id(buf, id); - - r = tox_add_friend(tox, id, buf, strlen(buf)); - if (r < 0) - ftruncate(gslots[REQUEST].fd[ERR], 0); - switch (r) { - case TOX_FAERR_TOOLONG: - dprintf(gslots[REQUEST].fd[ERR], "Message is too long\n"); - break; - case TOX_FAERR_NOMESSAGE: - dprintf(gslots[REQUEST].fd[ERR], "Please add a message to your request\n"); - break; - case TOX_FAERR_OWNKEY: - dprintf(gslots[REQUEST].fd[ERR], "That appears to be your own ID\n"); - break; - case TOX_FAERR_ALREADYSENT: - dprintf(gslots[REQUEST].fd[ERR], "Friend request already sent\n"); - break; - case TOX_FAERR_UNKNOWN: - dprintf(gslots[REQUEST].fd[ERR], "Unknown error while sending your request\n"); - break; - case TOX_FAERR_BADCHECKSUM: - dprintf(gslots[REQUEST].fd[ERR], "Bad checksum while verifying address\n"); - break; - case TOX_FAERR_SETNEWNOSPAM: - dprintf(gslots[REQUEST].fd[ERR], "Friend already added but nospam doesn't match\n"); - break; - default: - printout("Friend request sent\n"); - break; - } - datasave(); -} - -static void -loop(void) -{ - struct friend *f; - time_t t0, t1; - int connected = 0; - int i, n; - int fdmax; - fd_set rfds; - struct timeval tv; - - t0 = time(NULL); - printout("Connecting to DHT...\n"); - toxconnect(); - while (1) { - if (tox_isconnected(tox) == 1) { - if (connected == 0) { - printout("Connected to DHT\n"); - connected = 1; - } - } else { - connected = 0; - t1 = time(NULL); - if (t1 > t0 + 5) { - t0 = time(NULL); - printout("Connecting to DHT...\n"); - toxconnect(); - } - } - tox_do(tox); - - FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - fdmax = STDIN_FILENO; - - for (i = 0; i < LEN(gslots); i++) { - FD_SET(gslots[i].fd[IN], &rfds); - if (gslots[i].fd[IN] > fdmax) - fdmax = gslots[i].fd[IN]; - } - - TAILQ_FOREACH(f, &friendhead, entry) { - /* Only monitor friends that are online */ - if (tox_get_friend_connection_status(tox, f->fid) == 1) { - for (i = 0; i < NR_FFIFOS; i++) { - FD_SET(f->fd[i], &rfds); - if (f->fd[i] > fdmax) - fdmax = f->fd[i]; - } - } - } - - tv.tv_sec = 0; - tv.tv_usec = tox_do_interval(tox) * 1000; - n = select(fdmax + 1, &rfds, NULL, NULL, &tv); - if (n < 0) { - if (errno == EINTR) - continue; - perror("select"); - exit(EXIT_FAILURE); - } - - /* Check for broken transfers, i.e. the friend went offline - * in the middle of a transfer. - */ - TAILQ_FOREACH(f, &friendhead, entry) { - if (tox_get_friend_connection_status(tox, f->fid) == 0) { - if (f->t.state != TRANSFER_NONE) { - printout("Stale transfer detected, friend offline\n"); - f->t.state = TRANSFER_NONE; - free(f->t.buf); - } - } - } - - /* If we hit the receiver too hard, we will run out of - * local buffer slots. In that case tox_file_send_data() - * will return -1 and we will have to queue the buffer to - * send it later. If this is the last buffer read from - * the FIFO, then select() won't make the fd readable again - * so we have to check if there's anything pending to be - * sent. - */ - TAILQ_FOREACH(f, &friendhead, entry) { - if (tox_get_friend_connection_status(tox, f->fid) == 0) - continue; - if (f->t.state == TRANSFER_NONE) - continue; - if (f->t.pending == 0) - continue; - switch (f->t.state) { - case TRANSFER_INPROGRESS: - sendfriendfile(f); - if (f->t.state == TRANSFER_DONE) { - printout("Transfer complete\n"); - f->t.state = TRANSFER_NONE; - free(f->t.buf); - } - break; - } - } - - if (n == 0) - continue; - - if (FD_ISSET(STDIN_FILENO, &rfds) != 0) - cmdrun(); - - for (i = 0; i < LEN(gslots); i++) { - if (FD_ISSET(gslots[i].fd[IN], &rfds) == 0) - continue; - (*gslots[i].cb)(NULL); - } - - TAILQ_FOREACH(f, &friendhead, entry) { - for (i = 0; i < NR_FFIFOS; i++) { - if (FD_ISSET(f->fd[i], &rfds) == 0) - continue; - switch (i) { - case TEXT_IN_FIFO: - sendfriendtext(f); - break; - case FILE_IN_FIFO: - switch (f->t.state) { - case TRANSFER_NONE: - /* prepare a new transfer */ - f->t.state = TRANSFER_INITIATED; - tox_new_file_sender(tox, f->fid, - 0, (uint8_t *)"file", strlen("file") + 1); - printout("Initiated transfer to %s\n", - f->namestr[0] == '\0' ? "Anonymous" : f->namestr); - break; - case TRANSFER_INPROGRESS: - sendfriendfile(f); - if (f->t.state == TRANSFER_DONE) { - printout("Transfer complete\n"); - f->t.state = TRANSFER_NONE; - free(f->t.buf); - } - break; - } - break; - default: - fprintf(stderr, "Unhandled FIFO read\n"); - } - } - } - } -} - -int -main(int argc, char *argv[]) -{ - printrat(); - printf("Type h for help\n"); - toxinit(); - localinit(); - friendload(); - loop(); - return EXIT_SUCCESS; -} -- cgit v1.2.3