X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Ffilenet.c;h=6b9b4fc3633c003f69f2ccb52fd83bb5d837d9b5;hb=d5b1f8590f16f19cd1a94eb2affc850ec2d42fa4;hp=81a83c4d79ef60bb88ddc47018cb26db84246d92;hpb=d3372da97568d5e1f35fa19787c8ec8af93a0435;p=doldaconnect.git diff --git a/daemon/filenet.c b/daemon/filenet.c index 81a83c4..6b9b4fc 100644 --- a/daemon/filenet.c +++ b/daemon/filenet.c @@ -1,6 +1,6 @@ /* * Dolda Connect - Modular multiuser Direct Connect-style client - * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com) + * Copyright (C) 2004 Fredrik Tolf * * 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 @@ -30,6 +30,8 @@ #include "utils.h" #include "net.h" +static void freepeer(struct fnetpeer *peer); + static struct fnet *networks = NULL; struct fnetnode *fnetnodes = NULL; int numfnetnodes = 0; @@ -52,6 +54,9 @@ static struct fnetnode *newfn(struct fnet *fnet) CBCHAININIT(new, fnetnode_chat); CBCHAININIT(new, fnetnode_unlink); CBCHAININIT(new, fnetnode_destroy); + CBCHAININIT(new, fnetpeer_new); + CBCHAININIT(new, fnetpeer_del); + CBCHAININIT(new, fnetpeer_chdi); new->next = NULL; new->prev = NULL; numfnetnodes++; @@ -61,14 +66,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) - putfnetnode(fn); - putsock(fn->sk); - fn->sk = NULL; - } + if(fn->connected) + fn->fnet->kill(fn); } void getfnetnode(struct fnetnode *fn) @@ -79,6 +78,16 @@ void getfnetnode(struct fnetnode *fn) #endif } +static void freepeers(struct btree *n) +{ + if(n == NULL) + return; + freepeers(n->l); + freepeers(n->r); + freepeer(n->d); + free(n); +} + void putfnetnode(struct fnetnode *fn) { struct fnetnode *cur; @@ -98,16 +107,22 @@ void putfnetnode(struct fnetnode *fn) CBCHAINFREE(fn, fnetnode_chat); CBCHAINFREE(fn, fnetnode_unlink); CBCHAINFREE(fn, fnetnode_destroy); - if(fn->fnet->destroy != NULL) + CBCHAINFREE(fn, fnetpeer_new); + CBCHAINFREE(fn, fnetpeer_del); + CBCHAINFREE(fn, fnetpeer_chdi); + if((fn->fnet->destroy != NULL) && fn->connected) fn->fnet->destroy(fn); - while(fn->peers != NULL) - fnetdelpeer(fn->peers); + while(fn->args != NULL) + freewcspair(fn->args, &fn->args); + freepeers(fn->peers); if(fn->mynick != NULL) free(fn->mynick); + if(fn->pubid != NULL) + 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); numfnetnodes--; } @@ -156,10 +171,10 @@ 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); } @@ -202,7 +217,7 @@ static struct fnetpeerdatum *adddatum(struct fnetnode *fn, wchar_t *id, int data return(new); } -static struct fnetpeerdi *difindoradd(struct fnetpeer *peer, struct fnetpeerdatum *datum) +static struct fnetpeerdi *difindoradd(struct fnetpeer *peer, struct fnetpeerdatum *datum, int *isnew) { int i; @@ -217,8 +232,12 @@ static struct fnetpeerdi *difindoradd(struct fnetpeer *peer, struct fnetpeerdatu memset(&peer->peerdi[peer->dinum], 0, sizeof(struct fnetpeerdi)); peer->peerdi[peer->dinum].datum = datum; datum->refcount++; + if(isnew != NULL) + *isnew = 1; return(&peer->peerdi[peer->dinum++]); } else { + if(isnew != NULL) + *isnew = 0; return(&peer->peerdi[i]); } } @@ -227,35 +246,50 @@ void fnetpeersetstr(struct fnetpeer *peer, wchar_t *id, wchar_t *value) { struct fnetpeerdatum *datum; struct fnetpeerdi *di; + int changed; if((datum = finddatum(peer->fn, id)) == NULL) datum = adddatum(peer->fn, id, FNPD_STR); - di = difindoradd(peer, datum); - if(di->data.str != NULL) + di = difindoradd(peer, datum, &changed); + if(di->data.str != NULL) { + changed = (changed || wcscmp(value, di->data.str)); free(di->data.str); + } else { + changed = 1; + } di->data.str = swcsdup(value); + if(changed) + CBCHAINDOCB(peer->fn, fnetpeer_chdi, peer->fn, peer, di); } void fnetpeersetnum(struct fnetpeer *peer, wchar_t *id, int value) { struct fnetpeerdatum *datum; struct fnetpeerdi *di; + int changed; if((datum = finddatum(peer->fn, id)) == NULL) datum = adddatum(peer->fn, id, FNPD_INT); - di = difindoradd(peer, datum); + di = difindoradd(peer, datum, &changed); + changed = (changed || (di->data.num != value)); di->data.num = value; + if(changed) + CBCHAINDOCB(peer->fn, fnetpeer_chdi, peer->fn, peer, di); } void fnetpeersetlnum(struct fnetpeer *peer, wchar_t *id, long long value) { struct fnetpeerdatum *datum; struct fnetpeerdi *di; + int changed; if((datum = finddatum(peer->fn, id)) == NULL) datum = adddatum(peer->fn, id, FNPD_LL); - di = difindoradd(peer, datum); + di = difindoradd(peer, datum, &changed); + changed = (changed || (di->data.lnum != value)); di->data.lnum = value; + if(changed) + CBCHAINDOCB(peer->fn, fnetpeer_chdi, peer->fn, peer, di); } static void putdatum(struct fnetpeer *peer, struct fnetpeerdatum *datum) @@ -293,6 +327,11 @@ void fnetpeerunset(struct fnetpeer *peer, wchar_t *id) putdatum(peer, datum); } +static int peercmpid(void *a, void *b) +{ + return(wcscmp(((struct fnetpeer *)a)->id, ((struct fnetpeer *)b)->id)); +} + struct fnetpeer *fnetaddpeer(struct fnetnode *fn, wchar_t *id, wchar_t *nick) { struct fnetpeer *new; @@ -304,28 +343,18 @@ struct fnetpeer *fnetaddpeer(struct fnetnode *fn, wchar_t *id, wchar_t *nick) new->flags.w = 0; new->dinum = 0; new->peerdi = NULL; - new->next = fn->peers; - new->prev = NULL; - if(fn->peers != NULL) - fn->peers->prev = new; - fn->peers = new; + bbtreeput(&fn->peers, new, peercmpid); fn->numpeers++; CBCHAINDOCB(fn, fnetnode_ac, fn, L"numpeers"); + CBCHAINDOCB(fn, fnetpeer_new, fn, new); return(new); } -void fnetdelpeer(struct fnetpeer *peer) +static void freepeer(struct fnetpeer *peer) { int i; - if(peer->next != NULL) - peer->next->prev = peer->prev; - if(peer->prev != NULL) - peer->prev->next = peer->next; - if(peer->fn->peers == peer) - peer->fn->peers = peer->next; peer->fn->numpeers--; - CBCHAINDOCB(peer->fn, fnetnode_ac, peer->fn, L"numpeers"); free(peer->id); free(peer->nick); for(i = 0; i < peer->dinum; i++) @@ -339,19 +368,50 @@ void fnetdelpeer(struct fnetpeer *peer) free(peer); } +void fnetdelpeer(struct fnetpeer *peer) +{ + bbtreedel(&peer->fn->peers, peer, peercmpid); + CBCHAINDOCB(peer->fn, fnetnode_ac, peer->fn, L"numpeers"); + CBCHAINDOCB(peer->fn, fnetpeer_del, peer->fn, peer); + freepeer(peer); +} + +void fnetpeerdm(struct fnetnode *fn) +{ + struct btree *new; + struct fnetpeer *peer; + int intact; + + new = NULL; + intact = 1; + for(peer = btreeiter(fn->peers); peer != NULL; peer = btreeiter(NULL)) { + if(!peer->flags.b.delete) { + bbtreeput(&new, peer, peercmpid); + } else { + intact = 0; + CBCHAINDOCB(peer->fn, fnetpeer_del, peer->fn, peer); + freepeer(peer); + } + } + btreefree(fn->peers); + fn->peers = new; + if(!intact) + CBCHAINDOCB(peer->fn, fnetnode_ac, peer->fn, L"numpeers"); +} + struct fnetpeer *fnetfindpeer(struct fnetnode *fn, wchar_t *id) { - struct fnetpeer *cur; + struct fnetpeer key; - for(cur = fn->peers; (cur != NULL) && wcscmp(cur->id, id); cur = cur->next); - return(cur); + key.id = id; + return(btreeget(fn->peers, &key, peercmpid)); } 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; @@ -366,7 +426,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); @@ -398,6 +458,15 @@ void fnetsetstate(struct fnetnode *fn, int newstate) CBCHAINDOCB(fn, fnetnode_ac, fn, L"state"); } +wchar_t *fnfilebasename(wchar_t *path) +{ + wchar_t *p; + + if((p = wcsrchr(path, L'/')) != NULL) + return(p + 1); + return(path); +} + struct fnet *findfnet(wchar_t *name) { struct fnet *fnet; @@ -410,10 +479,11 @@ struct fnet *findfnet(wchar_t *name) return(fnet); } -struct fnetnode *fnetinitconnect(wchar_t *name, char *addr) +struct fnetnode *fnetinitconnect(wchar_t *name, wchar_t *owner, char *addr, struct wcspair *args) { struct fnet *fnet; struct fnetnode *fn; + struct wcspair *arg; if((fnet = findfnet(name)) == NULL) { @@ -421,6 +491,16 @@ struct fnetnode *fnetinitconnect(wchar_t *name, char *addr) return(NULL); } fn = newfn(fnet); + fn->owner = swcsdup(owner); + fn->pubid = icmbstowcs(addr, NULL); + if(fn->pubid == NULL) + fn->pubid = swcsdup(L""); + fn->args = args; + for(arg = fn->args; arg != NULL; arg = arg->next) + { + if(!wcscmp(arg->key, L"nick")) + fnetsetnick(fn, arg->val); + } getfnetnode(fn); if(netresolve(addr, (void (*)(struct sockaddr *, int, void *))resolvecb, fn) < 0) return(NULL); @@ -455,9 +535,26 @@ void fnethandlechat(struct fnetnode *fn, int public, wchar_t *name, wchar_t *pee static struct configvar myvars[] = { + /** The number of seconds to wait between searches. Most hubs + * require at least ten seconds, and quite often network lag will + * often make searches arrive to the hub more often than sent. It + * may be semi-dangerous to specify too low a value, since hubs + * will often kick users that search too often (even when the + * reason is network lag -- there is no way for the hub to know + * this), but it is quite annoying to set too high a value. 15 to + * 40 seconds are the recommended range (although the default is + * 15 seconds, it is recommended to set to 30 seconds). */ {CONF_VAR_INT, "srchwait", {.num = 15}}, + /** The TOS value to use for hub connections (see the TOS VALUES + * section). */ {CONF_VAR_INT, "fntos", {.num = 0}}, + /** The TOS value to use for peer connections (see the TOS VALUES + * section). */ {CONF_VAR_INT, "fnptos", {.num = 0}}, + /** Specifies a maximum number of simultaneously connected + * hubs. Attempts to connect to new hubs beyond this limit will + * return an error. Set to zero to remove the limit. */ + {CONF_VAR_INT, "maxnodes", {.num = 0}}, {CONF_VAR_END} };