/*
* Dolda Connect - Modular multiuser Direct Connect-style client
- * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
+ * Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
*
* 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
};
struct adchub {
+ struct socket *sk;
char *inbuf;
size_t inbufdata, inbufsize;
wchar_t *sid;
}
#define ADC_CMDFN(name) static void name(struct fnetnode *fn, wchar_t *command, wchar_t *sender, int argc, wchar_t **argv)
-#define ADC_CMDCOM struct socket *sk = fn->sk; struct adchub *hub = fn->data;
+#ifdef __GNUC__
+#define UNUSED __attribute__ ((unused))
+#else
+#define UNUSED
+#endif
+#define ADC_CMDCOM \
+ struct adchub *hub UNUSED = fn->data; \
+ struct socket *sk UNUSED = hub->sk;
ADC_CMDFN(cmd_sup)
{
flog(LOG_DEBUG, "unknown adc command: %ls", qcmd->args[0]);
}
-static int hubread(struct socket *sk, struct fnetnode *fn)
+static void hubread(struct socket *sk, struct fnetnode *fn)
{
int ret;
struct adchub *hub;
hub = fn->data;
if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
- return(0);
+ return;
if(hub->inbufdata > 1024)
hub->inbufdata = 0;
bufcat(hub->inbuf, newbuf, datalen);
if(errno == EILSEQ) {
flog(LOG_DEBUG, "adc fnetnode %i sent illegal utf-8 sequence", fn->id);
killfnetnode(fn);
- return(0);
+ return;
} else if(errno == EINVAL) {
break;
} else if(errno == E2BIG) {
/* continue; */
} else {
flog(LOG_WARNING, "bug? iconv returned unexpected error: %s", strerror(errno));
- return(0);
+ return;
}
}
}
newqcmd(&hub->queue, parseadc(hub->cb));
memmove(hub->cb, p, (hub->cbdata -= (p - hub->cb)) * sizeof(*(hub->cb)));
}
- return(0);
}
-static int huberr(struct socket *sk, int err, struct fnetnode *fn)
+static void huberr(struct socket *sk, int err, struct fnetnode *fn)
{
killfnetnode(fn);
- return(0);
}
-static void hubconnect(struct fnetnode *fn)
+static void hubconnect(struct fnetnode *fn, struct socket *sk)
{
struct adchub *hub;
- CBREG(fn->sk, socket_read, (int (*)(struct socket *, void *))hubread, (void (*)(void *))putfnetnode, fn);
- CBREG(fn->sk, socket_err, (int (*)(struct socket *, int, void *))huberr, (void (*)(void *))putfnetnode, fn);
+ sk->readcb = (void (*)(struct socket *, void *))hubread;
+ sk->errcb = (void (*)(struct socket *, int, void *))huberr;
+ sk->data = fn;
hub = smalloc(sizeof(*hub));
memset(hub, 0, sizeof(*hub));
+ getsock(hub->sk = sk);
if((hub->ich = iconv_open("wchar_t", "utf-8")) == (iconv_t)-1) {
flog(LOG_CRIT, "iconv cannot handle UTF-8: %s", strerror(errno));
killfnetnode(fn);
return;
}
fn->data = hub;
- sendadc(fn->sk, 0, L"HSUP", L"ADBASE", eoc, NULL);
+ sendadc(sk, 0, L"HSUP", L"ADBASE", eoc, NULL);
}
static void hubdestroy(struct fnetnode *fn)
{
struct adchub *hub;
- if((hub = fn->data) == NULL)
- return;
+ hub = fn->data;
iconv_close(hub->ich);
if(hub->inbuf != NULL)
free(hub->inbuf);
free(hub);
}
+static void hubkill(struct fnetnode *fn)
+{
+ struct adchub *hub;
+
+ hub = fn->data;
+ hub->sk->close = 1;
+}
+
static int hubsetnick(struct fnetnode *fn, wchar_t *newnick)
{
return(0);
static struct fnet adcnet_store = {
.connect = hubconnect,
.destroy = hubdestroy,
+ .kill = hubkill,
.setnick = hubsetnick,
.reqconn = hubreqconn,
.name = L"adc"
if((hub = fn->data) == NULL)
continue;
if((qcmd = ulqcmd(&hub->queue)) != NULL) {
- if((fn->sk != NULL) && (fn->sk->state == SOCK_EST))
+ if((hub->sk != NULL) && (hub->sk->state == SOCK_EST))
dispatch(qcmd, fn);
freeqcmd(qcmd);
ret = 1;
}
static struct configvar myvars[] = {
+ /** Specifies a specific UDP port to use for ADC search
+ * results. If left unspecified, a port is allocated
+ * dynamically. Useful for NAT routers (see also the
+ * net.visibleipv4 address for those cases). */
{CONF_VAR_INT, "udpport", {.num = 0}},
+ /** Specifies a specific TCP port to use for ADC peer
+ * connections. If left unspecified, a port is allocated
+ * dynamically. Useful for NAT routers (see also the
+ * net.visibleipv4 address for those cases). */
{CONF_VAR_INT, "tcpport", {.num = 0}},
{CONF_VAR_END}
};