/*

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 <sys/time.h>

/* address families */

#define kGroup				0
#define kClient				1
#define kReflector			2

/* data types */
#define kMinVideoDataType		1
#define kHalfSizeVideoType		1
#define kFullSizeVideoType		2
#define kMaxVideoDataType		2
#define kAudio				3

#define kAuxDataTypeSupervisor          256
#define kAuxDataTypeData                257

#define kControlType			100
#define kConfigVideoType		101
#define kPacketLossReport		102
#define kAckType			103
#define kMessageType1                   104
#define kMessageType2                   105
#define kConfigRefType		        106

/* video control messages */
#define kNoMessage			0
	
#define kOpenConnection			1
#define kStartVideo			2
#define kModifyVideo			3
#define kRefuseVideo			4
#define kStopVideo			5
#define kCloseConnection		6


#define kBCCOpen                        100
#define kREFOpen                        101


#define kGotOpen		-kOpenConnection
#define kGotStart		-kStartVideo
#define kGotModify		-kModifyVideo
#define kGotRefuse		-kRefuseVideo
#define kGotStop		-kStopVideo
#define kGotClose		-kCloseConnection

#define kContinueConnection		12
#define kSuspendMessage			13

#define kFrameEndMessage		20


/* connect mode */
#define kInternal			-1
#define kNoConnection			0
#define kWaitingForOpenAck		1
#define kWaitingForClientAck		2
#define kSuspended			3
#define kConnected			4

/* send/receive mode */
#define kNoVideoSource			-1
#define kNoSize				0
#define kHalfSize			1
#define kFullSize			2
#define kDefaultSize			100

/* copy mode */
#define kAsIs				0
#define kHalf				1
#define kDouble				2

/* grab frame mode */
#define kNoFrames			0
#define kGrab1Frame			1
#define kGrab2Frames			2

#define VERSION_STRING	               "3.00B3"
#define VERSION_NUM                     2
#define LOGFILE                         "reflect.log"
#define CONFIGFILE			"reflect.conf"
#define DENY_ACCESS			"You are not currently permitted access to this reflector."
#define MAX_CL                          "Sorry, maximum number of users exceeded."
#define CFD                             "Sorry, the Conference ID has changed.  Please reconnect with the correct one."
#define CAPMSG                          "Please lower you cap to 80kbits."
#define MLMSG                           "Maximum # of lurkers exceeded - try again later."
#define MSMSG                           "Maximum # of senders exceeded - try again later."


#define VID_PORT 			7648
#define CONTROL_PORT 			7649   
#define NV_PORT 			7650   
#define RF_PORT 			7651   


#define MAXMSG 				2048
#define MAXCLIENT 			40
#define DEFMAXCLIENT 			20
#define MAXSRCREF  			20 
#define MAXNVSTREAMS                    8

#define CONFBUF                         2000
#define MOTDBUF                         800
#define MSGBUF                          80

#define VIDEO 				1
#define CONTROL 			2
#define REF1VIDEO 			3
#define REF2VIDEO 			4
#define MAVEN				5
#define MAVEN_CNTL			6

#define VAT                             7
#define VAT_CNTL                        8
#define NV_MCAST                        9
#define NV_UCAST                        10

#define ACKOPEN 			3
#define TIMEOUT 			15 
#define KALIVE 			        2 
#define TRATE 			        10 
#define HRATE 			        60 
#define NV_SDESC_TIMER                  5
#define NV_OCP_TIMER                    5
#define VAT_SPEAKER_INTERVAL            300


#define MHEADERLEN                      8
#define NVVERSION                       0x40
#define NVCONTENT                       27
#define SSRCLEN                         8
#define NVOBIT                          0x80
#define NVSBIT                          0x40
#define SDESC                           33
#define FINAL                           0x80
#define SSRC                            1
#define NV_CHAN                         32
#define RTP_EPOCH_OFFSET                ((unsigned long) 2208988800)
#define NV_CLIENT_VERS                  20

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif


typedef struct PacketLossData 
{
    unsigned short  packetsSent;
    unsigned short  packetsRecv;
} PacketLossData;


typedef struct addr
{
    short           family;        
    unsigned short  port;
    unsigned long   addr;
} addr;

typedef struct Routing {
    addr            dest;
    addr            src;
} Routing;

typedef struct VideoPacketHeader {
    Routing         routing;           /* 16 byte socket header for exploder */
    unsigned long   seqNum;
    short           message;
    short           dataType;
    short           len;
} VideoPacketHeader;

#define HEADERLEN 26

#define conferenceid routing.dest.port

typedef struct OpenContinueData 
{
        short			clientCount;
        unsigned long		seqNum;
        char			name[20];
        unsigned char		sendMode;
        unsigned char		recvMode;
        unsigned char		flags;
        unsigned char		version;
/*  
	ClientInfo		clients[clientCount] 
*/
} OpenContinueData;

#define OCDLEN 30

#define REC_AUDIO		0x01
#define AUDIO_CAPABLE		0x02
#define WANT_LURCKERS		0x04
#define PC_CLIENT		0x08
#define PRIVATE_AUDIO           0x10
#define WANT_VERSION            0x20

#define VERSION1                1
#define VERSION5                5

typedef struct ClientInfo 
{
        unsigned long		clientIP;
        char			flags;
        char			aux;
        char			IWillRecv;
        char			IWillSend;
        PacketLossData		loss;
} ClientInfo;

#define CILEN 12

#define UPDATE_VIDEO    0x01
#define UPDATE_AUDIO    0x02
#define IWillRecAudio   0x04
#define UPDATE_AUXDATA  0x08

typedef struct OpenContinuePacket 
{
        VideoPacketHeader	header;
        OpenContinueData	config;
} OpenContinuePacket;

typedef struct ControlPacket 
{
    VideoPacketHeader   header;
} ControlPacket;

typedef struct slist
{
   struct   slist    *snd_nptr;
   struct   client   *snd_client;
   unsigned long     snd_auxmask;
} slist;

typedef struct client 
{
    struct client     *clnt_nptr;           /* next client                                        */
    struct client     *clnt_pptr;           /* ptr to REF3_SOURCE if this client is a REF3_ORIGIN */
    addr              clnt_addr;            /* client's address                                   */
    slist             *clnt_vlist;          /* list of clients receiving video                    */
    slist             *clnt_alist;          /* list of clients receiving audio                    */
    slist             *clnt_xlist;          /* list of clients receiving aux data                 */
    short             clnt_rtimer;          /* client's recieve timer                             */
    short             clnt_stimer;          /* client's send timer                                */
    short             clnt_ntimer;	    /* timer for sending OCP for nv clients               */
    short             clnt_id;		    /* client's id                                        */	
    short             clnt_talker;          /* cnt of audio pkts rec'ed - used for logging current speaker  */
    short             clnt_caploop;         /* # of times through the timer loop before calculating CAP     */
    short             clnt_hdloop;          /* # of times through the timer loop before deleting hold downs */
    unsigned short    clnt_conf_id;         /* conference id the client connected with            */
    unsigned long     clnt_flags;           /* flags                                              */
    unsigned long     clnt_bytecnt;         /* byte count for video packets                       */
    unsigned long     clnt_sdesc_time;      /* timestamp of last SDESC option transmitted         */
    unsigned long     clnt_seq;             /* OCP seq # to send for nv clients                   */
    unsigned long     clnt_ocp_cnt;         /* # of OCP sent on behalf of this client             */
    struct timeval    clnt_tp;              /* time value used in calculating the byte cnt        */
    OpenContinueData  clnt_config;          /* client's configuration                             */
} client;

#define CLIENT        0x00000001            /* normal Mac/PC client                                       */
 
#define BCC_CLIENT    0x00000002            /* another reflector serving as a BCC client                  */
#define BCC_ORIGIN    0x00000004            /* this client originates from a BCC server reflector         */
#define BCC_SERVER    0x00000008            /* another reflector serving as a BCC server                  */

#define REF1_SERVER   0x00000010            /* another reflector serving as a multicast source            */
#define REF1_ORIGIN   0x00000020            /* this client originates from multicast source reflector (one way)    */
#define REF1_CLIENT   0x00000040            /* another reflector serving as a multicast recipient         */


#define REF2_SERVER   0x00000080            /* another reflector participating in a 2way mcast            */
#define REF2_ORIGIN   0x00000100            /* this client originates from multicast group  reflector (two way)    */

#define HOLD_DOWN     0x00000200            /* this client is being held down                             */
#define DELETE        0x00000400            /* this client is deleted                                     */

#define REF3_SERVER   0x00000800            /* another reflector participating in a 2way ucast            */
#define REF3_ORIGIN   0x00001000            /* this client originates from unicat group reflector (two way)    */

#define NV_UCLIENT    0x00002000            /* this is an NV unicast client                               */
#define NV_MCLIENT    0x00004000            /* this is an NV multicast client                             */

#define BCC_GCLIENT   0x00008000            /* general bcc client                                         */

typedef struct 
{
   unsigned long site_id;
   char     id_string[1];                   
}  SiteId;

/* 
   list to keep track of how long since each member of a vat mixer stream
   last spoke.  The SiteId pointer points into the idlist of the maven client
   which represents this vat-mixer.  The how_long field is a measure of how
   many CTRL_TYPE_IDLIST messages the mixer has sent since the associated member
   last spoke.  
*/

typedef struct VatMixerSpeaker 
{
   struct VatMixerSpeaker *next;
   short spoke;                                /* tick count when this client last spoke */
   SiteId *who;
} VatMixerSpeaker;

#define MAX_MAVEN_NAME_LEN 40

typedef struct vat_client 
{
    struct vat_client     *mvn_nptr;           /* next client               */
    struct vat_client     *mvn_pptr;           /* ptr to parent maven client if this is a mixer's client */
    addr                  mvn_addr;            /* client's address          */
    unsigned long         mvn_flags;           /* flags                                              */

    unsigned long         mvn_seq;             /* sequence #                */
    unsigned long         mvn_ocp_seq;         /* sequence # for OCP        */
    unsigned long         mvn_spoke;           /* tick count when this client last spoke */

    short                 mvn_rtimer;          /* client's recieve timer    */
    short                 mvn_talker;          /* cnt of audio pkts rec'ed - used for logging current speaker */

    char                  mvn_recv_type;       /* MCAST or UCAST */
    char                  mvn_name[MAX_MAVEN_NAME_LEN];            /* client's name  */

    struct IDMsgHdr       *mvn_idlist;         /* If this maven/vat client is a mixer and is sending
                                                  CTRL_TYPE_IDLIST messages, then this is a pointer
                                                  to the most up to date such message it has
                                                  sent.  Otherwise NULL.  Note that often it is
                                                  not a mixer but another reflector... but that
                                                  is indistinguishable from our standpoint. */
    int                   mvn_idlist_len;      /* the length of the above-mentioned idlist  */

} vat_client;

/* definitions for flags                                            */
#define VAT_CLIENT         0x00000001      
#define VAT_MIXER          0x00000002       
#define VAT_MIXER_CLIENT   0x00000004        

#define SPEAK_OCP     60                      /* 
                                                  if a maven client hasn't spoken for the last SPEAK_TIMEOUT seconds  
                                                  then stop sending OCP on behalf of it to CUSM clients 
                                               */
#define MCAST 0
#define UCAST 1

struct CtrlMsgHdr 
{
        unsigned char flags;
        unsigned char type;
        unsigned short confid;
        char idmsg[1];
};

#define CTRLMSGSIZE (4)

#define CTRL_TYPE_ID 1
#define CTRL_TYPE_DONE 2
#define CTRL_TYPE_IDLIST 3

/* 
   the following structures have been added for the construction of
   vat CTRL_TYPE_IDLIST message generation  
*/

struct IDMsgHdr 
{
  unsigned char flags;
  unsigned char type;
  unsigned short confid;
  unsigned char nsids;
  unsigned char ainfo;
  unsigned short blksize;
};

typedef struct 
{
   unsigned char nsid;
   unsigned char flags;
   unsigned short confid;
   unsigned long ts;
}  vat_hdr_t;

#define NSID_MASK      0x3f
#define VATHF_NEWTS    0x80
#define VATHF_FMTMASK  0x1f;

typedef struct nv_client
{
   struct nv_client *nv_nptr;          /* pointer to next nv_client in the list                     */
   addr             nv_addr;           /* address of this client                                    */
   slist            *nv_vlist;         /* list of CUSM clients receiving this NV's video            */
   unsigned long    nv_flags;          /* flags                                                     */
   short            nv_rtimer;         /* client's receive timer                                    */
   short            nv_hdloop;         /* # of times through the timer loop before deleting hold downs */
} nv_client;

#define UNICAST_NV        0x0001       /* this nv is coming in via unicast                          */
#define MULTICAST_NV      0x0002       /* this nv is coming in via multicast                        */

typedef struct AuxDataHeader
{
	char          adhVersion;
	char          adhHeaderLenght;
	char          adhOpcode;
	char          adhPriority;
	unsigned long adhPrune;
	char          adhStatus;
	char          adhUNUSED1;
	short         adhSegmentLength;
	long          adhType;
	long          adhItemNumber;
	long          adhItemID;
	long          adhItemLength;
	long          adhSegmentOffset;
} AuxDataHeader;

/* this is used to identify chunks of data that are tacked onto the end of OC packet's */

typedef struct
{
	short dataType;
	short bytes;
} OCExtraHeader;

#define kAuxTMAdvExtraType 1


typedef struct
{
	short count;
	short seqNum;
} TMapHeader;
