/*

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 <varargs.h>
#include <signal.h>
#include <errno.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>

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

#include <net/if.h>
#include <netinet/in.h>

#include "reflect.h"
#include "refmon.h"
#include "globals.h"

client *open_connection(vidptr,csock,type)
   VideoPacketHeader   *vidptr;
   struct sockaddr_in  *csock;
   int                 type;
{
    client        *cltptr,*ctmp;
    short         client_id,cnt;
    struct timezone  tzp;
    struct in_addr      in;



    switch (type)
    {
       case BCC_CLIENT:
       case BCC_GCLIENT:
	  if (type == BCC_CLIENT)
	  {
             dolog("BCC client at %s is opening connection\n", inet_ntoa(csock->sin_addr));
             bcc_client_cnt++;
	  }
          else
	  {
             dolog("BCC general client at %s is opening connection\n", inet_ntoa(csock->sin_addr));
             bcc_gclient_cnt++;
	  }
          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= type; 
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);


	  if (type == BCC_CLIENT)
             strcpy(cltptr->clnt_config.name,"BCC CLIENT");
          else
             strcpy(cltptr->clnt_config.name,"BCC GCLIENT");

          cltptr->clnt_nptr = chead;
          chead = cltptr;
          return(cltptr);

       case BCC_SERVER:
          dolog("BCC server at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= BCC_SERVER;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
          strcpy(cltptr->clnt_config.name,"BCC SERVER");

          cltptr->clnt_nptr = chead;
          chead = cltptr;

          bcc_server_cnt++;

          open_connection(vidptr,(struct sockaddr_in *) &vidptr->routing.src,BCC_ORIGIN);
          return(cltptr);

       case BCC_ORIGIN:  
          dolog("BCC server's client at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          if ((client_id = get_client_id()) == -1)
          {
             dolog("maximum # of clients exceeded\n");
             return(NULL);
          }
      
          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= BCC_ORIGIN;
          cltptr->clnt_id = client_id;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
      
          cltptr->clnt_nptr = chead;
          chead = cltptr;

          bcc_origin_cnt++;
      
          update_client(cltptr,vidptr,FALSE,FALSE);

          return(cltptr);

       case REF1_CLIENT:   
          dolog("REF downstream client at %s is opening connection\n", inet_ntoa(csock->sin_addr));

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF1_CLIENT; 
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
          strcpy(cltptr->clnt_config.name,"Downsteam REF");

          cltptr->clnt_nptr = chead;
          chead = cltptr;

          ref1_client_cnt++;

          return(cltptr);

       case REF1_SERVER:

          dolog("REF upstream server at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF1_SERVER;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
          strcpy(cltptr->clnt_config.name,"Upstream REF");

          cltptr->clnt_nptr = chead;
          chead = cltptr;

          ref1_server_cnt++;

          open_connection(vidptr,(struct sockaddr_in *) &vidptr->routing.src,REF1_ORIGIN);
          return(cltptr);

       case REF1_ORIGIN:   
          dolog("REF upstream server's client at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          if ((client_id = get_client_id()) == -1)
          {
             dolog("maximum # of clients exceeded\n");
             return(NULL);
          }
      
          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF1_ORIGIN;
          cltptr->clnt_id = client_id;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
      
          cltptr->clnt_nptr = chead;
          chead = cltptr;

          ref1_origin_cnt++;

          update_client(cltptr,vidptr,FALSE,FALSE);

          return(cltptr);

       case REF2_SERVER:   

          dolog("REF group server at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF2_SERVER;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
          strcpy(cltptr->clnt_config.name,"Group REF");

          cltptr->clnt_nptr = chead;
          chead = cltptr;

          ref2_server_cnt++;

          open_connection(vidptr,(struct sockaddr_in *) &vidptr->routing.src,REF2_ORIGIN);
          return(cltptr);

       case REF2_ORIGIN:

          dolog("REF group server's client at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          if ((client_id = get_client_id()) == -1)
          {
             dolog("maximum # of clients exceeded\n");
             return(NULL);
          }

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF2_ORIGIN;
          cltptr->clnt_id = client_id;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);

          cltptr->clnt_nptr = chead;
          chead = cltptr;
      
          ref2_origin_cnt++;

          update_client(cltptr,vidptr,FALSE,FALSE);
          return(cltptr);

       case REF3_SERVER:   

          dolog("REF unicast group server at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF3_SERVER;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
          strcpy(cltptr->clnt_config.name,"Group Uni REF");

          for (cnt=0; cnt<ref_ucast_cnt; cnt++)
             if (ref_ucast_list[cnt] == csock->sin_addr.s_addr)
             {
                cltptr->clnt_id = cnt;
                break;
             } 

          cltptr->clnt_nptr = chead;
          chead = cltptr;

          ref3_server_cnt++;

          return(cltptr);

       case REF3_ORIGIN:

          dolog("REF unicast group server's client at %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          if ((client_id = get_client_id()) == -1)
          {
             dolog("maximum # of clients exceeded\n");
             return(NULL);
          }

          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= REF3_ORIGIN;
          cltptr->clnt_id = client_id;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);

          cltptr->clnt_nptr = chead;
          chead = cltptr;
      
          ref3_origin_cnt++;

          update_client(cltptr,vidptr,FALSE,FALSE);
          return(cltptr);


       case CLIENT:
          dolog("Client at source %s is opening a connection\n", inet_ntoa(csock->sin_addr));

          if (csock->sin_addr.s_addr != vidptr->routing.src.addr)
          {
             in.s_addr = vidptr->routing.src.addr;
             dolog("Client's network address does not agree with protocol address %s\n",inet_ntoa(in));
             return(NULL);
          }

          if ((client_id = get_client_id()) == -1)
          {
             dolog("maximum # of clients exceeded\n");
             return(NULL);
          }
      
          cltptr = (client *) get_client();
          cltptr->clnt_addr.family = AF_INET;
          cltptr->clnt_addr.port = vidptr->routing.src.port;
          cltptr->clnt_flags |= CLIENT;
          cltptr->clnt_id = client_id;
          cltptr->clnt_conf_id = vidptr->conferenceid;
          bcopy(&csock->sin_addr,&cltptr->clnt_addr.addr,4);
      
          cltptr->clnt_nptr = chead;
          chead = cltptr;

          client_cnt++;

	  check_restricted_senders(vidptr);
      
          update_client(cltptr,vidptr,TRUE,TRUE);

	  if (cltptr->clnt_config.sendMode)
	  {
	     if (++send_ccnt > maxsenders)
	     {
		if (maxsenders != -1)
		{
                   dolog("maximum # of senders exceeded\n");
                   write_msg(&cltptr->clnt_addr,kMessageType1,ms_buf);
                   delete_client(cltptr);
                   return(NULL);
		}
	     }
	  }
	  else
	  {
	     if (++lurker_ccnt > maxlurkers)
	     {
		if (maxlurkers != -1)
		{
                   dolog("maximum # of lurkers exceeded\n");
                   write_msg(&cltptr->clnt_addr,kMessageType1,ml_buf);
                   delete_client(cltptr);
                   return(NULL);
                }
	     }
	  }

          if (client_cnt >= maxallowed)
          {
             write_msg(&cltptr->clnt_addr,kMessageType1,mp_buf);
             delete_client(cltptr);
             return(NULL);
          }

          if (motd_len != 0)
             write_msg(&cltptr->clnt_addr,kMessageType2,motd_buf);

          gettimeofday(&cltptr->clnt_tp, &tzp);
          return(cltptr);
    }
}

void continue_connection(cltptr,vidptr)
   client              *cltptr;
   VideoPacketHeader   *vidptr;
{
    client        *ctmp;
    char          *cptr;
    unsigned long seqnum,diff;
    short         type;
    short         doslist;
    unsigned char old_sendMode;

    cltptr->clnt_hdloop = 0;
    cltptr->clnt_flags &= ~HOLD_DOWN;

    if (cltptr->clnt_flags & CLIENT)
    {
       cptr = ((char *)vidptr + HEADERLEN);
       seqnum = ntohl(*((unsigned long *) (cptr + 2)));

       check_restricted_senders(vidptr);
       
       diff = seqnum - cltptr->clnt_config.seqNum;
       if (diff > 0)
       {
          old_sendMode = cltptr->clnt_config.sendMode;
          if (diff == 1)
             update_client(cltptr,vidptr,TRUE,FALSE);
          else
             update_client(cltptr,vidptr,TRUE,TRUE);

          if (((old_sendMode == 0) && (cltptr->clnt_config.sendMode != 0)) ||
              ((old_sendMode != 0) && (cltptr->clnt_config.sendMode == 0))) 
	  {
	     if (old_sendMode)
	     {
                send_ccnt--;
		lurker_ccnt++;
		dolog("Client %s is going from a sender to a lurker\n",cltptr->clnt_config.name);
		if ((maxlurkers != -1) && (lurker_ccnt > maxlurkers))
		{
                   write_msg(&cltptr->clnt_addr,kMessageType1,ml_buf);
                   delete_client(cltptr);
		}
	     }
	     else
	     {
                send_ccnt++;
		lurker_ccnt--;
		dolog("Client %s is going from a lurker to a sender\n",cltptr->clnt_config.name);
		if ((maxsenders != -1) && (send_ccnt > maxsenders))
		{
                   write_msg(&cltptr->clnt_addr,kMessageType1,ms_buf);
                   delete_client(cltptr);
		}
	     }
	 }
       }

       if ((cltptr->clnt_stimer >= ACKOPEN) || (cltptr->clnt_config.flags & WANT_VERSION))
       {
#ifdef DEBUG
          if (debug)
             printf("ACK timeout sending open ack to %s\n",cltptr->clnt_config.name);
#endif
          write_cmsg(VERSION_NUM,cltptr);
       }
       return;
    }


    if (cltptr->clnt_flags & BCC_SERVER)
    {
       type = BCC_ORIGIN;
       doslist = FALSE;
    }
    else
    if (cltptr->clnt_flags & REF1_SERVER)
    {
       type = REF1_ORIGIN;
       doslist = FALSE;
    }
    else
    if (cltptr->clnt_flags & REF2_SERVER)
    {
       type = REF2_ORIGIN;
       doslist = TRUE;
    }
    else
    if (cltptr->clnt_flags & REF3_SERVER)
    {
       type = REF3_ORIGIN;
       doslist = TRUE;
    }
    else
       return;


    if ((ctmp = find_client(vidptr->routing.src.addr)) != NULL)
    {
       ctmp->clnt_rtimer = 0;
       cptr = ((char *)vidptr + HEADERLEN);
       seqnum = ntohl(*((unsigned long *) (cptr + 2)));
       
       diff = seqnum - ctmp->clnt_config.seqNum;
       if (diff == 1)
          update_client(ctmp,vidptr,doslist,FALSE);
       else
          if (diff > 1)
             update_client(ctmp,vidptr,doslist,TRUE);
    }
    else
       if ((ctmp = open_connection(vidptr,(struct sockaddr_in *) &vidptr->routing.src,type)) != NULL)
       {
          if (type == REF3_ORIGIN)
             ctmp->clnt_pptr = cltptr;
       }

     
}

void update_client(cltptr,vidptr,doslist,all)
    client              *cltptr;
    VideoPacketHeader   *vidptr;
    short               doslist;
    short               all;
{
    ClientInfo       *ciptr;
    client           *ctmp;
    slist            *stmp;
    char             *cptr;

    char             name_len;
    short            cnt;
    struct in_addr   in;


    cptr = ((char *) vidptr + HEADERLEN);

    cltptr->clnt_config.clientCount = ntohs(*((short *)cptr));
    cptr += sizeof(short);

    if (cltptr->clnt_config.clientCount > 20)
       return;

    dolog("updating client %s client count %d   seq %ld\n",
          cltptr->clnt_config.name,cltptr->clnt_config.clientCount,cltptr->clnt_config.seqNum);

    cltptr->clnt_config.seqNum = ntohl(*((unsigned long *)cptr));

    cptr += sizeof(unsigned long);

    name_len = *cptr++; 
    if (name_len > 19)
    {
       dolog("bogus name length %d\n",name_len);
       name_len = 19;
    }

    for (cnt = 0; cnt < name_len; cnt++)
    {
       cltptr->clnt_config.name[cnt] = cptr[cnt];

       if (cltptr->clnt_config.name[cnt] == '\n')
          cltptr->clnt_config.name[cnt] = ' ';

       if (cltptr->clnt_config.name[cnt] == '\r')
          cltptr->clnt_config.name[cnt] = ' ';
    }       

    cltptr->clnt_config.name[name_len] = 0;

    cptr += 19;

    cltptr->clnt_config.sendMode = *cptr++;
    cltptr->clnt_config.recvMode = *cptr++;
    cltptr->clnt_config.flags = *cptr++;

    if ((cltptr->clnt_config.version = *cptr++) < VERSION1)
       all = TRUE;

    /* delete this client from the other client's send list                                     */

    if (doslist == FALSE)
       return;

    if (all)
    {
       ctmp = chead;
       while (ctmp != NULL)
       {
          ctmp->clnt_vlist = unlink_slist(ctmp->clnt_vlist,cltptr);
          ctmp->clnt_alist = unlink_slist(ctmp->clnt_alist,cltptr);
          ctmp->clnt_xlist = unlink_slist(ctmp->clnt_xlist,cltptr);
          ctmp = ctmp->clnt_nptr;
       }
    }

    /*
    ctmp = chead;
    while (ctmp != NULL)
    {
       stmp = ctmp->clnt_vlist;
       cnt = 0;
       while (stmp != NULL)
       {
          cnt++;
          if (stmp->snd_client == cltptr)
             dolog("SLIST IS DAMAGED\n");
          stmp = stmp->snd_nptr;
       }
       dolog("%s's slist count %d\n",ctmp->clnt_config.name,cnt);
       ctmp = ctmp->clnt_nptr;
    }
    */

    ciptr = (ClientInfo *) (cptr);

    for (cnt = 0; cnt < cltptr->clnt_config.clientCount; cnt++)
    {
       if (all)
       {
          if ((ctmp = find_client(ciptr->clientIP)) == NULL)
          {
             if (find_vat_client(ciptr->clientIP) == NULL)
	     {
                in.s_addr = ciptr->clientIP;
                dolog("%s wants to update %s but client not found\n",cltptr->clnt_config.name,inet_ntoa(in));
                write_close(cltptr,ciptr->clientIP);
	     }
             ciptr++;
             continue;
          }

          if (ciptr->IWillRecv)
          {
             if (cltptr->clnt_config.version >= VERSION5)
                dolog("%s wants to receive video from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
             else
                dolog("%s wants to receive audio and video from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);

             stmp = (slist *) get_slist();
             stmp->snd_nptr = ctmp->clnt_vlist;
             ctmp->clnt_vlist = stmp;
             stmp->snd_client = cltptr;

             if (cltptr->clnt_config.version  < VERSION5)
             {
                stmp = (slist *) get_slist();
                stmp->snd_nptr = ctmp->clnt_alist;
                ctmp->clnt_alist = stmp;
                stmp->snd_client = cltptr;
             }

          }

          if (ciptr->flags & IWillRecAudio)
          {
             dolog("%s wants to receive audio from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
  
             stmp = (slist *) get_slist();
             stmp->snd_nptr = ctmp->clnt_alist;
             ctmp->clnt_alist = stmp;
             stmp->snd_client = cltptr;
          }

          if (ciptr->aux != 0)
          {
             dolog("%s wants to receive aux data from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
  
             stmp = (slist *) get_slist();
             stmp->snd_nptr = ctmp->clnt_xlist;
             ctmp->clnt_xlist = stmp;
             stmp->snd_client = cltptr;
             stmp->snd_auxmask = ciptr->aux;
          }
       }        
       else
          if (ciptr->flags & (UPDATE_VIDEO | UPDATE_AUDIO | UPDATE_AUXDATA))
          {
             if ((ctmp = find_client(ciptr->clientIP)) == NULL)
             {
                if (find_vat_client(ciptr->clientIP) == NULL)
		{
                   in.s_addr = ciptr->clientIP;
                   dolog("%s wants to update client at %s but client not found\n",cltptr->clnt_config.name,inet_ntoa(in));
                   write_close(cltptr,ciptr->clientIP);
		}
                ciptr++;
                continue;
             }

             if (ciptr->flags & UPDATE_VIDEO)
             {
                if (ciptr->IWillRecv)
                {
                   if (cltptr->clnt_config.version  >= VERSION5)
                      dolog("%s wants to receive video from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
                   else
                      dolog("%s wants to receive video and audio from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);

                   /* make sure the client isn't already in the list  */
                   stmp = ctmp->clnt_vlist;
                   while (stmp != NULL)
                   {
                      if (stmp->snd_client == cltptr)
                         break;
                      stmp = stmp->snd_nptr;
                   }

                   if (stmp == NULL)
                   {
                      stmp = (slist *) get_slist();
                      stmp->snd_nptr = ctmp->clnt_vlist;
                      ctmp->clnt_vlist = stmp;
                      stmp->snd_client = cltptr;

                      if (cltptr->clnt_config.version  < VERSION5)
                      {
                         stmp = (slist *) get_slist();
                         stmp->snd_nptr = ctmp->clnt_alist;
                         ctmp->clnt_alist = stmp;
                         stmp->snd_client = cltptr;
                      }
                   }
                }
                else
                {
                   if (cltptr->clnt_config.version  >= VERSION5)
                   {
                      dolog("%s no longer wants to receive video from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
                      ctmp->clnt_vlist = unlink_slist(ctmp->clnt_vlist,cltptr);
                   }
                   else
                   {
                      dolog("%s no longer wants to receive video or audio from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
                      ctmp->clnt_vlist = unlink_slist(ctmp->clnt_vlist,cltptr);
                      ctmp->clnt_alist = unlink_slist(ctmp->clnt_alist,cltptr);
                   }
                }
             }

             if (ciptr->flags & UPDATE_AUDIO)
             {
                if (ciptr->flags & IWillRecAudio)
                {
                   dolog("%s wants to receive audio from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);

                   /* make sure the client isn't already in the list  */
                   stmp = ctmp->clnt_alist;
                   while (stmp != NULL)
                   {
                      if (stmp->snd_client == cltptr)
                         break;
                      stmp = stmp->snd_nptr;
                   }
   
                   if (stmp == NULL)
                   {
                      stmp = (slist *) get_slist();
                      stmp->snd_nptr = ctmp->clnt_alist;
                      ctmp->clnt_alist = stmp;
                      stmp->snd_client = cltptr;
                   }
                }
                else
                {
                   dolog("%s no longer wants to receive audio from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
                   ctmp->clnt_alist = unlink_slist(ctmp->clnt_alist,cltptr);
                }
             }
   
             if (ciptr->flags & UPDATE_AUXDATA)
             {
                if (ciptr->aux != 0)
                {
                   dolog("%s wants to receive aux data from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
   
                   /* make sure the client isn't already in the list  */
                   stmp = ctmp->clnt_xlist;
                   while (stmp != NULL)
                   {
                      if (stmp->snd_client == cltptr)
                         break;
                      stmp = stmp->snd_nptr;
                   }
   
                   if (stmp == NULL)
                   {
                      stmp = (slist *) get_slist();
                      stmp->snd_nptr = ctmp->clnt_xlist;
                      ctmp->clnt_xlist = stmp;
                      stmp->snd_client = cltptr;
                   }
                   stmp->snd_auxmask = ciptr->aux;
                }
                else
                {
                   dolog("%s no longer wants to aux data from %s\n",cltptr->clnt_config.name,ctmp->clnt_config.name);
                   ctmp->clnt_xlist = unlink_slist(ctmp->clnt_xlist,cltptr);
                }
             }
          }
       ciptr++;
    }
}


void check_restricted_senders(vidptr)
    VideoPacketHeader   *vidptr;
{
    OCExtraHeader    *oceh;
    TMapHeader       *tptr;
    char             *cptr;
    short            size,cnt;


    /* 
       if the high bit is set on the conference_id then don't allow clients to "send",
       unless the ids match, but otherwise allow them to remain connnected as lurkers
    */

    if (conference_id & 0x8000) 
    {
        if (ntohs(vidptr->conferenceid) == conference_id)
	   return;
    }
    else
       if (local_senders)
          return;

    for (cnt=0; cnt < admit_cnt; cnt++)
       if (admit_senders[cnt] == vidptr->routing.src.addr)
          return;

    cptr = ((char *) vidptr + HEADERLEN);
    cnt = ntohs(*((short *)cptr));

    cptr += 26;                                        /* index to sendMode in the OpenContinueData */
    *cptr = 0;                                         /* not capable of sending video              */

    cptr += 2;                                         /* index to flags in the OpenCOntinueData    */
    *cptr &= ~AUDIO_CAPABLE;                           /* indicate not audio capable          */


    /*
       figure out if there is an AUX Data advertisement field in this OCP, if so clear out
       the count, so that no one will as for this client's AUX Data.
    */

    size = HEADERLEN + OCDLEN + (cnt * CILEN);

    if (size == ntohs(vidptr->len))
       return;

    oceh = (OCExtraHeader *) ((char *) vidptr + size);
    if (oceh->dataType != kAuxTMAdvExtraType)
       return;

    tptr = (TMapHeader *) ((char *) oceh + sizeof(OCExtraHeader));

    tptr->count = 0;
}
