From ffa81d5f0167a81cc81e9eec69062f0aeaf7754a Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sun, 21 Oct 2007 21:19:28 +0200 Subject: [PATCH] Filenet socket rework. There was a rather large problem where the socket for a fn connection was stored in the fnetnode itself, and filenet.c had opinions on clearing its data internally in killfnetnode, which led to a number of consistency problems -- the code was ugly, and the daemon would occasionally segfault if killfnetnode had cleared sk->data prematurely for some reason. Now, each fnet module takes care of the socket itself, so that it is modified internally only. The code is much cleaner that way. --- daemon/filenet.c | 26 ++++++-------------- daemon/filenet.h | 5 ++-- daemon/fnet-adc.c | 31 ++++++++++++++--------- daemon/fnet-dc.c | 73 ++++++++++++++++++++++++++++++------------------------- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/daemon/filenet.c b/daemon/filenet.c index f11836f..82ed1d2 100644 --- a/daemon/filenet.c +++ b/daemon/filenet.c @@ -64,17 +64,8 @@ static struct fnetnode *newfn(struct fnet *fnet) void killfnetnode(struct fnetnode *fn) { fnetsetstate(fn, FNN_DEAD); - if(fn->sk != NULL) - { - fn->sk->close = 1; - if(fn->sk->data == fn) - { - fn->sk->data = NULL; - putfnetnode(fn); - } - putsock(fn->sk); - fn->sk = NULL; - } + if(fn->connected) + fn->fnet->kill(fn); } void getfnetnode(struct fnetnode *fn) @@ -107,7 +98,7 @@ void putfnetnode(struct fnetnode *fn) CBCHAINFREE(fn, fnetpeer_new); CBCHAINFREE(fn, fnetpeer_del); CBCHAINFREE(fn, fnetpeer_chdi); - if(fn->fnet->destroy != NULL) + if((fn->fnet->destroy != NULL) && fn->connected) fn->fnet->destroy(fn); while(fn->args != NULL) freewcspair(fn->args, &fn->args); @@ -119,8 +110,6 @@ void putfnetnode(struct fnetnode *fn) free(fn->pubid); if(fn->name != NULL) free(fn->name); - if(fn->sk != NULL) - putsock(fn->sk); if(fn->owner != NULL) free(fn->owner); free(fn); @@ -171,11 +160,12 @@ static void conncb(struct socket *sk, int err, struct fnetnode *data) putfnetnode(data); return; } - data->sk = sk; fnetsetstate(data, FNN_HS); socksettos(sk, confgetint("fnet", "fntos")); - data->fnet->connect(data); + data->fnet->connect(data, sk); + data->connected = 1; putfnetnode(data); + putsock(sk); } static void resolvecb(struct sockaddr *addr, int addrlen, struct fnetnode *data) @@ -387,7 +377,7 @@ int fnetsetnick(struct fnetnode *fn, wchar_t *newnick) { int ret; - if(fn->fnet->setnick != NULL) + if((fn->fnet->setnick != NULL) && fn->connected) ret = fn->fnet->setnick(fn, newnick); else ret = 0; @@ -402,7 +392,7 @@ int fnetsetnick(struct fnetnode *fn, wchar_t *newnick) int fnetsendchat(struct fnetnode *fn, int public, wchar_t *to, wchar_t *string) { - if(fn->fnet->sendchat == NULL) + if((fn->fnet->sendchat == NULL) || !fn->connected) { errno = ENOTSUP; return(-1); diff --git a/daemon/filenet.h b/daemon/filenet.h index 4c49dfa..d6a73dd 100644 --- a/daemon/filenet.h +++ b/daemon/filenet.h @@ -44,8 +44,9 @@ struct fnet { struct fnet *next; wchar_t *name; - void (*connect)(struct fnetnode *fn); + void (*connect)(struct fnetnode *fn, struct socket *sk); void (*destroy)(struct fnetnode *fn); + void (*kill)(struct fnetnode *fn); int (*setnick)(struct fnetnode *fn, wchar_t *newnick); int (*reqconn)(struct fnetpeer *peer); int (*sendchat)(struct fnetnode *fn, int public, wchar_t *to, wchar_t *string); @@ -99,12 +100,12 @@ struct fnetnode int state; int linked; int regstatus; + int connected; time_t srchwait, lastsrch; wchar_t *name, *pubid; wchar_t *mynick; wchar_t *owner; struct fnet *fnet; - struct socket *sk; struct fnetpeerdatum *peerdata; struct fnetpeer *peers; struct wcspair *args; diff --git a/daemon/fnet-adc.c b/daemon/fnet-adc.c index 98d760f..2e920e6 100644 --- a/daemon/fnet-adc.c +++ b/daemon/fnet-adc.c @@ -59,6 +59,7 @@ struct qcmd { }; struct adchub { + struct socket *sk; char *inbuf; size_t inbufdata, inbufsize; wchar_t *sid; @@ -198,8 +199,8 @@ static void freeqcmd(struct qcmd *qcmd) #define UNUSED #endif #define ADC_CMDCOM \ - struct socket *sk UNUSED = fn->sk; \ - struct adchub *hub UNUSED = fn->data; + struct adchub *hub UNUSED = fn->data; \ + struct socket *sk UNUSED = hub->sk; ADC_CMDFN(cmd_sup) { @@ -351,14 +352,14 @@ static void huberr(struct socket *sk, int err, struct fnetnode *fn) killfnetnode(fn); } -static void hubconnect(struct fnetnode *fn) +static void hubconnect(struct fnetnode *fn, struct socket *sk) { struct adchub *hub; - fn->sk->readcb = (void (*)(struct socket *, void *))hubread; - fn->sk->errcb = (void (*)(struct socket *, int, void *))huberr; - fn->sk->data = fn; - getfnetnode(fn); + getsock(hub->sk = sk); + 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)); @@ -368,15 +369,14 @@ static void hubconnect(struct fnetnode *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); @@ -385,6 +385,14 @@ static void hubdestroy(struct fnetnode *fn) 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); @@ -398,6 +406,7 @@ static int hubreqconn(struct fnetpeer *peer) static struct fnet adcnet_store = { .connect = hubconnect, .destroy = hubdestroy, + .kill = hubkill, .setnick = hubsetnick, .reqconn = hubreqconn, .name = L"adc" @@ -420,7 +429,7 @@ static int run(void) 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; diff --git a/daemon/fnet-dc.c b/daemon/fnet-dc.c index 880b1e3..3618b12 100644 --- a/daemon/fnet-dc.c +++ b/daemon/fnet-dc.c @@ -101,6 +101,7 @@ struct qcommand struct dchub { + struct socket *sk; char *inbuf; size_t inbufdata, inbufsize; struct qcommand *queue; @@ -1127,7 +1128,7 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char * goto out; prefix = sprintf2("$SR %s ", hub->nativenick); infix = sprintf2(" %i/%i\005", slotsleft(), confgetint("transfer", "slots")); - postfix = sprintf2(" (%s)\005%s|", formataddress(fn->sk->remote, fn->sk->remotelen), args + 4); + postfix = sprintf2(" (%s)\005%s|", formataddress(hub->sk->remote, hub->sk->remotelen), args + 4); dsk = sk; getsock(dsk); } else { @@ -1140,7 +1141,7 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char * addr.sin_port = htons(atoi(p2)); prefix = sprintf2("$SR %s ", hub->nativenick); infix = sprintf2(" %i/%i\005", slotsleft(), confgetint("transfer", "slots")); - postfix = sprintf2(" (%s)|", formataddress(fn->sk->remote, fn->sk->remotelen)); + postfix = sprintf2(" (%s)|", formataddress(hub->sk->remote, hub->sk->remotelen)); netdgramconn(dsk = netdupsock(udpsock), (struct sockaddr *)&addr, sizeof(addr)); } @@ -1392,7 +1393,7 @@ static void cmd_to(struct socket *sk, struct fnetnode *fn, char *cmd, char *args return; *p2 = 0; p2 += 2; - hubrecvchat(fn->sk, fn, p, p2); + hubrecvchat(hub->sk, fn, p, p2); hubhandleaction(sk, fn, cmd, args); } @@ -2339,10 +2340,10 @@ static int hubreqconn(struct fnetpeer *peer) return(1); /* Shouldn't happen, of course, but who knows... */ if(tcpsock != NULL) { - sendctm(peer->fn->sk, mbsnick); + sendctm(hub->sk, mbsnick); expectpeer(mbsnick, peer->fn); } else { - qstrf(peer->fn->sk, "$RevConnectToMe %s %s|", hub->nativenick, mbsnick); + qstrf(hub->sk, "$RevConnectToMe %s %s|", hub->nativenick, mbsnick); } free(mbsnick); return(0); @@ -2382,12 +2383,12 @@ static int hubsendchat(struct fnetnode *fn, int public, wchar_t *to, wchar_t *st { if(*to == L'\0') { - qstrf(fn->sk, "<%s> %s|", hub->nativenick, mbsstring); + qstrf(hub->sk, "<%s> %s|", hub->nativenick, mbsstring); } else { - qstrf(fn->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring); + qstrf(hub->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring); } } else { - qstrf(fn->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring); + qstrf(hub->sk, "$To: %s From: %s $<%s> %s|", mbsto, hub->nativenick, hub->nativenick, mbsstring); } free(mbsto); free(mbsstring); @@ -2502,7 +2503,7 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis struct hash *hash; hub = fn->data; - if((fn->state != FNN_EST) || (fn->sk == NULL) || (fn->sk->state != SOCK_EST)) + if((fn->state != FNN_EST) || (hub->sk == NULL) || (hub->sk->state != SOCK_EST)) return(1); list = findsexprstrs(srch->sexpr); findsizelimit(srch->sexpr, &minsize, &maxsize); @@ -2580,15 +2581,15 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis addtobuf(sstr, 0); if(tcpsock != NULL) { - if(sockgetremotename2(udpsock, fn->sk, &name, &namelen) < 0) + if(sockgetremotename2(udpsock, hub->sk, &name, &namelen) < 0) { flog(LOG_WARNING, "cannot get address of UDP socket"); } else { - qstrf(fn->sk, "$Search %s %s|", formataddress(name, namelen), sstr); + qstrf(hub->sk, "$Search %s %s|", formataddress(name, namelen), sstr); free(name); } } else { - qstrf(fn->sk, "$Search Hub:%s %s|", hub->nativenick, sstr); + qstrf(hub->sk, "$Search Hub:%s %s|", hub->nativenick, sstr); } free(sstr); freesl(&list); @@ -2920,10 +2921,13 @@ static void udpread(struct socket *sk, void *data) { for(fn = fnetnodes; fn != NULL; fn = fn->next) { - if((fn->fnet == &dcnet) && (fn->sk != NULL) && addreq(fn->sk->remote, (struct sockaddr *)&hubaddr)) + if((fn->fnet == &dcnet) && ((hub = fn->data) != NULL)) { - myfn = fn; - break; + if((hub->sk != NULL) && addreq(hub->sk->remote, (struct sockaddr *)&hubaddr)) + { + myfn = fn; + break; + } } } } @@ -3123,13 +3127,15 @@ static void freedcpeer(struct dcpeer *peer) numdcpeers--; } -static void hubconnect(struct fnetnode *fn) +static void hubconnect(struct fnetnode *fn, struct socket *sk) { - fn->sk->readcb = (void (*)(struct socket *, void *))hubread; - fn->sk->errcb = (void (*)(struct socket *, int, void *))huberr; - getfnetnode(fn); - fn->data = newdchub(fn); - fn->sk->data = fn; + struct dchub *hub; + + sk->readcb = (void (*)(struct socket *, void *))hubread; + sk->errcb = (void (*)(struct socket *, int, void *))huberr; + fn->data = hub = newdchub(fn); + sk->data = fn; + getsock(hub->sk = sk); return; } @@ -3140,15 +3146,7 @@ static void hubdestroy(struct fnetnode *fn) struct qcommand *qcmd; hub = (struct dchub *)fn->data; - if((fn->sk != NULL) && (fn->sk->data == fn)) - { - fn->sk->data = NULL; - fn->sk->readcb = NULL; - fn->sk->errcb = NULL; - putfnetnode(fn); - } - if(hub == NULL) - return; + putsock(hub->sk); while((qcmd = ulqcmd(&hub->queue)) != NULL) freeqcmd(qcmd); if(hub->supports != NULL) @@ -3168,6 +3166,14 @@ static void hubdestroy(struct fnetnode *fn) free(hub); } +static void hubkill(struct fnetnode *fn) +{ + struct dchub *hub; + + hub = (struct dchub *)fn->data; + hub->sk->close = 1; +} + static wchar_t *dcbasename(wchar_t *filename) { wchar_t *ret; @@ -3190,6 +3196,7 @@ static struct fnet dcnet = .name = L"dc", .connect = hubconnect, .destroy = hubdestroy, + .kill = hubkill, .setnick = hubsetnick, .reqconn = hubreqconn, .sendchat = hubsendchat, @@ -3721,10 +3728,10 @@ static int run(void) { if(*qcmd->string == '$') { - if((fn->sk != NULL) && (fn->sk->state == SOCK_EST)) - dispatchcommand(qcmd, hubcmds, fn->sk, fn); + if((hub->sk != NULL) && (hub->sk->state == SOCK_EST)) + dispatchcommand(qcmd, hubcmds, hub->sk, fn); } else if(*qcmd->string != 0) { - hubrecvchat(fn->sk, fn, NULL, qcmd->string); + hubrecvchat(hub->sk, fn, NULL, qcmd->string); } freeqcmd(qcmd); ret = 1; -- 2.11.0