📄 ssapunitdata.c
字号:
/* **************************************************************** * * * HULA project * * * * program: ssapunitdata.c * * author: kurt dobbins * * date: 3/89 * * * * This program implements the connectionless ssap unitdata * * interface. It implements the ISO 9548 "Connectionless-Mode * * Session Protocol". * * * * entry points: * * * * SUnitDataBind (sd, calling, called, qos) * * SUnitDataUnbind (sd) * * SuSave (sd, vecp, vec, si) * * SUnitDataRequest (calling, called, qos, data, cc, si) * * SUnitDataWrite (sd, data, cc, si) * * SUnitDataWriteV (sd, uv) * * SUnitDataRead (sd, sud, secs) * * x SSelectUnitDataMask (sd, mask, nfds) * * x TUNITDATAser (sig, code, sc) * * x SUnitDataWakeUp (tb, td) * * * * x = not implemented * * * **************************************************************** * * * * * NOTICE * * * * Acquisition, use, and distribution of this module and * * related materials are subject to the restrictions of a * * license agreement. * * * * This software is for prototype purposes only. * * * **************************************************************** *//* LINTLIBRARY */#include <stdio.h>#include <signal.h>#include "spkt.h"#include "ssap.h"#include "susap.h"#include "tusap.h"#include "uderrors.h"#include "tailor.h"#ifdef HULA/* DATA */#define SSAP_NOT_ASYNC 0#define SSAP_ASYNC 1int TUNITDATAser ();/* **************************************************************** * * * SUnitDataBind * * * * This routine binds the local address to a socket. * * Optionally it allows a remote address to be bound as an * * address pair. If the remote address is specified, it is * * considered a permanent binding; otherwise, the bind to a * * remote address can be done anytime which essentially allows * * dynamic binding (and rebinding) to remote addresses. But * * no matter what, the local address must always be specified. * * * * It allocates and initializes a ssap control block for the * * socket and calls the tsap to initialize unitdata service. * * * * This routine must be called prior to using the SUnitData * * interface for subsequent SUniteWrite requests. If this * * isn't called, then SUnitDataRequest must be called for each * * unit data request. * * * * Note: BIND has write sematics only. * * * * * * returns: transport descriptor * * updated si struct if any error (NOTOK) returned * * * **************************************************************** */int SUnitDataBind (sd, local, remote, qos, si)int sd;struct SSAPaddr *local;struct SSAPaddr *remote;struct QOStype *qos;struct SSAPindication *si;{ int fd; SBV smask; int result; register struct ssapblk *sb; struct TSAPdisconnect td;#ifdef HULADEBUG printf ("\n in SUnitDataBind \n");#endif isodetailor ("ssap");/* * Check for missing parameters. */ missing_udP (si); if (!local && !remote) return susaplose (si, SC_PARAMETER, NULLCP, SuErrString (UDERR_MISSING_PARAMETER)); /* * Check if we need to create a new socket or just * reuse (essentially "rebind") the current socket * for the specified address pair. */ if (sd < 0) { /* * Allocate a new ssap block for this calling/called address pair. */#ifdef HULADEBUG printf ("\n allocating new ssap block \n");#endif if ( (sb = newsublk () ) == NULL) return susaplose (si, SC_CONGEST, NULLCP, SuErrString (UDERR_NO_MEMORY)); } else { /* * Find the correct session block and set the signal mask. */ if ((sb = findsublk (sd)) == NULL) { /* * Check for special case where a server has set up a * listen socket and is now binding the address so the * socket exists but no ssap block has been set up. */ if (local) {#ifdef HULADEBUG printf ("\n allocating new ssap block for listen socket\n");#endif if ( (sb = newsublk () ) == NULL) return susaplose (si, SC_CONGEST, NULLCP, SuErrString(UDERR_NO_MEMORY)); } else { (void) sigsetmask (smask); return susaplose (si, SC_PARAMETER, NULLCP, SuErrString(UDERR_INVALID_SESSION_DESC)); } }#ifdef HULADEBUG printf ("\n re-binding on current ssap block \n");#endif } /* * Set up the addresses if not specified. */ if (local == NULLSA) { static struct SSAPaddr salocal; local = &salocal; bzero ((char *) local, sizeof *local); } if (remote == NULLSA) { static struct SSAPaddr saremote; remote = &saremote; bzero ((char *) remote, sizeof *remote); } if (local -> sa_selectlen == 0) { local -> sa_port = htons((u_short)(0x8000 | (getpid() & 0x7fff))); local -> sa_selectlen = sizeof local -> sa_port; } /* * Now bind (or re-bind) the address pair and get back a socket descriptor. */ fd = TUnitDataBind (sd, &local -> sa_addr, &remote -> sa_addr, qos, &td); if (fd == NOTOK) { freesublk (sb); return ts2suslose (si, "TUnitDataBind", &td); }/* * Now finish setting up the control block. */ sb -> sb_fd = fd; sb -> sb_version = SB_VRSN1_CLNS; /* version 1 connectionless */ sb -> sb_flags = SB_CLNS; /* connectionless service */#if FALSE sb -> sb_tsdu_us = 0;#endif sb -> sb_initiating = *local; /* strcut copy */ sb -> sb_responding = *remote; /* struct copy */#if FALSE if (qos) sb -> sb_qos = *qos; #endif return fd;} /* *//* **************************************************************** * * * SUnitDataUnbind * * * * This routine releases datagram service for the session * * provider. It frees the ssap block for the socket and then * * closes the socket. * * * * returns: OK, NOTOK * * * **************************************************************** */int SUnitDataUnbind (sd, si)int sd;struct SSAPindication *si;{register struct ssapblk *sb;int result;SBV smask; /* signal save mask */struct TSAPdisconnect td;#ifdef HULADEBUG printf ("\n in SUnitDataUnbind \n");#endif/* * Find the correct session block and set the signal mask. */ ssap_udPsig (sb, sd);/* * Close the transport socket and free its resources. */ if ( (result = TUnitDataUnbind (sb -> sb_fd, &td)) != OK ) return NOTOK; /* * Now free the ssapblk. */#ifdef HULADEBUG printf ("\n freeing the ssap block \n");#endif freesublk (sb); return OK; }/* *//* **************************************************************** * * * SuSave * * * * This routine sets up a control block path and socket for * * datagram that has arrived on the server listen socket. * * * * returns: socket descriptor from TuSave * * * **************************************************************** */int SuSave (sd, vecp, vec, si)int sd;register int vecp;register char **vec;register struct SSAPindication *si;{ register struct ssapblk *sb; struct TSAPdisconnect tds; struct TSAPdisconnect *td = &tds; int result; SBV smask; /* signal save mask */ missing_udP (vec); missing_udP (si); /* * Check if we need to create a new socket or just * reuse an already bound socket. */ if (sd < 0) { /* * Allocate a new ssap block for this calling/called address pair. */ if ( (sb = newsublk () ) == NULL) return susaplose (si, SC_CONGEST, NULLCP, SuErrString (UDERR_NO_MEMORY)); } else { /* * Find the correct session block and set the signal mask. */ if ((sb = findsublk (sd)) == NULL) { (void) sigsetmask (smask); return susaplose (si, SC_PARAMETER, NULLCP, SuErrString(UDERR_INVALID_SESSION_DESC)); } } /* * Now pass thru the request to TSAP. */ if ( (result = TuSave (sd, vecp, vec, td) ) == NOTOK) return ts2suslose ( si, "TuSave", td); return result;}/* */ /* **************************************************************** * * * SUnitDataRequest * * * * This routine implements the S-UNITDATA.REQUEST primitive * * for writing data thru a datagram session service. This * * routine is used for unitdata service to remote addresses * * that havn't been binded. This routine blocks until the * * data is written. * * * **************************************************************** */int SUnitDataRequest (calling, called, data, cc, qos, si)struct SSAPaddr *calling, *called;register char *data;int cc;struct QOStype *qos;struct SSAPindication *si;{int sd;#ifdef HULADEBUG printf ("\n in SUnitDataRequest \n");#endif/* * Create the socket on the fly. We do the bind here because * tsap data writes expect iovecs instead of char data ptr. */ sd = SUnitDataBind (NOTOK, calling, called, qos, si); if (sd == NOTOK) return NOTOK;/* * Now do the S_UNITDATA send. */ if (SUnitDataWrite (sd, data, cc, si) == NOTOK) return NOTOK;/* * Unbind the socket. */ SUnitDataUnbind (sd, si); return OK;}/* *//* **************************************************************** * * * SUnitDataWrite * * * * This routine implements the ssap unit write interface for * * writing user data over transport datagram service where * * the datagram service has already been established and the * * remote address has been binded on the socket. * * * * This routine blocks until completion. * * * **************************************************************** */int SUnitDataWrite (sd, data, cc, si)int sd;register char *data;int cc;struct SSAPindication *si;{int n, len, j;SBV smask; /* signal save mask */int result; /* write result */register struct ssapblk *sb; /* ssap ctl blk ptr */register struct ssapkt *s;struct TSAPdisconnect tds;register struct TSAPdisconnect *td = &tds;struct udvec vvs[3];register struct udvec *vv, *xv;#ifdef HULADEBUG printf ("\n in SUnitDataWrite \n"); printf ("\n writing on socket %d \n", sd);#endif /* * Check for missing parameters. */ missing_udP (data); missing_udP (si); /* * Check user data. */ if ( (cc <= 0) || (cc > UD_MAX_DATA) ) return susaplose (si, SC_PARAMETER, NULLCP, SuErrString(UDERR_ILLEGAL_UD_SIZE)); /* * Block any signals while we do the write. */ smask = sigioblock (); /* * Find the correct session block and set the signal mask. */ ssap_udPsig (sb, sd); /* * Init our working udvec struct. */ vv = vvs; vvs[0].uv_base = vvs[1].uv_base = vvs[2].uv_base = NULL; /* * Allocate a new UNITDATA spkt for this datagram message. */#ifdef HULADEBUG printf ("\n allocating new SPKT \n");#endif if ((s = newspkt (SPDU_UD)) == NULL) return susaplose (si, SC_CONGEST, NULLCP, SuErrString(UDERR_NO_MEMORY)); /* * Set the parameter field values in the spkt for encoding. */ s -> s_mask |= (SMASK_SPDU_UD | SMASK_UD_VERSION); s -> s_ud_version = sb -> sb_version; if (sb -> sb_initiating.sa_selectlen > 0) { s -> s_mask |= SMASK_UD_CALLING; bcopy (sb -> sb_initiating.sa_selector, s -> s_ud_calling, s -> s_ud_callinglen = sb -> sb_initiating.sa_selectlen); } if (sb -> sb_responding.sa_selectlen > 0) { s -> s_mask |= SMASK_UD_CALLED; bcopy (sb -> sb_responding.sa_selector, s -> s_ud_called, s -> s_ud_calledlen = sb -> sb_responding.sa_selectlen); }#ifdef HULADEBUG spkt2text (stdout, s, NULL);#endif /* * Format the session protocol data unit. * The encode routine will put the SPDU header in the base * portion of the work udvec[0] passed to it. */#ifdef HULADEBUG printf ("\n formatting the unitdata SPDU \n");#endif if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) { susaplose (si, SC_PROTOCOL, NULLCP, SuErrString (UDERR_ENCODE_UDSPDU_FAILED)); freespkt (s); return NOTOK; }#ifdef HULADEBUG for (j = 0; j < vv->uv_len; j++) printf ( " %x ", *(vv->uv_base + j) );#endif /* * Now copy the user data to the work udvec. The SPDU UD header * was encoded and put as the 1st base element so put the user * data as the second element. */ xv = ++vv; xv -> uv_base = data; xv -> uv_len = cc; freespkt (s); s = NULL; /* * Do the unit data write over the TSAP unitdata service. */#ifdef HULADEBUG printf ("\n calling the TSAP unitdata write \n");#endif if ( (result = TUnitDataWrite (sb -> sb_fd, vvs, td)) == NOTOK) ts2suslose (si, "TUnitDataWrite", td); /* * Free the encoded header. */ free (vvs[0].uv_base); /* * Restore the mask. */ (void) sigiomask (smask); if (result == NOTOK) return NOTOK; else return OK;}/* */#define NSPUV 12 /* really should be MSG_MAXIOVLEN - 4 *//* **************************************************************** * * * SUnitDataWriteV * * * * This routine implements the ssap unit write interface for * * writing user vextors over transport datagram service where * * the datagram service has already been established and the *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -