15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier
55e96a66cSDavid du Colombier typedef struct Lstn Lstn;
6e12a9870SDavid du Colombier struct Lstn {
75e96a66cSDavid du Colombier int afd;
82cca75a1SDavid du Colombier int flags;
95e96a66cSDavid du Colombier char* address;
105e96a66cSDavid du Colombier char dir[NETPATHLEN];
115e96a66cSDavid du Colombier
125e96a66cSDavid du Colombier Lstn* next;
135e96a66cSDavid du Colombier Lstn* prev;
14e12a9870SDavid du Colombier };
155e96a66cSDavid du Colombier
165e96a66cSDavid du Colombier static struct {
17*d7aba6c3SDavid du Colombier RWLock lock;
185e96a66cSDavid du Colombier
195e96a66cSDavid du Colombier Lstn* head;
205e96a66cSDavid du Colombier Lstn* tail;
215e96a66cSDavid du Colombier } lbox;
225e96a66cSDavid du Colombier
235e96a66cSDavid du Colombier static void
lstnFree(Lstn * lstn)245e96a66cSDavid du Colombier lstnFree(Lstn* lstn)
255e96a66cSDavid du Colombier {
26*d7aba6c3SDavid du Colombier wlock(&lbox.lock);
275e96a66cSDavid du Colombier if(lstn->prev != nil)
285e96a66cSDavid du Colombier lstn->prev->next = lstn->next;
295e96a66cSDavid du Colombier else
305e96a66cSDavid du Colombier lbox.head = lstn->next;
315e96a66cSDavid du Colombier if(lstn->next != nil)
325e96a66cSDavid du Colombier lstn->next->prev = lstn->prev;
335e96a66cSDavid du Colombier else
345e96a66cSDavid du Colombier lbox.tail = lstn->prev;
35*d7aba6c3SDavid du Colombier wunlock(&lbox.lock);
365e96a66cSDavid du Colombier
375e96a66cSDavid du Colombier if(lstn->afd != -1)
385e96a66cSDavid du Colombier close(lstn->afd);
39*d7aba6c3SDavid du Colombier vtfree(lstn->address);
40*d7aba6c3SDavid du Colombier vtfree(lstn);
415e96a66cSDavid du Colombier }
425e96a66cSDavid du Colombier
435e96a66cSDavid du Colombier static void
lstnListen(void * a)445e96a66cSDavid du Colombier lstnListen(void* a)
455e96a66cSDavid du Colombier {
465e96a66cSDavid du Colombier Lstn *lstn;
475e96a66cSDavid du Colombier int dfd, lfd;
485e96a66cSDavid du Colombier char newdir[NETPATHLEN];
495e96a66cSDavid du Colombier
50*d7aba6c3SDavid du Colombier threadsetname("listen");
515e96a66cSDavid du Colombier
525e96a66cSDavid du Colombier lstn = a;
535e96a66cSDavid du Colombier for(;;){
545e96a66cSDavid du Colombier if((lfd = listen(lstn->dir, newdir)) < 0){
555e96a66cSDavid du Colombier fprint(2, "listen: listen '%s': %r", lstn->dir);
565e96a66cSDavid du Colombier break;
575e96a66cSDavid du Colombier }
585e96a66cSDavid du Colombier if((dfd = accept(lfd, newdir)) >= 0)
592cca75a1SDavid du Colombier conAlloc(dfd, newdir, lstn->flags);
605e96a66cSDavid du Colombier else
612cca75a1SDavid du Colombier fprint(2, "listen: accept %s: %r\n", newdir);
629b70c2d0SDavid du Colombier close(lfd);
635e96a66cSDavid du Colombier }
645e96a66cSDavid du Colombier lstnFree(lstn);
655e96a66cSDavid du Colombier }
665e96a66cSDavid du Colombier
675e96a66cSDavid du Colombier static Lstn*
lstnAlloc(char * address,int flags)682cca75a1SDavid du Colombier lstnAlloc(char* address, int flags)
695e96a66cSDavid du Colombier {
705e96a66cSDavid du Colombier int afd;
715e96a66cSDavid du Colombier Lstn *lstn;
725e96a66cSDavid du Colombier char dir[NETPATHLEN];
735e96a66cSDavid du Colombier
74*d7aba6c3SDavid du Colombier wlock(&lbox.lock);
755e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
765e96a66cSDavid du Colombier if(strcmp(lstn->address, address) != 0)
775e96a66cSDavid du Colombier continue;
78*d7aba6c3SDavid du Colombier werrstr("listen: already serving '%s'", address);
79*d7aba6c3SDavid du Colombier wunlock(&lbox.lock);
805e96a66cSDavid du Colombier return nil;
815e96a66cSDavid du Colombier }
825e96a66cSDavid du Colombier
835e96a66cSDavid du Colombier if((afd = announce(address, dir)) < 0){
84*d7aba6c3SDavid du Colombier werrstr("listen: announce '%s': %r", address);
85*d7aba6c3SDavid du Colombier wunlock(&lbox.lock);
865e96a66cSDavid du Colombier return nil;
875e96a66cSDavid du Colombier }
885e96a66cSDavid du Colombier
89*d7aba6c3SDavid du Colombier lstn = vtmallocz(sizeof(Lstn));
905e96a66cSDavid du Colombier lstn->afd = afd;
91*d7aba6c3SDavid du Colombier lstn->address = vtstrdup(address);
922cca75a1SDavid du Colombier lstn->flags = flags;
935e96a66cSDavid du Colombier memmove(lstn->dir, dir, NETPATHLEN);
945e96a66cSDavid du Colombier
955e96a66cSDavid du Colombier if(lbox.tail != nil){
965e96a66cSDavid du Colombier lstn->prev = lbox.tail;
975e96a66cSDavid du Colombier lbox.tail->next = lstn;
985e96a66cSDavid du Colombier }
995e96a66cSDavid du Colombier else{
1005e96a66cSDavid du Colombier lbox.head = lstn;
1015e96a66cSDavid du Colombier lstn->prev = nil;
1025e96a66cSDavid du Colombier }
1035e96a66cSDavid du Colombier lbox.tail = lstn;
104*d7aba6c3SDavid du Colombier wunlock(&lbox.lock);
1055e96a66cSDavid du Colombier
106*d7aba6c3SDavid du Colombier if(proccreate(lstnListen, lstn, STACK) < 0){
107*d7aba6c3SDavid du Colombier werrstr("listen: thread '%s': %r", lstn->address);
1085e96a66cSDavid du Colombier lstnFree(lstn);
1095e96a66cSDavid du Colombier return nil;
1105e96a66cSDavid du Colombier }
1115e96a66cSDavid du Colombier
1125e96a66cSDavid du Colombier return lstn;
1135e96a66cSDavid du Colombier }
1145e96a66cSDavid du Colombier
1155e96a66cSDavid du Colombier static int
cmdLstn(int argc,char * argv[])1165e96a66cSDavid du Colombier cmdLstn(int argc, char* argv[])
1175e96a66cSDavid du Colombier {
1182cca75a1SDavid du Colombier int dflag, flags;
1195e96a66cSDavid du Colombier Lstn *lstn;
1202cca75a1SDavid du Colombier char *usage = "usage: listen [-dIN] [address]";
1215e96a66cSDavid du Colombier
1225e96a66cSDavid du Colombier dflag = 0;
1232cca75a1SDavid du Colombier flags = 0;
1245e96a66cSDavid du Colombier ARGBEGIN{
1255e96a66cSDavid du Colombier default:
1265e96a66cSDavid du Colombier return cliError(usage);
1275e96a66cSDavid du Colombier case 'd':
1285e96a66cSDavid du Colombier dflag = 1;
1295e96a66cSDavid du Colombier break;
1302cca75a1SDavid du Colombier case 'I':
1312cca75a1SDavid du Colombier flags |= ConIPCheck;
1322cca75a1SDavid du Colombier break;
1332cca75a1SDavid du Colombier case 'N':
1342cca75a1SDavid du Colombier flags |= ConNoneAllow;
1352cca75a1SDavid du Colombier break;
1365e96a66cSDavid du Colombier }ARGEND
1375e96a66cSDavid du Colombier
1385e96a66cSDavid du Colombier switch(argc){
1395e96a66cSDavid du Colombier default:
1405e96a66cSDavid du Colombier return cliError(usage);
1415e96a66cSDavid du Colombier case 0:
142*d7aba6c3SDavid du Colombier rlock(&lbox.lock);
1435e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
1445e96a66cSDavid du Colombier consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
145*d7aba6c3SDavid du Colombier runlock(&lbox.lock);
1465e96a66cSDavid du Colombier break;
1475e96a66cSDavid du Colombier case 1:
1485e96a66cSDavid du Colombier if(!dflag){
1492cca75a1SDavid du Colombier if(lstnAlloc(argv[0], flags) == nil)
1505e96a66cSDavid du Colombier return 0;
1515e96a66cSDavid du Colombier break;
1525e96a66cSDavid du Colombier }
1535e96a66cSDavid du Colombier
154*d7aba6c3SDavid du Colombier wlock(&lbox.lock);
1555e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
1565e96a66cSDavid du Colombier if(strcmp(lstn->address, argv[0]) != 0)
1575e96a66cSDavid du Colombier continue;
1585e96a66cSDavid du Colombier if(lstn->afd != -1){
1595e96a66cSDavid du Colombier close(lstn->afd);
1605e96a66cSDavid du Colombier lstn->afd = -1;
1615e96a66cSDavid du Colombier }
1625e96a66cSDavid du Colombier break;
1635e96a66cSDavid du Colombier }
164*d7aba6c3SDavid du Colombier wunlock(&lbox.lock);
1655e96a66cSDavid du Colombier
1665e96a66cSDavid du Colombier if(lstn == nil){
167*d7aba6c3SDavid du Colombier werrstr("listen: '%s' not found", argv[0]);
1685e96a66cSDavid du Colombier return 0;
1695e96a66cSDavid du Colombier }
1705e96a66cSDavid du Colombier break;
1715e96a66cSDavid du Colombier }
1725e96a66cSDavid du Colombier
1735e96a66cSDavid du Colombier return 1;
1745e96a66cSDavid du Colombier }
1755e96a66cSDavid du Colombier
1765e96a66cSDavid du Colombier int
lstnInit(void)1775e96a66cSDavid du Colombier lstnInit(void)
1785e96a66cSDavid du Colombier {
1795e96a66cSDavid du Colombier cliAddCmd("listen", cmdLstn);
1805e96a66cSDavid du Colombier
1815e96a66cSDavid du Colombier return 1;
1825e96a66cSDavid du Colombier }
183