/*
                   CONFIRM

 Function: handle the "confirm" verb processing.
 Input: pointer to "confirm" structure.

 CopyRight 1995. Nicholas Poljakov all rights reserved.

 */


#include <stdio.h>
#include <conf.h>
#include <state1.h>
#include <rcb.h>
#include <tcb.h>
#include <lucb.h>
#include <cma.h>
#include <psp.h>
#include <repass.h>
#include <prefix.h>
#include <string.h>
#include <malloc.h>

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 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_sess(void *, 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 *);

confirm(pptr)
struct confirm *pptr;
{
extern struct psp psp_ini;
struct rcb *p_rcb;
struct repass *p_rep;
struct tcb *ptr_tcb;
struct lucb *ptr_lucb;
struct prefix *p_prf;
struct prefix *t_prf;
struct cma ar;
unsigned char type;
char *p;
char *pl;
char p1;

int code;
int state;

#if OS_TYPE == 1 /* Unix System V */
/*********  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, "conf");
pnum = 1;
drec = pptr;
lenr = sizeof(struct confirm);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

       if (chkparm(pptr, &ar) == -1) {
          return(0);
       }
       p_rcb = ar.p_rcb;
       ptr_tcb = ar.p_tcb;

       p_rep = (struct repass *)pptr;

       if (p_rep -> complete == 1) {
             goto WaitCfd;
       }

    /*   в  RCB  заносим код примитива  */
       p_rcb ->verb_code = pptr -> code;
       p_rcb -> verb_ptr = (char *)pptr;

       pptr -> rts = No;
       pptr -> prim_rc = 0;
       pptr -> sec_rc = 0;

       if ((state = fsm_conv('s', Confirm, p_rcb)) == -1)
            {
                pptr -> prim_rc = PORT_ABENDED;
		return 0;
            }
       if (state == 1)
            {
                pptr -> prim_rc = PORT_ABENDED;
		return 0;
            }
       else
           {
               switch (p_rcb->error_state)   {

                 case CONV_FAILURE_PROTOCOL_ERROR:
                      {
                        pptr->prim_rc = RESOURCE_FAILURE_NO_RETRY;
                        fsm_conv('r',RESOURCE_FAILURE_RC,p_rcb);
                        break;
                      }
                 case CONV_FAILURE_SON:
                      {
                         pptr->prim_rc=RESOURCE_FAILURE_RETRY;
                         fsm_conv('r',RESOURCE_FAILURE_RC,p_rcb);
                         break;
                      }
                 case ALLOCATE_FAILURE_RETRY:
                 case ALLOCATE_FAILURE_NO_RETRY:
                 case SYNC_LEVEL_NOT_SUPPORTED:
                      {
                         pptr->prim_rc = ALLOCATION_ERROR;
                         if(p_rcb->error_state == ALLOCATION_FAILURE_RETRY)
                         pptr->sec_rc = ALLOCATION_FAILURE_RETRY;
                         if(p_rcb->error_state == ALLOCATION_FAILURE_NO_RETRY)
                            {
                               pptr->sec_rc = ALLOCATION_FAILURE_NO_RETRY;
                            }
                         else
                            {
                               pptr->sec_rc = SYNC_LEVEL_NOT_SUPPORTED_BY_LU;
                            }
                         fsm_conv('r',ALLOCATION_ERROR_RC,p_rcb);
                         break;
                      }
                 case RCVD_ERROR:  break;   /* This will be correct later! */

                 case NO_RQS:  {
                        switch (p_rcb -> conv_state) {
				case SEND : type = Confirm;
                                            break;
                                case pend_deall : type = Deallocate_confirm;
                        }
                        buffmng('A', NULL, NULL, p_rcb, 0, 0, type);
                        sendhsf(p_rcb);
                 }
            }
     } /* else (for conv_state check ) */

     p_rep -> complete = 1; /* req. to retry */
     p_rep -> p_rcb = p_rcb;
     return (0);

WaitCfd:  /* Wait for the Confirmed verb from the Partner */

     /* Search for the last element in the input queue
      * and test if it's "Confirmed", if so
      * delete it and continue execution.
      */
     p_prf = p_rcb -> first_in;
     while (p_prf -> next != NULL) ;
     if ((p_prf -> type == COnfirmed) || (p_prf -> type == Request_to_send)) {

        /* Delete the element with "Confirmed" command
         * from the input queue.
         */
        t_prf = p_prf -> prev;
        free( p_prf );
        if (t_prf == NULL) {
           p_rcb -> first_in = NULL;
        }
        else
           t_prf -> next = NULL;

        if (p_prf -> type == Request_to_send) {
           pptr -> rts = YES;
           goto WaitCfd;
        }
     }
     else
           goto WaitCfd;

     if (p_rcb -> first_in == NULL) {
        p_rcb -> hsps = No;
     }
     p_rep -> complete = 0; /* Function completed */

     return 0;
}
