/*
 * This file implements session managed objects of the RTP-MIB module.
 * $Id: rtp-mib-session.c 8676 2008-01-17 23:11:17Z ispringer $
 */
/* General includes */
#include <sys/types.h>

/* Apache includes */
#ifdef WIN32
/* Apache includes */
#include <httpd.h>
#include <http_log.h>
#include <apr_hash.h>
#include <apr_optional.h>
#endif

/* SNMP includes */
#include <ucd-snmp-config.h>
#include <asn1.h>
#include <snmp.h>
#include <snmp_api.h>
#include <snmp_impl.h>
#include <snmp_debug.h>
#include <snmp_vars.h>
#include <var_struct.h>

#include "covalent-snmp-config.h"
#include "rtp-mib.h"

#ifndef SNMP_MIN
#define SNMP_MIN(a,b)   (((a)<(b)) ? (a) : (b))
#endif

#define NEXT    FALSE
#define EXACT   TRUE
#define INDEX   2

#define RTPSESSIONNEWINDEX               1

#define RTPSESSIONINVERSESTARTTIME       1

#define RTPSESSIONDOMAIN                 2
#define RTPSESSIONREMADDR                3
#define RTPSESSIONLOCADDR                4
#define RTPSESSIONIFINDEX                5
#define RTPSESSIONSENDERJOINS            6
#define RTPSESSIONRECEIVERJOINS          7
#define RTPSESSIONBYES                   8
#define RTPSESSIONSTARTTIME              9
#define RTPSESSIONMONITOR                10
#define RTPSESSIONROWSTATUS              11

#ifdef RTP_SESSION_GROUP

static unsigned int session_new_index = 0;
rtp_session_info_t *top_session;

static int
write_rtpSessionNewIndex(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
long temp;

    if (var_val_type != ASN_INTEGER){
        DEBUGMSGTL(("rtp-mib","write to rtpSessionNewIndex not ASN_INTEGER\n"));
        return SNMP_ERR_WRONGTYPE;
    }
    if (var_val_len > sizeof(temp)){
        DEBUGMSGTL(("rtp-mib","write to rtpSessionNewIndex: bad length\n"));
        return SNMP_ERR_WRONGLENGTH;
    }
    temp = *((long *) var_val);
    if (temp != (long)session_new_index)
          return SNMP_ERR_INCONSISTENTVALUE;
    if (action == COMMIT) {
        if (session_new_index == 2147483647) {
          session_new_index = 0;
        } else {
          session_new_index++;
        }
    }
    return SNMP_ERR_NOERROR;
}

static unsigned char *
read_rtpMIBObjects(struct variable *vp,
    oid *name, size_t *length,
    int exact, size_t *var_len, WriteMethod **write_method)
{
int result;

    result = snmp_oid_compare(name, *length, vp->name, vp->namelen);
    if ((exact && (result != 0)) || (!exact && (result >= 0)))
        return(NULL);
    memcpy( (char *)name,(char *)vp->name, vp->namelen * sizeof(oid));
    *length = vp->namelen;

    *write_method = write_rtpSessionNewIndex;
    *var_len = sizeof(long_return);    /* default to 'long' results */
    switch (vp->magic) {
    case RTPSESSIONNEWINDEX:
        long_return = session_new_index;
        return (unsigned char *) &long_return;
    default:
         ERROR_MSG("");
    }
    return NULL;
}

static int
write_rtpSessionDomain(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOERROR;
}

static int
write_rtpSessionRemAddr(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOERROR;
}

static int
write_rtpSessionIfIndex(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOERROR;
}

static int
write_rtpSessionRowStatus(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOERROR;
}

rtp_session_info_t *
get_rtp_session_inverse_entry_index(int exact,
        oid *name, size_t *namelength,
        oid *newname, size_t *newname_length,
        rtp_session_info_t *session)
{
size_t  len = *newname_length;
int i;
int result;

    while (session) {
        len = *newname_length;

        /* Compute the rtpSessionDomain index portion */
        newname[ *newname_length++ ] = session->rtpSessionDomainLength;
        for( i = 0 ; i < session->rtpSessionDomainLength ; i++ )
                newname[ *newname_length++ ] = session->rtpSessionDomain[ i ];

        /* Compute the rtpSessionRemAddr index portion */
        newname[ *newname_length++ ] = 6;
        newname[ *newname_length++ ] = session->rtpSessionRemAddr[0];
        newname[ *newname_length++ ] = session->rtpSessionRemAddr[1];
        newname[ *newname_length++ ] = session->rtpSessionRemAddr[2];
        newname[ *newname_length++ ] = session->rtpSessionRemAddr[3];
        newname[ *newname_length++ ] = (session->rtpSessionRemAddrPort / 256);
        newname[ *newname_length++ ] = (session->rtpSessionRemAddrPort % 256);

        /* Compute the rtpSessionLocAddr index portion */
        newname[ *newname_length++ ] = 6;
        newname[ *newname_length++ ] = session->rtpSessionLocAddr[0];
        newname[ *newname_length++ ] = session->rtpSessionLocAddr[1];
        newname[ *newname_length++ ] = session->rtpSessionLocAddr[2];
        newname[ *newname_length++ ] = session->rtpSessionLocAddr[3];
        newname[ *newname_length++ ] = (session->rtpSessionLocAddrPort / 256);
        newname[ *newname_length++ ] = (session->rtpSessionLocAddrPort % 256);

        /* Compute the rtpSessionIndex index portion */
        newname[ *newname_length++ ] = session->rtpSessionIndex;

        result = snmp_oid_compare(name, *namelength, newname, *newname_length);
        if (((exact == NEXT) && (0 > result)) || 
            ((exact == EXACT) && (0 == result))) {
            return(session);
        }
        session = session->next_in_rtpSessionInverseTable;
    }
    return(NULL);
}

static unsigned char *
read_rtpSessionInverseEntry(struct variable *vp,
    oid *name, size_t *length,
    int exact, size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newname_length;
rtp_session_info_t *session;

    session = get_rtp_session_inverse_entry_index(exact,
                                    name, length, newname, &newname_length, top_session);
    if (session) {
        session = session->next_in_rtpSenderInverseTable;
    }

    *length = newname_length;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *write_method = 0;
    *var_len = sizeof(long);

    switch (vp->magic) {
    case RTPSESSIONINVERSESTARTTIME:
        return (unsigned char *) NULL;
    default:
         ERROR_MSG("");
    }
    return NULL;
}

rtp_session_info_t *
get_rtp_session_entry_index(int exact,
        oid *name, size_t *namelength,
        oid *newname, size_t *newname_length,
        rtp_session_info_t *session)
{
int result;
oid *ptr;

    ptr = &(newname[ (*newname_length)++ ]);
    while (session) {
        /* Compute the rtpSessionIndex index portion */
        *ptr = session->rtpSessionIndex;
        result = snmp_oid_compare(name, *namelength, newname, *newname_length);
        if (((exact == NEXT) && (0 > result)) ||
            ((exact == EXACT) && (0 == result))) {
            return(session);
        }
        session = session->next_in_rtpSessionTable;
    }
    return(NULL);
}

static unsigned char *
read_rtpSessionEntry(struct variable *vp,
    oid *name, size_t *length,
    int exact, size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newname_length;
rtp_session_info_t *session;

    newname_length = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, newname_length * sizeof(oid));
    session = get_rtp_session_entry_index(exact,
                                name, length, newname, &newname_length, top_session);
    if (!session) {
        return(NULL);
    }

    switch (vp->magic) {
    case RTPSESSIONDOMAIN:
        return (unsigned char *) NULL;
    case RTPSESSIONREMADDR:
        return (unsigned char *) NULL;
    case RTPSESSIONLOCADDR:
        return (unsigned char *) NULL;
    case RTPSESSIONIFINDEX:
        return (unsigned char *) NULL;
    case RTPSESSIONSENDERJOINS:
        return (unsigned char *) NULL;
    case RTPSESSIONRECEIVERJOINS:
        return (unsigned char *) NULL;
    case RTPSESSIONBYES:
        return (unsigned char *) NULL;
    case RTPSESSIONSTARTTIME:
        return (unsigned char *) NULL;
    case RTPSESSIONMONITOR:
        return (unsigned char *) NULL;
    case RTPSESSIONROWSTATUS:
        return (unsigned char *) NULL;
    default:
         ERROR_MSG("");
    }
    return NULL;
}


static oid rtpMIBObjects_oid[] = {1, 3, 6, 1, 2, 1, 87, 1};
struct variable2 rtpMIBObjects_variables[] = {
    { RTPSESSIONNEWINDEX, ASN_INTEGER, RWRITE, read_rtpMIBObjects, 2, {1, 0} },
};

static oid rtpSessionInverseEntry_oid[] = {1, 3, 6, 1, 2, 1, 87, 1, 2, 1};
struct variable2 rtpSessionInverseEntry_variables[] = {
    { RTPSESSIONINVERSESTARTTIME, ASN_INTEGER, RONLY, read_rtpSessionInverseEntry, 1, {1} },
};

static oid rtpSessionEntry_oid[] = {1, 3, 6, 1, 2, 1, 87, 1, 3, 1};
struct variable2 rtpSessionEntry_variables[] = {
    { RTPSESSIONDOMAIN, ASN_OBJECT_ID, RWRITE, read_rtpSessionEntry, 1, {2} },
    { RTPSESSIONREMADDR, ASN_OCTET_STR, RWRITE, read_rtpSessionEntry, 1, {3} },
    { RTPSESSIONLOCADDR, ASN_OCTET_STR, RONLY, read_rtpSessionEntry, 1, {4} },
    { RTPSESSIONIFINDEX, ASN_INTEGER, RWRITE, read_rtpSessionEntry, 1, {5} },
    { RTPSESSIONSENDERJOINS, ASN_INTEGER, RONLY, read_rtpSessionEntry, 1, {6} },
    { RTPSESSIONRECEIVERJOINS, ASN_INTEGER, RONLY, read_rtpSessionEntry, 1, {7} },
    { RTPSESSIONBYES, ASN_INTEGER, RONLY, read_rtpSessionEntry, 1, {8} },
    { RTPSESSIONSTARTTIME, ASN_INTEGER, RONLY, read_rtpSessionEntry, 1, {9} },
    { RTPSESSIONMONITOR, ASN_INTEGER, RONLY, read_rtpSessionEntry, 1, {10} },
    { RTPSESSIONROWSTATUS, ASN_INTEGER, RWRITE, read_rtpSessionEntry, 1, {11} },
};

void init_rtp_session_group(void)
{
    REGISTER_MIB("rtpMIBObjects", rtpMIBObjects_variables,
         variable2, rtpMIBObjects_oid);
    REGISTER_MIB("rtpSessionInverseEntry", rtpSessionInverseEntry_variables,
         variable2, rtpSessionInverseEntry_oid);
    REGISTER_MIB("rtpSessionEntry", rtpSessionEntry_variables,
         variable2, rtpSessionEntry_oid);
}

#endif /* RTP_SESSION_GROUP */
