summaryrefslogtreecommitdiff
path: root/ratox.c
diff options
context:
space:
mode:
authorpranomostro <pranomestro@gmail.com>2017-03-03 15:39:30 +0100
committerpranomostro <pranomestro@gmail.com>2017-03-03 15:41:21 +0100
commitd10df26852b6db53156e1f892e29239435c66299 (patch)
tree73ab6b3b7df46f08d0fb3eae4ec17a3164e9690b /ratox.c
parent799e250bbc9cf89bb09b7cfa4afbc4dbb9a46657 (diff)
parente8f046c0e616a7a0b10d1bb85abe887c1a374179 (diff)
Merge branch 'toktok'.
This merge updates ratox to toktoks toxcore, which is being developed, and adds groupchats (although lacking audio group chats at the moment).
Diffstat (limited to 'ratox.c')
-rw-r--r--ratox.c500
1 files changed, 467 insertions, 33 deletions
diff --git a/ratox.c b/ratox.c
index 97a3f55..2dcaee6 100644
--- a/ratox.c
+++ b/ratox.c
@@ -3,8 +3,6 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <arpa/inet.h>
-
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@@ -88,8 +86,9 @@ static void setstatus(void *);
static void setuserstate(void *);
static void sendfriendreq(void *);
static void setnospam(void *);
+static void newconf(void *);
-enum { NAME, STATUS, STATE, REQUEST, NOSPAM };
+enum { NAME, STATUS, STATE, REQUEST, NOSPAM, CONF };
static struct slot gslots[] = {
[NAME] = { .name = "name", .cb = setname, .outisfolder = 0, .dirfd = -1, .fd = {-1, -1, -1} },
@@ -97,6 +96,7 @@ static struct slot gslots[] = {
[STATE] = { .name = "state", .cb = setuserstate, .outisfolder = 0, .dirfd = -1, .fd = {-1, -1, -1} },
[REQUEST] = { .name = "request", .cb = sendfriendreq, .outisfolder = 1, .dirfd = -1, .fd = {-1, -1, -1} },
[NOSPAM] = { .name = "nospam", .cb = setnospam, .outisfolder = 0, .dirfd = -1, .fd = {-1, -1, -1} },
+ [CONF] = { .name = "conf", .cb = newconf, .outisfolder = 1, .dirfd = -1, .fd = {-1, -1, -1} },
};
enum { FTEXT_IN, FFILE_IN, FCALL_IN, FTEXT_OUT, FFILE_OUT, FCALL_OUT,
@@ -118,6 +118,18 @@ static struct file ffiles[] = {
[FCALL_STATE] = { .type = STATIC, .name = "call_state", .flags = O_WRONLY | O_TRUNC | O_CREAT },
};
+enum { CMEMBERS, CINVITE, CLEAVE, CTITLE_IN, CTITLE_OUT, CTEXT_IN, CTEXT_OUT };
+
+static struct file cfiles[] = {
+ [CMEMBERS] = { .type = STATIC, .name = "members", .flags = O_WRONLY | O_TRUNC | O_CREAT },
+ [CINVITE] = { .type = FIFO, .name = "invite", .flags = O_RDONLY | O_NONBLOCK },
+ [CLEAVE] = { .type = FIFO, .name = "leave", .flags = O_RDONLY | O_NONBLOCK },
+ [CTITLE_IN] = { .type = FIFO, .name = "title_in", .flags = O_RDONLY | O_NONBLOCK },
+ [CTITLE_OUT] = { .type = STATIC, .name = "title_out", .flags = O_WRONLY | O_TRUNC | O_CREAT },
+ [CTEXT_IN] = { .type = FIFO, .name = "text_in", .flags = O_RDONLY | O_NONBLOCK },
+ [CTEXT_OUT] = { .type = STATIC, .name = "text_out", .flags = O_WRONLY | O_APPEND | O_CREAT },
+};
+
static char *ustate[] = {
[TOX_USER_STATUS_NONE] = "available",
[TOX_USER_STATUS_AWAY] = "away",
@@ -162,6 +174,14 @@ struct friend {
TAILQ_ENTRY(friend) entry;
};
+struct conference {
+ uint32_t num;
+ char numstr[2 * sizeof(uint32_t) + 1];
+ int dirfd;
+ int fd[LEN(cfiles)];
+ TAILQ_ENTRY(conference) entry;
+};
+
struct request {
uint8_t id[TOX_PUBLIC_KEY_SIZE];
char idstr[2 * TOX_PUBLIC_KEY_SIZE + 1];
@@ -170,8 +190,19 @@ struct request {
TAILQ_ENTRY(request) entry;
};
+struct invite {
+ char *fifoname;
+ uint8_t *cookie;
+ size_t cookielen;
+ uint32_t inviter;
+ int fd;
+ TAILQ_ENTRY(invite) entry;
+};
+
static TAILQ_HEAD(friendhead, friend) friendhead = TAILQ_HEAD_INITIALIZER(friendhead);
+static TAILQ_HEAD(confhead, conference) confhead = TAILQ_HEAD_INITIALIZER(confhead);
static TAILQ_HEAD(reqhead, request) reqhead = TAILQ_HEAD_INITIALIZER(reqhead);
+static TAILQ_HEAD(invhead, invite) invhead = TAILQ_HEAD_INITIALIZER(invhead);
static Tox *tox;
static ToxAV *toxav;
@@ -197,6 +228,7 @@ static void cbcalldata(ToxAV *, uint32_t, const int16_t *, size_t, uint8_t, uint
static void cancelcall(struct friend *, char *);
static void sendfriendcalldata(struct friend *);
+static void writemembers(struct conference *);
static void cbconnstatus(Tox *, uint32_t, TOX_CONNECTION, void *);
static void cbfriendmessage(Tox *, uint32_t, TOX_MESSAGE_TYPE, const uint8_t *, size_t, void *);
@@ -208,10 +240,18 @@ static void cbfilecontrol(Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL, void *);
static void cbfilesendreq(Tox *, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
static void cbfiledata(Tox *, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
+static void cbconfinvite(Tox *, uint32_t, TOX_CONFERENCE_TYPE, const uint8_t *, size_t, void *);
+static void cbconfmessage(Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const uint8_t *, size_t, void *);
+static void cbconftitle(Tox *, uint32_t, uint32_t, const uint8_t *, size_t, void *);
+static void cbconfmembers(Tox *, uint32_t, uint32_t, TOX_CONFERENCE_STATE_CHANGE, void *);
+
static void canceltxtransfer(struct friend *);
static void cancelrxtransfer(struct friend *);
static void sendfriendtext(struct friend *);
static void removefriend(struct friend *);
+static void invitefriend(struct conference *);
+static void sendconftext(struct conference *);
+static void updatetitle(struct conference *);
static int readpass(const char *, uint8_t **, uint32_t *);
static void dataload(struct Tox_Options *);
static void datasave(void);
@@ -221,8 +261,10 @@ static int toxconnect(void);
static void id2str(uint8_t *, char *);
static void str2id(char *, uint8_t *);
static void friendcreate(uint32_t);
+static void confcreate(uint32_t);
static void friendload(void);
static void frienddestroy(struct friend *);
+static void confdestroy(struct conference *);
static void loop(void);
static void initshutdown(int);
static void toxshutdown(void);
@@ -444,6 +486,122 @@ cbcalldata(ToxAV *av, uint32_t fnum, const int16_t *data, size_t len,
}
static void
+cbconfinvite(Tox *m, uint32_t frnum, TOX_CONFERENCE_TYPE type, const uint8_t *cookie, size_t clen, void * udata)
+{
+ size_t i, j, namelen;
+ struct file invfifo;
+ struct invite *inv;
+ uint8_t id[TOX_PUBLIC_KEY_SIZE];
+
+ if(type != TOX_CONFERENCE_TYPE_TEXT) {
+ weprintf(": %d : Only text conference supported at the moment\n");
+ return;
+ }
+
+ if (!tox_friend_get_public_key(tox, frnum, id, NULL)) {
+ weprintf(": %d : Key: Failed to get for invite\n", frnum);
+ return;
+ }
+
+ inv = calloc(1, sizeof(*inv));
+ if (!inv)
+ eprintf("calloc:");
+ inv->fd = -1;
+
+ inv->inviter = frnum;
+ inv->cookielen = clen;
+ inv->cookie = malloc(inv->cookielen);
+ if (!inv->cookie)
+ eprintf("malloc:");
+
+ memcpy(inv->cookie, cookie, clen);
+
+ namelen = 2 * TOX_PUBLIC_KEY_SIZE + 1 + 2 * clen + 2;
+ inv->fifoname = malloc(namelen);
+ if (!inv->fifoname)
+ eprintf("malloc:");
+
+ i = 0;
+ id2str(id, inv->fifoname);
+ i += 2 * TOX_PUBLIC_KEY_SIZE;
+ inv->fifoname[i] = '_';
+ i++;
+ for(j = 0; j < clen; i+=2, j++)
+ sprintf(inv->fifoname + i, "%02X", cookie[j]);
+ i++;
+ inv->fifoname[i] = '\0';
+
+ invfifo.name = inv->fifoname;
+ invfifo.flags = O_RDONLY | O_NONBLOCK;
+ fiforeset(gslots[CONF].fd[OUT], &inv->fd, invfifo);
+
+ TAILQ_INSERT_TAIL(&invhead, inv, entry);
+
+ logmsg("Invite > %s\n", inv->fifoname);
+}
+
+static void
+cbconfmessage(Tox *m, uint32_t cnum, uint32_t pnum, TOX_MESSAGE_TYPE type, const uint8_t *data, size_t len, void *udata)
+{
+ struct conference *c;
+ time_t t;
+ uint8_t msg[len + 1], namt[TOX_MAX_NAME_LENGTH + 1];
+ char buft[64];
+
+ memcpy(msg, data, len);
+ msg[len] = '\0';
+
+ TAILQ_FOREACH(c, &confhead, entry) {
+ if (c->num == cnum) {
+ t = time(NULL);
+ strftime(buft, sizeof(buft), "%F %R", localtime(&t));
+ if (!tox_conference_peer_get_name(tox, c->num, pnum, namt, NULL)) {
+ weprintf("Unable to obtain name for peer %d in conference %s\n", pnum, c->numstr);
+ return;
+ }
+ namt[tox_conference_peer_get_name_size(tox, c->num, pnum, NULL)] = '\0';
+ dprintf(c->fd[CTEXT_OUT], "%s <%s> %s\n", buft, namt, msg);
+ if (confmsg_log)
+ logmsg("%s: %s <%s> %s\n", c->numstr, buft, namt, msg);
+ break;
+ }
+ }
+}
+
+static void
+cbconftitle(Tox *m, uint32_t cnum, uint32_t pnum, const uint8_t *data, size_t len, void * udata)
+{
+ struct conference *c;
+ char title[TOX_MAX_NAME_LENGTH + 1];
+
+ memcpy(title, data, len);
+ title[len] = '\0';
+
+ TAILQ_FOREACH(c, &confhead, entry) {
+ if (c->num == cnum) {
+ ftruncate(c->fd[CTITLE_OUT], 0);
+ lseek(c->fd[CTITLE_OUT], 0, SEEK_SET);
+ dprintf(c->fd[CTITLE_OUT], "%s\n", title);
+ logmsg(": %s : Title > %s\n", c->numstr, title);
+ break;
+ }
+ }
+}
+
+static void
+cbconfmembers(Tox *m, uint32_t cnum, uint32_t pnum, TOX_CONFERENCE_STATE_CHANGE type, void *udata)
+{
+ struct conference *c;
+
+ TAILQ_FOREACH(c, &confhead, entry) {
+ if (c->num == cnum) {
+ writemembers(c);
+ break;
+ }
+ }
+}
+
+static void
cancelcall(struct friend *f, char *action)
{
logmsg(": %s : Audio > %s\n", f->name, action);
@@ -508,6 +666,33 @@ sendfriendcalldata(struct friend *f)
}
static void
+writemembers(struct conference *c)
+{
+ size_t i;
+ uint32_t peers, pnum;
+ uint8_t name[TOX_MAX_NAME_LENGTH + 1];
+ TOX_ERR_CONFERENCE_PEER_QUERY err;
+
+ /*The peer list is written when we invite the members by the callback*/
+ ftruncate(c->fd[CMEMBERS], 0);
+ peers = tox_conference_peer_count(tox, c->num, &err);
+
+ if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
+ weprintf("Unable to obtain peer count for conference %d\n", c->num);
+ return;
+ }
+ for (pnum = 0; pnum < peers; pnum++) {
+ if (!tox_conference_peer_get_name(tox, c->num, pnum, name, NULL)) {
+ weprintf("Unable to obtain the name for peer %d\n", pnum);
+ } else {
+ i = tox_conference_peer_get_name_size(tox, c->num, pnum, NULL);
+ name[i] = '\0';
+ dprintf(c->fd[CMEMBERS], "%s\n", name);
+ }
+ }
+}
+
+static void
cbconnstatus(Tox *m, uint32_t frnum, TOX_CONNECTION status, void *udata)
{
struct friend *f;
@@ -568,7 +753,8 @@ cbfriendmessage(Tox *m, uint32_t frnum, TOX_MESSAGE_TYPE type, const uint8_t *da
t = time(NULL);
strftime(buft, sizeof(buft), "%F %R", localtime(&t));
dprintf(f->fd[FTEXT_OUT], "%s %s\n", buft, msg);
- logmsg(": %s > %s\n", f->name, msg);
+ if (friendmsg_log)
+ logmsg(": %s > %s\n", f->name, msg);
break;
}
}
@@ -811,7 +997,8 @@ cbfilesendreq(Tox *m, uint32_t frnum, uint32_t fnum, uint32_t kind, uint64_t fsz
}
static void
-cbfiledata(Tox *m, uint32_t frnum, uint32_t fnum, uint64_t pos, const uint8_t *data, size_t len, void *udata)
+cbfiledata(Tox *m, uint32_t frnum, uint32_t fnum, uint64_t pos,
+ const uint8_t *data, size_t len, void *udata)
{
struct friend *f;
ssize_t n;
@@ -913,6 +1100,72 @@ removefriend(struct friend *f)
frienddestroy(f);
}
+static void
+invitefriend(struct conference *c)
+{
+ ssize_t n;
+ char buf[2 * TOX_ADDRESS_SIZE + 1];
+ struct friend *f;
+
+ n = fiforead(c->dirfd, &c->fd[CINVITE], cfiles[CINVITE], buf, sizeof(buf));
+
+ if (n > sizeof(buf) || n <= 0)
+ return;
+ if (buf[n - 1] == '\n')
+ buf[n - 1] = '\0';
+
+ TAILQ_FOREACH(f, &friendhead, entry)
+ if (!memcmp(buf, f->idstr, sizeof(f->idstr)))
+ break;
+ if (!f) {
+ logmsg("Conference %s > no friend with id %s found\n", c->numstr, buf);
+ return;
+ }
+ if (tox_friend_get_connection_status(tox, f->num, NULL) == TOX_CONNECTION_NONE) {
+ logmsg("Conference %s > %s not online, can't be invited\n", c->numstr, buf);
+ return;
+ }
+ if (!tox_conference_invite(tox, f->num, c->num, NULL))
+ weprintf("Failed to invite %s\n", buf);
+ else
+ logmsg("Conference %s > Invite %s\n", c->numstr, buf);
+}
+
+static void
+sendconftext(struct conference *c)
+{
+ ssize_t n;
+ uint8_t buf[TOX_MAX_MESSAGE_LENGTH];
+
+ n = fiforead(c->dirfd, &c->fd[CTEXT_IN], cfiles[CTEXT_IN], buf, sizeof(buf));
+ if (n <= 0)
+ return;
+ if (buf[n - 1] == '\n' && n > 1)
+ n--;
+ if (!tox_conference_send_message(tox, c->num, TOX_MESSAGE_TYPE_NORMAL,
+ buf, n, NULL))
+ weprintf("%s: Message : Failed to send, error %d\n", c->numstr);
+}
+
+static void
+updatetitle(struct conference *c)
+{
+ ssize_t n;
+ uint8_t title[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
+
+ n = fiforead(c->dirfd, &c->fd[CTITLE_IN], cfiles[CTITLE_IN], title, sizeof(title) - 1);
+ if (n <= 0)
+ return;
+ if (title[n - 1] == '\n')
+ n--;
+ title[n] = '\0';
+ if (!tox_conference_set_title(tox, c->num, title, n, NULL)) {
+ weprintf("%s : Title : Failed to set to \"%s\"\n", title, c->numstr);
+ return;
+ }
+ logmsg("Conference %s > Title > %s\n", c->numstr, title);
+}
+
static int
readpass(const char *prompt, uint8_t **target, uint32_t *len)
{
@@ -1120,7 +1373,7 @@ localinit(void)
/* Dump Nospam */
ftruncate(gslots[NOSPAM].fd[OUT], 0);
- dprintf(gslots[NOSPAM].fd[OUT], "%08X\n", ntohl(tox_self_get_nospam(tox)));
+ dprintf(gslots[NOSPAM].fd[OUT], "%08X\n", tox_self_get_nospam(tox));
return 0;
}
@@ -1158,22 +1411,27 @@ toxinit(void)
framesize = (AUDIOSAMPLERATE * AUDIOFRAME * AUDIOCHANNELS) / 1000;
- tox_callback_friend_connection_status(tox, cbconnstatus, NULL);
- tox_callback_friend_message(tox, cbfriendmessage, NULL);
- tox_callback_friend_request(tox, cbfriendrequest, NULL);
- tox_callback_friend_name(tox, cbnamechange, NULL);
- tox_callback_friend_status_message(tox, cbstatusmessage, NULL);
- tox_callback_friend_status(tox, cbfriendstate, NULL);
- tox_callback_file_recv_control(tox, cbfilecontrol, NULL);
- tox_callback_file_recv(tox, cbfilesendreq, NULL);
- tox_callback_file_recv_chunk(tox, cbfiledata, NULL);
- tox_callback_file_chunk_request(tox, cbfiledatareq, NULL);
+ tox_callback_friend_connection_status(tox, cbconnstatus);
+ tox_callback_friend_message(tox, cbfriendmessage);
+ tox_callback_friend_request(tox, cbfriendrequest);
+ tox_callback_friend_name(tox, cbnamechange);
+ tox_callback_friend_status_message(tox, cbstatusmessage);
+ tox_callback_friend_status(tox, cbfriendstate);
+ tox_callback_file_recv_control(tox, cbfilecontrol);
+ tox_callback_file_recv(tox, cbfilesendreq);
+ tox_callback_file_recv_chunk(tox, cbfiledata);
+ tox_callback_file_chunk_request(tox, cbfiledatareq);
toxav_callback_call(toxav, cbcallinvite, NULL);
toxav_callback_call_state(toxav, cbcallstate, NULL);
toxav_callback_audio_receive_frame(toxav, cbcalldata, NULL);
+ tox_callback_conference_invite(tox, cbconfinvite);
+ tox_callback_conference_message(tox, cbconfmessage);
+ tox_callback_conference_title(tox, cbconftitle);
+ tox_callback_conference_namelist_change(tox, cbconfmembers);
+
if (toxopt.savedata_data)
free((void *)toxopt.savedata_data);
@@ -1326,6 +1584,64 @@ friendcreate(uint32_t frnum)
}
static void
+confcreate(uint32_t cnum)
+{
+ struct conference *c;
+ DIR *d;
+ size_t i;
+ int r;
+ uint8_t title[TOX_MAX_NAME_LENGTH + 1];
+ TOX_ERR_CONFERENCE_TITLE err;
+
+ c = calloc(1, sizeof(*c));
+ if(!c)
+ eprintf("calloc:");
+ c->num = cnum;
+ sprintf(c->numstr, "%08X", c->num);
+ r = mkdir(c->numstr, 0777);
+ if(r < 0 && errno != EEXIST)
+ eprintf("mkdir %s:", c->numstr);
+
+ d = opendir(c->numstr);
+ if (!d)
+ eprintf("opendir %s:", c->numstr);
+
+ r = dirfd(d);
+ if (r < 0)
+ eprintf("dirfd %s:", c->numstr);
+ c->dirfd = r;
+
+ for (i = 0; i < LEN(cfiles); i++) {
+ c->fd[i] = -1;
+ if (cfiles[i].type == FIFO) {
+ fiforeset(c->dirfd, &c->fd[i], cfiles[i]);
+ } else if (cfiles[i].type == STATIC) {
+ c->fd[i] = fifoopen(c->dirfd, cfiles[i]);
+ }
+ }
+
+ writemembers(c);
+
+ /* No warning is printed here in the case of an error
+ * because this always fails when joining after an invite,
+ * but cbconftitle() is called in the next iteration afterwards,
+ * so it doesn't matter after all.
+ */
+
+ i = tox_conference_get_title_size(tox, c->num, &err);
+ if (err != TOX_ERR_CONFERENCE_TITLE_OK)
+ i = 0;
+ tox_conference_get_title(tox, c->num, title, NULL);
+ title[i] = '\0';
+ ftruncate(c->fd[CTITLE_OUT], 0);
+ dprintf(c->fd[CTITLE_OUT], "%s\n", title);
+
+ TAILQ_INSERT_TAIL(&confhead, c, entry);
+
+ logmsg("Conference %s > Created\n", c->numstr);
+}
+
+static void
frienddestroy(struct friend *f)
{
size_t i;
@@ -1346,6 +1662,22 @@ frienddestroy(struct friend *f)
}
static void
+confdestroy(struct conference *c)
+{
+ size_t i;
+
+ for (i = 0; i <LEN(cfiles); i++) {
+ if(c->dirfd != -1) {
+ unlinkat(c->dirfd, cfiles[i].name, 0);
+ if (c->fd[i] != -1)
+ close(c->fd[i]);
+ }
+ }
+ rmdir(c->numstr);
+ TAILQ_REMOVE(&confhead, c, entry);
+}
+
+static void
friendload(void)
{
size_t sz;
@@ -1526,7 +1858,7 @@ setnospam(void *data)
}
nsval = strtoul((char *)nospam, NULL, 16);
- tox_self_set_nospam(tox, htonl(nsval));
+ tox_self_set_nospam(tox, nsval);
datasave();
logmsg("Nospam > %08X\n", nsval);
ftruncate(gslots[NOSPAM].fd[OUT], 0);
@@ -1544,18 +1876,44 @@ end:
}
static void
+newconf(void *data)
+{
+ uint32_t cnum;
+ size_t n;
+ char title[TOX_MAX_NAME_LENGTH + 1];
+
+ n = fiforead(gslots[CONF].dirfd, &gslots[CONF].fd[IN], gfiles[IN],
+ title, sizeof(title) - 1);
+ if (n <= 0)
+ return;
+ if (title[n - 1] == '\n')
+ n--;
+ title[n] = '\0';
+ cnum = tox_conference_new(tox, NULL);
+ if (cnum == UINT32_MAX) {
+ weprintf("Failed to create new conference\n");
+ return;
+ }
+ if (!tox_conference_set_title(tox, cnum, (uint8_t *)title, n, NULL))
+ weprintf("Failed to set conference title to \"%s\"", title);
+ confcreate(cnum);
+}
+
+static void
loop(void)
{
- struct file reqfifo;
+ struct file reqfifo, invfifo;
struct friend *f, *ftmp;
struct request *req, *rtmp;
+ struct conference *c, *ctmp;
+ struct invite *inv, *itmp;
struct timeval tv;
fd_set rfds;
time_t t0, t1, c0, c1;
size_t i;
int connected = 0, n, r, fd, fdmax;
- char tstamp[64], c;
- uint32_t frnum;
+ char tstamp[64], ch;
+ uint32_t frnum, cnum;
t0 = time(NULL);
logmsg("DHT > Connecting\n");
@@ -1583,7 +1941,7 @@ loop(void)
toxconnect();
}
}
- tox_iterate(tox);
+ tox_iterate(tox, NULL);
toxav_iterate(toxav);
/* Prepare select-fd-set */
@@ -1596,6 +1954,9 @@ loop(void)
TAILQ_FOREACH(req, &reqhead, entry)
FD_APPEND(req->fd);
+ TAILQ_FOREACH(inv, &invhead, entry)
+ FD_APPEND(inv->fd);
+
TAILQ_FOREACH(f, &friendhead, entry) {
/* Only monitor friends that are online */
if (tox_friend_get_connection_status(tox, f->num, NULL) != TOX_CONNECTION_NONE) {
@@ -1609,6 +1970,13 @@ loop(void)
FD_APPEND(f->fd[FREMOVE]);
}
+ TAILQ_FOREACH(c, &confhead, entry) {
+ FD_APPEND(c->fd[CLEAVE]);
+ FD_APPEND(c->fd[CTITLE_IN]);
+ FD_APPEND(c->fd[CTEXT_IN]);
+ FD_APPEND(c->fd[CINVITE]);
+ }
+
tv.tv_sec = 0;
tv.tv_usec = interval(tox, toxav) * 1000;
n = select(fdmax + 1, &rfds, NULL, NULL, &tv);
@@ -1655,6 +2023,7 @@ loop(void)
}
}
+
/* Answer pending calls */
TAILQ_FOREACH(f, &friendhead, entry) {
if (tox_friend_get_connection_status(tox, f->num, NULL) == TOX_CONNECTION_NONE)
@@ -1715,9 +2084,9 @@ loop(void)
reqfifo.name = req->idstr;
reqfifo.flags = O_RDONLY | O_NONBLOCK;
if (fiforead(gslots[REQUEST].fd[OUT], &req->fd, reqfifo,
- &c, 1) != 1)
+ &ch, 1) != 1)
continue;
- if (c != '0' && c != '1')
+ if (ch != '0' && ch != '1')
continue;
frnum = tox_friend_add_norequest(tox, req->id, NULL);
if (frnum == UINT32_MAX) {
@@ -1725,7 +2094,7 @@ loop(void)
fiforeset(gslots[REQUEST].fd[OUT], &req->fd, reqfifo);
continue;
}
- if (c == '1') {
+ if (ch == '1') {
friendcreate(frnum);
logmsg("Request : %s > Accepted\n", req->idstr);
datasave();
@@ -1740,6 +2109,48 @@ loop(void)
free(req);
}
+ for (inv = TAILQ_FIRST(&invhead); inv; inv = itmp) {
+ itmp = TAILQ_NEXT(inv, entry);
+ if (FD_ISSET(inv->fd, &rfds) == 0)
+ continue;
+ invfifo.name = inv->fifoname;
+ invfifo.flags = O_RDONLY | O_NONBLOCK;
+ if (fiforead(gslots[CONF].fd[OUT], &inv->fd, invfifo,
+ &ch, 1) != 1)
+ continue;
+ if (ch != '0' && ch != '1')
+ continue;
+ else if (ch == '1'){
+ cnum = tox_conference_join(tox, inv->inviter, (uint8_t *)inv->cookie,
+ inv->cookielen, NULL);
+ if(cnum == UINT32_MAX)
+ weprintf("Failed to join conference\n");
+ else
+ confcreate(cnum);
+ }
+ unlinkat(gslots[CONF].fd[OUT], inv->fifoname, 0);
+ close(inv->fd);
+ TAILQ_REMOVE(&invhead, inv, entry);
+ free(inv->fifoname);
+ free(inv->cookie);
+ free(inv);
+ }
+
+ for (c = TAILQ_FIRST(&confhead); c; c = ctmp) {
+ ctmp = TAILQ_NEXT(c, entry);
+ if (FD_ISSET(c->fd[CINVITE], &rfds))
+ invitefriend(c);
+ if (FD_ISSET(c->fd[CLEAVE], &rfds)) {
+ logmsg("Conference %s > Leave\n", c->numstr);
+ tox_conference_delete(tox, c->num, NULL);
+ confdestroy(c);
+ }
+ if (FD_ISSET(c->fd[CTEXT_IN], &rfds))
+ sendconftext(c);
+ if (FD_ISSET(c->fd[CTITLE_IN], &rfds))
+ updatetitle(c);
+ }
+
for (f = TAILQ_FIRST(&friendhead); f; f = ftmp) {
ftmp = TAILQ_NEXT(f, entry);
if (FD_ISSET(f->fd[FTEXT_IN], &rfds))
@@ -1805,7 +2216,9 @@ toxshutdown(void)
{
struct friend *f, *ftmp;
struct request *r, *rtmp;
- size_t i, m;
+ struct conference *c, *ctmp;
+ struct invite *i, *itmp;
+ size_t s, m;
logmsg("Shutdown\n");
@@ -1817,6 +2230,12 @@ toxshutdown(void)
frienddestroy(f);
}
+ /* Conferences */
+ for (c = TAILQ_FIRST(&confhead); c; c=ctmp) {
+ ctmp = TAILQ_NEXT(c, entry);
+ confdestroy(c);
+ }
+
/* Requests */
for (r = TAILQ_FIRST(&reqhead); r; r = rtmp) {
rtmp = TAILQ_NEXT(r, entry);
@@ -1831,18 +2250,33 @@ toxshutdown(void)
free(r);
}
+ /* Invites */
+ for (i = TAILQ_FIRST(&invhead); i; i = itmp) {
+ itmp = TAILQ_NEXT(i, entry);
+
+ if(gslots[CONF].fd[OUT] != -1) {
+ unlinkat(gslots[CONF].fd[OUT], i->fifoname, 0);
+ if (i->fd != -1)
+ close(i->fd);
+ }
+ TAILQ_REMOVE(&invhead, i, entry);
+ free(i->fifoname);
+ free(i->cookie);
+ free(i);
+ }
+
/* Global files and slots */
- for (i = 0; i < LEN(gslots); i++) {
+ for (s = 0; s < LEN(gslots); s++) {
for (m = 0; m < LEN(gfiles); m++) {
- if (gslots[i].dirfd != -1) {
- unlinkat(gslots[i].dirfd, gfiles[m].name,
- (gslots[i].outisfolder && m == OUT)
+ if (gslots[s].dirfd != -1) {
+ unlinkat(gslots[s].dirfd, gfiles[m].name,
+ (gslots[s].outisfolder && m == OUT)
? AT_REMOVEDIR : 0);
- if (gslots[i].fd[m] != -1)
- close(gslots[i].fd[m]);
+ if (gslots[s].fd[m] != -1)
+ close(gslots[s].fd[m]);
}
- }
- rmdir(gslots[i].name);
+ }
+ rmdir(gslots[s].name);
}
unlink("id");
if (idfd != -1)