// $Header: /usr/u/moudgill/project/Socket/RCS/server3.C,v 1.5 1992/10/02 18:34:02 moudgill Exp moudgill $
// 17th December, 1991. Mayan Moudgill.

static const char rcsid[] = "$Id: server3.C,v 1.5 1992/10/02 18:34:02 moudgill Exp moudgill $";

#include "sstream.h"
#ifdef __linux__
#include <stdlib.h>
#else
#include <libc.h>
#endif

void pipedef(sstream& s)
{
   cerr << "lost other end of " << s.sd() << "\n";
   exit(1);
}

const int maxsocks = 8;
int       num = 0;
int       n[maxsocks];
sstream   c[maxsocks];

int left()
{
   if( num > 0) {
      return 1;
   }
   for(int i =0 ; i < maxsocks; i++) {
      if( n[i] != 0) {
         return 1;
      }
   }
   return 0;
}

int  getnum(sstream& s)
{
   for(int i = 0; s.sd() != c[i].sd(); i++) {
   }
   return i;
}

int  getnum(int n)
{
   for(int i = 0; n != c[i].sd(); i++) {
   }
   return i;
}

void getcount(sstream& s)
{
int   x;
 
   s >> x;
   cerr << "going to process " << x << " numbers for " << s.sd() << "\n";
   n[getnum(s)] = x;
}

void  negnum(sstream &t)
{
int c;
int p;

   t >> c;
   if( !t ) {
      cerr << "couldn't recv " <<  t.sd() << " "
	    << t.serror() << " " << t.serrno() << "\n";
      //exit(2);
   }
   cerr << "read " << c << " from " << t.sd() << "\n";
   t << (-c) << "\n" ;
   if( !t ) {
      cerr << "couldn't send\n";
      //exit(3);
   }
   p = getnum(t);
   n[p]--;
   if( n[p] == 0 ) {
      t.close();
   }
} 

void getconnect(sstream& s)
{
   c[--num].accept(s);
   n[num] = -1;
   c[num].sstate(sstream::unitbufferbit);
   if( !c[num] ) {
      cerr << "could not accept connection #" << num << "\n";
      exit(6);
   }
   cerr << "connection #" << num << " " << c[num].sd() << " to "
	 << c[num].tohost() << " " << c[num].toport() << "\n";

   c[num].pipehandler(pipedef);
   if( num == 0) {
      cerr << "closing server port\n";
      s.close();
   }
}

void main(int argc, char * argv[])
{
sstream::showtrace = sstream::showerror = sstream::showsyscall = 1;
sstream   s;
selset    r;
seliter   x;

   if( argc < 3) {
      cerr << "error: usage : " << argv[0] << " <port> <# connect>\n";
      exit(4);
   }

   num = atoi(argv[2]);
   s.setbuf(0,0);
   s.open(atoi(argv[1]));

   if( !s  ) {
      cerr << "could not open\n";
      exit(5);
   }

   cerr << "server " << s.sd() << " bound to " << s.host() << " "
	 << s.port() << "\n";

    while( left() ) {
      cerr << "waiting\n";
      r = sstream::sockets();
      selwait(r, 0, 0);
      if( r[s.sd()] ) {
	r -= s.sd();
	getconnect(s);
      }
      for( int i = x(r); !x; i = ++x) {
	 if( n[getnum(i)] != 0 ) {
	    if( n[getnum(i)] == -1 )  {
	       getcount( c[getnum(i)]);
	    }
	    else {
	       negnum( c[getnum(i)]);
	    }
	 }
	 else {
	    c[getnum(i)].close();
	 }
      }
    }
}
