|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 76825 (0x12c19)
Types: TextFile
Names: »isoc.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z«
└─⟦de7628f85⟧
└─⟦this⟧ »isode-6.0/support/isoc.c«
/* isoc.c - "minimal" ISODE client for testing */
#ifndef lint
static char *rcsid = "$Header: /f/osi/support/RCS/isoc.c,v 7.1 89/12/07 21:19:51 mrose Exp $";
#endif
/*
* $Header: /f/osi/support/RCS/isoc.c,v 7.1 89/12/07 21:19:51 mrose Exp $
*
*
* $Log: isoc.c,v $
* Revision 7.1 89/12/07 21:19:51 mrose
* stuff
*
* Revision 7.0 89/11/23 22:27:15 mrose
* Release 6.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.
*
*/
#include <stdio.h>
#include <varargs.h>
#include "rosap.h"
#include "rtsap.h"
#include "acsap.h"
#include "psap2.h"
#include "ssap.h"
#include "tsap.h"
#ifdef TCP
#include "internet.h"
#ifdef BSD42
#include <sys/ioctl.h>
#endif
#ifdef SVR3
#include <fcntl.h>
#endif
#endif
#include "isoservent.h"
#include "tailor.h"
#include <sys/stat.h>
#undef TIMER
#undef TMS
#ifdef BSD42
#define TIMER
#endif
#ifdef SYS5
#define TIMER
#ifndef HPUX
#include <sys/times.h>
#define TMS
#endif
#endif
#if !defined (TCP) || defined (FIONBIO) || defined (SVR3)
#define ASYNC
#endif
/* \f
DATA */
#define ISN(req) \
(req & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY)) \
? (long) ((getpid () % (SERIAL_MAX - SERIAL_MIN + 1)) + SERIAL_MIN) \
: SERIAL_NONE
static enum { echo, sink, XXX } mode = XXX;
static int testing_queued_writes = 0;
static char *isacs = NULL;
static int isrts = 0;
static int status = 0;
static char *myname = "isoc";
void adios (), advise ();
void ts_adios (), ts_advise ();
void ss_adios (), ss_advise ();
void ps_adios (), ps_advise ();
void acs_adios (), acs_advise ();
void rts_adios (), rts_advise ();
void ros_adios (), ros_advise ();
long lseek ();
/* \f
MAIN */
#define chkacs() if (isacs) \
adios (NULLCP, "no association control for %s", \
argv[2])
/* ARGSUSED */
main (argc, argv, envp)
int argc;
char **argv,
**envp;
{
register struct isoservent *is;
if (myname = rindex (argv[0], '/'))
myname++;
if (myname == NULL || *myname == NULL)
myname = argv[0];
isodetailor (myname, 1);
if (argc != 4)
adios (NULLCP, "usage: %s host provider entity", myname);
#ifdef TCP
if (strcmp (argv[2], "raw") == 0) {
raw_main (argv[3], argv[1]);
exit (0);
}
#endif
if (index (argv[3], '/')) {
mode = strcmp (isacs = argv[3], "isode/sink") ? echo : sink;
}
else {
if ((is = getisoserventbyname (argv[3], argv[2])) == NULL)
adios (NULLCP, "%s/%s: unknown provider/entity pair",
argv[2], argv[3]);
mode = strcmp (is -> is_entity, "sink") ? echo : sink;
}
if (strcmp (argv[2], "tsap") == 0) {
chkacs ();
ts_main (is, argv[1]);
}
else
if (strcmp (argv[2], "ssap") == 0) {
chkacs ();
ss_main (is, argv[1]);
}
else
if (strcmp (argv[2], "psap") == 0)
ps_main (is, argv[1]);
else
if (strcmp (argv[2], "rtsap") == 0) {
isrts = 1;
rts_main (is, argv[1]);
}
else
if (strcmp (argv[2], "rosap") == 0)
ros_main (is, argv[1]);
else
adios (NULLCP, "unknown provider: \"%s\"", argv[2]);
exit (status); /* NOTREACHED */
}
/* \f
RAW */
#ifdef TCP
static int raw_main (service, addr)
char *service,
*addr;
{
int sd,
cc,
i,
j;
char *cp,
*dp;
register struct hostent *hp;
register struct servent *sp;
struct sockaddr_in in_socket;
register struct sockaddr_in *isock = &in_socket;
struct stat st;
if (strcmp (service, "sink"))
adios (NULLCP, "only sink on raw tcp is supported");
if ((sp = getservbyname (service, "tcp")) == NULL)
adios (NULLCP, "%s/%s: unknown service", "tcp", service);
if ((hp = gethostbystring (addr)) == NULL)
adios (NULLCP, "%s: unknown host", addr);
bzero ((char *) isock, sizeof *isock);
isock -> sin_family = hp -> h_addrtype;
isock -> sin_port = sp -> s_port;
inaddr_copy (hp, isock);
if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK)
adios ("socket", "unable to start");
fprintf (stderr, "%s... ", hp -> h_name);
(void) fflush (stderr);
if (join_tcp_server (sd, isock) == NOTOK) {
fprintf (stderr, "failed\n");
adios ("socket", "unable to connect");
}
fprintf (stderr, "connected\n");
if (fstat (fileno (stdin), &st) == NOTOK
|| (st.st_mode & S_IFMT) != S_IFREG
|| (cc = st.st_size) == 0)
adios (NULLCP, "standard input not a regular file");
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
#ifdef TIMER
timer (0);
#endif
if (write_tcp_socket (sd, cp, cc) != cc)
adios ("writing", "error");
(void) close_tcp_socket (sd);
#ifdef TIMER
timer (cc);
#endif
}
#endif
/* \f
TSAP */
static int ts_main (is, addr)
struct isoservent *is;
char *addr;
{
int sd,
cc,
i,
j,
expedited,
expd;
char *cp,
*dp,
buffer[BUFSIZ];
struct TSAPaddr *ta;
struct TSAPconnect tcs;
register struct TSAPconnect *tc = &tcs;
struct TSAPdisconnect tds;
register struct TSAPdisconnect *td = &tds;
struct stat st;
if ((ta = is2taddr (addr, NULLCP, is)) == NULL)
adios (NULLCP, "address translation failed");
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
#ifndef ASYNC
if (TConnRequest (NULLTA, ta, 1, NULLCP, 0, NULLQOS, tc, td) == NOTOK) {
fprintf (stderr, "failed\n");
ts_adios (td, "T-CONNECT.REQUEST");
}
sd = tc -> tc_sd;
#else
if ((i = TAsynConnRequest (NULLTA, ta, 1, NULLCP, 0, NULLQOS, tc, td, 1))
== NOTOK) {
fprintf (stderr, "failed\n");
ts_adios (td, "T-(ASYN-)CONNECT.REQUEST");
}
sd = tc -> tc_sd, cc = 0;
while (i == CONNECTING_1 || i == CONNECTING_2) {
int nfds;
fd_set mask,
*rmask,
*wmask;
nfds = 0;
FD_ZERO (&mask);
if (TSelectMask (sd, &mask, &nfds, td) == NOTOK) {
fprintf (stderr, "failed\n");
ts_adios (td, "T-(ASYN-)CONNECT.REQUEST(TSelectMask)");
}
rmask = (i == CONNECTING_2) ? &mask : NULLFD;
wmask = (i == CONNECTING_2) ? NULLFD : &mask;
fprintf (stderr, ".");
(void) fflush (stderr);
if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
fprintf (stderr, "failed\n");
adios ("failed", "select");
}
if ((rmask && FD_ISSET (sd, rmask) == 0)
|| (wmask && FD_ISSET (sd, wmask) == 0))
continue;
if ((i = TAsynRetryRequest (sd, tc, td)) == NOTOK) {
fprintf (stderr, "failed\n");
ts_adios (td, "T-ASYN-RETRY.REQUEST");
}
}
#endif
fprintf (stderr, "connected\n");
if (getenv ("TEST_QUEUED_WRITES")) {
if (TSetQueuesOK (tc -> tc_sd, 1, td) == NOTOK)
ts_adios (td, "T-SET-QUEUES-OK");
tsap_log -> ll_events |= LLOG_EXCEPTIONS;
tsap_log -> ll_file = "-";
(void) ll_close (tsap_log);
testing_queued_writes = 1;
}
expd = tc -> tc_expedited;
#ifdef DEBUG
{
advise (NULLCP, "responding TSAP address: %s",
taddr2str (&tc -> tc_responding));
if (tc -> tc_cc > 0)
advise (NULLCP, "greetings: %d octets", tc -> tc_cc);
}
#endif
if (fstat (fileno (stdin), &st) != NOTOK
&& (st.st_mode & S_IFMT) == S_IFREG
&& (cc = st.st_size) != 0) {
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
for (i = 10; i > 0; i--) {
#ifdef TIMER
timer (0);
#endif
ts_datarequest (sd, cp, cc, 0);
#ifdef TIMER
timer (cc);
#endif
}
free (cp);
}
else
for (expedited = 0;
fgets (buffer, sizeof buffer, stdin);
expedited = !expedited) {
if ((cc = strlen (buffer) + 1) > TX_SIZE && expedited)
expedited = 0;
ts_datarequest (sd, buffer, cc, expd ? expedited : 0);
}
if (TDiscRequest (sd, NULLCP, 0, td) == NOTOK)
ts_adios (td, "T-DISCONNECT.REQUEST");
}
/* \f
*/
static int ts_datarequest (sd, data, cc, expedited)
int sd;
char *data;
int cc,
expedited;
{
struct TSAPdata txs;
register struct TSAPdata *tx = &txs;
struct TSAPdisconnect tds;
register struct TSAPdisconnect *td = &tds;
if ((expedited ? TExpdRequest (sd, data, cc, td)
: TDataRequest (sd, data, cc, td)) == NOTOK)
if (expedited)
ts_adios (td, "T-EXPEDITED-DATA.REQUEST");
else
ts_adios (td, "T-DATA.REQUEST");
if (mode == echo) {
if (testing_queued_writes) {
int vecp;
char *vec[4];
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (sd, &rfds);
if (TNetAccept (&vecp, vec, sd + 1, &rfds, NULLFD, NULLFD, NOTOK,
td) == NOTOK)
ts_adios (td, "T-NET-ACCEPT");
}
if (TReadRequest (sd, tx, NOTOK, td) == NOTOK)
ts_adios (td, "T-READ.REQUEST");
if (cc != tx -> tx_cc) {
advise (NULLCP, "length mismatch, orig=%d echo=%d",
cc, tx -> tx_cc);
status++;
}
else
if (qcmp (data, &tx -> tx_qbuf, cc))
status++;
TXFREE (tx)
}
}
/* \f
*/
static void ts_adios (td, event)
register struct TSAPdisconnect *td;
char *event;
{
ts_advise (td, event);
_exit (1);
}
static void ts_advise (td, event)
register struct TSAPdisconnect *td;
char *event;
{
char data[BUFSIZ];
if (td -> td_cc > 0) {
(void) sprintf (data, "[%s] %*.*s",
TErrString (td -> td_reason),
td -> td_cc, td -> td_cc, td -> td_data);
}
else
(void) sprintf (data, "[%s]", TErrString (td -> td_reason));
advise (NULLCP, "%s: %s", event, data);
}
/* \f
SSAP */
static int requirements = SR_HALFDUPLEX | SR_DUPLEX | SR_EXPEDITED
| SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY
| SR_NEGOTIATED | SR_CAPABILITY | SR_EXCEPTIONS | SR_TYPEDATA;
static int owned = 0;
static int avail = 0;
static long ssn;
static int nmodes;
static int datamodes[4];
static char userdata[1024];
/* \f
*/
static int ss_main (is, addr)
struct isoservent *is;
char *addr;
{
int sd,
cc,
i,
j,
k,
l,
tokens;
char *cp,
*dp,
buffer[BUFSIZ];
struct SSAPactid ids;
register struct SSAPactid *id = &ids;
register struct SSAPaddr *sz;
struct SSAPref sfs;
register struct SSAPref *sf;
struct SSAPconnect scs;
register struct SSAPconnect *sc = &scs;
struct SSAPrelease srs;
register struct SSAPrelease *sr = &srs;
struct SSAPindication sis;
register struct SSAPindication *si = &sis;
register struct SSAPabort *sa = &si -> si_abort;
struct stat st;
bzero (userdata, sizeof userdata);
if ((sz = is2saddr (addr, NULLCP, is)) == NULL)
adios (NULLCP, "address translation failed");
if ((sf = addr2ref (SLocalHostName ())) == NULL) {
sf = &sfs;
(void) bzero ((char *) sf, sizeof *sf);
}
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if (requirements & requires) \
tokens |= ST_CALL_VALUE << shift; \
}
dotokens ();
#undef dotoken
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
#ifndef ASYNC
if (SConnRequest (sf, NULLSA, sz, requirements, tokens, ISN (requirements),
userdata, sizeof userdata /*SS_SIZE*/, NULLQOS, sc, si) == NOTOK) {
fprintf (stderr, "failed\n");
ss_adios (sa, "S-CONNECT.REQUEST");
}
sd = sc -> sc_sd;
#else
if ((i = SAsynConnRequest (sf, NULLSA, sz, requirements, tokens,
ISN (requirements), userdata, sizeof userdata /*SS_SIZE*/, NULLQOS,
sc, si, 1))
== NOTOK) {
fprintf (stderr, "failed\n");
ss_adios (sa, "S-(ASYN-)CONNECT.REQUEST");
}
sd = sc -> sc_sd, cc = 0;
while (i == CONNECTING_1 || i == CONNECTING_2) {
int nfds;
fd_set mask,
*rmask,
*wmask;
nfds = 0;
FD_ZERO (&mask);
if (SSelectMask (sd, &mask, &nfds, si) == NOTOK) {
fprintf (stderr, "failed\n");
ss_adios (sa, "S-(ASYN-)CONNECT.REQUEST(SSelectMask)");
}
rmask = (i == CONNECTING_2) ? &mask : NULLFD;
wmask = (i == CONNECTING_2) ? NULLFD : &mask;
fprintf (stderr, ".");
if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
fprintf (stderr, "failed\n");
adios ("failed", "select");
}
if ((rmask && FD_ISSET (sd, rmask) == 0)
|| (wmask && FD_ISSET (sd, wmask) == 0))
continue;
if ((i = SAsynRetryRequest (sd, sc, si)) == NOTOK) {
fprintf (stderr, "failed\n");
ss_adios (sa, "S-ASYN-RETRY.REQUEST");
}
}
#endif
if (sc -> sc_result != SC_ACCEPT) {
fprintf (stderr, "failed\n");
if (sc -> sc_cc > 0)
adios (NULLCP, "connection rejected: [%s] %*.*s",
SErrString (sc -> sc_result),
sc -> sc_cc, sc -> sc_cc, sc -> sc_data);
else
adios (NULLCP, "connection rejected: [%s]",
SErrString (sc -> sc_result));
}
fprintf (stderr, "connected\n");
#ifdef DEBUG
{
advise (NULLCP, "responding SSAP address: %s",
saddr2str (&sc -> sc_responding));
if (sc -> sc_cc > 0)
advise (NULLCP, "greetings: %d octets", sc -> sc_cc);
}
#endif
requirements = sc -> sc_requirements;
nmodes = 0;
datamodes[nmodes++] = SX_NORMAL;
if (requirements & SR_EXPEDITED)
datamodes[nmodes++] = SX_EXPEDITED;
if ((requirements & SR_CAPABILITY) && (requirements & SR_ACTIVITY))
datamodes[nmodes++] = SX_CAPDIND;
if (requirements & SR_TYPEDATA)
datamodes[nmodes++] = SX_TYPED;
#define dotoken(requires,shift,bit,type) \
{ \
if (requirements & requires) \
switch (sc -> sc_settings & (ST_MASK << shift)) { \
case ST_CALL_VALUE: \
adios (NULLCP, "%s token: choice", type); \
\
case ST_INIT_VALUE: \
owned |= bit, avail |= bit; \
break; \
\
case ST_RESP_VALUE: \
avail |= bit; \
break; \
\
default: \
adios (NULLCP, "%s token: reserved", type); \
} \
}
dotokens ();
#undef dotoken
if (requirements & SR_ACTIVITY) {
(void) strcpy (id -> sd_data, mode == echo ? "echo" : "sink");
id -> sd_len = strlen (id -> sd_data);
if (SActStartRequest (sd, id, userdata, SV_SIZE, si) == NOTOK)
ss_adios (sa, "S-ACTIVITY-START.REQUEST");
}
if (fstat (fileno (stdin), &st) != NOTOK
&& (st.st_mode & S_IFMT) == S_IFREG
&& (cc = st.st_size) != 0) {
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
for (i = 10; i > 0; i--) {
#ifdef TIMER
timer (0);
#endif
ss_datarequest (sd, cp, cc, SX_NORMAL, 0);
#ifdef TIMER
timer (cc);
#endif
}
free (cp);
}
else {
for (j = l = 0; fgets (buffer, sizeof buffer, stdin); ) {
k = j >= nmodes ? SX_EXPEDITED : datamodes[j++ % nmodes];
if ((cc = strlen (buffer) + 1) > SX_EXSIZE && k == SX_EXPEDITED) {
if ((k = datamodes[j++ % nmodes]) == SX_EXPEDITED)
k = datamodes[j++ % nmodes];
}
switch (k) {
case SX_CAPDIND:
if (!(requirements & SR_RESYNC) || l++ & 0x01) {
ss_waitfor (sd, ST_ACT_TOKEN);
if (l & 0x03) {
if (SActIntrRequest (sd, SP_SEQUENCE, si)
== NOTOK)
ss_adios (sa, "S-ACTIVITY-INTERRUPT.REQUEST");
}
else {
if (SActDiscRequest (sd, SP_SEQUENCE, si)
== NOTOK)
ss_adios (sa, "S-ACTIVITY-DISCARD.REQUEST");
}
ss_waitfor (sd, -1);
goto push_data;
}
if (!(requirements & SR_RESYNC))
break;
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if (requirements & requires) \
tokens |= ST_CALL_VALUE << shift; \
}
dotokens ();
#undef dotoken
if (SReSyncRequest (sd, SYNC_SET, ssn - 1, tokens,
userdata, SN_SIZE, si) == NOTOK)
ss_adios (sa, "S-RESYNCHRONIZE.REQUEST");
ss_waitfor (sd, -1);
break;
case SX_EXPEDITED:
if (j >= nmodes)
j = j % nmodes;/* fall... */
if (!(requirements & SR_EXPEDITED))
k = SX_NORMAL; /* fall... */
default:
push_data: ;
ss_datarequest (sd, buffer, cc, k, 1);
if (k == SX_CAPDIND
&& SActResumeRequest (sd, id, id,
(long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1))
+ SERIAL_MIN, sf, userdata, SV_SIZE, si)
== NOTOK)
ss_adios (sa, "S-ACTIVITY-RESUME.REQUEST");
break;
}
}
if (requirements & SR_EXCEPTIONS) {
if (owned & ST_DAT_TOKEN)
if (SGTokenRequest (sd, ST_DAT_TOKEN, si) == NOTOK)
ss_adios (sa, "S-TOKEN-GIVE.REQUEST");
else
owned &= ~ST_DAT_TOKEN;
if (SUReportRequest (sd, SP_NOREASON, userdata, SP_SIZE, si)
== NOTOK)
ss_adios (sa, "S-U-EXCEPTION-REPORT.REQUEST");
ss_waitfor (sd, -1);
}
}
if ((requirements & SR_MAJORSYNC) && !(requirements & SR_ACTIVITY)) {
if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
| ST_MAJ_TOKEN);
if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si)
== OK)
break; /* else fall */
default:
ss_adios (sa, "S-MAJOR-SYNC.REQUEST");
}
ss_waitfor (sd, -1);
}
if (requirements & SR_ACTIVITY) {
if (SActEndRequest (sd, &ssn, userdata, SV_SIZE, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, avail);
if (SActEndRequest (sd, &ssn, userdata, SV_SIZE, si) == OK)
break; /* else fall */
default:
ss_adios (sa, "S-ACTIVITY-END.REQUEST");
}
ss_waitfor (sd, -1);
if (SGControlRequest (sd, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, avail);
if (SGControlRequest (sd, si) == OK)
break; /* else fall */
default:
ss_adios (sa, "S-CONTROL-GIVE.REQUEST");
}
owned = 0;
ss_waitfor (sd, -1);
}
if (SRelRequest (sd, userdata, SF_SIZE, NOTOK, sr, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
case SC_WAITING:
ss_waitfor (sd, avail);
if (SRelRequest (sd, userdata, SF_SIZE, NOTOK, sr, si) == OK)
break; /* else fall */
default:
ss_adios (sa, "S-RELEASE.REQUEST");
}
if (!sr -> sr_affirmative) {
(void) SUAbortRequest (sd, NULLCP, 0, si);
if (sr -> sr_cc > 0)
adios (NULLCP, "release rejected by peer: %*.*s",
sr -> sr_cc, sr -> sr_cc, sr -> sr_data);
else
adios (NULLCP, "release rejected by peer");
}
SRFREE (sr);
}
/* \f
*/
static int ss_datarequest (sd, data, cc, dm, sync)
int sd;
char *data;
int cc,
dm,
sync;
{
int result;
struct SSAPdata sxs;
register struct SSAPdata *sx = &sxs;
struct SSAPindication sis;
register struct SSAPindication *si = &sis;
register struct SSAPabort *sa = &si -> si_abort;
switch (dm) {
default:
if (SDataRequest (sd, data, cc, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, ST_DAT_TOKEN);
if (SDataRequest (sd, data, cc, si) == OK)
break;/* else fall */
default:
ss_adios (sa, "S-DATA.REQUEST");
}
break;
case SX_EXPEDITED:
if (SExpdRequest (sd, data, cc, si) == NOTOK)
ss_adios (sa, "S-EXPEDITED-DATA.REQUEST");
break;
case SX_CAPDIND:
if (SCapdRequest (sd, data, cc, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, avail & ~ST_RLS_TOKEN);
if (SCapdRequest (sd, data, cc, si) == OK)
break;/* else fall */
default:
ss_adios (sa, "S-CAPABILITY-DATA.REQUEST");
}
break;
case SX_TYPED:
if (STypedRequest (sd, data, cc, si) == NOTOK)
ss_adios (sa, "S-TYPED-DATA.REQUEST");
break;
}
if (mode == echo || dm == SX_CAPDIND)
for (;;) {
switch (result = SReadRequest (sd, sx, NOTOK, si)) {
case NOTOK:
ss_adios (sa, "S-READ.REQUEST");
case OK:
if ((dm != SX_CAPDIND ? dm : SX_CAPDCNF)
!= sx -> sx_type) {
advise (NULLCP,
"data indication type mismatch, orig=%d echo=%d",
dm, sx -> sx_type);
status++;
}
if (cc != sx -> sx_cc) {
advise (NULLCP, "length mismatch, orig=%d echo=%d",
cc, sx -> sx_cc);
status++;
}
else
if (qcmp (data, &sx -> sx_qbuf, cc))
status++;
SXFREE (sx)
break;
case DONE:
ss_event (sd, si);
continue;
default:
adios (NULLCP, "unknown return from SReadRequest=%d",
result);
}
break;
}
if (sync &&
(requirements & SR_MINORSYNC) && !(requirements & SR_ACTIVITY)) {
if (SMinSyncRequest (sd, SYNC_CONFIRM, &ssn, userdata, SN_SIZE, si)
== NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN);
if (SMinSyncRequest (sd, SYNC_CONFIRM, &ssn, userdata,
SN_SIZE, si) == OK)
break; /* else fall */
default:
ss_adios (sa, "S-MINOR-SYNC.REQUEST");
}
ss_waitfor (sd, -1);
}
else
if (sync
&& (requirements & SR_ACTIVITY)
&& (requirements & SR_MAJORSYNC)
&& dm == SX_NORMAL) {
if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si) == NOTOK)
switch (sa -> sa_reason) {
case SC_OPERATION:
ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
| ST_MAJ_TOKEN);
if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si)
== OK)
break;/* else fall */
default:
ss_adios (sa, "S-MAJOR-SYNC.REQUEST");
}
ss_waitfor (sd, -1);
}
}
/* \f
*/
static int ss_waitfor (sd, want)
int sd,
want;
{
int result,
tokens;
char buffer[BUFSIZ];
struct SSAPdata sxs;
register struct SSAPdata *sx = &sxs;
struct SSAPindication sis;
register struct SSAPindication *si = &sis;
register struct SSAPabort *sa = &si -> si_abort;
for (;;) {
if (want == -1) {
want = avail;
goto read_it;
}
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if ((want & bit) && !(owned & bit)) \
tokens |= bit; \
}
dotokens ();
#undef dotoken
if (tokens == 0)
return;
if (SPTokenRequest (sd, tokens, userdata, ST_SIZE, si) == NOTOK)
ss_adios (sa, "S-TOKEN-PLEASE.REQUEST");
read_it: ;
switch (result = SReadRequest (sd, sx, NOTOK, si)) {
case NOTOK:
ss_adios (sa, "S-READ.REQUEST");
case OK:
(void) strcpy (buffer, "protocol screw-up");
if (SUAbortRequest (sd, buffer, strlen (buffer) + 1, si) == NOTOK)
ss_adios (sa, "S-U-ABORT.REQUEST");
adios (NULLCP, "%s, data indication type=0x%x",
buffer, sx -> sx_type);
case DONE:
ss_event (sd, si);
break;
default:
adios (NULLCP, "unknown return from SReadRequest=%d",
result);
}
}
}
/* \f
*/
static ss_event (sd, si)
int sd;
register struct SSAPindication *si;
{
register struct SSAPabort *sa = &si -> si_abort;
register struct SSAPactivity *sv = &si -> si_activity;
register struct SSAPfinish *sf = &si -> si_finish;
register struct SSAPreport *sp = &si -> si_report;
register struct SSAPsync *sn = &si -> si_sync;
register struct SSAPtoken *st = &si -> si_token;
switch (si -> si_type) {
case SI_TOKEN:
switch (st -> st_type) {
case ST_GIVE:
case ST_CONTROL:
owned = st -> st_owned;
break;
case ST_PLEASE:
if (SGTokenRequest (sd,
(int) st -> st_tokens, si)
== NOTOK)
ss_adios (sa, "S-TOKEN-GIVE.REQUEST");
else
owned &= ~st -> st_tokens;
break;
default:
adios (NULLCP,
"unknown token indication type=0x%x, %d bytes",
st -> st_type, st -> st_cc);
}
STFREE (st);
break;
case SI_SYNC:
switch (sn -> sn_type) {
case SN_MAJORIND:
adios (NULLCP, "majorsync indication %d, %d bytes",
sn -> sn_ssn, sn -> sn_cc);
break;
case SN_MAJORCNF:
break;
case SN_MINORIND:
adios (NULLCP, "minorsync indication %d%s, %d bytes",
sn -> sn_ssn, sn -> sn_options == SYNC_CONFIRM
? " (wants confirmation)" : NULLCP, sn -> sn_cc);
break;
case SN_MINORCNF:
break;
case SN_RESETIND:
#define dotoken(requires,shift,bit,type) \
{ \
if (requirements & requires) \
switch (sn -> sn_settings & (ST_MASK << shift)) { \
case ST_CALL_VALUE << shift: \
sn -> sn_settings &= ~(ST_MASK << shift); \
sn -> sn_settings |= ST_RESP_VALUE << shift; \
case ST_RESP_VALUE << shift: \
owned &= ~bit; \
break; \
\
case ST_INIT_VALUE << shift: \
owned |= bit; \
break; \
\
default: \
adios (NULLCP, "%s token: reserved", type); \
break; \
} \
}
dotokens ();
#undef dotoken
if (SReSyncResponse (sd, sn -> sn_ssn, sn -> sn_settings,
userdata, SN_SIZE, si) == NOTOK)
ss_adios (sa, "S-RESYNCHRONIZE.RESPONSE");
break;
case SN_RESETCNF:
break;
default:
adios (NULLCP,
"unknown sync indication=0x%x, ssn=%d, %d bytes",
sn -> sn_type, sn -> sn_ssn, sn -> sn_cc);
}
SNFREE (sn);
break;
case SI_ACTIVITY:
switch (sv -> sv_type) {
case SV_START:
adios (NULLCP,
"activity start indication: %*.*s, %d bytes",
sv -> sv_id.sd_len, sv -> sv_id.sd_len,
sv -> sv_id.sd_data, sv -> sv_cc);
case SV_RESUME:
adios (NULLCP,
"activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d, %d bytes",
sv -> sv_id.sd_len, sv -> sv_id.sd_len,
sv -> sv_id.sd_data, sv -> sv_oid.sd_len,
sv -> sv_oid.sd_len, sv -> sv_oid.sd_data,
sprintref (&sv -> sv_connect), sv -> sv_ssn,
sv -> sv_cc);
case SV_INTRIND:
adios (NULLCP,
"activity interrupt indication %d, %d bytes",
sv -> sv_reason, sv -> sv_cc);
case SV_INTRCNF:
break;
case SV_DISCIND:
adios (NULLCP,
"activity discard indication %d, %d bytes",
sv -> sv_reason, sv -> sv_cc);
case SV_DISCCNF:
break;
case SV_ENDIND:
adios (NULLCP, "activity end indication %d, %d bytes",
sv -> sv_ssn, sv -> sv_cc);
case SV_ENDCNF:
break;
default:
adios (NULLCP,
"unknown activity indication=0x%x, %d bytes",
sv -> sv_type, sv -> sv_cc);
}
SVFREE (sv);
break;
case SI_REPORT:
if (requirements & SR_DAT_EXISTS) {
if (SGTokenRequest (sd, ST_DAT_TOKEN, si) == NOTOK)
ss_adios (sa, "S-TOKEN-GIVE.REQUEST (to clear exception)");
else
owned &= ~ST_DAT_TOKEN;
}
else
if (SUAbortRequest (sd, NULLCP, 0, si) == NOTOK)
ss_adios (sa, "S-U-ABORT.REQUEST");
else
adios (NULLCP, "aborted");
SPFREE (sp);
break;
case SI_FINISH:
if (SRelResponse (sd, SC_REJECTED, NULLCP, 0, si) == NOTOK)
ss_adios (sa, "S-RELEASE.RESPONSE");
SFFREE (sf);
break;
default:
adios (NULLCP, "unknown indication type=0x%x",
si -> si_type);
}
}
/* \f
*/
static void ss_adios (sa, event)
register struct SSAPabort *sa;
char *event;
{
ss_advise (sa, event);
_exit (1);
}
static void ss_advise (sa, event)
register struct SSAPabort *sa;
char *event;
{
char buffer[BUFSIZ];
if (sa -> sa_cc > 0)
(void) sprintf (buffer, "[%s] %*.*s",
SErrString (sa -> sa_reason),
sa -> sa_cc, sa -> sa_cc, sa -> sa_data);
else
(void) sprintf (buffer, "[%s]", SErrString (sa -> sa_reason));
advise (NULLCP, "%s: %s%s", event, buffer,
sa -> sa_peer ? " (peer initiated)" : "");
SAFREE (sa);
}
/* \f
PSAP */
static int prequirements = 0;
#define srequirements requirements
static int nctxs;
static int datactxs[NPCTX];
/* \f
*/
static int ps_main (is, addr)
struct isoservent *is;
char *addr;
{
int sd,
cc,
i,
j,
k,
l,
m,
tokens;
char *cp,
*dp,
buffer[BUFSIZ];
register struct PSAPaddr *pz;
struct SSAPactid ids;
register struct SSAPactid *id = &ids;
struct SSAPref sfs;
register struct SSAPref *sf;
struct PSAPconnect pcs;
register struct PSAPconnect *pc = &pcs;
struct PSAPctxlist pls;
register struct PSAPctxlist *pl = &pls;
struct PSAPrelease prs;
register struct PSAPrelease *pr = &prs;
struct PSAPindication pis;
register struct PSAPindication *pi = &pis;
register struct PSAPabort *pa = &pi -> pi_abort;
struct AcSAPconnect accs;
register struct AcSAPconnect *acc = &accs;
struct AcSAPrelease acrs;
register struct AcSAPrelease *acr = &acrs;
struct AcSAPindication acis;
register struct AcSAPindication *aci = &acis;
register struct AcSAPabort *aca = &aci -> aci_abort;
register PE pe;
PE udata[NPDATA];
AEI aei;
OID oid,
ode;
struct stat st;
if (isacs) {
if ((aei = str2aei (addr, isacs)) == NULLAEI)
adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
if ((pz = aei2addr (aei)) == NULLPA)
adios (NULLCP, "address translation failed");
cp = mode == echo ? "isode echo pci" : "isode sink pci";
if ((ode = ode2oid (cp)) == NULLOID)
adios (NULLCP, "%s: unknown object descriptor", cp);
ode = oid_cpy (ode);
}
else
if ((pz = is2paddr (addr, NULLCP, is)) == NULL)
adios (NULLCP, "address translation failed");
if ((sf = addr2ref (PLocalHostName ())) == NULL) {
sf = &sfs;
(void) bzero ((char *) sf, sizeof *sf);
}
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if (srequirements & requires) \
tokens |= ST_CALL_VALUE << shift; \
}
dotokens ();
#undef dotoken
for (i = (pl -> pc_nctx = NPCTX - (isacs ? 1 : 0)) - 1; i >= 0; i--) {
pl -> pc_ctx[i].pc_id = i * 2 + 1;
if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
adios (NULLCP, "iso asn.1 abstract syntax: unknown");
pl -> pc_ctx[i].pc_asn = oid_cpy (oid);
pl -> pc_ctx[i].pc_atn = NULLOID;
}
for (i = 0; i < NPDATA; i++) {
if ((pe = int2prim (i)) == NULLPE)
adios (NULLCP, "unable to allocate hello");
pe -> pe_context = (i % pl -> pc_nctx) * 2 + 1;
udata[i] = pe;
}
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
if (isacs) {
#ifndef ASYNC
if (AcAssocRequest (ode, NULLAEI, aei, NULLPA, pz, pl, ode,
prequirements, srequirements, ISN (srequirements), tokens, sf,
udata, NACDATA, NULLQOS, acc, aci)
== NOTOK) {
fprintf (stderr, "failed\n");
acs_adios (aca, "A-ASSOCIATE.REQUEST");
}
sd = acc -> acc_sd;
#else
if ((i = AcAsynAssocRequest (ode, NULLAEI, aei, NULLPA, pz, pl, ode,
prequirements, srequirements, ISN (srequirements), tokens, sf,
udata, NACDATA, NULLQOS, acc, aci, 1)) == NOTOK) {
fprintf (stderr, "failed\n");
acs_adios (aca, "A-(ASYN-)ASSOCIATE.REQUEST");
}
sd = acc -> acc_sd, cc = 0;
while (i == CONNECTING_1 || i == CONNECTING_2) {
int nfds;
fd_set mask,
*rmask,
*wmask;
nfds = 0;
FD_ZERO (&mask);
if (PSelectMask (sd, &mask, &nfds, pi) == NOTOK) {
fprintf (stderr, "failed\n");
acs_adios (aca, "A-(ASYN-)ASSOCIATE.REQUEST(PSelectMask)");
}
rmask = (i == CONNECTING_2) ? &mask : NULLFD;
wmask = (i == CONNECTING_2) ? NULLFD : &mask;
fprintf (stderr, ".");
if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
fprintf (stderr, "failed\n");
adios ("failed", "select");
}
if ((rmask && FD_ISSET (sd, rmask) == 0)
|| (wmask && FD_ISSET (sd, wmask) == 0))
continue;
if ((i = AcAsynRetryRequest (sd, acc, aci)) == NOTOK) {
fprintf (stderr, "failed\n");
acs_adios (aca, "A-ASYN-RETRY.REQUEST");
}
}
#endif
if (acc -> acc_result != ACS_ACCEPT) {
fprintf (stderr, "failed\n");
adios (NULLCP, "connection rejected: [%s], %d elements",
AcErrString (acc -> acc_result), acc -> acc_ninfo);
}
}
else {
#ifndef ASYNC
if (PConnRequest (NULLPA, pz, pl, NULLOID, prequirements,
srequirements, srequirements
& (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY)
? (long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1)) + SERIAL_MIN
: SERIAL_NONE, tokens, sf, udata, NPDATA, NULLQOS, pc, pi) == NOTOK) {
fprintf (stderr, "failed\n");
ps_adios (pa, "P-CONNECT.REQUEST");
}
sd = pc -> pc_sd;
#else
if ((i = PAsynConnRequest (NULLPA, pz, pl, NULLOID, prequirements,
srequirements, ISN (srequirements), tokens, sf, udata, NPDATA,
NULLQOS, pc, pi, 1)) == NOTOK) {
fprintf (stderr, "failed\n");
ps_adios (pa, "P-CONNECT.REQUEST");
}
sd = pc -> pc_sd, cc = 0;
while (i == CONNECTING_1 || i == CONNECTING_2) {
int nfds;
fd_set mask,
*rmask,
*wmask;
nfds = 0;
FD_ZERO (&mask);
if (PSelectMask (sd, &mask, &nfds, pi) == NOTOK) {
fprintf (stderr, "failed\n");
ps_adios (pa, "P-CONNECT.REQUEST(PSelectMask)");
}
rmask = (i == CONNECTING_2) ? &mask : NULLFD;
wmask = (i == CONNECTING_2) ? NULLFD : &mask;
fprintf (stderr, ".");
if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
fprintf (stderr, "failed\n");
adios ("failed", "select");
}
if ((rmask && FD_ISSET (sd, rmask) == 0)
|| (wmask && FD_ISSET (sd, wmask) == 0))
continue;
if ((i = PAsynRetryRequest (sd, pc, pi)) == NOTOK) {
fprintf (stderr, "failed\n");
ps_adios (pa, "P-ASYN-RETRY.REQUEST");
}
}
#endif
if (pc -> pc_result != PC_ACCEPT) {
fprintf (stderr, "failed\n");
adios (NULLCP, "connection rejected: [%s], %d elements",
PErrString (pc -> pc_result), pc -> pc_ninfo);
}
}
fprintf (stderr, "connected\n");
if (isacs) {
pc = &acc -> acc_connect;
#ifdef DEBUG
{
advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
advise (NULLCP,
"responding AE title: %s, responding PSAP address: %s",
sprintaei (&acc -> acc_respondtitle),
paddr2str (&pc -> pc_responding, NULLNA));
advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
pl = &pc -> pc_ctxlist;
for (i = 0; i < pl -> pc_nctx; i++)
advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
advise (NULLCP, "default %d", pc -> pc_defctxresult);
advise (NULLCP, "p/s requirements 0x%x/0x%x",
pc -> pc_prequirements, pc -> pc_srequirements);
}
#endif
pl = &pc -> pc_ctxlist;
if (mode == echo) {
if (acc -> acc_ninfo != NACDATA)
adios (NULLCP, "expecting %d hellos, got %d elements",
NACDATA, acc -> acc_ninfo);
for (i = 0; i < NACDATA; i++) {
if ((pe = acc -> acc_info[i]) == NULLPE)
adios (NULLCP, "hello %d: NULL", i);
if ((j = prim2num (pe)) == NOTOK
&& pe -> pe_errno != PE_ERR_NONE)
adios (NULLCP, "hello %d: %s", i,
pe_error (pe -> pe_errno));
if (j != i)
adios (NULLCP, "hello %d: value %d", i, j);
if (pe -> pe_context != udata[i] -> pe_context)
adios (NULLCP, "hello %d: context of %d instead of %d",
i, pe -> pe_context, udata[i] -> pe_context);
}
}
goto do_release;
}
else {
#ifdef DEBUG
{
advise (NULLCP, "responding PSAP address: %s",
paddr2str (&pc -> pc_responding, NULLNA));
advise (NULLCP, "greetings: %d elements", pc -> pc_ninfo);
pl = &pc -> pc_ctxlist;
for (i = 0; i < pl -> pc_nctx; i++)
advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
advise (NULLCP, "default %d", pc -> pc_defctxresult);
advise (NULLCP, "p/s requirements 0x%x/0x%x",
pc -> pc_prequirements, pc -> pc_srequirements);
}
#endif
if (mode == echo) {
if (pc -> pc_ninfo != NPDATA)
adios (NULLCP, "expecting %d hellos, got %d elements",
NPDATA, pc -> pc_ninfo);
for (i = 0; i < NPDATA; i++) {
if ((pe = pc -> pc_info[i]) == NULLPE)
adios (NULLCP, "hello %d: NULL", i);
if ((j = prim2num (pe)) == NOTOK
&& pe -> pe_errno != PE_ERR_NONE)
adios (NULLCP, "hello %d: %s", i,
pe_error (pe -> pe_errno));
if (j != i)
adios (NULLCP, "hello %d: value %d", i, j);
if (pe -> pe_context != udata[i] -> pe_context)
adios (NULLCP, "hello %d: context of %d instead of %d",
i, pe -> pe_context, udata[i] -> pe_context);
}
}
}
nctxs = 0;
pl = &pc -> pc_ctxlist;
for (i = 0; i < pl -> pc_nctx; i++)
if (pl -> pc_ctx[i].pc_result == PC_ACCEPT)
datactxs[nctxs++] = pl -> pc_ctx[i].pc_id;
srequirements = pc -> pc_srequirements;
nmodes = 0;
datamodes[nmodes++] = SX_NORMAL;
if (srequirements & SR_EXPEDITED)
datamodes[nmodes++] = SX_EXPEDITED;
if ((srequirements & SR_CAPABILITY) && (srequirements & SR_ACTIVITY))
datamodes[nmodes++] = SX_CAPDIND;
if (srequirements & SR_TYPEDATA)
datamodes[nmodes++] = SX_TYPED;
#define dotoken(requires,shift,bit,type) \
{ \
if (srequirements & requires) \
switch (pc -> pc_settings & (ST_MASK << shift)) { \
case ST_CALL_VALUE: \
adios (NULLCP, "%s token: choice", type); \
\
case ST_INIT_VALUE: \
owned |= bit, avail |= bit; \
break; \
\
case ST_RESP_VALUE: \
avail |= bit; \
break; \
\
default: \
adios (NULLCP, "%s token: reserved", type); \
} \
}
dotokens ();
#undef dotoken
if (isacs)
ACCFREE (acc)
else
PCFREE (pc);
if (srequirements & SR_ACTIVITY) {
(void) strcpy (id -> sd_data, mode == echo ? "echo" : "sink");
id -> sd_len = strlen (id -> sd_data);
if (PActStartRequest (sd, id, udata, NPDATA, pi) == NOTOK)
ps_adios (pa, "P-ACTIVITY-START.REQUEST");
}
if (fstat (fileno (stdin), &st) != NOTOK
&& (st.st_mode & S_IFMT) == S_IFREG
&& (cc = st.st_size) != 0) {
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
if ((pe = oct2prim (cp, cc)) == NULLPE)
adios (NULLCP, "unable to allocate PSDU");
free (cp);
if (nctxs)
pe -> pe_context = datactxs[0];
for (i = 10; i > 0; i--) {
#ifdef TIMER
timer (0);
#endif
ps_datarequest (sd, pe, SX_NORMAL, 0);
#ifdef TIMER
timer (cc);
#endif
}
pe_free (pe);
}
else {
for (j = l = m = 0; fgets (buffer, sizeof buffer, stdin); ) {
k = j >= nmodes ? SX_EXPEDITED : datamodes[j++ % nmodes];
if ((cc = strlen (buffer) + 1) > SX_EXSIZE - 7
&& k == SX_EXPEDITED) {
if ((k = datamodes[j++ % nmodes]) == SX_EXPEDITED)
k = datamodes[j++ % nmodes];
}
switch (k) {
case SX_CAPDIND:
if (!(requirements & SR_RESYNC) || l++ & 0x01) {
ps_waitfor (sd, ST_ACT_TOKEN);
if (l & 0x03) {
if (PActIntrRequest (sd, SP_SEQUENCE, pi)
== NOTOK)
ps_adios (pa, "P-ACTIVITY-INTERRUPT.REQUEST");
}
else {
if (PActDiscRequest (sd, SP_SEQUENCE, pi)
== NOTOK)
ps_adios (pa, "P-ACTIVITY-DISCARD.REQUEST");
}
ps_waitfor (sd, -1);
goto push_data;
}
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if (requirements & requires) \
tokens |= ST_CALL_VALUE << shift; \
}
dotokens ();
#undef dotoken
if (PReSyncRequest (sd, SYNC_SET, ssn - 1, tokens,
udata, NPDATA, pi) == NOTOK)
ps_adios (pa, "P-RESYNCHRONIZE.REQUEST");
ps_waitfor (sd, -1);
break;
case SX_EXPEDITED:
if (j >= nmodes)
j = j % nmodes;
if (!(srequirements & SR_EXPEDITED))
k = SX_NORMAL; /* fall... */
default:
push_data: ;
if ((pe = oct2prim (buffer, cc)) == NULLPE)
adios (NULLCP, "unable to allocate PSDU");
if (nctxs && k != SX_EXPEDITED)
pe -> pe_context = datactxs[m++ % nctxs];
ps_datarequest (sd, pe, k, 1);
pe_free (pe);
if (k == SX_CAPDIND
&& PActResumeRequest (sd, id, id,
(long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1))
+ SERIAL_MIN, sf, udata, NPDATA, pi)
== NOTOK)
ps_adios (pa, "P-ACTIVITY-RESUME.REQUEST");
break;
}
}
if (requirements & SR_EXCEPTIONS) {
if (owned & ST_DAT_TOKEN)
if (PGTokenRequest (sd, ST_DAT_TOKEN, pi) == NOTOK)
ps_adios (pa, "P-TOKEN-GIVE.REQUEST");
else
owned &= ~ST_DAT_TOKEN;
if (PUReportRequest (sd, SP_NOREASON, udata, NPDATA, pi) == NOTOK)
ps_adios (pa, "P-U-EXCEPTION-REPORT.REQUEST");
ps_waitfor (sd, -1);
}
}
if ((requirements & SR_MAJORSYNC) && !(requirements & SR_ACTIVITY)) {
if (PMajSyncRequest (sd, &ssn, udata, NPDATA, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
| ST_MAJ_TOKEN);
if (PMajSyncRequest (sd, &ssn, udata, NPDATA, pi) == OK)
break; /* else fall */
default:
ps_adios (pa, "P-MAJOR-SYNC.REQUEST");
}
ps_waitfor (sd, -1);
}
if (requirements & SR_ACTIVITY) {
if (PActEndRequest (sd, &ssn, udata, NPDATA, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, avail);
if (PActEndRequest (sd, &ssn, udata, NPDATA, pi) == OK)
break; /* else fall */
default:
ps_adios (pa, "P-ACTIVITY-END.REQUEST");
}
ps_waitfor (sd, -1);
if (PGControlRequest (sd, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, avail);
if (PGControlRequest (sd, pi) == OK)
break; /* else fall */
default:
ps_adios (pa, "P-CONTROL-GIVE.REQUEST");
}
owned = 0;
ps_waitfor (sd, -1);
}
do_release: ;
if (isacs) {
if (AcRelRequest (sd, ACF_NORMAL, udata, NACDATA, NOTOK, acr, aci)
== NOTOK)
switch (aca -> aca_reason) {
case ACS_OPERATION:
ps_waitfor (sd, avail);
if (AcRelRequest (sd, ACF_NORMAL, udata, NACDATA, NOTOK,
acr, aci) == OK)
break; /* else fall */
default:
acs_adios (aca, "A-RELEASE.REQUEST");
}
if (!acr -> acr_affirmative) {
(void) AcUAbortRequest (sd, NULLPEP, 0, aci);
adios (NULLCP, "release rejected by peer: %d, %d elements",
acr -> acr_reason, acr -> acr_ninfo);
}
#ifdef DEBUG
advise (NULLCP, "A-RELEASE.CONFIRMATION: %d, %d elements",
acr -> acr_reason, acr -> acr_ninfo);
#endif
ACRFREE (acr);
}
else {
if (PRelRequest (sd, udata, NPDATA, NOTOK, pr, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
case PC_WAITING:
ps_waitfor (sd, avail);
if (PRelRequest (sd, udata, NPDATA, NOTOK, pr, pi) == OK)
break; /* else fall */
default:
ps_adios (pa, "P-RELEASE.REQUEST");
}
if (!pr -> pr_affirmative) {
(void) PUAbortRequest (sd, NULLPEP, 0, pi);
adios (NULLCP, "release rejected by peer: %d elements",
pr -> pr_ninfo);
}
PRFREE (pr);
}
for (i = 0; i < NPDATA; i++)
pe_free (udata[i]);
}
/* \f
*/
static int ps_datarequest (sd, pe, dm, sync)
int sd;
PE pe;
int dm,
sync;
{
int result;
struct PSAPdata pxs;
register struct PSAPdata *px = &pxs;
struct PSAPindication pis;
register struct PSAPindication *pi = &pis;
register struct PSAPabort *pa = &pi -> pi_abort;
switch (dm) {
default:
if (PDataRequest (sd, &pe, 1, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, ST_DAT_TOKEN);
if (PDataRequest (sd, &pe, 1, pi) == OK)
break;/* else fall */
default:
ps_adios (pa, "P-DATA.REQUEST");
}
break;
case SX_EXPEDITED:
if (PExpdRequest (sd, &pe, 1, pi) == NOTOK)
ps_adios (pa, "P-EXPEDITED-DATA.REQUEST");
break;
case SX_CAPDIND:
if (PCapdRequest (sd, &pe, 1, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, avail & ~ST_RLS_TOKEN);
if (PCapdRequest (sd, &pe, 1, pi) == OK)
break;/* else fall */
default:
ps_adios (pa, "P-CAPABILITY-DATA.REQUEST");
}
break;
case SX_TYPED:
if (PTypedRequest (sd, &pe, 1, pi) == NOTOK)
ps_adios (pa, "P-TYPED-DATA.REQUEST");
break;
}
if (mode == echo || dm == SX_CAPDIND)
for (;;) {
switch (result = PReadRequest (sd, px, NOTOK, pi)) {
case NOTOK:
ps_adios (pa, "P-READ.REQUEST");
case OK:
if ((dm != SX_CAPDIND ? dm : SX_CAPDCNF)
!= px -> px_type) {
advise (NULLCP,
"data indication type mismatch, orig=%d echo=%d",
dm, px -> px_type);
status++;
}
if (px -> px_ninfo != 1) {
advise (NULLCP, "length mismatch, orig=%d echo=%d",
1, px -> px_ninfo);
status++;
}
if (pe -> pe_context != (*px -> px_info) -> pe_context) {
advise (NULLCP, "context mismatch, orig=%d echo=%d",
pe -> pe_context,
(*px -> px_info) -> pe_context);
status++;
}
if (pe_cmp (pe, *px -> px_info)) {
advise (NULLCP, "data mismatch");
status++;
}
PXFREE (px)
break;
case DONE:
ps_event (sd, pi);
continue;
default:
adios (NULLCP, "unknown return from PReadRequest=%d",
result);
}
break;
}
if (sync &&
(srequirements & SR_MINORSYNC) && !(srequirements & SR_ACTIVITY)) {
if (PMinSyncRequest (sd, SYNC_CONFIRM, &ssn, NULLPEP, 0, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN);
if (PMinSyncRequest (sd, SYNC_CONFIRM, &ssn, NULLPEP, 0,
pi) == OK)
break; /* else fall */
default:
ps_adios (pa, "P-MINOR-SYNC.REQUEST");
}
ps_waitfor (sd, -1);
}
else
if (sync
&& (srequirements & SR_ACTIVITY)
&& (srequirements & SR_MAJORSYNC)
&& dm == SX_NORMAL) {
if (PMajSyncRequest (sd, &ssn, NULLPEP, 0, pi) == NOTOK)
switch (pa -> pa_reason) {
case PC_OPERATION:
ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
| ST_MAJ_TOKEN);
if (PMajSyncRequest (sd, &ssn, NULLPEP, 0, pi) == OK)
break;/* else fall */
default:
ps_adios (pa, "P-MAJOR-SYNC.REQUEST");
}
ps_waitfor (sd, -1);
}
}
/* \f
*/
static int ps_waitfor (sd, want)
int sd,
want;
{
int result,
tokens;
struct PSAPdata pxs;
register struct PSAPdata *px = &pxs;
struct PSAPindication pis;
register struct PSAPindication *pi = &pis;
register struct PSAPabort *pa = &pi -> pi_abort;
for (;;) {
if (want == -1) {
want = avail;
goto read_it;
}
tokens = 0;
#define dotoken(requires,shift,bit,type) \
{ \
if ((want & bit) && !(owned & bit)) \
tokens |= bit; \
}
dotokens ();
#undef dotoken
if (tokens == 0)
return;
if (PPTokenRequest (sd, tokens, NULLPEP, 0, pi) == NOTOK)
ps_adios (pa, "P-TOKEN-PLEASE.REQUEST");
read_it: ;
switch (result = PReadRequest (sd, px, NOTOK, pi)) {
case NOTOK:
ps_adios (pa, "P-READ.REQUEST");
case OK:
ps_abort (sd, "protocol screw-up");
case DONE:
ps_event (sd, pi);
break;
default:
adios (NULLCP, "unknown return from PReadRequest=%d",
result);
}
}
}
/* \f
*/
static ps_event (sd, pi)
int sd;
register struct PSAPindication *pi;
{
register struct PSAPabort *pa = &pi -> pi_abort;
register struct PSAPactivity *pv = &pi -> pi_activity;
register struct PSAPfinish *pf = &pi -> pi_finish;
register struct PSAPreport *pp = &pi -> pi_report;
register struct PSAPsync *pn = &pi -> pi_sync;
register struct PSAPtoken *pt = &pi -> pi_token;
struct AcSAPindication acis;
register struct AcSAPindication *aci = &acis;
register struct AcSAPabort *aca = &aci -> aci_abort;
register struct AcSAPfinish *acf = &aci -> aci_finish;
switch (pi -> pi_type) {
case PI_TOKEN:
switch (pt -> pt_type) {
case ST_GIVE:
case ST_CONTROL:
owned = pt -> pt_owned;
break;
case ST_PLEASE:
if (PGTokenRequest (sd,
(int) pt -> pt_tokens, pi)
== NOTOK)
ps_adios (pa, "P-TOKEN-GIVE.REQUEST");
else
owned &= ~pt -> pt_tokens;
break;
default:
adios (NULLCP,
"unknown token indication type=0x%x",
pt -> pt_type);
}
PTFREE (pt);
break;
case PI_SYNC:
switch (pn -> pn_type) {
case SN_MAJORIND:
adios (NULLCP, "majorsync indication %d",
pn -> pn_ssn);
break;
case SN_MAJORCNF:
break;
case SN_MINORIND:
adios (NULLCP, "minorsync indication %d%s",
pn -> pn_ssn, pn -> pn_options == SYNC_CONFIRM
? " (wants confirmation)" : NULLCP);
break;
case SN_MINORCNF:
break;
case SN_RESETIND:
#define dotoken(requires,shift,bit,type) \
{ \
if (srequirements & requires) \
switch (pn -> pn_settings & (ST_MASK << shift)) { \
case ST_CALL_VALUE << shift: \
pn -> pn_settings &= ~(ST_MASK << shift); \
pn -> pn_settings |= ST_RESP_VALUE << shift; \
case ST_RESP_VALUE << shift: \
owned &= ~bit; \
break; \
\
case ST_INIT_VALUE << shift: \
owned |= bit; \
break; \
\
default: \
adios (NULLCP, "%s token: reserved", type); \
break; \
} \
}
dotokens ();
#undef dotoken
if (PReSyncResponse (sd, pn -> pn_ssn, pn -> pn_settings,
NULLPEP, 0, pi) == NOTOK)
ps_adios (pa, "P-RESYNCHRONIZE.RESPONSE");
break;
case SN_RESETCNF:
break;
default:
adios (NULLCP, "unknown sync indication=0x%x, ssn=%d",
pn -> pn_type, pn -> pn_ssn);
}
PNFREE (pn);
break;
case PI_ACTIVITY:
switch (pv -> pv_type) {
case SV_START:
adios (NULLCP, "activity start indication: %*.*s",
pv -> pv_id.sd_len, pv -> pv_id.sd_len,
pv -> pv_id.sd_data);
case SV_RESUME:
adios (NULLCP,
"activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d",
pv -> pv_id.sd_len, pv -> pv_id.sd_len,
pv -> pv_id.sd_data, pv -> pv_oid.sd_len,
pv -> pv_oid.sd_len, pv -> pv_oid.sd_data,
sprintref (&pv -> pv_connect), pv -> pv_ssn);
case SV_INTRIND:
adios (NULLCP, "activity interrupt indication %d",
pv -> pv_reason);
case SV_INTRCNF:
break;
case SV_DISCIND:
adios (NULLCP, "activity discard indication %d",
pv -> pv_reason);
case SV_DISCCNF:
break;
case SV_ENDIND:
adios (NULLCP, "activity end indication %d",
pv -> pv_ssn);
case SV_ENDCNF:
break;
default:
adios (NULLCP, "unknown activity indication=0x%x",
pv -> pv_type);
}
PVFREE (pv);
break;
case PI_REPORT:
advise (NULLCP, "%s report %d",
pp -> pp_peer ? "user" : "provider", pp -> pp_reason);
if (srequirements & SR_DAT_EXISTS) {
if (PGTokenRequest (sd, ST_DAT_TOKEN, pi) == NOTOK)
ps_adios (pa, "P-TOKEN-GIVE.REQUEST (to clear exception)");
else
owned &= ~ST_DAT_TOKEN;
}
else
ps_abort (sd, "aborted");
PPFREE (pp);
break;
case PI_FINISH:
if (isacs) {
if (AcFINISHser (sd, pf, aci) == NOTOK)
acs_adios (aca, "AcFINISHser");
#ifdef DEBUG
advise (NULLCP, "A-RELEASE.INDICATION %d, %d elements",
acf -> acf_reason, acf -> acf_ninfo);
if (AcRelResponse (sd, ACS_USER_NOREASON, ACR_NOTFINISHED,
NULLPEP, 0, aci) == NOTOK)
acs_adios (aca, "A-RELEASE.RESPONSE");
#endif
ACFFREE (acf);
}
else {
if (PRelResponse (sd, PC_REJECTED, NULLPEP, 0, pi) == NOTOK)
ps_adios (pa, "P-RELEASE.RESPONSE");
PFFREE (pf);
}
break;
default:
adios (NULLCP, "unknown indication type=0x%x", pi -> pi_type);
}
}
/* \f
*/
static ps_abort (sd, reason)
int sd;
char *reason;
{
struct PSAPindication pis;
register struct PSAPindication *pi = &pis;
register struct PSAPabort *pa = &pi -> pi_abort;
struct AcSAPindication acis;
register struct AcSAPindication *aci = &acis;
register struct AcSAPabort *aca = &aci -> aci_abort;
if (isacs) {
if (AcUAbortRequest (sd, NULLPEP, 0, aci) == NOTOK)
acs_adios (aca, "A-U-ABORT.REQUEST");
}
else {
if (PUAbortRequest (sd, NULLPEP, 0, pi) == NOTOK)
ps_adios (pa, "P-U-ABORT.REQUEST");
}
adios (NULLCP, "%s", reason);
}
/* \f
*/
static void ps_adios (pa, event)
register struct PSAPabort *pa;
char *event;
{
ps_advise (pa, event);
_exit (1);
}
static void ps_advise (pa, event)
register struct PSAPabort *pa;
char *event;
{
char buffer[BUFSIZ];
if (pa -> pa_cc > 0)
(void) sprintf (buffer, "[%s] %*.*s",
PErrString (pa -> pa_reason),
pa -> pa_cc, pa -> pa_cc, pa -> pa_data);
else
(void) sprintf (buffer, "[%s]", PErrString (pa -> pa_reason));
advise (NULLCP, "%s: %s%s", event, buffer,
pa -> pa_peer ? " (peer initiated)" : "");
}
/* \f
AcSAP */
static void acs_adios (aca, event)
register struct AcSAPabort *aca;
char *event;
{
acs_advise (aca, event);
_exit (1);
}
static void acs_advise (aca, event)
register struct AcSAPabort *aca;
char *event;
{
char buffer[BUFSIZ];
if (aca -> aca_cc > 0)
(void) sprintf (buffer, "[%s] %*.*s",
AcErrString (aca -> aca_reason),
aca -> aca_cc, aca -> aca_cc, aca -> aca_data);
else
(void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason));
advise (NULLCP, "%s: %s (source %d)", event, buffer,
aca -> aca_source);
}
/* \f
RtSAP */
static int turn = 0;
/* \f
*/
static int rts_main (is, addr)
struct isoservent *is;
char *addr;
{
int sd,
cc,
i,
j,
ros;
char *cp,
*dp,
buffer[BUFSIZ];
register struct PSAPaddr *pa;
struct PSAPctxlist pls;
register struct PSAPctxlist *pl = &pls;
struct AcSAPrelease acrs;
register struct AcSAPrelease *acr = &acrs;
struct RtSAPaddr rtzs;
register struct RtSAPaddr *rtz = &rtzs;
struct RtSAPconnect rtcs;
register struct RtSAPconnect *rtc = &rtcs;
struct RtSAPindication rtis;
register struct RtSAPindication *rti = &rtis;
register struct RtSAPabort *rta = &rti -> rti_abort;
#ifdef DEBUG
struct AcSAPconnect *acc= &rtc -> rtc_connect;
struct PSAPconnect *pc = &acc -> acc_connect;
#endif
register PE pe;
AEI aei;
OID oid,
ode;
struct stat st;
if ((pe = int2prim (i = getpid ())) == NULLPE)
adios (NULLCP, "unable to allocate hello");
turn = mode == sink;
if (isacs) {
if (ros = strncmp (isacs, "isode/ros_", strlen ("isode/ros_")) == 0)
mode = strcmp (isacs, "isode/ros_sink") ? echo : sink;
else
mode = strcmp (isacs, "isode/rtse sink") ? echo : sink;
turn = mode == sink;
if ((aei = str2aei (addr, isacs)) == NULLAEI)
adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
if ((pa = aei2addr (aei)) == NULLPA)
adios (NULLCP, "address translation failed");
cp = mode == echo ? "isode echo pci" : "isode sink pci";
if ((ode = ode2oid (cp)) == NULLOID)
adios (NULLCP, "%s: unknown object descriptor", cp);
ode = oid_cpy (ode);
for (j = (pl -> pc_nctx = NPCTX - 2) - 1; j >= 0; j--) {
pl -> pc_ctx[j].pc_id = j * 2 + 1;
if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
adios (NULLCP, "iso asn.1 abstract syntax: unknown");
pl -> pc_ctx[j].pc_asn = oid_cpy (oid);
pl -> pc_ctx[j].pc_atn = NULLOID;
}
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
if (RtOpenRequest (RTS_TWA, turn ? RTS_INITIATOR : RTS_RESPONDER,
ode, NULLAEI, aei, NULLPA, pa, pl, ode, pe,
NULLQOS, rtc, rti) == NOTOK) {
fprintf (stderr, "failed\n");
rts_adios (rta, "RT-OPEN.REQUEST");
}
}
else {
register struct SSAPaddr *sa;
if (ros = strncmp (is -> is_entity, "ros_", strlen ("ros_")) == 0) {
mode = strcmp (is -> is_entity, "ros_sink") ? echo : sink;
turn = mode == sink;
}
rtz -> rta_port = is -> is_port; /* yikes! */
if ((is = getisoserventbyname ("rts", "ssap")) == NULL)
adios (NULLCP, "ssap/rts: unknown entity");
if ((sa = is2saddr (addr, NULLCP, is)) == NULLSA)
adios (NULLCP, "address translation failed");
rtz -> rta_addr = *sa; /* struct copy */
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
if (RtBeginRequest (rtz, RTS_TWA, turn ? RTS_INITIATOR : RTS_RESPONDER,
pe, rtc, rti) == NOTOK) {
fprintf (stderr, "failed\n");
rts_adios (rta, "RT-BEGIN.REQUEST");
}
}
pe_free (pe);
if (rtc -> rtc_result != RTS_ACCEPT) {
fprintf (stderr, "failed\n");
adios (NULLCP, "association rejected: [%s]",
RtErrString (rtc -> rtc_result));
}
fprintf (stderr, "connected\n");
#ifdef DEBUG
advise (NULLCP, "sent greetings of %d", i);
#endif
sd = rtc -> rtc_sd;
if (rtc -> rtc_data) {
if ((i = prim2num (rtc -> rtc_data)) == NOTOK
&& rtc -> rtc_data -> pe_errno != PE_ERR_NONE)
adios (NULLCP, "error decoding hello: %s (%d)",
pe_error (rtc -> rtc_data -> pe_errno), i);
#ifdef DEBUG
advise (NULLCP, "received greetings of %d", i);
#endif
}
#ifdef DEBUG
if (isacs) {
advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
advise (NULLCP,
"responding AE title: %s, responding PSAP address: %s",
sprintaei (&acc -> acc_respondtitle),
paddr2str (&pc -> pc_responding, NULLNA));
advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
pl = &pc -> pc_ctxlist;
for (i = 0; i < pl -> pc_nctx; i++)
advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
advise (NULLCP, "default %d", pc -> pc_defctxresult);
advise (NULLCP, "p/s requirements 0x%x/0x%x",
pc -> pc_prequirements, pc -> pc_srequirements);
}
#endif
RTCFREE (rtc);
if (ros) {
struct RoSAPindication rois;
register struct RoSAPpreject *rop = &rois.roi_preject;
if (RoSetService (sd, RoRtService, &rois) == NOTOK)
ros_adios (rop, "set RO/PT fails");
do_ros (sd);
return;
}
if (fstat (fileno (stdin), &st) != NOTOK
&& (st.st_mode & S_IFMT) == S_IFREG
&& (cc = st.st_size) != 0) {
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
if ((pe = oct2prim (cp, cc)) == NULLPE)
adios (NULLCP, "unable to allocate APDU");
free (cp);
for (i = 10; i > 0; i--) {
#ifdef TIMER
timer (0);
#endif
rts_transferequest (sd, pe);
#ifdef TIMER
timer (cc);
#endif
}
pe_free (pe);
}
else
while (fgets (buffer, sizeof buffer, stdin)) {
if ((pe = oct2prim (buffer, strlen (buffer) + 1)) == NULLPE)
adios (NULLCP, "unable to allocate APDU");
rts_transferequest (sd, pe);
pe_free (pe);
}
if (isacs) {
if ((pe = int2prim (i = getpid ())) == NULLPE)
adios (NULLCP, "unable to allocate hello");
if (RtCloseRequest (sd, ACF_NORMAL, pe, acr, rti) == NOTOK)
switch (rta -> rta_reason) {
case RTS_OPERATION:
case RTS_WAITING:
rts_waitfor (sd);
if (RtCloseRequest (sd, ACF_NORMAL, pe, acr, rti)
== OK)
break; /* else fall */
default:
rts_adios (rta, "RT-CLOSE.REQUEST");
}
if (!acr -> acr_affirmative) {
(void) RtUAbortRequest (sd, NULLPE, rti);
adios (NULLCP, "release rejected by peer: %d, %d elements",
acr -> acr_reason, acr -> acr_ninfo);
}
if (mode == echo) {
if (acr -> acr_ninfo != 1)
advise (NULLCP, "got %d elements returned on close",
acr -> acr_ninfo);
if (pe_cmp (pe, acr -> acr_info[0])) {
advise (NULLCP, "data mismatch");
status++;
}
}
ACRFREE (acr);
pe_free (pe);
}
else
if (RtEndRequest (sd, rti) == NOTOK)
switch (rta -> rta_reason) {
case RTS_OPERATION:
case RTS_WAITING:
rts_waitfor (sd);
if (RtEndRequest (sd, rti) == OK)
break; /* else fall */
default:
rts_adios (rta, "RT-END.REQUEST");
}
}
/* \f
*/
static int rts_transferequest (sd, pe)
int sd;
register PE pe;
{
int result;
struct RtSAPindication rtis;
register struct RtSAPindication *rti = &rtis;
register struct RtSAPabort *rta = &rti -> rti_abort;
register struct RtSAPtransfer *rtt = &rti -> rti_transfer;
if (RtTransferRequest (sd, pe, NOTOK, rti) == NOTOK)
switch (rta -> rta_reason) {
case RTS_OPERATION:
rts_waitfor (sd);
if (RtTransferRequest (sd, pe, NOTOK, rti) == OK)
break; /* else fall */
default:
if (RTS_FATAL (rta -> rta_reason))
rts_adios (rta, "RT-TRANSFER.REQUEST");
rts_advise (rta, "RT-TRANSFER.REQUEST");
return;
}
if (mode == echo)
for (;;)
switch (result = RtWaitRequest (sd, NOTOK, rti)) {
case NOTOK:
rts_adios (rta, "RT-WAIT.REQUEST");
case OK:
if (pe_cmp (pe, rtt -> rtt_data)) {
advise (NULLCP, "data mismatch");
status++;
}
RTTFREE (rtt);
return;
case DONE:
rts_event (sd, rti);
break;
default:
adios (NULLCP, "unknown return from RtWaitRequest=%d",
result);
}
}
/* \f
*/
static int rts_waitfor (sd)
int sd;
{
int result;
struct RtSAPindication rtis;
register struct RtSAPindication *rti = &rtis;
register struct RtSAPabort *rta = &rti -> rti_abort;
static int priority = 1;
if (turn)
return;
if (RtPTurnRequest (sd, priority++, rti) == NOTOK)
rts_adios (rta, "RT-TURN-PLEASE.REQUEST");
while (!turn)
switch (result = RtWaitRequest (sd, NOTOK, rti)) {
case NOTOK:
rts_adios (rta, "RT-WAIT.REQUEST");
case OK:
adios (NULLCP, "protocol screw-up");
case DONE:
rts_event (sd, rti);
break;
default:
adios (NULLCP, "unknown return from RtWaitRequest=%d",
result);
}
}
/* \f
*/
static int rts_event (sd, rti)
int sd;
register struct RtSAPindication *rti;
{
register struct RtSAPabort *rta = &rti -> rti_abort;
register struct RtSAPturn *rtu = &rti -> rti_turn;
switch (rti -> rti_type) {
case RTI_TURN:
if (rtu -> rtu_please) {
if (RtGTurnRequest (sd, rti) == NOTOK)
rts_adios (rta, "RT-TURN-GIVE.REQUEST");
turn = 0;
}
else
turn = 1;
break;
case RTI_CLOSE:
adios (NULLCP, "got RT-END.INDICATION");
case RTI_FINISH:
adios (NULLCP, "got RT-CLOSE.INDICATION");
default:
adios (NULLCP, "unknown indication type=0x%x",
rti -> rti_type);
}
}
/* \f
*/
static void rts_adios (rta, event)
register struct RtSAPabort *rta;
char *event;
{
rts_advise (rta, event);
_exit (1);
}
static void rts_advise (rta, event)
register struct RtSAPabort *rta;
char *event;
{
char buffer[BUFSIZ];
if (rta -> rta_cc > 0)
(void) sprintf (buffer, "[%s] %*.*s", RtErrString (rta -> rta_reason),
rta -> rta_cc, rta -> rta_cc, rta -> rta_data);
else
(void) sprintf (buffer, "[%s]", RtErrString (rta -> rta_reason));
advise (NULLCP, "%s: %s", event, buffer);
}
/* \f
RoSAP */
static int ros_main (is, addr)
struct isoservent *is;
char *addr;
{
int sd,
i;
char *cp;
struct SSAPref sfs;
register struct SSAPref *sf;
register struct PSAPaddr *pa;
struct AcSAPconnect accs;
register struct AcSAPconnect *acc = &accs;
struct AcSAPindication acis;
register struct AcSAPindication *aci = &acis;
register struct AcSAPabort *aca = &aci -> aci_abort;
struct RoSAPaddr roas;
register struct RoSAPaddr *roa = &roas;
struct RoSAPconnect rocs;
register struct RoSAPconnect *roc = &rocs;
struct RoSAPindication rois;
register struct RoSAPindication *roi = &rois;
register struct RoSAPpreject *rop = &roi -> roi_preject;
#ifdef DEBUG
struct PSAPconnect *pc = &acc -> acc_connect;
#endif
struct PSAPctxlist pls;
register struct PSAPctxlist *pl = &pls;
AEI aei;
OID oid,
ode;
register PE pe;
if (isacs) {
if ((aei = str2aei (addr, isacs)) == NULLAEI)
adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
if ((pa = aei2addr (aei)) == NULLPA)
adios (NULLCP, "address translation failed");
cp = mode == echo ? "isode echo pci" : "isode sink pci";
if ((ode = ode2oid (cp)) == NULLOID)
adios (NULLCP, "%s: unknown object descriptor", cp);
ode = oid_cpy (ode);
if ((sf = addr2ref (PLocalHostName ())) == NULL) {
sf = &sfs;
(void) bzero ((char *) sf, sizeof *sf);
}
pl -> pc_nctx = 1;
pl -> pc_ctx[0].pc_id = 1;
if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
adios (NULLCP, "iso asn.1 abstract syntax: unknown");
pl -> pc_ctx[0].pc_asn = oid_cpy (oid);
pl -> pc_ctx[0].pc_atn = NULLOID;
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
if (AcAssocRequest (ode, NULLAEI, aei, NULLPA, pa, pl, ode,
0, ROS_MYREQUIRE, SERIAL_NONE, 0, sf, NULLPEP, 0, NULLQOS,
acc, aci)
== NOTOK)
acs_adios (aca, "A-ASSOCIATE.REQUEST");
if (acc -> acc_result != ACS_ACCEPT) {
fprintf (stderr, "failed\n");
adios (NULLCP, "association rejected: [%s]",
AcErrString (acc -> acc_result));
}
fprintf (stderr, "connected\n");
sd = acc -> acc_sd;
#ifdef DEBUG
pa = &pc -> pc_responding;
{
advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
advise (NULLCP,
"responding AE title: %s, responding PSAP address: %s",
sprintaei (&acc -> acc_respondtitle),
paddr2str (&pc -> pc_responding, NULLNA));
advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
pl = &pc -> pc_ctxlist;
for (i = 0; i < pl -> pc_nctx; i++)
advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
advise (NULLCP, "default %d", pc -> pc_defctxresult);
advise (NULLCP, "p/s requirements 0x%x/0x%x",
pc -> pc_prequirements, pc -> pc_srequirements);
}
#endif
ACCFREE (acc);
if (RoSetService (sd, RoPService, roi) == NOTOK)
ros_adios (rop, "set RO/PT fails");
}
else {
register struct SSAPaddr *sa;
roa -> roa_port = is -> is_port; /* yikes! */
if ((is = getisoserventbyname ("ros", "ssap")) == NULL)
adios (NULLCP, "ssap/ros: unknown entity");
if ((sa = is2saddr (addr, NULLCP, is)) == NULLSA)
adios (NULLCP, "address translation failed");
roa -> roa_addr = *sa; /* struct copy */
if ((pe = int2prim (i = getpid ())) == NULLPE)
adios (NULLCP, "unable to allocate hello");
fprintf (stderr, "%s... ", addr);
(void) fflush (stderr);
if (RoBeginRequest (roa, pe, roc, roi) == NOTOK) {
fprintf (stderr, "failed\n");
ros_adios (rop, "RO-BEGIN.REQUEST");
}
pe_free (pe);
if (roc -> roc_result != ROS_ACCEPT) {
fprintf (stderr, "failed\n");
adios (NULLCP, "association rejected: [%s]",
RoErrString (roc -> roc_result));
}
fprintf (stderr, "connected\n");
#ifdef DEBUG
advise (NULLCP, "sent greetings of %d", i);
#endif
sd = roc -> roc_sd;
if (roc -> roc_data) {
if ((i = prim2num (roc -> roc_data)) == NOTOK
&& roc -> roc_data -> pe_errno != PE_ERR_NONE)
adios (NULLCP, "error decoding hello: %s (%d)",
pe_error (roc -> roc_data -> pe_errno), i);
#ifdef DEBUG
advise (NULLCP, "received greetings of %d", i);
#endif
}
ROCFREE (roc);
}
do_ros (sd);
}
/* \f
*/
static int do_ros (sd)
int sd;
{
int cc,
i,
j;
char *cp,
*dp,
buffer[BUFSIZ];
struct RoSAPindication rois;
register struct RoSAPindication *roi = &rois;
register struct RoSAPpreject *rop = &roi -> roi_preject;
struct AcSAPrelease acrs;
register struct AcSAPrelease *acr = &acrs;
register PE pe;
struct stat st;
if (fstat (fileno (stdin), &st) != NOTOK
&& (st.st_mode & S_IFMT) == S_IFREG
&& (cc = st.st_size) != 0) {
(void) lseek (fileno (stdin), 0L, 0);
if ((cp = malloc ((unsigned) cc)) == NULL)
adios (NULLCP, "no memory");
for (dp = cp, j = cc; j > 0; dp += i, j -= i)
switch (i = read (fileno (stdin), dp, j)) {
case NOTOK:
adios ("on stdin", "read failed");
case OK:
adios (NULLCP, "premature end-of-file");
default:
break;
}
if ((pe = oct2prim (cp, cc)) == NULLPE)
adios (NULLCP, "unable to allocate invocation argument");
free (cp);
for (i = 10; i > 0; i--) {
#ifdef TIMER
timer (0);
#endif
ros_invokerequest (sd, pe);
#ifdef TIMER
timer (cc);
#endif
}
pe_free (pe);
}
else
while (fgets (buffer, sizeof buffer, stdin)) {
if ((pe = oct2prim (buffer, strlen (buffer) + 1)) == NULLPE)
adios (NULLCP, "unable to allocate invocation argument");
ros_invokerequest (sd, pe);
pe_free (pe);
}
if (isrts) {
struct RtSAPindication rtis;
register struct RtSAPindication *rti = &rtis;
register struct RtSAPabort *rta = &rti -> rti_abort;
if (isacs) {
if (RtCloseRequest (sd, ACF_NORMAL, NULLPE, acr, rti) == NOTOK)
switch (rta -> rta_reason) {
case RTS_OPERATION:
case RTS_WAITING:
rts_waitfor (sd);
if (RtCloseRequest (sd, ACF_NORMAL, NULLPE, acr, rti)
== OK)
break; /* else fall */
default:
rts_adios (rta, "RT-CLOSE.REQUEST");
}
if (!acr -> acr_affirmative) {
(void) RtUAbortRequest (sd, NULLPE, rti);
adios (NULLCP, "release rejected by peer: %d, %d elements",
acr -> acr_reason, acr -> acr_ninfo);
}
}
else
if (RtEndRequest (sd, rti) == NOTOK)
switch (rta -> rta_reason) {
case RTS_OPERATION:
case RTS_WAITING:
rts_waitfor (sd);
if (RtEndRequest (sd, rti) == OK)
break; /* else fall */
default:
rts_adios (rta, "RT-END.REQUEST");
}
}
else
if (isacs) {
struct AcSAPindication acis;
register struct AcSAPindication *aci = &acis;
register struct AcSAPabort *aca = &aci -> aci_abort;
if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci)
== NOTOK)
acs_adios (aca, "A-RELEASE.REQUEST");
if (!acr -> acr_affirmative) {
(void) AcUAbortRequest (sd, NULLPEP, 0, aci);
adios (NULLCP, "release rejected by peer: %d, %d elements",
acr -> acr_reason, acr -> acr_ninfo);
}
ACRFREE (acr);
}
else
if (RoEndRequest (sd, ROS_NOPRIO, roi) == NOTOK)
ros_adios (rop, "RO-END.REQUEST");
}
/* \f
*/
static int ros_invokerequest (sd, pe)
int sd;
PE pe;
{
int result;
struct RoSAPindication rois;
register struct RoSAPindication *roi = &rois;
register struct RoSAPpreject *rop = &roi -> roi_preject;
static int id = 0;
static int op = 0;
switch (result = RoInvokeRequest (sd, op++, ROS_SYNC, pe, ++id, NULLIP,
ROS_NOPRIO, roi)) {
case NOTOK:
if (ROS_FATAL (rop -> rop_reason))
ros_adios (rop, "RO-INVOKE.REQUEST");
ros_advise (rop, "RO-INVOKE.REQUEST");
break;
case OK:
switch (roi -> roi_type) {
case ROI_INVOKE:
adios (NULLCP, "got RO-INVOKE.INDICATION");
case ROI_RESULT:
{
register struct RoSAPresult *ror = &roi -> roi_result;
if (ror -> ror_id != id) {
advise (NULLCP, "id mismatch (wanted %d, got %d)",
id, ror -> ror_id);
status++;
if (RoURejectRequest (sd, &ror -> ror_id,
ROS_RRP_UNRECOG, ROS_NOPRIO, roi) == NOTOK)
ros_adios (rop, "RO-REJECT-U.REQUEST");
}
else
if (mode == echo
&& pe_cmp (pe, ror -> ror_result)) {
advise (NULLCP, "data mismatch");
status++;
}
RORFREE (ror);
}
break;
case ROI_ERROR:
{
register struct RoSAPerror *roe = &roi -> roi_error;
if (roe -> roe_id != id) {
advise (NULLCP, "id mismatch (wanted %d, got %d)",
id, roe -> roe_id);
status++;
if (RoURejectRequest (sd, &roe -> roe_id,
ROS_REP_UNRECOG, ROS_NOPRIO, roi) == NOTOK)
ros_adios (rop, "RO-REJECT-U.REQUEST");
}
else
if (mode == echo
&& pe_cmp (pe, roe -> roe_param)) {
advise (NULLCP, "data mismatch");
status++;
}
ROEFREE (roe);
}
break;
case ROI_UREJECT:
{
register struct RoSAPureject *rou = &roi -> roi_ureject;
if (rou -> rou_noid)
advise (NULLCP, "RO-REJECT-U.INDICATION: %s",
RoErrString (rou -> rou_reason));
else
advise (NULLCP, "RO-REJECT-U.INDICATION: %s (id=%d)",
RoErrString (rou -> rou_reason),
rou -> rou_id);
if (!rou -> rou_noid && rou -> rou_id != id) {
advise (NULLCP, "id mismatch (wanted %d, got %d)",
id, rou -> rou_id);
status++;
}
}
break;
default:
adios (NULLCP, "unknown indication type=%d",
roi -> roi_type);
}
if (isrts)
turn = 0;
break;
case DONE:
adios (NULLCP, "got RO-END.INDICATION");
default:
adios (NULLCP, "unknown return from RoInvokeRequest=%d", result);
}
}
/* \f
*/
static void ros_adios (rop, event)
register struct RoSAPpreject *rop;
char *event;
{
ros_advise (rop, event);
_exit (1);
}
static void ros_advise (rop, event)
register struct RoSAPpreject *rop;
char *event;
{
char buffer[BUFSIZ];
if (rop -> rop_cc > 0)
(void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason),
rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
else
(void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason));
advise (NULLCP, "%s: %s", event, buffer);
}
/* \f
TIMER */
#ifdef TIMER
#ifndef NBBY
#define NBBY 8
#endif
#ifndef TMS
static timer (cc)
int cc;
{
int bytes;
long ms;
float bs;
struct timeval stop,
td;
static struct timeval start;
if (cc == 0) {
(void) gettimeofday (&start, (struct timezone *) 0);
return;
}
else
(void) gettimeofday (&stop, (struct timezone *) 0);
tvsub (&td, &stop, &start);
ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
bytes = mode == echo ? cc * 2 : cc;
bs = (((float) bytes * NBBY * 1000) / (float) (ms ? ms : 1)) / NBBY;
advise (NULLCP, "%d bytes %s in %d.%02d seconds (%.2f Kbytes/s)",
cc, mode == echo ? "echoed" : "sunk",
td.tv_sec, td.tv_usec / 10000, bs / 1024);
}
static tvsub (tdiff, t1, t0)
register struct timeval *tdiff,
*t1,
*t0;
{
tdiff -> tv_sec = t1 -> tv_sec - t0 -> tv_sec;
tdiff -> tv_usec = t1 -> tv_usec - t0 -> tv_usec;
if (tdiff -> tv_usec < 0)
tdiff -> tv_sec--, tdiff -> tv_usec += 1000000;
}
#else
long times ();
static timer (cc)
int cc;
{
int bytes;
long ms;
float bs;
long stop,
td,
secs,
msecs;
struct tms tm;
static long start;
if (cc == 0) {
start = times (&tm);
return;
}
else
stop = times (&tm);
td = stop - start;
secs = td / 60, msecs = (td % 60) * 1000 / 60;
ms = (secs * 1000) + msecs;
bytes = mode == echo ? cc * 2 : cc;
bs = (((float) bytes * NBBY * 1000) / (float) (ms ? ms : 1)) / NBBY;
advise (NULLCP, "%d bytes %s in %d.%02d seconds (%.2f KBytes/s)",
cc, mode == echo ? "echoed" : "sunk",
secs, msecs / 10, bs / 1024);
}
#endif
#endif
/* \f
QBUF */
static int qcmp (b, qb, l)
register char *b;
register struct qbuf *qb;
register int l;
{
register struct qbuf *qp;
for (qp = qb -> qb_forw; qp != qb; qp = qp -> qb_forw) {
if ((l -= qp -> qb_len) < 0) {
advise (NULLCP, "length mismatch(1)");
return NOTOK;
}
if (bcmp (b, qp -> qb_data, qp -> qb_len)) {
advise (NULLCP, "data mismatch");
return NOTOK;
}
b += qp -> qb_len;
}
if (l != 0) {
advise (NULLCP, "length mismatch(2)");
return NOTOK;
}
return OK;
}
/* \f
ERRORS */
#ifndef lint
void _advise ();
void adios (va_alist)
va_dcl
{
va_list ap;
va_start (ap);
_advise (ap);
va_end (ap);
_exit (1);
}
#else
/* VARARGS */
void adios (what, fmt)
char *what,
*fmt;
{
adios (what, fmt);
}
#endif
#ifndef lint
void advise (va_alist)
va_dcl
{
va_list ap;
va_start (ap);
_advise (ap);
va_end (ap);
}
static void _advise (ap)
va_list ap;
{
char buffer[BUFSIZ];
asprintf (buffer, ap);
(void) fflush (stdout);
fprintf (stderr, "%s: ", myname);
(void) fputs (buffer, stderr);
(void) fputc ('\n', stderr);
(void) fflush (stderr);
}
#else
/* VARARGS */
void advise (what, fmt)
char *what,
*fmt;
{
advise (what, fmt);
}
#endif