/*

Copyright 1993, 1994, Cornell University

Cornell hereby grants permission to use, copy, modify, and distribute this program for any purpose 
and without fee, provided that these copyright and permission notices appear on all copies and 
supporting documentation, the name of Cornell not be used in advertising or publicity pertaining 
to distribution of the program without specific prior permission, notice be given in supporting 
documentation that copying and distribution is by permission of Cornell.  CORNELL MAKES NO 
REPRESENTATIONS OR WARRANTEES, EXPRESS OR IMPLIED.  By way of example, but not limitation, 
CORNELL MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR 
PURPOSE OR THAT THE USE OF THIS SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, 
TRADEMARKS, OR OTHER RIGHTS.  Cornell shall not be held liable for any liability with respect to 
any claim by the user or any other party arising from use of the program.

This material is partially based on work sponsored by the National Science Foundation under Cooperative 
Agreement No. NCR-9318337.  The government has certain rights in this material.

*/



#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>

#ifndef LINUX
#include <sys/socketvar.h>
#endif

#include <netinet/in.h>

#include <unistd.h>
#include <fcntl.h>

#include <sys/time.h>
#include <errno.h>
#include "reflect.h"
#include "globals.h"

char                        hostname[MAXHOSTNAMELEN];


void init_socket()
{
    struct sockaddr_in  saddr;
#ifdef MULTI
    struct ip_mreq mreq;
#endif
    unsigned char ttl;
    unsigned char loop;

    

    if (nv_ucast_port != 0){
      
      if ((nv_ucast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
        my_perror("socket: nv_ucast socket");
      
      saddr.sin_family = AF_INET;
      saddr.sin_addr.s_addr = htonl(INADDR_ANY);
      saddr.sin_port = htons(nv_ucast_port);
      
      if (bind(nv_ucast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
        my_perror("bind error port, nv_ucast_sock");
      
    }

    if (maven_port != 0)
    {

       if ((maven_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: maven socket");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(maven_port);

       if (bind(maven_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port, maven_sock");

       if ((maven_cntl_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: maven control socket");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(maven_port+1);

       if (bind(maven_cntl_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port, maven_cntl_sock");

       if ((maven_cntl_sock_out = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: maven control socket out");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(0);

       if (bind(maven_cntl_sock_out, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port, maven_cntl_sock_out");
    }

    if ((vid_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
        my_perror("socket: video socket");

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(VID_PORT);

    if (bind(vid_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
        my_perror("bind error port, vid_sock");

    if ((cntrl_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        my_perror("socket: control socket");

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    saddr.sin_port = htons(CONTROL_PORT);

    if (bind(cntrl_sock, &saddr, sizeof(struct sockaddr_in)) < 0)
        my_perror("bind error port, cntrl_sock");

#ifdef MULTI
    if (rfout_mcast.sin_addr.s_addr)
    {
       if ((rfout_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: rfout multicast socket");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(RF_PORT);

       if (bind(rfout_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port");

       ttl = rf_ttl;
       setsockopt(rfout_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
    }

    if (rfin_mcast.sin_addr.s_addr)
    {
       if ((rfin_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: rfin multicast socket");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(RF_PORT);

       if (bind(rfin_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port");

       mreq.imr_multiaddr.s_addr = rfin_mcast.sin_addr.s_addr;
       mreq.imr_interface.s_addr = INADDR_ANY;

       setsockopt(rfin_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
    }

    if (inout_mcast.sin_addr.s_addr)
    {
       if ((inout_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: inout multicast socket");

       saddr.sin_family = AF_INET;
       saddr.sin_addr.s_addr = htonl(INADDR_ANY);
       saddr.sin_port = htons(RF_PORT);

       if (bind(inout_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
           my_perror("bind error port");

       ttl = inout_ttl;
       setsockopt(inout_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

       mreq.imr_multiaddr.s_addr = inout_mcast.sin_addr.s_addr;
       mreq.imr_interface.s_addr = INADDR_ANY;

       setsockopt(inout_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

       loop = 0;
       setsockopt(inout_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
    }


    /* if the config file has given us a vat-mc-port and no vat-mc-in/out multicast
       address, then it has been configured incorrectly, and we should exit. */

    if ((vat_port) && !(vat_in_mcast.sin_addr.s_addr) && !(vat_out_mcast.sin_addr.s_addr)){
      printf("No vat multicast in or out address given w/ vat-mc-port.\n");
      exit(-1);
    }


    /* Bind the appropriate ports if we have read vat-mc-in/out from the config file.  */
    if ((vat_in_mcast.sin_addr.s_addr) || (vat_out_mcast.sin_addr.s_addr)){

      if (vat_port == 0){
        printf("No vat multicast port provided in config file.\n");
        exit(-1);
      }

      /* vat mcast receive only */
      if ((vat_in_mcast.sin_addr.s_addr) && !(vat_out_mcast.sin_addr.s_addr)){
     
        if ((vat_in_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
          my_perror("socket: vat_in_mcast socket");
      
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(vat_port);

        if (bind(vat_in_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port");

        mreq.imr_multiaddr.s_addr = vat_in_mcast.sin_addr.s_addr;
        mreq.imr_interface.s_addr = INADDR_ANY;

        setsockopt(vat_in_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
        if (debug)
          printf("vat_in_mcast_sock bound\n");

      }
      

      /* vat mcast send only */
      else if (!(vat_in_mcast.sin_addr.s_addr) && (vat_out_mcast.sin_addr.s_addr)){

        if ((vat_out_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: vat_out_mcast socket");

        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(vat_port);
        
        if (bind(vat_out_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port");

        ttl = vat_ttl;
        setsockopt(vat_out_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));


        /*
        loop = 0;
        setsockopt(vat_out_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
        */

        if (debug)
          printf("vat_out_mcast_sock bound\n");
      
      }

      /* vat mcast send & receive */
      else if (((vat_in_mcast.sin_addr.s_addr) && (vat_out_mcast.sin_addr.s_addr)) && 
          (vat_in_mcast.sin_addr.s_addr) == (vat_out_mcast.sin_addr.s_addr)){

        vat_inout_mcast.sin_addr.s_addr = vat_out_mcast.sin_addr.s_addr;

        if ((vat_inout_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
          my_perror("socket: vat_inout_mcast socket");
        
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(vat_port);

        if (bind(vat_inout_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port");

        ttl = vat_ttl;
        setsockopt(vat_inout_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

        mreq.imr_multiaddr.s_addr = vat_inout_mcast.sin_addr.s_addr;
        mreq.imr_interface.s_addr = INADDR_ANY;

        setsockopt(vat_inout_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

        loop = 0;
        setsockopt(vat_inout_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));

        if (debug)
          printf("vat_inout_mcast_sock bound\n");
      }
    
      else{
        printf("Can't have different vat-mc-in and vat-mc-out multicast addresses!");
        exit(-1);
      }

      /* bind the vat control socket */
      if ((vat_cntl_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
        my_perror("socket: vat_cntl_mcast socket");

      saddr.sin_family = AF_INET;
      saddr.sin_addr.s_addr = htonl(INADDR_ANY);
      saddr.sin_port = htons(vat_port+1);

      if (bind(vat_cntl_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
        my_perror("bind error port, vat_cntl_mcast_sock");

      ttl = vat_ttl;
      setsockopt(vat_cntl_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

      loop = 0;
      setsockopt(vat_cntl_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));

      if (debug)
        printf("vat_cntl_mcast_sock bound\n");
    }


        
      
  /* if the config file has given us a nv-mc-port and no nv-mc-in/out multicast
       address, then it has been configured incorrectly, and we should exit. */

    if ((nv_mcast_port) && !(nv_in_mcast.sin_addr.s_addr) && !(nv_out_mcast.sin_addr.s_addr)){
      printf("No nv multicast in or out address given w/ nv-mc-port.\n");
      exit(-1);
    }


    /* Bind the appropriate ports if we have read nv-mc-in/out from the config file.  */
    if ((nv_in_mcast.sin_addr.s_addr) || (nv_out_mcast.sin_addr.s_addr)){

      if (nv_mcast_port == 0){
        printf("No nv multicast port provided in config file.\n");
        exit(-1);
      }

      /* nv mcast receive only */
      if ((nv_in_mcast.sin_addr.s_addr) && !(nv_out_mcast.sin_addr.s_addr)){
     
        if ((nv_in_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
          my_perror("socket: nv_in_mcast socket");
      
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(nv_mcast_port);

        if (bind(nv_in_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port");

        mreq.imr_multiaddr.s_addr = nv_in_mcast.sin_addr.s_addr;
        mreq.imr_interface.s_addr = INADDR_ANY;

        setsockopt(nv_in_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
        if (debug)
          printf("nv_in_mcast_sock bound\n");

      }
      

      /* nv mcast send only */
      else if (!(nv_in_mcast.sin_addr.s_addr) && (nv_out_mcast.sin_addr.s_addr)){

        if ((nv_out_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
           my_perror("socket: nv_out_mcast socket");

        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(nv_mcast_port);
        
        if (bind(nv_out_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port");

        ttl = nv_ttl;
        setsockopt(nv_out_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));


        /*
        loop = 0;
        setsockopt(nv_out_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
        */

        if (debug)
          printf("nv_out_mcast_sock bound\n");
      
      }

      /* nv mcast send & receive */
      else if (((nv_in_mcast.sin_addr.s_addr) && (nv_out_mcast.sin_addr.s_addr)) && 
          (nv_in_mcast.sin_addr.s_addr) == (nv_out_mcast.sin_addr.s_addr)){

        nv_inout_mcast.sin_addr.s_addr = nv_out_mcast.sin_addr.s_addr;
        nv_inout_mcast.sin_family = AF_INET;
        nv_inout_mcast.sin_port = htons(nv_mcast_port);

        if ((nv_inout_mcast_sock = socket(AF_INET, SOCK_DGRAM, 0))  < 0)
          my_perror("socket: nv_inout_mcast socket");
        
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        saddr.sin_port = htons(nv_mcast_port);

        if (bind(nv_inout_mcast_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
          my_perror("bind error port -- nv_inout_mcast_sock");

        ttl = nv_ttl;
        setsockopt(nv_inout_mcast_sock,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

        mreq.imr_multiaddr.s_addr = nv_inout_mcast.sin_addr.s_addr;
        mreq.imr_interface.s_addr = INADDR_ANY;

        setsockopt(nv_inout_mcast_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

        loop = 0;
        setsockopt(nv_inout_mcast_sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));

        if (debug)
          printf("nv_inout_mcast_sock bound\n");
      }
    
      else{
        printf("Can't have different nv-mc-in and nv-mc-out multicast addresses!");
        exit(-1);
      }
      
    }





#endif 

    if ((fcntl(vid_sock, F_SETFL, FNDELAY)) < 0 )
        my_perror("fcntl error");

    if (maven_sock)
    {
       if ((fcntl(maven_sock, F_SETFL, FNDELAY)) < 0 )
           my_perror("fcntl error");

       if ((fcntl(maven_cntl_sock, F_SETFL, FNDELAY)) < 0 )
           my_perror("fcntl error");
    }

    if ((fcntl(cntrl_sock, F_SETFL, FNDELAY)) < 0) 
        my_perror("fcntl error");

    if (gethostname(hostname,MAXHOSTNAMELEN) < 0)
        my_perror("getnostname");

    msg_sock = 0;
    setsockopt(cntrl_sock,SOL_SOCKET,SO_REUSEADDR,1,0);
    listen(cntrl_sock,5);
}

void init_timer()
{
    struct itimerval    value;
    struct itimerval    ovalue;
    void                sighandler();

    value.it_interval.tv_sec = 1;
    value.it_interval.tv_usec = 0;
    value.it_value.tv_sec = 1;
    value.it_value.tv_usec = 0;

    setitimer(ITIMER_REAL, &value, &ovalue);

    signal(SIGALRM, sighandler);
}

void sighandler()
{
    timer_expired++;
    signal(SIGALRM, sighandler);
}

int receive(pkt,msglen,caddr)
    char               *pkt;
    int                *msglen;
    struct sockaddr_in *caddr; 
{
    fd_set                      readfds;
    int                         cadrlen,ready;

    while (1)
    {
       if (timer_expired)
       {
          timer_expired--;
          do_timer();
       }

       FD_ZERO(&readfds);
       FD_SET(vid_sock, &readfds);

       if (maven_sock)
       {
          FD_SET(maven_sock,&readfds);
          FD_SET(maven_cntl_sock,&readfds);
       }
       
       if (nv_ucast_sock) 
         FD_SET(nv_ucast_sock,&readfds);

#ifdef MULTI
       if (rfin_mcast.sin_addr.s_addr)
         FD_SET(rfin_mcast_sock,&readfds);
       
       if (inout_mcast.sin_addr.s_addr)
         FD_SET(inout_mcast_sock,&readfds);


       /* if we want to receive, set the appropriate bits in 
          the readfds structure for the in and cntl vat sockets */

       if (vat_in_mcast.sin_addr.s_addr){
         FD_SET(vat_in_mcast_sock,&readfds);
         FD_SET(vat_cntl_mcast_sock,&readfds);

       }

       /* same as above, but if we are sending and receiving */
       if (vat_inout_mcast.sin_addr.s_addr){
         FD_SET(vat_inout_mcast_sock,&readfds);
         FD_SET(vat_cntl_mcast_sock,&readfds);

       }
       
       /* if we are just sending, we don't need to read any
          control signals -- do we?  Commented out for now */

       /*
       if (vat_out_mcast.sin_addr.s_addr)
         FD_SET(vat_cntl_mcast_sock,&readfds);
       */
       
       /* now do the same for the nv sockets as we just did for the vat ones */

       if (nv_in_mcast.sin_addr.s_addr)
         FD_SET(nv_in_mcast_sock,&readfds);

       if (nv_inout_mcast.sin_addr.s_addr)
         FD_SET(nv_inout_mcast_sock,&readfds);
       

#endif
       if (msg_sock == 0)
          FD_SET(cntrl_sock, &readfds);

       if (msg_sock != 0)
          FD_SET(msg_sock, &readfds);
       
       if ((ready = select(FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0)
       {
          if (errno == EINTR)
             continue;
          else
             my_perror("select error");
       }

       if (ready == 0)
           continue;

       cadrlen = sizeof(struct sockaddr_in);

       if (FD_ISSET(vid_sock, &readfds)) 
       {
          
          if ((*msglen = recvfrom(vid_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
	     continue;	/* not doing this makes reflector crash easily. */
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on vid_sock");
          }

          return(VIDEO);
       }

       if (FD_ISSET(nv_ucast_sock, &readfds)) 
       {
          
         if ((*msglen = recvfrom(nv_ucast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
         {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on nv_ucast_sock");
          }
          if (debug)
             printf("packet received through nv_ucast_sock\n");
          return(NV_UCAST);
       }


       if (FD_ISSET(maven_sock, &readfds)) 
       {
          
          if ((*msglen = recvfrom(maven_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on maven_sock");
          }
          if (debug)
             printf("packet received through maven_sock\n");
          return(MAVEN);
       }

       if (FD_ISSET(maven_cntl_sock, &readfds)) 
       {
          
          if ((*msglen = recvfrom(maven_cntl_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on maven_cntl_sock");
          }
          if (debug)
             printf("\npacket received on maven_cntl_sock %s \n", inet_ntoa(caddr->sin_addr));
        
          return(MAVEN_CNTL);
       }

#ifdef MULTI
       if ((rfin_mcast_sock) && (FD_ISSET(rfin_mcast_sock, &readfds)))
       {
          
          if ((*msglen = recvfrom(rfin_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on rfin_mcast_sock");
          }

          return(REF1VIDEO);
       }

       if ((inout_mcast_sock) && (FD_ISSET(inout_mcast_sock, &readfds)))
       {
          
          if ((*msglen = recvfrom(inout_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on inout_mcast_sock");
          }

          return(REF2VIDEO);
       }

       if ((vat_in_mcast_sock) && (FD_ISSET(vat_in_mcast_sock, &readfds))){

         if  ((*msglen = recvfrom(vat_in_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0) {
           
           if (errno == EINTR)
             continue;

           my_perror("recvfrom error on vat_in_mcast_sock");

         }
         if (debug)
            printf("packet received on vat_in_mcast_sock\n");
         return(VAT);

       }

       if ((vat_inout_mcast_sock) && (FD_ISSET(vat_inout_mcast_sock, &readfds))){

         if  ((*msglen = recvfrom(vat_inout_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0) {
           
           if (errno == EINTR)
             continue;

           my_perror("recvfrom error on vat_inout_mcast_sock");

         }
         if (debug)
            printf("packet received on vat_inout_mcast_sock\n");
         return(VAT);

       }

       if (FD_ISSET(vat_cntl_mcast_sock, &readfds)) 
       {
                  
          if ((*msglen = recvfrom(vat_cntl_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on vat_cntl_mcast_sock");
          }
        
          if (debug)
             printf("\npacket received on vat_cntl_sock %s \n", inet_ntoa(caddr->sin_addr));
          return(VAT_CNTL);
       }

       
       if ((nv_in_mcast_sock) && (FD_ISSET(nv_in_mcast_sock, &readfds))){
         
         if  ((*msglen = recvfrom(nv_in_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0) {
           
           if (errno == EINTR)
             continue;

           my_perror("recvfrom error on nv_in_mcast_sock");

         }
         if (debug)
            printf("packet received on nv_in_mcast_sock\n");
         return(NV_MCAST);

       }

       if ((nv_inout_mcast_sock) && (FD_ISSET(nv_inout_mcast_sock, &readfds))){

         if  ((*msglen = recvfrom(nv_inout_mcast_sock,pkt,MAXMSG,0,caddr,&cadrlen)) < 0) {
           
           if (errno == EINTR)
             continue;

           my_perror("recvfrom error on nv_inout_mcast_sock");

         }
         if (debug)
            printf("packet received on nv_inout_mcast_sock\n");
         return(NV_MCAST);

       }
       
#endif

       if (FD_ISSET(cntrl_sock, &readfds))
       {
          if (msg_sock != 0)
          {
             dolog("control message with a non-zero msg_sock\n");
             exit(1);
          }

          if ((msg_sock = accept(cntrl_sock,caddr,&cadrlen)) < 0)
          {
             if (errno == EINTR)
             {
                msg_sock = 0;
                continue;
             }

             my_perror("accept");
             exit(1);
          }


          if ((control_ip == 0) || ((control_ip != -1) && (control_ip != caddr->sin_addr.s_addr)))
          {
             dolog("Control message from %s is disallowed\n",inet_ntoa(caddr->sin_addr));
             close(msg_sock);
             msg_sock = 0;
             continue;
          }


          dolog("incoming control message new msg_sock is %d\n",msg_sock);
          setsockopt(msg_sock,SOL_SOCKET,SO_REUSEADDR,1,0);
          continue;
        }

       if (FD_ISSET(msg_sock, &readfds))
       {
          if ((*msglen = recv(msg_sock,pkt,MAXMSG,0)) < 0)
          {
             if (errno == EINTR)
                continue;

             my_perror("recvfrom error on msg_sock");
             exit (1);
          }
   
          if (*msglen == 0)
          {
             close(msg_sock);
             msg_sock = 0;
             continue;
          }
   
          return (CONTROL);
       }
    }
}
