home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
internet
/
tcpipsrc
/
h
/
if
/
Radio
/
c
/
NR4
< prev
next >
Wrap
Text File
|
1993-12-22
|
27KB
|
707 lines
/* net/rom level 4 (transport) protocol implementation
* Copyright 1989 by Daniel M. Frank, W9NK. Permission granted for
* non-commercial distribution only.
*/
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "ax25.h"
#include "lapb.h"
#include "netrom.h"
#include "nr4.h"
#include "misc.h"
#undef NR4DEBUG
/* Globals: */
/* The circuit table */
struct nr4circp Nr4circuits[NR4MAXCIRC] ;
/* Various limits */
unsigned Nr4window = 4 ; /* Max window to negotiate */
unsigned Nr4retries = 10 ; /* Max retries */
unsigned Nr4qlimit = 2048 ; /* Max bytes on receive queue */
/* Timers */
long Nr4irtt = 15000 ; /* Initial round trip time */
long Nr4acktime = 3000 ; /* ACK delay timer */
long Nr4choketime = 180000 ; /* CHOKEd state timeout */
/* This function is called when a net/rom layer four frame */
/* is discovered inside a datagram addressed to us */
void nr4input(struct nr4hdr *hdr, struct mbuf *bp)
{
struct nr4hdr rhdr ;
struct nr4cb *cb ;
struct ax25_addr dest ;
int op ;
unsigned window ;
int acceptc ; /* indicates that connection should be accepted */
int newconn ; /* indicates that this is a new incoming */
/* connection. You'll see. */
int gotchoke ; /* The choke flag was set in this packet */
op = hdr->opcode & NR4OPCODE ; /* Mask off flags */
if (op == NR4OPCONRQ) { /* process connect request first */
acceptc = 1 ;
newconn = 0 ;
/* These fields are sent regardless of success */
rhdr.yourindex = hdr->u.conreq.myindex ;
rhdr.yourid = hdr->u.conreq.myid ;
dest = hdr->u.conreq.node ;
/* Check to see if we have already received a connect */
/* request for this circuit. */
if ((cb = match_n4circ(hdr->u.conreq.myindex, hdr->u.conreq.myid,
&hdr->u.conreq.user, &hdr->u.conreq.node))
== NULLNR4CB) { /* No existing circuit if NULL */
/* Try to get a new circuit */
if ((cb = new_n4circ()) == NULLNR4CB) {
acceptc = 0 ;
} else {
/* Window is set to min of the offered and local windows */
window = hdr->u.conreq.window > Nr4window ?
Nr4window : hdr->u.conreq.window ;
if (init_nr4window(cb, window) == -1) {
free_n4circ(cb) ;
acceptc = 0 ;
} else {
/* Set up control block */
cb->yournum = hdr->u.conreq.myindex ;
cb->yourid = hdr->u.conreq.myid ;
cb->user = hdr->u.conreq.user ;
cb->node = hdr->u.conreq.node ;
cb->luser = mycall ;/* we are local user on incomings */
cb->srtt = Nr4irtt ;/* Default round trip time */
nr4defaults(cb) ; /* set up timers, window pointers */
cb->s_upcall = nr4_incom ;
cb->state = NR4STDISC ;
newconn = 1 ;
} /* End if window successfully allocated */
} /* End if new circuit available */
} /* End if no existing circuit matching parameters */
/* Now set up response */
if (!acceptc) {
rhdr.opcode = NR4OPCONAK | NR4CHOKE ;/* choke means reject */
rhdr.u.conack.myindex = 0 ;
rhdr.u.conack.myid = 0 ;
rhdr.u.conack.window = 0 ;
} else {
rhdr.opcode = NR4OPCONAK ;
rhdr.u.conack.myindex = cb->mynum ;
rhdr.u.conack.myid = cb->myid ;
rhdr.u.conack.window = cb->window ;
}
nr4sframe(&dest, &rhdr, NULLBUF) ;
/* Why, you ask, do we wait until now for the state change */
/* upcall? Well, it's like this: if the state change triggers */
/* something like the mailbox to send its banner, the banner */
/* would have gone out *before* the conn ack if we'd done this */
/* in the code above. This is what happens when you don't plan */
/* too well. Learn from my mistakes :-) */
if (newconn)
nr4state(cb, NR4STCON) ;/* connected (no 3-way handshake) */
free_p(bp) ;
return ;
} /* end connect request code */
/* validate circuit number */
if ((cb = get_n4circ(hdr->yourindex, hdr->yourid)) == NULLNR4CB) {
free_p(bp) ;
return ;
}
/* Check for choke flag */
if (hdr->opcode & NR4CHOKE)
gotchoke = 1 ;
else
gotchoke = 0 ;
/* Here's where the interesting stuff gets done */
switch (cb->state) {
case NR4STCPEND:
switch (op) {
case NR4OPCONAK:
stop_timer(&cb->tcd) ;
if (gotchoke) { /* connect rejected */
cb->dreason = NR4RREFUSED ;
nr4state(cb, NR4STDISC) ;
break ;
}
cb->yournum = hdr->u.conack.myindex ;
cb->yourid = hdr->u.conack.myid ;
window = hdr->u.conack.window > Nr4window ?
Nr4window : hdr->u.conack.window ;
if (init_nr4window(cb, window) == -1) {
cb->dreason = NR4RRESET ;
nr4state(cb, NR4STDISC) ;
} else {
nr4defaults(cb) ; /* set up timers, window pointers */
if (cb->cdtries == 1) /* No retries */
cb->srtt = cb->tcd.count * MSPTICK ;/* Use measured rtt */
else
cb->srtt = Nr4irtt ; /* else use default */
nr4state(cb, NR4STCON) ;
nr4output(cb) ; /* start sending anything on the txq */
}
break ;
default: /* We can't respond to anything else without */
/* Their ID and index */
free_p(bp) ;
return ;
}
break ;
case NR4STCON:
switch (op) {
case NR4OPDISRQ:
/* format reply packet */
rhdr.opcode = NR4OPDISAK ;
rhdr.yourindex = cb->yournum ;
rhdr.yourid = cb->y