Net2/usr/src/contrib/isode/rosap/ro2ssinitiat.c

/* ro2ssinitiat.c - initiator */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/rosap/RCS/ro2ssinitiat.c,v 7.3 91/02/22 09:41:18 mrose Interim $";
#endif

/* 
 * $Header: /f/osi/rosap/RCS/ro2ssinitiat.c,v 7.3 91/02/22 09:41:18 mrose Interim $
 *
 * Based on an TCP-based implementation by George Michaelson of University
 * College London.
 *
 *
 * $Log:	ro2ssinitiat.c,v $
 * Revision 7.3  91/02/22  09:41:18  mrose
 * Interim 6.8
 * 
 * Revision 7.2  90/11/05  13:33:07  mrose
 * update
 * 
 * Revision 7.1  90/07/01  21:05:52  mrose
 * pepsy
 * 
 * Revision 6.1  89/06/24  00:55:54  mrose
 * reason
 * 
 * Revision 6.0  89/03/18  23:42:16  mrose
 * Release 5.0
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


/* LINTLIBRARY */

#include <stdio.h>
#include <signal.h>
#include "../acsap/OACS-types.h"
#include "ropkt.h"
#include "isoservent.h"
#include "tailor.h"

/*    RO-BEGIN.REQUEST */

int	RoBeginRequest (called, data, roc, roi)
struct RoSAPaddr *called;
PE	data;
struct RoSAPconnect *roc;
struct RoSAPindication *roi;
{
    SBV     smask;
    int     result;

    isodetailor (NULLCP, 0);

    missingP (called);
    missingP (roc);
    bzero ((char *) roc, sizeof *roc);
    missingP (roi);

    smask = sigioblock ();

    result = RoBeginRequestAux (called, data, roc, roi);

    (void) sigiomask (smask);

    return result;
}

/*  */

static int  RoBeginRequestAux (called, data, roc, roi)
struct RoSAPaddr *called;
PE	data;
struct RoSAPconnect *roc;
struct RoSAPindication *roi;
{
    int	    len,
	    result,
	    settings;
    char   *base;
#ifdef	notdef
    register struct isoservent *is;
#endif
    PE	pe;
    register struct assocblk *acb;
    struct SSAPref ref;
    struct SSAPconnect scs;
    register struct SSAPconnect *sc = &scs;
    struct SSAPindication sis;
    register struct SSAPindication *si = &sis;
    register struct SSAPabort *sa = &si -> si_abort;
    struct type_OACS_PConnect pcnnct;
    struct type_OACS_DataTransferSyntax dts;
    struct member_OACS_1 udata;
    struct type_OACS_ConnectionData condata;
    struct type_OACS_PAccept	*paccpt;
    struct type_OACS_PRefuse pref;

    if ((acb = newacblk ()) == NULL)
	return rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory");

    pcnnct.member_OACS_0 = &dts;
    dts.parm = int_OACS_DataTransferSyntax_x409;
    pcnnct.pUserData = &udata;
    udata.optionals = 0;
    udata.member_OACS_2 = &condata;
    condata.offset = type_OACS_ConnectionData_open;
    if (data)
	condata.un.open = data;
    else
	/* Seems to be needed to make the responder happy. */
	condata.un.open = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL);
    udata.applicationProtocol = (int) ntohs (called -> roa_port);
    if (encode_OACS_PConnect (&pe, 1, 0, NULLCP, &pcnnct) == NOTOK) {
no_mem: ;
	result = rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory");
	goto out1;
    }

    PLOGP (rosap_log,OACS_PConnect, pe, "PConnect", 0);

    if (pe2ssdu (pe, &base, &len) == NOTOK)
	goto no_mem;

    if (data)
	(void) pe_extract (pe, data), data = NULLPE;
    pe_free (pe);
    pe = NULLPE;

#ifdef	notdef		/* SEK doesn't like this */
    if (called -> roa_addr.sa_selectlen == 0) {
	if ((is = getisoserventbyname ("ros", "ssap")) == NULL) {
	    result = rosaplose (roi, ROS_ADDRESS, NULLCP,
			"ssap/ros: unknown entity");
	    goto out2;
	}
	if (is -> is_selectlen > SSSIZE) {	/* XXX */
	    result = rosaplose (roi, ROS_ADDRESS, NULLCP,
			"ssap/ros: selector too long (%d octets)",
			is -> is_selectlen);
	    goto out2;
	}
	bcopy (is -> is_selector, called -> roa_addr.sa_selector,
	    called -> roa_addr.sa_selectlen = is -> is_selectlen);
    }
#endif

    acb -> acb_requirements = SR_BCSUBSET;
    settings = 0;
#define dotoken(requires,shift,bit,type) \
{ \
    if (acb -> acb_requirements & requires) \
	settings |= ST_INIT_VALUE << shift; \
}
    dotokens ();
#undef	dotoken

    bzero ((char *) &ref, sizeof ref);	/* ECMA says don't encode this yet */
    if (SConnRequest (&ref, NULLSA, &called -> roa_addr,
		acb -> acb_requirements, settings, SERIAL_NONE, base, len,
		NULLQOS, sc, si) == NOTOK) {
	result = ss2roslose (NULLACB, roi, "SConnRequest", sa);
	goto out2;
    }
    free (base);

    bzero ((char *) roc, sizeof *roc);

    if (sc -> sc_result == SC_ACCEPT) {
	acb -> acb_fd = sc -> sc_sd;
	acb -> acb_uabort = SUAbortRequest;
    }
    else
        if (sc -> sc_result == SC_ABORT) {
	    acb -> acb_fd = NOTOK;

	    (void) ss2rosabort (acb, sa, roi);

	    roc -> roc_sd = NOTOK;
	    roc -> roc_result = ROS_ABORTED;

	    return OK;
	}

    if ((pe = ssdu2pe (sc -> sc_data, sc -> sc_cc, NULLCP, &result))
	    == NULLPE) {
	if (sc -> sc_result != SC_ACCEPT) {
	    bzero ((char *) sa, sizeof *sa);
	    sa -> sa_reason = sc -> sc_result;
	    acb -> acb_fd = NOTOK;
	    (void) ss2roslose (acb, roi, "SConnRequest(pseudo)", sa);

	    roc -> roc_sd = NOTOK;
	    roc -> roc_result = roi -> roi_preject.rop_reason;

	    result = OK;
	}
	else
	    result = ropktlose (acb, roi, result != PS_ERR_NMEM ? ROS_PROTOCOL
		    : ROS_CONGEST, NULLCP, "%s", ps_error (result));
	goto out1;
    }

    SCFREE (sc);

    if (sc -> sc_result != SC_ACCEPT) {
	if (parse_OACS_PRefuse (pe, 1, NULLIP, NULLVP, &pref) == NOTOK) {
	    result = pylose ();
	    goto out1;
	}

	PLOGP (rosap_log,OACS_PRefuse, pe, "PRefuse", 1);

	pe_free (pe);
	
	freeacblk (acb);

	roc -> roc_sd = NOTOK;
	switch (pref.parm) {
	    case REFUSE_BUSY: 
		roc -> roc_result = ROS_BUSY;
		break;

	    case REFUSE_VALIDATE: 
		roc -> roc_result = ROS_VALIDATE;
		break;

	    default: 
		roc -> roc_result = ROS_PROTOCOL;
		break;
	}

	return OK;
    }

    acb -> acb_flags = ACB_CONN | ACB_ROS | ACB_INIT;
    (void) RoSService (acb, roi);
    if (!((acb -> acb_requirements = sc -> sc_requirements) & SR_DUPLEX)
	    && !(acb -> acb_requirements & SR_HALFDUPLEX)) {
	result = ropktlose (acb, roi, ROS_PROTOCOL, NULLCP,
		    "desired session requirements denied");
	goto out1;
    }
    if (acb -> acb_requirements & SR_HALFDUPLEX)
	acb -> acb_flags |= ACB_TURN;	/* it it is there we must have it */

    if (parse_OACS_PAccept (pe, 1, NULLIP, NULLVP, &paccpt) == NOTOK) {
	result = pylose ();
	goto out1;
    }

    PLOGP (rosap_log,OACS_PAccept, pe, "PAccept", 1);

    roc -> roc_sd = acb -> acb_fd;
    roc -> roc_result = ROS_ACCEPT;
    if (paccpt -> pUserData -> member_OACS_5->offset
	    == type_OACS_ConnectionData_open)
	roc -> roc_data = pe_expunge (pe, paccpt -> pUserData
						 -> member_OACS_5 -> un.open);
    else
	roc -> roc_data = NULLPE;
	
    free_OACS_PAccept (paccpt);
    return OK;

out2: ;
    free (base);

out1: ;
    SCFREE (sc);
    if (pe) {
	if (data)
	    (void) pe_extract (pe, data);
	pe_free (pe);
    }
    freeacblk (acb);

    return result;
}