/*********************************************************
*                                                        *
*                  Get Session                           *
*                                                        *
*   This procedure handles the allocation of half-       *
*   session which will be used for conversation.         *
*                                                        *
*   INPUT :  GET_SESSION record.                         *
*   OUTPUT:  SESSION_ALLOCATED record.                   *
*                                                        *
 *                                                       *
 * CopyRight 1995. Nicholas Poljakov all rights reserved.*
 *                                                       *
*********************************************************/
#include <state1.h>
#include <stdio.h>
#include <session.h>
#include <lucb.h>
#include <tcb.h>
#include <rcb.h>
#include <scb.h>
#include <rpl.h>
#include <nib.h>
#include <common.h>
#include <malloc.h>
#include <repass.h>
#include <string.h>
#include <drcb.h>
#if OS_TYPE == 1
#include <memory.h>
#endif
int sk_r_wt(void *);
int SendBlock(void *, void *);
int setrc(void *, void *);
int sendhsf(void *);
int sendhs(void *);
int sendbm(void *, void *);
int sendat(void *);
int rtsend(void *);
unsigned long rmfmh5(void *, void *);
int recwait(void *);
int rcvru(void *, void *);
int rcvhs(void *, void *, void *, void *);
int ralloc(void *, void *);
int psrm(int, void *, void *);
int ps_conv(int, void *);
int proterr(void *, unsigned long);
int preptrcv(void *, void *);
int post_rcb(void *);
struct repass *postopen(void *);
int phsrec(void *);
int pfmh5(void *);
int opndst(void *);
int obtsess(void *, unsigned char);
int Lrf_handler(void *);
int get_attr(void *);
int fsm_error(unsigned char, void *);
int fsm_conv(unsigned char, unsigned char, void *);
int flush (void *);
int dcp(void *);
int dealloc(void *);
int crtp(void *);
int conv(void *);
int chkparm(void *, void *);
int check_end(unsigned int, void *);
struct rqb *call_appl(void *);
int buffmng(unsigned char, void *, void *, void *, unsigned, unsigned char, unsigned);
unsigned long attltck(void *);
unsigned long attacheck(void *);
char *cgetmem(int, int);
int sendhsf(void *);
int opndst(void *);
int alloc_rcb(void *, void *);
int allocate(void *);
int clsdst(void *);

get_sess(in, out)
char *in;
char *out;
{
    struct gets *p_gets;
    struct sessa *p_sessa;
    struct tcb *p_tcb;
    struct rcb *p_rcb;
    struct lucb *p_lucb;
    struct scb *p_scb;
    struct scb *temp;
    struct scb *temp1;
    struct rpl *p_rpl;
    struct nib *p_nib;
    struct repass *p_rep;
    struct com *p_com;
    struct drcb d_rcb;
    char *pr;
    unsigned long crl;
    char *p;
    int i;

#if OS_TYPE == 1
/*********  Trace facility **********/
unsigned int rtype;   /* type of record */
unsigned int pnum;    /* point number */
char pname[8];        /* name of module */
char *drec;       /* record for dump */
int  lenr;            /* record length */

rtype = INPROC;
strcpy(pname, "getsess");
pnum = 1;
drec = NULL;
lenr = 0;
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

    p_gets = (struct gets *)in;
    p_sessa = (struct sessa *)out;
    p_tcb = p_gets -> p_tcb;
    p_rcb = p_gets -> p_rcb;
    p_lucb = p_tcb -> p_lucb;

/*
 * Serching for the SCB for the LU_NAME specified in the RCB associating with
 * this request.
 */
    temp = p_lucb -> scb_list;
    temp1 = temp;
    if (temp == NULL) {
        goto All_scb;
    }
    while (temp != NULL) {
        if (memcmp(temp -> lu_name, p_rcb -> lu_name, 8) != 0) {
            goto Next_scb;
        }
        break;
        Next_scb: temp1 = temp;
                  temp = temp -> next;
    }
    if (temp == NULL) {
        goto All_scb;
    }
    switch (temp -> use) {
        case IN_USE :
                      {
                        p_sessa -> rc = UNSUC_RETRY;
                        p_sessa -> p_scb = NULL;
			d_rcb.p_rcb = p_rcb;
			d_rcb.p_tcb = p_tcb;
                        psrm(DEALLOCATE_RCB, &d_rcb, 0);
			return 0;
                      }
        case FREE :
                      {
                        p_sessa -> rc = OK;
                        p_sessa -> p_scb = temp;
                        p_rcb -> p_scb = temp;
                        temp -> use = IN_USE;
                        temp -> p_rcb = p_rcb;
                        p_com = p_rcb -> verb_ptr;
                        p_rpl = temp -> p_rpl;
                        p_rcb -> sess_corl = p_rpl -> arg;
                        /*
                        if ((i = sendhs(p_rcb)) == OK) {
                            p_com -> prim_rc = OK;
                        }
                        else
                                p_com -> prim_rc = ALLOCATION_FAILURE_RETRY;
                        */
                        p_com -> prim_rc = OK;
			return 0;
                      }
     }
     All_scb:
             if (p_lucb -> cur_sess < p_lucb -> lu_session_limit) {
                p_lucb -> cur_sess++;
             }
             else
                    {
                        if (freesess(p_lucb) == -1) {
                            p_sessa -> rc = UNSUC_RETRY;
                            p_sessa -> p_scb = NULL;
			    return 0;
                        }
                        else
                                {
                                    p_lucb -> cur_sess++;
                                }
                    }
             /* Allocate new SCB */
             if ((p_scb = malloc(sizeof(struct scb))) == NULL) {
                  p_sessa -> rc = UNSUC_RETRY;
                  p_sessa -> p_scb = NULL;
		  return 0;
             }
             /*
              * Allocate RPL
              */
             if ((p_rpl = malloc(sizeof(struct rpl))) == NULL) {
                  p_sessa -> rc = UNSUC_RETRY;
                  p_sessa -> p_scb = NULL;
		  return 0;
             }
             i = 0;
             memset(p_rpl, i, sizeof(struct rpl));
             /*
              * Allocate NIB
              */
             if ((p_nib = malloc(sizeof(struct nib))) == NULL) {
                  p_sessa -> rc = UNSUC_RETRY;
                  p_sessa -> p_scb = NULL;
		  return 0;
             }
             i = 0;
             memset(p_nib, i, sizeof(struct nib));
             p_scb -> p_rpl = p_rpl;
             p_scb -> p_rcb = p_rcb;
             p_rcb -> p_scb = p_scb;
             p_scb -> use = IN_USE;
             p_scb -> random_data = NULL;
             p_scb -> next = NULL;
             for (i = 0; i < 8; i++) {
                p_nib -> sym[i] = p_rcb -> lu_name[i];
                p_nib -> mode[i] = p_lucb -> lu_name[i];
                p_scb -> lu_name[i] = p_rcb -> lu_name[i];
                p_scb -> mode_name[i] = p_rcb -> mode_name[i];
             }
             if (temp1 == NULL) {
                p_lucb -> scb_list = p_scb;
                p_scb -> prev = NULL;
             }
             else
                    {
                        temp1 -> next = p_scb;
                        p_scb -> prev = temp1;
                    }
             /*
              * Set fields in RPL, NIB and issue OPNDST
              */
             p_rpl -> arg = p_nib;
             p_rpl -> p_nib = p_nib;
             p_rpl -> acb = p_lucb -> p_acb;
             p_rpl -> rsrv3 = 0; /* primary LU */
           /* Set correlator in RCB and NIB.user */
             pr = p_rpl;
             crl = pr;
             p = &crl;
             p_rcb -> sess_corl = crl;
             for (i = 0; i < 4; i++) {
                p_nib -> user[i] = p[i];
             }
             p_sessa -> p_scb = p_scb;
             p_rep = p_rcb -> verb_ptr;
             p_rep -> p_rcb = p_rcb;

#if OS_TYPE == 1
/*********  Trace facility **********/
rtype = GREC;
strcpy(pname, "getsess");
pnum = 2;
drec = p_nib;
lenr = sizeof(struct nib);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

             if (opndst(p_rpl) != OK) {
                p_sessa -> rc = UNSUC_NO_RETRY;
             }
             else
                    {
                       p_sessa -> rc = OK;
                       p_rep -> complete = 1; /* req. to retry */
                    }
             free(p_nib);
             p_rpl -> p_nib = NULL;
             return (0);
}
/*
 * "Freesess" function closes unused sessions and removs the
 * corresponded SCB from the SCB chain.
 */
freesess(p_lucb)
struct lucb *p_lucb;
{
    struct scb *p_scb;
    struct scb *temp;
    struct scb *temp1;
    struct rpl *p_rpl;
    struct nib *p_nib;
    unsigned cnt;

#if OS_TYPE == 1
/*********  Trace facility **********/
unsigned int rtype;   /* type of record */
unsigned int pnum;    /* point number */
char pname[8];        /* name of module */
char *drec;           /* record for dump */
int  lenr;            /* record length */

rtype = INPROC;
strcpy(pname, "freeses");
pnum = 1;
drec = p_lucb;
lenr = sizeof(struct lucb);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

    cnt = p_lucb -> cur_sess;
    p_scb = p_lucb -> scb_list;

    while (p_scb != NULL) {
       if (p_scb -> use == FREE) {
          p_rpl = p_scb -> p_rpl;
          clsdst(p_rpl);
        /* remove SCB from chain */
          temp = p_scb -> prev;
          temp1 = p_scb -> next;
          if (temp == NULL) {
                p_lucb -> scb_list = temp1;
          }
          else
                temp -> next = temp1;
          if (temp1 != NULL)
                temp1 -> prev = temp;
          p_nib = p_rpl -> p_nib;
          free(p_rpl);
          if (p_nib != NULL) {
             free(p_nib);
          }
          free(p_scb);
          p_lucb -> cur_sess--;
       }
       p_scb = p_scb -> next;
    }
    if (cnt == p_lucb -> cur_sess) {
        return(-1); /* No SCB freed */
    }
    return(0);
}
