PAGE 56,132 ; DATA SEGMENT PUBLIC 'DATA' INCLUDE ENVIRON.ASM INCLUDE STRUCS.ASM IFNDEF PCSWITCH EXTRN TENHZCOUNT:WORD ENDIF EXTRN REALTIMETICKS:WORD CONNECTEDMSG DB 'Connected to ' LCONNECTEDMSG EQU $-CONNECTEDMSG FAILEDMSG DB 'Failure with ' LFAILEDMSG EQU $-FAILEDMSG BUSYMSG DB 'Busy from ' LBUSYMSG EQU $-BUSYMSG RETURNEDMSG DB 'Returned to Node ' LRETURNED EQU $-RETURNEDMSG SAVELINK DW 0 ; CURRENT LINK SAVEPORT DB 0 ; CURRENT PORT ; TEMPFIELD DB 7 DUP (0) ; TEMP STORAGE FOR CALL NEXTID DB 55H ; NEXT ID TO ALLOCATE ; FRAGFLAG DB 0 ; MESSAGE FRAGMENTATION FLAG BBSMSG DB 0 ; SET IF MESSAGE IS TO BBS ADDRESS CONNECTSESSION DW 0 ; INCOMING SESSION CONACKCALL DB 20 DUP (0) ; TARGET CALL DURING CONNECT ACK PROCESSING ; BPQNODE DB 0 ; SET IF CALLER IS A BPQ NODE BPQPARAMS DB 10 DUP (0) ; EXTENDED CONNECT PARAMS IF FROM THENODE ; ; FIRST WORD - L4 TIMEOUT ; NEXT BYTE - 'SPY FLAG' ; TRANSPORTLENGTH DB TYPE TRANSPORTENTRY PUBLIC NEXTID,SAVELINK,SAVEPORT EXTRN L3FRAMES:WORD,L4FRAMESTX:WORD,L4FRAMESRX:WORD,HEADERCHAR:BYTE EXTRN L4FRAMESRETRIED:WORD,L4CONNECTSIN:WORD,OLDFRAMES:WORD EXTRN L4DELAY:WORD,L4DEFAULTWINDOW:BYTE,PACLEN:BYTE,APPLMASK:BYTE EXTRN MYCALL:BYTE,BBSCALL:BYTE,AX25CALL:BYTE,NORMCALL:BYTE,QCOUNT:BYTE EXTRN ROUTEQUAL:BYTE,BUFFER:WORD,SAVENBOUR:WORD EXTRN NORMLEN:WORD,SAVEDAPPLFLAGS:BYTE IFDEF PCSWITCH EXTRN BPQHOSTVECTOR:WORD,BPQVECLENGTH:WORD,BPQHOSTSTREAMS:ABS ENDIF EXTRN IPHOSTVECTOR:BYTE EXTRN L4T1:WORD,L3LIVES:BYTE,L4TABLE:WORD,MAXCIRCUITS:WORD EXTRN L4LIMIT:WORD,L4N2:BYTE,NODE:BYTE,D10:BYTE EXTRN TNCTABLE:WORD,NUMBEROFSTREAMS:WORD,DISCFLAG:BYTE EXTRN FULL_CTEXT:BYTE,CTEXTMSG:WORD,CTEXTLEN:WORD DATA ENDS CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA,SS:DATA ; PUBLIC L4BG,PROCESSIFRAME,GETFREECIRCUIT,SENDL4CONNECT PUBLIC SENDCONNECTREPLY,CONNECTFAILED,INFORMPARTNER,L4TIMERPROC PUBLIC CLEARSESSIONENTRY,CONNECTREFUSED,Q_IP_MSG PUBLIC CHECKIFBUSY,CLOSESESSIONPARTNER,SETUPUSERSESSION PUBLIC CLOSECURRENTSESSION,RETURNEDTONODE,INC_ID PUBLIC ATTACHTOBBS,SETUPBPQCONSOLESESSION IF TNC2 PUBLIC SETUPCONSOLESESSION EXTRN DOCONMODECHANGE:NEAR EXTRN SEND_CONNECTED:NEAR,SENDSTARDISC:NEAR,CONSOLESEND:NEAR ENDIF EXTRN Q_ADD:NEAR,GETBUFF:NEAR,RELBUFF:NEAR,COMPARECALLS:NEAR EXTRN GETPORTQUALITY:NEAR,CHECKNEIGHBOUR:NEAR EXTRN CONVFROMAX25:NEAR,CONVTOAX25:NEAR,GETPORTTABLEENTRY:NEAR EXTRN Q_REM:NEAR,REFRESHROUTE:NEAR,COUNT_Q:NEAR EXTRN GETPORTPACLEN:NEAR,HEXOUT:NEAR EXTRN COMMANDHANDLER:NEAR,FINDDESTINATION:NEAR,L3SWAPADDRESSES:NEAR EXTRN FINDNEIGHBOUR:NEAR,SETUPNODEHEADER:NEAR EXTRN CHECKL3TABLES:NEAR,L3CONNECTFAILED:NEAR,L3LINKCLOSED:NEAR EXTRN DECODENODENAME:NEAR,COUNT_QUEUED_FRAMES:NEAR EXTRN COUNT_AT_L2:NEAR L4BG: ; ; PROCESS DATA QUEUED ON SESSIONS ; MOV BX,L4TABLE MOV CX,MAXCIRCUITS L4BG00: CMP L4USER[BX],0 JNE L4BG01 JMP L4BG99 ; SPARE ENTRY L4BG01: ; IFNDEF PCSWITCH EXTRN BUILD_DUMP_FRAME:NEAR ; ; SEE IF REMOTE DUMP ACTIVE ; CMP DUMPPTR[BX],0 JE NODUMP CMP L4TX_Q[BX],0 JNE NODUMP ; ALERADY SOMETHING QUEUED PUSH CX CALL BUILD_DUMP_FRAME POP CX NODUMP: ENDIF ; ; CHECK FOR L4BUSY SET AND NO LONGER BUSY ; TEST NAKBITS[BX],L4BUSY JZ L4NOTBUSY CALL CHECKIFBUSY TEST AL,L4BUSY JNZ L4NOTBUSY ; STILL BUSY AND NAKBITS[BX],NOT L4BUSY PUSH BX PUSH CX ; CALL SENDL4IACK ; SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES ; POP CX POP BX L4NOTBUSY: TEST L4CIRCUITTYPE[BX],BPQHOST JNZ JMP_50 ; LEAVE HERE IF BPQ HOST MODE LEA SI,L4TX_Q[BX] ; FRAMES TO SEND? CMP WORD PTR [SI],0 JE JMP_50 ; NO ; ; SEE IF BUSY - NEED DIFFERENT TESTS FOR EACH SESSION TYPE ; IF TNC2 TEST L4CIRCUITTYPE[BX],HOST JZ L4BG04 MOV DI,L4TARGET[BX] ; TO TNC DATA TEST RTSFLAG[DI],1 JNZ L4BG50 ; BUSY JMP SHORT L4BG10 ; OK L4BG04: ENDIF TEST L4CIRCUITTYPE[BX],SESSION JZ L4BG06 ; ; L4 SESSION - WILL NEED BUFFERS FOR SAVING COPY, ; AND POSSIBLY FRAGMENTATION ; CMP QCOUNT,15 JB JMP_50 ; WAIT TILL THERE ARE MORE ; TEST FLAGS[BX],L4BUSY JZ L4BG05 ; NOT CHOKED ; ; CHOKED - MAKE SURE TIMER IS RUNNING ; MOV AX,SESSIONT1[BX] CMP L4TIMER[BX],0 JNZ L4BG50 ; OK - TIMER IS RUNNING MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; RESTART TIMER JMP_50: JMP L4BG50 ; AND WAIT L4BG05: ; ; CHECK WINDOW ; MOV AL,TXSEQNO[BX] SUB AL,L4WS[BX] ; LAST FRAME ACKED - GIVES NUMBER OUTSTANING ; ; MOD 256, SO SHOULD HANDLE WRAP?? ; CMP AL,L4WINDOW[BX] JB L4BG10 ; OK JMP L4BG50 ; BUSY L4BG06: TEST L4CIRCUITTYPE[BX],L2LINK JZ L4BG10 ; NOT DEFINED?? ; ; L2 LINK - SI IS POINTING TO Q HEADER, BX TO SESSION ; PUSH BX MOV BX,L4TARGET[BX] ; TO LINK MOV AH,0 CALL COUNT_AT_L2 ; SEE HOW MANY QUEUED POP BX CMP AH,5 JA L4BG50 ; BUSY L4BG10: CALL Q_REM PUSH BX PUSH CX ; ; IF CROSSLINK, QUEUE TO NEIGHBOUR, ELSE QUEUE ON LINK ENTRY ; TEST L4CIRCUITTYPE[BX],SESSION ; NOT CROSSLINK JZ L4BG20 ; CALL SENDL4MESSAGE ; PUT IN LEVEL 4 HEADER JMP SHORT L4BG30 ; L4BG20: IF TNC2 TEST L4CIRCUITTYPE[BX],HOST JZ L4BG23 ; ; CONSOLE CIRCUIT ; MOV BX,L4TARGET[BX] ; TO TNC DATA CALL CONSOLESEND JMP SHORT L4BG30 ENDIF L4BG23: MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,TX_Q[BX] L4BG25: CALL Q_ADD L4BG30: POP CX POP BX MOV L4KILLTIMER[BX],0 ; RESET SESSION TIMEOUT JMP L4BG01 ; SEE IF MORE L4BG50: LEA SI,L4RX_Q[BX] ; FRAMES RECEIVED? CLI CALL Q_REM STI JZ L4BG55 ; NO PUSH BX PUSH CX ; MOV BUFFER,DI CALL IFRM150 POP CX POP BX CMP L4USER[BX],0 JE L4BG99 ; HAVE JUST CLOSED SESSION! JMP L4BG50 ; SEE IF NMORE L4BG55: ; ; IF ACK IS PENDING, AND WE ARE AT RX WINDOW, SEND ACK NOW ; MOV AL,RXSEQNO[BX] SUB AL,L4LASTACKED[BX] ; NUMBER TO ACK CMP AL,L4WINDOW[BX] JB L4BG56 ; NOT AT WINDOW PUSH BX PUSH CX CALL SENDL4IACK POP CX POP BX L4BG56: L4BG99: ADD BX,TYPE TRANSPORTENTRY LOOP L4BGXX RET L4BGXX: JMP L4BG00 ; TOO FAR FOR LOOP SENDL4MESSAGE: CMP MSGLENGTH[DI],6 JE NULLMESSAGE ; NO DATA - DISCARD IT MOV FRAGFLAG,0 ; NO FRAGMENTATION MOV BUFFER,DI ; SAVE MESSAGE CALL GETBUFF JNZ SENDL4M00 ; ; DONT THINK WE SHOULD GET HERE, UNLESS QCOUNT IS CORRUPT, ; BUT IF WE DO, SHOULD RETURN MSG TO FREE Q - START TIMER, AND ; DROP THROUGH TO RELBUFF ; MOV DI,BUFFER MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; RESTART TIMER NULLMESSAGE: CALL RELBUFF RET SENDL4M00: MOV L3PID[DI],0CFH ; NET MESSAGE PUSH DI LEA SI,L4MYCALL[BX] ; CALL WE ARE USING LEA DI,L3SRCE[DI] MOV CX,7 REP MOVSB MOV SI,L4TARGET[BX] ; FAR END NODE LEA SI,DEST_CALL[SI] MOV CX,7 REP MOVSB POP DI PUSH DI MOV AL,L3LIVES MOV L3MONR[DI],AL MOV AX,WORD PTR FARINDEX[BX] MOV WORD PTR L4INDEX[DI],AX MOV AL,TXSEQNO[BX] MOV L4TXNO[DI],AL INC TXSEQNO[BX] ; ; SET UP RTT TIMER ; CMP RTT_TIMER[BX],0 JNE RTT_RUNNING ; ALREADY TIMING MOV RTT_SEQ[BX],AL ; ; GET TIME FROM BIOS DATA AREA OR RTC ; IFDEF PCSWITCH MOV AX,REALTIMETICKS ELSE MOV AX,TENHZCOUNT ENDIF MOV RTT_TIMER[BX],AX ; SAVE RTT_RUNNING: MOV AL,RXSEQNO[BX] MOV L4RXNO[DI],AL MOV L4LASTACKED[BX],AL ; SAVE LAST NUMBER ACKED CALL GETBUSYBIT ; SEE IF CROSSSESSION IS BUSY MOV AL,L4INFO OR AL,NAKBITS[BX] ; PUT IN NAK/CHOKE BITS MOV L4FLAGS[DI],AL MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; SET TIMER MOV L4ACKREQ[BX],0 ; CANCEL ACK NEEDED MOV SI,BUFFER MOV CX,MSGLENGTH[SI] CMP CX,242 ; 236 DATA + 6 HEADER JBE SETUPHOK ; ; MUST FRAGMENT MESSAGE ; OR L4FLAGS[DI],L4MORE MOV FRAGFLAG,1 MOV CX,242 SETUPHOK: ADD CX,20 MOV MSGLENGTH[DI],CX SUB CX,26 LEA DI,L4DATA[DI] LEA SI,6[SI] REP MOVSB ; ; CREATE COPY FOR POSSIBLE RETRY ; ; AT THIS POINT ADDR OF COPY IS ON STACK, ORIGINAL MSG IN BUFFER CALL GETBUFF POP SI ; NEW MESSAGE JZ SETUPH99 ; SHOULD NEVER HAPPEN ; PUSH SI ; SAVE PUSH DI MOV CX,MSGLENGTH[SI] REP MOVSB LEA SI,L4HOLD_Q[BX] POP DI ; COPY CALL Q_ADD ; PUT ON QUEUE ; POP DI ; MESSAGE PUSH BX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD ; QUEUE ON DEST INC DEST_COUNT[BX] ; COUNT THEM POP BX INC L4FRAMESTX JNZ INC000 INC L4FRAMESTX+2 INC000: CMP FRAGFLAG,0 JE SETUPHEND ; NO FRAGMENTATION ; ; MESSAGE WAS TOO BIG - ADJUST IT AND LOOP BACK ; MOV DI,BUFFER MOV CX,MSGLENGTH[DI] SUB CX,242 JBE SETUPHEND ; WOT!! ; ; CX = DATA TO SEND ; ADD CX,6 ; HEADER MOV MSGLENGTH[DI],CX LEA SI,242[DI] LEA DI,6[DI] SUB CX,6 REP MOVSB ; MOVE DATA UP MOV DI,BUFFER JMP SENDL4MESSAGE SETUPH99: ; ; FAILED TO GET BUFFER FOR 2ND COPY - SHOULD NOT HAPPEN UNLESS QCOUNT ; IS CORRUPT BUT SHOULD TIDY UP. FIRST COPY IS IN SI ; MOV DI,SI CALL RELBUFF SETUPHEND: MOV DI,BUFFER CALL RELBUFF ; RELEASE ORIGINAL MESSAGE RET CHECKIFBUSY: ; ; RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY ; MOV AH,0 PUSH SI MOV SI,BX ; COUNT QUEUED USES SI CMP L4CROSSLINK[BX],0 ; CONNECTED? JNE CHECKBPARTNER ; ; IF NOT CONNECTED, CHECK L4 AND L2 TX QUEUES ; (TO STOP TERMINAL KILLING NODE BY SENDING LOTS ; OF COMMANDS TO CMD HANDLER) ; CALL COUNT_QUEUED_FRAMES ; ; COUNTS NUMBER OF FRAMES QUEUED ON A SESSION (IN SI) ; RETURN TOTAL IN AL, NUMBER QUEUED ABOVE LINK IN AH (FOR HOST MODE TESTS) ; JMP SHORT CHECKBTEST ; CHECKBPARTNER: MOV SI,L4CROSSLINK[BX] ; TO PARTNER CALL COUNT_QUEUED_FRAMES ; FRAMES NOT ACKED CHECKBTEST: MOV AH,AL CMP L4WINDOW[BX],AL JA CHECKBRET ; NOT BUSY ; ; NUMBER QUEUED = WINDOW - STOP SENDING ; MOV AL,L4BUSY POP SI RET CHECKBRET: MOV AL,0 POP SI RET PROCESSIFRAME: ; ; IF UP/DOWN LINK, AND CIRCUIT ESTABLISHED, ADD LEVEL 3/4 HEADERS ; (FRAGMENTING IF NECESSARY), AND PASS TO TRANSPORT CONTROL ; FOR ESTABLISHED ROUTE ; ; IF INTERNODE MESSAGE, PASS TO ROUTE CONTROL ; ; IF UP/DOWN, AND NO CIRCUIT, PASS TO COMMAND HANDLER ; MOV BUFFER,DI ; SAVE MOV SAVELINK,BX ; SAVE LINK TABLE MOV AL,LINKPORT[BX] MOV SAVEPORT,AL ; SAVE PORT ; ; IT IS POSSIBLE TO MULTIPLEX NETROM AND IP STUFF ON THE SAME LINK ; CMP L3PID[DI],0CCH JE Q_IP_MSG CMP L3PID[DI],0CDH JE Q_IP_MSG CMP L3PID[DI],0CFH JE INTERNODE ; MUST BE INTERNODE! CMP LINKTYPE[BX],3 JNE IFRM100 ; UP/DOWN INTERNODE: ; ; IF LINKTYPE IS NOT 3, MUST CHECK IF WE HAVE ACCIDENTALLY ATTACHED A ; BBS PORT TO THE NODE ; CMP LINKTYPE[BX],3 JE ALREADY_L3 CMP CIRCUITPOINTER[BX],0 ; ANY SESSION? JE MAKEIT_L3 ; NOTHING ATTACHED ; ; MUST KILL SESSION ; CALL INFORMPARTNER ; CLOSE IT MOV CIRCUITPOINTER[BX],0 ; AND UNHOOK MAKEIT_L3: MOV LINKTYPE[BX],3 ; NOW WE KNOW ITS A CROSSLINK ALREADY_L3: ; ; MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT ; WE THINK IS A NODE-NODE LINK ; CMP L3PID[DI],0CFH JE PIDOK JMP L3DISCARD Q_IP_MSG: MOV BX,OFFSET IPHOSTVECTOR ; ; VECTOR FORMAT IS: ; ; 0-1 2 BYTES - ADDRESS OF SESSION ENTRY ; 2 1 BYTE - STATE CHANGE FLAGS ; 3 1 BYTE - APPLICATION MASK ; 4 1 BYTE - APPLICATION FLAGS - TOP BIT ENABLES MONITORING ; 5-6 2 BYTES - RAW FRAME QUEUE ; TEST BYTE PTR 4[BX],80H JZ NOSAVE ; NOT ENABLED ; ; CHECK WE ARENT USING TOO MANY BUFFERS ; PUSH DI CMP WORD PTR 5[BX],0 JE IPOK ; NONE QUEUED PUSH BX ADD BX,5 ; TO HEADER CALL COUNT_Q POP BX CMP AL,20 JB IPOK LEA SI,5[BX] CALL Q_REM JZ IPOK ; WOT? CALL RELBUFF IPOK: POP DI LEA SI,5[BX] CALL Q_ADD ; PUT ON QUEUE RET NOSAVE: CALL RELBUFF RET PIDOK: CALL NETROMMSG RET IFRM100: CMP CIRCUITPOINTER[BX],0 JE IFRM200 ; NOT CONNECTED ; ; UPLINK WITH CIRCUIT - PASS ACROSS ; MOV BX,CIRCUITPOINTER[BX] ; TO CIRCUIT ENTRY IFRM150: MOV L4KILLTIMER[BX],0 ; RESET SESSION TIMEOUT CMP L4CROSSLINK[BX],0 ; CONNECTED? JE IFRM250 ; NO, SO PASS TO COMMAND HANDLER MOV DX,BX ; SAVE MOV BX,L4CROSSLINK[BX] ; TO SESSION PARTNER CMP L4STATE[BX],5 JE IFRM155 ; OK ; ; MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION ; AND PASS MESSAGE TO COMMAND HANDLER ; TEST L4CIRCUITTYPE[BX],L2LINK ; L2 SESSION? JZ IFRM152 ; NO ; ; MUST CANCEL L2 SESSION ; PUSH BX MOV BX,L4TARGET[BX] MOV CIRCUITPOINTER[BX],0 ; CLEAR REVERSE LINK MOV L2STATE[BX],4 ; DISCONNECTING MOV L2TIMER[BX],1 ; USE TIMER TO KICK OFF DISC PUSH BX MOV AL,LINKPORT[BX] CALL GETPORTTABLEENTRY MOV AL,PORTN2[BX] POP BX SUB AL,2 MOV L2RETRIES[BX],AL ; ONLY SEND DISC ONCE ; POP BX IFRM152: CALL CLEARSESSIONENTRY MOV BX,DX ; RESTORE OLD SESSION MOV L4CROSSLINK[BX],0 ; CLEAR CROSS LINK JMP SHORT IFRM250 IFRM155: LEA SI,L4TX_Q[BX] CALL Q_ADD ; PASS TO DEST RET ; IFRM200: ; ; UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE ; CALL GETPORTPACLEN ; PACLEN FOR THIS PORT PUSH AX CALL SETUPUSERSESSION POP AX JZ IFRM202 ; OK RET ; SEND BUSY?? IFRM202: MOV SESSPACLEN[BX],AL IFRM250: MOV DI,BUFFER CALL COMMANDHANDLER ; BUFFER USED FOR REPLY OR CONNECT RET SETUPUSERSESSION: ; ; UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE ; PUSH BX ; SAVE LINK ENTRY CALL GETFREECIRCUIT ; GET AN ENTRY JZ IFRM210 ; OK POP BX RET IFRM210: MOV AX,BX POP BX MOV CIRCUITPOINTER[BX],AX ; SETUP LINK-CIRCUIT CONNECTION LEA SI,LINKCALL[BX] ; CALLER'S CALLSIGN PUSH BX ; SAVE LINK ENTRY MOV BX,AX LEA DI,L4USER[BX] MOV CX,7 REP MOVSB ; PUT IN CALL ; MOV SI,OFFSET MYCALL ; ALWAYS USE NODE CALL LEA DI,L4MYCALL[BX] MOV CX,7 REP MOVSB MOV CIRCUITINDEX[BX],DL ; OUR INDEX MOV AL,NEXTID MOV CIRCUITID[BX],AL ; OUR ID CALL INC_ID POP AX ; LINK MOV L4TARGET[BX],AX ; LINK POINTER MOV L4CIRCUITTYPE[BX],L2LINK+UPLINK ; UPLINK MOV L4STATE[BX],5 ; SET LINK ACTIVE MOV AX,L4T1 MOV SESSIONT1[BX],AX ; DEFAULT TIMEOUT MOV AL,L4DEFAULTWINDOW MOV L4WINDOW[BX],AL ; SET WINDOW XOR AL,AL RET INC_ID: INC NEXTID JNZ IDOK INC NEXTID ; KEEP NONZERO IDOK: RET NETROMMSG: ; ; MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT ; WE THINK IS A NODE-NODE LINK ; CMP L3PID[DI],0CFH JNE DISC00 ; IGNORE IT ; ; MESSAGE ON NODE-NODE SESSION ; ; BX = LINK, DI = BUFFER ; CMP NEIGHBOUR[BX],0 JNE NETMSG00 ; OK ; ; NO DESTINATION ASSOCIATED WITH THIS CIRCUIT - SET ONE UP ; CALL CHECKNEIGHBOUR CMP NEIGHBOUR[BX],0 JNE NETMSG00 ; NOW OK ; ; COULDNT SET UP NEIGHBOUR - CAN ONLY THROW IT AWAY ; DISC00: JMP L3DISCARD NETMSG00: CMP NODE,0 ; NODE SUPPORT INCLUDED? JE NONODECODE ; NO MOV BBSMSG,0 MOV DI,BUFFER LEA SI,L3DEST[DI] MOV DI,OFFSET MYCALL CALL COMPARECALLS JNE NONODECODE JMP FRAMEFORUS ; NONODECODE: MOV BBSMSG,1 ; SET MESSAGE IS FOR BBS ADDR MOV DI,BUFFER LEA SI,L3DEST[DI] MOV DI,OFFSET BBSCALL CALL COMPARECALLS JNE NOTFORUS JMP FRAMEFORUS NOTFORUS: ; ; NOT FOR US - PASS TO DESTINATION ; MOV DI,BUFFER DEC L3MONR[DI] JNZ FRAMESTILLOK L3DISCARD: MOV DI,BUFFER CALL RELBUFF RET ; DISCARD IT FRAMESTILLOK: ; MOV AL,L3LIVES CMP L3MONR[DI],AL JB LIVESOK MOV L3MONR[DI],AL ; ENFORCE LIMIT ON ALL FRAMES SENT LIVESOK: LEA SI,L3DEST[DI] CALL FINDDESTINATION JNZ L3DISCARD ; CANT FIND DESTINATION ; ; IF MESSAGE ORIGINTED HERE, THERE MUST BE A ROUTING LOOP - ; THERE IS LITTLE POINT SENDING IT OVER THE SAME ROUTE AGAIN, ; SO SET ANOTHER ROUTE ACTIVE IF POSSIBLE ; MOV DI,BUFFER LEA SI,L3SRCE[DI] MOV DI,OFFSET MYCALL CALL COMPARECALLS JE ROUTE_LOOP ; MOV DI,BUFFER LEA SI,L3SRCE[DI] MOV DI,OFFSET BBSCALL CALL COMPARECALLS JNE OKTORELAY ROUTE_LOOP: ; ; MESSAGE HAS COME BACK TO ITS STARTING POINT - ACTIVATE ANOTHER ROUTE, ; UNLESS THERE IS ONLY ONE, IN WHICH CASE DISCARD IT ; ; CMP ROUT2_NEIGHBOUR[BX],0 JZ L3DISCARD ; ONLY ONE ROUTE INC DEST_ROUTE[BX] ; TO NEXT CMP DEST_ROUTE[BX],4 JNE OKTORELAY ; MOV DEST_ROUTE[BX],1 ; TRY TO ACTIVATE FIRST ; OKTORELAY: ; ; IF CURRENT ROUTE IS BACK THE WAY WE CAME, THEN ACTIVATE ; ANOTHER (IF POSSIBLE). ; ; BX IS DEST ENTRY, SAVELINK HAS LINK FROM INCOMMING MESSAGE ; PUSH SI PUSH BX MOV SI,SAVELINK MOV SI,NEIGHBOUR[SI] ; ROUTE TABLE ENTRY FOR SENDER ; OF THIS MSG MOV AL,DEST_ROUTE[BX] OR AL,AL JNZ GOT_ACTIVE ; ; DONT HAVE AN ACTIVE ROUTE ; POP BX CMP ROUT1_NEIGHBOUR[BX],SI JNE NO_PROBLEM ; WILL ACTIVATE ANOTHER ROUTE ; ; FIRST ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE ; MOV DEST_ROUTE[BX],2 ; WILL BE RESET BY L3 CODE IF ; THERE IS NOT OTHER ROUTE JMP SHORT NO_PROBLEM GOT_ACTIVE: DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ACTIVE ROUTE ENTRY CMP ROUT1_NEIGHBOUR[BX],SI ; IS ACTIVE ONE BACK VIA ORIGINATOR? POP BX JNE NO_PROBLEM ; NO ; ; SET TO USE NEXT BEST ROUTE ; INC DEST_ROUTE[BX] ; TO NEXT CMP DEST_ROUTE[BX],4 JNE L4NEXT00 ; MOV DEST_ROUTE[BX],1 ; TRY TO ACTIVATE FIRST L4NEXT00: NO_PROBLEM: POP SI CALL CHECKL3TABLES ; CHECK THAT FAR NODE IS IN 'NODES', ; RETURNS NODE IN AX ; ; EVEN IF WE CANT PUT ORIGINATING NODE INTO OUR TABLES, PASS MSG ON ; ANYWAY - THE FINAL TARGET MAY HAVE ANOTHER WAY BACK ; LEA SI,DEST_Q[BX] MOV DI,BUFFER CALL Q_ADD INC L3FRAMES JNZ INC001 INC L3FRAMES+2 INC001: RET FRAMEFORUS: ; ; INTERNODE LINK ; INC L4FRAMESRX JNZ INC002 INC L4FRAMESRX+2 INC002: MOV DI,BUFFER MOV AL,L4FLAGS[DI] AND AL,0FH CMP AL,0 JE NETIPMSG ; IP OVER NETROM CMP AL,L4CREQ ; CONNECT REQUEST JE L4REQUEST ; ; OTHERS NEED A SESSION ; MOV AL,L4INDEX[DI] ; OUR ID MOV AH,0 MUL TRANSPORTLENGTH MOV BX,L4TABLE ADD BX,AX ; POINT TO ENTRY MOV AL,L4ID[DI] CMP AL,CIRCUITID[BX] ; CORRECT ID JNE L4DISCARD ; IGNORE ; ; HAVE FOUND CORRECT SESSION ENTRY ; MOV DI,BUFFER MOV AL,L4FLAGS[DI] AND AL,0FH CMP AL,L4CACK ; CONNECT ACK JE L4CONNACK CMP AL,L4DREQ ; DISCONNECT REQUEST JE L4DISREQ CMP AL,L4DACK ; DISCONNECT ACK JE L4DISACK CMP AL,L4INFO ; INFO JE L4IFRAME CMP AL,L4IACK ; INFO ACK JE L4INFOACK L4DISCARD: JMP L3DISCARD ; NO L4REQUEST: INC L4CONNECTSIN JNZ INC003 INC L4CONNECTSIN+2 INC003: CALL CONNECTREQUEST RET NETIPMSG: MOV MSGPORT[DI],0CFH JMP Q_IP_MSG L4DISREQ: MOV AX,WORD PTR FARINDEX[BX] MOV WORD PTR L4INDEX[DI],AX MOV L4FLAGS[DI],L4DACK CALL L3SWAPADDRESSES ; EXCHANGE SOURCE AND DEST MOV DI,BUFFER MOV AL,L3LIVES MOV L3MONR[DI],AL PUSH BX MOV BX,SAVELINK LEA SI,TX_Q[BX] ; SEND BACK TO ORIGINATOR CALL Q_ADD POP BX CALL CLOSESESSIONPARTNER ; SEND CLOSE TO PARTNER (IF PRESENT) RET L4CONNACK: JMP CONNECTACK L4DISACK: CALL CLEARSESSIONENTRY ; DELETE SESSION JMP L4DISCARD L4INFOACK: MOV AL,L4RXNO[DI] ; SEQUENCE CALL ACKFRAMES CALL REFRESHROUTE ; INDICATE ROUTE STILL OK JMP L4DISCARD L4IFRAME: ; ; MAKE SURE SESSION IS UP - FIRST I FRAME COULD ARRIVE BEFORE ; CONNECT ACK ; CMP L4STATE[BX],5 JB L4DISCARD ; SHOULD SAVE - WILL AVOID NEED TO ; RETRANSMIT MOV AL,L4RXNO[DI] ; SEQUENCE CALL ACKFRAMES ; ; IF STATE IS 4, THEN SESSION IS CLOSING - IGNORE ANY I FRAMES ; TEST FLAGS[BX],DISCPENDING JNZ L4DISCARD ; WAITING FOR ALL TO BE ACKED CMP L4STATE[BX],4 JE L4DISCARD ; ; CHECK RECEIVED SEQUENCE ; MOV AL,L4TXNO[DI] ; WHAT WE GOT SUB AL,RXSEQNO[BX] ; WHAT WE WANT JZ L4FRAME_OK ; ; AL IS THE NUMBER OF FRAMES MISSING. IF -VE, THEN IN FACT IT ; INDICATES A REPEAT ; CMP AL,128 JB FRAME_MISSING ; ; FRAME IS A REPEAT ; MOV L4ACKREQ[BX],1 ; SEND INFO ACK IN 1 SEC(IN CASE LAST ACK WAS LOST) JMP L4DISCARD ; FRAME_MISSING: ; ; EXPECTED FRAME HAS BEEN MISSED - ASK FOR IT AGAIN, ; AND KEEP THIS FRAME UNTIL MISSING ONE ARRIVES ; OR NAKBITS[BX],L4NAK ; SET NAK REQUIRED PUSH BX PUSH DI ; CALL SENDL4IACK ; SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES ; POP DI POP BX ; ; SEE IF WE ALREADY HAVE A COPY OF THIS ONE ; MOV SI,L4RESEQ_Q[BX] MOV AL,L4TXNO[DI] CHECK_FRAME_LOOP: CMP SI,0 JE NOTONQUEUE CMP AL,L4TXNO[SI] JE MSGONQUEUE MOV SI,[SI] ; FOLLOW CHAIN JMP CHECK_FRAME_LOOP NOTONQUEUE: LEA SI,L4RESEQ_Q[BX] CALL Q_ADD ; ADD TO CHAIN RET MSGONQUEUE: ; ; ALREADY HAVE A COPY - DISCARD IT ; JMP L4DISCARD ; L4FRAME_OK: AND NAKBITS[BX],0FFH-L4NAK ; CLEAR MESSAGE LOST STATE ; INC RXSEQNO[BX] ; ; REMOVE HEADERS, AND QUEUE INFO ; MOV CX,MSGLENGTH[DI] SUB CX,20 MOV MSGLENGTH[DI],CX ; NEW LENGTH SUB CX,6 JNC L4IFLENOK L4DISCARD_JMP: CALL L4DISCARD ; NO PID! JMP SHORT CHECK_RESEQ L4IFLENOK: LEA DI,L3PID[DI] MOV SI,DI ADD SI,21 ; FIRST DATA BYTE MOV AL,0F0H STOSB ; NORMAL PID JCXZ L4IFRM00 ; NO DATA REP MOVSB ; COPY DOWN L4IFRM00: ; ; QUEUE FRAME FOR TARGET ; CALL REFRESHROUTE ; SET ROUTE STILL OK MOV AX,L4DELAY MOV L4ACKREQ[BX],AL ; SEND INFO ACK AFTER L4DELAY (UNLESS I FRAME SENT) MOV DI,BUFFER PUSH BX CALL IFRM150 ; CHECK IF SETTING UP AND PASS ON POP BX CHECK_RESEQ: ; ; SEE IF ANYTHING ON RESEQ QUEUE TO PROCESS ; LEA SI,L4RESEQ_Q[BX] MOV DI,[SI] MOV AL,RXSEQNO[BX] ; WHAT WE WANT FIND_FRAME_LOOP: CMP DI,0 JE NOTFOUND CMP AL,L4TXNO[DI] JE FOUNDMESSAGE MOV SI,DI ; SAVE PREVIOUS IN CHAIN MOV DI,[DI] ; FOLLOW CHAIN JMP FIND_FRAME_LOOP NOTFOUND: RET FOUNDMESSAGE: ; ; REMOVE IT FROM QUEUE,AND PROCESS IT ; ; SI IS PREVIOUS IN QUEUE ; MOV AX,[DI] ; NEXT IN CHAIN MOV [SI],AX ; CHAIN TO PREVIOUS MOV BUFFER,DI ; SAVE ADDRESS ADD OLDFRAMES,1 ADC OLDFRAMES+2,0 ; COUNT FOR STATS JMP L4FRAME_OK CLEARSESSIONENTRY: PUSH SI ; ; RETURN ANY QUEUED BUFFERS TO FREE QUEUE ; LEA SI,L4TX_Q[BX] CALL RELEASEQUEUE LEA SI,L4RX_Q[BX] CLI CALL RELEASEQUEUE STI LEA SI,L4HOLD_Q[BX] CALL RELEASEQUEUE LEA SI,L4RESEQ_Q[BX] CALL RELEASEQUEUE MOV DI,BX MOV CX,TYPE TRANSPORTENTRY XOR AL,AL REP STOSB ; CLEAR ENTRY POP SI RET RELEASEQUEUE: PUSH SI CALL Q_REM JZ RELQUEUERET CALL RELBUFF POP SI JMP RELEASEQUEUE RELQUEUERET: POP SI RET ACKFRAMES: PUSH DI ; ; SEE HOW MANY FRAMES ARE ACKED - IF NEGATIVE, THAN THIS MUST BE A ; DELAYED REPEAT OF AN ACK ALREADY PROCESSED ; ACKFR00: MOV AH,AL SUB AH,L4WS[BX] ; LAST ACKED JE NO_NEW_ACK ; NOTHING HAS CHANGED ; ; THIS MAY BE A DELAYED REPEAT OF AN ACK ALREADY PROCESSED ; CMP AH,128 JB NEWACK ; ; REPEATED ACK ; POP DI RET ; IGNORE COMPLETELY NEWACK: ; ; FRAME L4WS HAS BEED ACKED - IT SHOULD BE FIRST ON HOLD QUEUE ; PUSH AX ; SAVE LEA SI,L4HOLD_Q[BX] CALL Q_REM JZ ACKFR10 ; WOT !! CALL RELBUFF ; RELEASE IT ACKFR10: ; ; CHECK RTT SEQUENCE ; MOV AL,L4WS[BX] CMP RTT_SEQ[BX],AL JNE NOT_RTT_ACK ; CMP RTT_TIMER[BX],0 JE NOT_RTT_ACK ; TIMER NOT ACTIVE ; ; FRAME BEING TIMED HAS BEEN ACKED - UPDATE DEST TIMER ; ; GET TIME FROM BIOS DATA AREA OR RTC ; IFDEF PCSWITCH MOV AX,REALTIMETICKS ELSE MOV AX,TENHZCOUNT ENDIF SUB AX,RTT_TIMER[BX] ; TIME IN 18THS/10THS ; MOV RTT_TIMER[BX],0 PUSH BX MOV BX,L4TARGET[BX] ; DEST ENTRY CMP DEST_RTT[BX],0 JE FIRST_TIME ; ; TAKE 7/8TH OF OLD VLAUE AND 1/8 OF THIS ; SHR AX,1 SHR AX,1 SHR AX,1 ; /8 MOV CX,DEST_RTT[BX] ; OLD VALUE SHR CX,1 SHR CX,1 SHR CX,1 ; 1/8 SUB DEST_RTT[BX],CX ; GIVES 7/8 FIRST_TIME: ADD DEST_RTT[BX],AX POP BX NOT_RTT_ACK: POP AX INC L4WS[BX] JMP ACKFR00 ; LOOP BACK TO SEE IF ANY MORE TO DO NO_NEW_ACK: MOV L4RETRIES[BX],0 ; CLEAR RETRY COUNT MOV L4TIMER[BX],0 CMP AL,TXSEQNO[BX] ; NEXT TO SEND JE ALL_ACKED MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; RESTART TIMER JMP ACKFR15 ALL_ACKED: CMP L4TX_Q[BX],0 JNE ACKFR15 ; STILL SOME TO SEND ; ; IF DISC PENDING, SEND IT ; TEST FLAGS[BX],DISCPENDING JZ ACKFR15 PUSH BX CALL SENDL4DISC POP BX POP DI RET ACKFR15: ; ; SEE IF CHOKE SET ; POP DI MOV AL,L4FLAGS[DI] AND AL,L4BUSY ; EXTRACT BUSY BIT AND FLAGS[BX],0FFH-L4BUSY OR FLAGS[BX],AL ; SAVE IT TEST L4FLAGS[DI],L4NAK JNZ NAKMSG ; REQUEST TO RETRANSMIT RET NAKMSG: ; ; RETRANSMIT REQUESTED MESSAGE - WILL BE FIRST ON HOLD QUEUE ; PUSH DI ; INCOMING MSG CALL GETBUFF JZ L4NAKRET ; CANT - NO BUFFERS ; PUSH DI MOV SI,L4HOLD_Q[BX] MOV CX,MSGLENGTH[SI] REP MOVSB ; COPY MESSAGE - LEAVE STATE ALONE POP DI ; MESSAGE PUSH BX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD ; QUEUE ON DEST POP BX L4NAKRET: POP DI RET CONNECTREQUEST: ; ; CONNECT REQUEST - SEE IF EXISTING SESSION ; IF NOT, GET AND FORMAT SESSION TABLE ENTRY ; SEND CONNECT ACK ; ; DI = BUFFER, BX = LINK ; MOV BPQNODE,0 ; NOT ONE OF MINE MOV AX,L4T1 MOV WORD PTR BPQPARAMS,AX ; SET DEFAULT T1 IN CASE NOT FROM ANOTHER THENODE MOV BPQPARAMS+2,0 ; 'SPY' NOT SET PUSH BX ; SAVE LINK CALL FINDCIRCUIT JZ L4CONN50 ; SESSION EXISTS - ASSUME RETRY AND SENF ACK ; OR BX,BX JZ L4CONN90 ; TABLES FULL - REJECT CALL SETUPNEWCIRCUIT CMP L4TARGET[BX],0 JE KILLSESSION ; NODE NOT IN TABLE, AND TABLE FULL ; - CANCEL IT ; ; IF CONNECT TO BBS, ALLOCATE BBS PORT ; CMP BBSMSG,0 JE L4CONN50 ; NORMAL CONNECT ; CMP BPQPARAMS+2,'Z' JE L4CONN50 ; 'SPY' CONNECT TO NODE MOV AL,PACLEN ; NETWORK ATTACH MOV APPLMASK,1 CALL ATTACHTOBBS ; FIND AND ATTACH FREE BBS SESSION - RETURN NZ IF FAILED JZ L4CONN50 ; OK KILLSESSION: CALL CLEARSESSIONENTRY JMP L4CONN90 ; REJECT L4CONN50: ; ; SEND CONNECT ACK ; MOV DI,BUFFER MOV AL,CIRCUITINDEX[BX] ; OUR INDEX MOV L4TXNO[DI],AL ; INTO REPLY MOV AL,CIRCUITID[BX] ; OUR ID MOV L4RXNO[DI],AL ; TO REPLY MOV AL,L4WINDOW[BX] MOV L4DATA[DI],AL ; WINDOW MOV L4FLAGS[DI],L4CACK ; ; IF CTEXT ON ALL CONNECTES IS REUQIRED, SEND IT ; ; ; IF CONNECT TO ALIAS, SEND CTEXT ; CMP FULL_CTEXT,1 ; FOR ANY CONNECT? JNE L4CONN95 ; NO CMP CTEXTLEN,0 JE L4CONN95 ; NOT DEFINED PUSH DI CALL GETBUFF JZ CTEXTRET ; NO BUFFERS PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID MOV SI,CTEXTMSG MOV CX,CTEXTLEN REP MOVSB MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER CTEXTRET: POP DI JMP SHORT L4CONN95 ; SEND RESPONSE L4CONN90: MOV DI,BUFFER MOV L4FLAGS[DI],L4CACK+L4BUSY; REJECT MOV L4DATA[DI],0 ; WINDOW L4CONN95: CALL L3SWAPADDRESSES ; EXCHANGE SOURCE AND DEST MOV DI,BUFFER MOV AL,L3LIVES MOV L3MONR[DI],AL LEA CX,L4DATA+1[DI] SUB CX,DI CMP BPQNODE,1 JNE L4CONN95A ; NOT BPQ MOV L4DATA+1[DI],AL ; OUR TTL INC CX L4CONN95A: MOV MSGLENGTH[DI],CX ; SET LENGTH POP BX LEA SI,TX_Q[BX] ; SEND BACK TO ORIGINATOR CALL Q_ADD RET L4CONN96: ; ; TABLES FULL - SHOULD CANCEL SESSION AND SEND REPLY ( OR CHECK FIRST) ; POP BX ; NEW LINK NENTY POP BX ; LINK RET ; ????? ATTACHTOBBS: ; ; AL CONTAINS PACLEN FOR TNC SESSION ; PUSH AX MOV CONNECTSESSION,BX ; ; LOOK FOR A FREE HOST SESSION ; ; TRY BPQ HOST MODE PORTS FIRST ; IFDEF PCSWITCH MOV BX,OFFSET BPQHOSTVECTOR MOV CX,BPQHOSTSTREAMS MOV AL,APPLMASK MOV AH,0 ; NO PORTS/ALL IN USE FLAG BPQHOSTLOOP: TEST 3[BX],AL ; CORRECT APPLICATION? JZ NEXTBPQPORT ; NO ; INC AH CMP WORD PTR [BX],0 ; SESSION ALREADY ATTACHED? JNE NEXTBPQPORT ; YES TEST BYTE PTR 2[BX],3 ; STATUS CHANGE NOT YET REPORTED? JNZ NEXTBPQPORT ; ; WEVE GOT A FREE BPQ HOST PORT - USE IT ; MOV AL,4[BX] MOV SAVEDAPPLFLAGS,AL PUSH BX ; HOST PORT ENTRY MOV AL,3[BX] CALL SETUPBPQCONSOLESESSION MOV SI,BX ; SESSION (OR ZERO) RETURNED IN BX POP BX MOV WORD PTR [BX],SI ; LINK SESSION TO HOST VECTOR MOV DI,CONNECTSESSION ; INCOMING CIRCUIT CMP SI,0 JE BBSBUSY ; CANT SET UP SESSION ; OR BYTE PTR 2[BX],2 ; INDICATE STATE CHANGE MOV L4CIRCUITTYPE[SI],BPQHOST+DOWNLINK MOV DI,CONNECTSESSION ; INCOMING CIRCUIT MOV L4CROSSLINK[DI],SI ; POINTER FROM NEW TO OLD MOV L4CROSSLINK[SI],DI ; POINTER FROM OLD TO NEW ; MOV AL,SAVEDAPPLFLAGS MOV SESS_APPLFLAGS[DI],AL ; SAVE IN SESSION ENTRY POP AX ; GET PACLEN MOV SESSPACLEN[SI],AL MOV BX,CONNECTSESSION ; RETURN WITH INCOMING SESSION IN BX XOR AL,AL RET NEXTBPQPORT: ADD BX,BPQVECLENGTH LOOP BPQHOSTLOOP ; ENDIF ; IF TNC2 ; NONE AVAILABLE - TRY OTHER PORT TYPES ; MOV BX,TNCTABLE MOV CX,NUMBEROFSTREAMS JCXZ BBSBUSY BBSC00: MOV AL,APPLMASK TEST APPLICATION[BX],AL ; CORRECT APPLICATION? JZ BBSC05 ; NO CMP CONOK[BX],0 JE BBSC05 ; CONOK OFF ; ; SEE IF BUSY ; INC AH TEST VMSR[BX],80H JZ BBSC10 ; NOT CONNECTED BBSC05: ADD BX,TYPE TNCDATA LOOP BBSC00 ENDIF BBSBUSY: POP BX ; CLEAR PACLEN FROM STACK MOV BX,CONNECTSESSION OR AL,1 RET ; WITH NZ SET IF TNC2 ; BBSC10: ; ; SET UP SESSION FOR TNC ; PUSH BX ; TNC PORT CALL SETUPCONSOLESESSION MOV SI,BX POP BX ; TNC PORT MOV KBSESSION[BX],SI MOV DI,CONNECTSESSION ; INCOMING CIRCUIT CMP SI,0 JE BBSBUSY ; CANT SET UP SESSION ; MOV L4CIRCUITTYPE[SI],HOST+DOWNLINK MOV DI,CONNECTSESSION ; INCOMING CIRCUIT MOV L4CROSSLINK[DI],SI ; POINTER FROM NEW TO OLD MOV L4CROSSLINK[SI],DI ; POINTER FROM OLD TO NEW ; MOV AH,APPLFLAGS[BX] MOV SAVEDAPPLFLAGS,AH ; GET FLAGS FOR LATER MOV SESS_APPLFLAGS[DI],AH ; SAVE IN SESSION ENTRY ; ; TNC2 BITS ; CALL DOCONMODECHANGE ; SET CONNECTED AND CHANGE MODE IF NEEDED ; TEST AH,MSG_TO_APPL JZ NOCONMSG ; DONT SEND CONNECTED CALL SEND_CONNECTED ; SEND *** CONNECTED NOCONMSG: POP AX ; PACLEN MOV TPACLEN[BX],AL MOV BX,CONNECTSESSION ; RETURN WITH INCOMING SESSION IN BX XOR AL,AL RET ENDIF SETUPNEWCIRCUIT: MOV SI,BUFFER MOV CX,MSGLENGTH[SI] ; GET LENGTH MOV AX,WORD PTR L4INDEX[SI] ; INDEX AND ID MOV WORD PTR FARINDEX[BX],AX; COPY MOV CIRCUITINDEX[BX],DL ; OUR INDEX MOV AL,NEXTID MOV CIRCUITID[BX],AL ; OUR ID CALL INC_ID LEA SI,L4DATA[SI] LODSB CMP AL,L4DEFAULTWINDOW JB L4CONN05 ; REQUESTED LESS THAN 4 MOV AL,L4DEFAULTWINDOW L4CONN05: MOV L4WINDOW[BX],AL ; SET WINDOW LEA DI,L4USER[BX] MOV CX,7 REP MOVSB ; COPY ORIGINATING CALL ; ; GET BPQ EXTENDED CONNECT PARAMS IF PRESENT ; MOV SI,BUFFER MOV CX,MSGLENGTH[SI] LEA SI,L4_BPQ[SI] ; TO MY EXTENDED PARAMS MOV DI,OFFSET BPQPARAMS SUB CX,L4_BPQ JCXZ NOT_THENODE ; ; MAKE SURE - OTHERS NOW USE EXTENDED CONNECTS ; CMP CX,2 ; TIMER JE SHORT THENODE CMP CX,3 ; SPY FLAG JNE SHORT NOT_THENODE THENODE: REP MOVSB ; GET THENODE EXTENDED CONNECT PARAMS MOV BPQNODE,1 ; A BPQ NODE NOT_THENODE: MOV L4CIRCUITTYPE[BX],SESSION+UPLINK ; CROSS CIRCUIT MOV L4STATE[BX],5 ; MOV SI,OFFSET MYCALL CMP BBSMSG,0 JE L4CONN06 ; NORMAL MOV SI,OFFSET BBSCALL ; USING BBS CALLSIGN L4CONN06: LEA DI,L4MYCALL[BX] MOV CX,7 REP MOVSB CALL CHECKL3TABLES ; CHECK THAT FAR NODE IS IN 'NODES', ; RETURNS NODE IN AX MOV L4TARGET[BX],AX ; SET LINK POINTER TO DEST CMP AX,0 JNE L4CONN07 ; OK ; ; NODE NOT IN TABLE, AND TABLE FULL - CANCEL IT ; RET L4CONN07: ; CMP BPQNODE,1 JNE L4CONN07A ; FAR END NOT BPQ PUSH BX MOV BX,AX OR DEST_STATE[BX],40H ; SET BPQ NODE BIT POP BX L4CONN07A: MOV AX,WORD PTR BPQPARAMS ; TIMEOUT FROM CONNECT MOV SESSIONT1[BX],AX ; DEFAULT TIMEOUT MOV AL,PACLEN ; L4 LINK - USE SYSTEM DEFAULT MOV SESSPACLEN[BX],AL ; DEFAULT RET CONNECTACK: ; ; EXTRACT EXTENDED PARAMS IF PRESENT ; CMP BYTE PTR MSGLENGTH[DI],L4DATA+1 JE NOTBPQ MOV AL,L4DATA+1[DI] SUB AL,L3MONR[DI] ADD AL,41H ; HOPS TO DEST + 40H MOV SI,L4TARGET[BX] AND DEST_STATE[SI],80H OR DEST_STATE[SI],AL ; SAVE NOTBPQ: ; ; SEE IF SUCCESS OR FAIL ; PUSH DI MOV SI,L4TARGET[BX] ; ADDR OF LINK/DEST ENTRY LEA SI,DEST_CALL[SI] CALL DECODENODENAME ; CONVERT TO ALIAS:CALL MOV DI,OFFSET CONACKCALL MOV CX,17 REP MOVSB POP DI TEST L4FLAGS[DI],L4BUSY JNZ L4CONNFAILED CMP L4STATE[BX],5 JE CONNACK05 ; MUST BE REPEAT MSG - DISCARD MOV AX,WORD PTR L4TXNO[DI] ; HIS INDEX MOV WORD PTR FARINDEX[BX],AX MOV L4STATE[BX],5 ; ACTIVE MOV L4TIMER[BX],0 ; CANCEL TIMER MOV L4RETRIES[BX],0 ; CLEAR RETRY COUNT MOV AL,L4DATA[DI] ; WINDOW MOV L4WINDOW[BX],AL ; SET WINDOW MOV DX,L4CROSSLINK[BX] ; POINT TO PARTNER ; MOV SI,OFFSET CONNECTEDMSG MOV CX,LCONNECTEDMSG JMP SHORT L4CONNCOMM L4CONNFAILED: ; MOV DX,L4CROSSLINK[BX] ; SAVE PARTNER CALL CLEARSESSIONENTRY ; CLEAR OUT THE SESSION PUSH BX MOV BX,DX MOV L4CROSSLINK[BX],0 ; CLEAR CROSSLINK POP BX MOV SI,OFFSET BUSYMSG ; ?? BUSY MOV CX,LBUSYMSG L4CONNCOMM: OR DX,DX JNZ L4CONNOK10 ; ; CROSSLINK HAS GONE?? - JUST CHUCK MESSAGE ; CONNACK05: JMP L4DISCARD L4CONNOK10: PUSH BX PUSH SI PUSH CX MOV DI,BUFFER ADD DI,5 MOV AL,0F0H STOSB ; PID CALL SETUPNODEHEADER ; PUT IN NODE ID POP CX POP SI REP MOVSB MOV SI,OFFSET CONACKCALL MOV CX,17 ; MAX LENGTH ALIAS:CALL REP MOVSB MOV AL,0DH STOSB MOV CX,DI MOV DI,BUFFER SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,DX ; CALLER'S SESSION LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER POP BX ; ORIGINAL CIRCUIT TABLE RET CONNECTREFUSED: ; ; L2 CONNECTION REQUEST REJECTED ; ; IF DOWNLINK, TELL PARTNER ; IF CROSSLINK, TELL ROUTE CONTROL ; CMP LINKTYPE[BX],3 JNE CONNECTR00 ; ; FAILURE TO SET UP CROSSLINK - TELL LEVEL 3 ; CALL L3CONNECTFAILED ; REPORT TO LEVEL 3 RET CONNECTR00: CMP CIRCUITPOINTER[BX],0 JNE CONNECTR01 RET ; NO CROSS LINK CONNECTR01: CALL GETBUFF JZ CONNECTF10 ; NO BUFFERS ?? WHAT SHOULD WE DO ?? PUSH BX PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID CALL SETUPNODEHEADER MOV SI,OFFSET BUSYMSG MOV CX,LBUSYMSG JMP SHORT CONNECTF05 ; CONNECTFAILED: ; ; CONNECTION REQUEST FAILED ; IF DOWNLINK, TELL PARTNER ; IF CROSSLINK, TELL ROUTE CONTROL ; CMP LINKTYPE[BX],3 JNE CONNECTF00 ; ; FAILURE TO SET UP CROSSLINK - TELL LEVEL 3 ; CALL L3CONNECTFAILED ; REPORT TO LEVEL 3 RET CONNECTF00: CMP CIRCUITPOINTER[BX],0 JNE CONNECTF01 RET ; NO CROSS LINK CONNECTF01: CALL GETBUFF JZ CONNECTF10 ; NO BUFFERS ?? WHAT SHOULD WE DO ?? PUSH BX PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID CALL SETUPNODEHEADER MOV SI,OFFSET FAILEDMSG MOV CX,LFAILEDMSG CONNECTF05: REP MOVSB LEA SI,LINKCALL[BX] PUSH DI ; SAVE CALL CONVFROMAX25 ; ADDR OF CALLED STATION POP DI MOV SI,OFFSET NORMCALL MOV CX,10 REP MOVSB MOV AL,0DH STOSB MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,CIRCUITPOINTER[BX] ; GET CIRCUIT TABLE ENTRY MOV DX,L4CROSSLINK[BX] ; TO INCOMMONG SESSION PUSH DI CALL CLEARSESSIONENTRY ; CANCEL OUTWARD LINK POP DI MOV BX,DX MOV L4CROSSLINK[BX],0 ; CLEAR REVERSE LINK ; LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER POP BX CONNECTF10: RET ; RETURNEDTONODE: ; ; SEND RETURNED TO ALIAS:CALL ; CALL GETBUFF JNZ RETURNED00 RET ; CANT RETURNED00: PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID MOV SI,OFFSET RETURNEDMSG MOV CX,LRETURNED REP MOVSB MOV SI,OFFSET MYCALL CALL DECODENODENAME MOV CX,20 RETURNED10: LODSB CMP AL,HEADERCHAR JE RETURNED20 ; STOSB LOOP RETURNED10 RETURNED20: MOV AL,0DH STOSB MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER RET SENDCONNECTREPLY: ; ; LINK SETUP COMPLETE - BX = LINK, DI = BUFFER ; CMP LINKTYPE[BX],3 JNE CONNECTED00 ; ; NODE - NODE SESSION SET UP - DONT NEED TO DO ANYTHING (I THINK!) ; CALL RELBUFF RET ; ; UP/DOWN LINK ; CONNECTED00: CMP CIRCUITPOINTER[BX],0 JNE CONNECTED01 CALL RELBUFF ; UP/DOWN WITH NO SESSION - NOONE TO TELL RET ; NO CROSS LINK CONNECTED01: MOV BUFFER,DI PUSH BX PUSH SI PUSH CX ADD DI,5 MOV AL,0F0H STOSB ; PID CALL SETUPNODEHEADER ; PUT IN NODE ID LEA SI,LINKCALL[BX] PUSH DI CALL CONVFROMAX25 ; ADDR OF CALLED STATION POP DI MOV BX,CIRCUITPOINTER[BX] MOV L4STATE[BX],5 ; SET LINK UP MOV BX,L4CROSSLINK[BX] ; TO INCOMING LINK POP CX POP SI REP MOVSB MOV SI,OFFSET NORMCALL MOV CX,NORMLEN REP MOVSB MOV AL,0DH STOSB MOV CX,DI MOV DI,BUFFER SUB CX,DI MOV MSGLENGTH[DI],CX LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER POP BX RET INFORMPARTNER: ; ; LINK IS DISCONNECTING - IF THERE IS A CROSSLINK, SEND DISC TO IT ; CMP LINKTYPE[BX],3 JNE INFORMP00 ; CALL L3LINKCLOSED ; REPORT TO LEVEL 3 RET INFORMP00: CMP CIRCUITPOINTER[BX],0 JNE INFORMP01 RET ; NO CROSS LINK INFORMP01: PUSH BX ; SAVE L2 LINK MOV BX,CIRCUITPOINTER[BX] CALL CLOSESESSIONPARTNER POP BX RET CLOSESESSIONPARTNER: ; ; SEND CLOSE TO CROSSLINKED SESSION AND CLEAR LOCAL SESSION ; CMP L4CROSSLINK[BX],0 JNE INFORMP0X ; NO CROSSLINK CALL CLEARSESSIONENTRY ; CLEAR INCOMING L4 ENTRY RET INFORMP0X: PUSH BX ; SAVE MOV BX,L4CROSSLINK[BX] ; TO PARTNER SESSION CALL CLOSECURRENTSESSION POP BX CALL CLEARSESSIONENTRY ; CLEAR INCOMING L4 ENTRY RET CLOSECURRENTSESSION: ; ; SHUT DOWN SESSION IN BX, AND UNLINK IF CROSSLINKED ; MOV L4CROSSLINK[BX],0 ; REMOVE CROSSLINK ; ; IF STAY FLAG SET, KEEP SESSION, AND SEND MESSAGE ; CMP DISCFLAG,'S' JE STAYHERE ; HOST MODE STAY TEST L4CIRCUITTYPE[BX],BPQHOST JNZ BPQHOSTCLOSE ; DONT HAVE A STAYFLAG CMP STAYFLAG[BX],0 JE DONTSTAY STAYHERE: CALL RETURNEDTONODE RET BPQHOSTCLOSE: ; ; BPQ HOST MODE SESSION - INDICATE STATUS CHANGE ; MOV SI,L4TARGET[BX] ; SI IS HOST CONTROL VECTOR MOV WORD PTR [SI],0 ; CLEAR SESSION POINTER OR BYTE PTR 2[SI],3 ; HOSTSTATECHANGE JMP INFORMP05C ; CLEAR SESSION DONTSTAY: TEST L4CIRCUITTYPE[BX],SESSION JNZ INFORMP03 IF TNC2 TEST L4CIRCUITTYPE[BX],HOST ; CONSOLE JZ INFORMP05 ; LEVEL 2 DISC REQUIRED ; ; SEND *** DISCONNECTED TO CONSOLE, AND CLEAR SESSION ; ; MOV SI,L4TARGET[BX] PUSH BX ; SAVE FAR SESSION MOV BX,SI ; TO TNC SESSION MOV KBSESSION[BX],0 ; CLEAR SESSION ENTRY OR MODEFLAG[BX],COMMAND ; BACK TO COMMAND MODE AND MODEFLAG[BX],NOT (CONV+TRANS) MOV TRANSTIMER[BX],0 ; CANCEL TRANS MODE SEND TIMER ; MOV SI,OFFSET CMDMSG ; MOV CX,4 ; CALL SENDREPLY ; CMD: PROMPT AND VMSR[BX],7FH ; CLEAR CONNECTED OR VMSR[BX],08H ; DELTA DCD CALL SENDSTARDISC ; SEND MESSAGE JMP INFORMP05B ; CLEAR SESSION ELSE JMP INFORMP05 ENDIF INFORMP03: ; ; L4 SESSION TO CLOSE ; CMP L4HOLD_Q[BX],0 JNE INFORMP03A ; WAITING FOR ACK - SEND DISC LATER CMP L4TX_Q[BX],0 JNE INFORMP03A ; STILL MORE TO SEND - SEND DISC LATER CALL SENDL4DISC RET INFORMP03A: OR FLAGS[BX],DISCPENDING ; SEND DISC WHEN ALL DATA ACKED RET INFORMP05: ; ; LEVEL 2 SESSION TO CLOSE ; ; COPY ANY PENDING DATA TO L2 TX Q, THEN GET RID OF SESSION ; LEA SI,L4TX_Q[BX] CALL Q_REM JZ NOWT_ON_SESSION PUSH BX ; SAVE SESSION MOV BX,L4TARGET[BX] ; GET LINK LEA SI,TX_Q[BX] CALL Q_ADD ; MOVE MESSAGE TO LINK LEVEL POP BX JMP INFORMP05 ; SEE IF MORE NOWT_ON_SESSION: ; ; NOTHING LEFT AT SESSION LEVEL ; PUSH BX ; SAVE SESSION MOV BX,L4TARGET[BX] ; GET LINK MOV CIRCUITPOINTER[BX],0 ; CLEAR REVERSE LINK ; MOV AL,LINKWS[BX] ; NEW WINDOW START CMP AL,LINKNS[BX] ; IS N(S) = NEW WINDOW START? JNE INFORMP05A ; STILL SOME TO ACK ; CMP TX_Q[BX],0 JNE INFORMP05A ; STILL MORE TO SEND - SEND DISC LATER ; ; NOTHING QUEUED - CAN SEND DISC NOW ; MOV L2STATE[BX],4 ; DISCONNECTING MOV L2TIMER[BX],1 ; USE TIMER TO KICK OFF DISC JMP SHORT INFORMP05B INFORMP05A: OR L2FLAGS[BX],DISCPENDING ; SEND DISC WHEN ALL DATA ACKED INFORMP05B: POP BX INFORMP05C: CALL CLEARSESSIONENTRY ; CLEAR L4 ENTRY RET GETFREECIRCUIT: MOV BX,L4TABLE MOV CX,MAXCIRCUITS MOV DL,0 GETFREE00: CMP BYTE PTR [BX],0 JNE GETFREE05 ; NOT A SPARE ENTRY RET GETFREE05: ADD BX,TYPE TRANSPORTENTRY INC DL ; INDEX LOOP GETFREE00 ; ; ENTRY NOT FOUND ; OR AL,1 RET FINDCIRCUIT: ; ; FIND CIRCUIT FOR AN INCOMING MESSAGE ; ; MESSAGE ADDR IN DI ; MOV BX,0 MOV DL,0 ; INDEX MOV SI,L4TABLE MOV CX,MAXCIRCUITS FINDLK00: CMP BYTE PTR [SI],0 JNE FINDLK05 ; NOT A SPARE ENTRY CMP BX,0 JNE FINDLK10 ; ALREADY FOUND A SPARE MOV BX,SI ; POINTER TO FIRST FREE MOV DH,DL JMP SHORT FINDLK10 ; TRY NEXT ENTRY FINDLK05: PUSH SI PUSH DI PUSH CX MOV SI,L4TARGET[SI] ; POINTER TO DEST ENTRY LEA SI,DEST_CALL[SI] LEA DI,L3SRCE[DI] ; ORIGIN FROM MESSAGE CALL COMPARECALLS ; COMPARE WITH LINKCALL POP CX POP DI POP SI JNE FINDLK10 ; WRONG NODE MOV AX,WORD PTR L4INDEX[DI] ; ID AND INDEX CMP AX,WORD PTR FARINDEX[SI] JE FINDLKRET ; CORRECT CIRCUIT FINDLK10: ADD SI,TYPE TRANSPORTENTRY INC DL ; INDEX LOOP FINDLK00 ; ; ENTRY NOT FOUND - BX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 MOV DL,DH ; FIRST FREE INDEX RET FINDLKRET: MOV BX,SI XOR AL,AL RET L4TIMERPROC: ; ; CHECK FOR TIMER EXPIRY ; MOV CX,MAXCIRCUITS MOV BX,L4TABLE L4TIM00: CMP L4USER[BX],0 JNE L4TIM01 ; ; SPARE ENTRY ; L4TIM300: ADD BX,TYPE TRANSPORTENTRY LOOP L4TIM00 RET L4TIM01: MOV AX,L4TIMER[BX] OR AX,AX JZ L4TIM100 ; NOT RUNNING DEC AX MOV L4TIMER[BX],AX ; DECREMENT JNZ L4TIM100 ; NOT EXPIRED CALL L4TIMEOUT ; TIMEOUT HAS OCCURED L4TIM100: CMP L4ACKREQ[BX],0 ; DELAYED ACK TIMER JE L4TIM200 ; NOT RUNNING DEC L4ACKREQ[BX] JNZ L4TIM200 ; STILL OK ; PUSH BX PUSH CX ; CALL SENDL4IACK ; SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES ; POP CX POP BX L4TIM200: INC L4KILLTIMER[BX] ; ; IF BIT 6 OF APPLFLAGS SET, SEND MSG EVERY 11 MINS TO KEEP SESSION OPEN ; CMP L4CROSSLINK[BX],0 ; CONNECTED? JE L4TIM202 ; NO TEST SESS_APPLFLAGS[BX],40H JZ L4TIM202 ; AUTOTIMER MODE NOT SELECTED CMP L4KILLTIMER[BX],11*60 ; 11 MINS JB L4TIM202 CALL AUTOTIMER L4TIM202: MOV AX,L4LIMIT OR AX,AX JZ L4TIM300 ; IF ZERO, RUN FOR EVER CMP L4KILLTIMER[BX],AX JB L4TIM300 ; MOV L4KILLTIMER[BX],0 ; ; CLOSE THIS SESSION, AND ITS PARTNER (IF ANY) ; PUSH BX PUSH CX PUSH L4CROSSLINK[BX] ; SAVE PARTNER SESSION MOV STAYFLAG[BX],0 CALL CLOSECURRENTSESSION ; CLOSE THIS ONE POP BX OR BX,BX JZ L4TIM250 ; NO CROSSLINK MOV L4KILLTIMER[BX],0 ; ITS TIMES IS ALSO ABOUT TO EXPIRE MOV STAYFLAG[BX],0 CALL CLOSECURRENTSESSION ; CLOSE IT AS WELL L4TIM250: POP CX POP BX JMP L4TIM300 L4TIMEOUT: ; ; TIMER EXPIRED ; ; IF LINK UP REPEAT TEXT ; IF S2, REPEAT CONNECT REQUEST ; IF S4, REPEAT DISCONNECT REQUEST ; CMP L4STATE[BX],1 ; NO IDLE STATE JLE L4TIMRET CMP L4STATE[BX],4 JA L4TIM30 ; LINK UP JE L4TIM05 ; SEND DISC AGAIN CMP L4STATE[BX],2 JE L4TIM10 ; SEND CONNECT AGAIN L4TIMRET: RET L4TIM05: ; ; RETRY DISCONNECT ; INC L4RETRIES[BX] MOV AL,L4N2 CMP L4RETRIES[BX],AL JL L4TIM08 ; ; RETRIED N2 TIMES - FAIL LINK ; L4TIM06: PUSH BX PUSH CX CALL CLEARSESSIONENTRY POP CX POP BX RET L4TIM08: PUSH BX PUSH CX CALL SENDL4DISC POP CX POP BX RET ; ; RETRY CONNECT ; L4TIM10: INC L4RETRIES[BX] MOV AL,L4N2 CMP L4RETRIES[BX],AL JL L4TIM12 ; ; RETRIED N2 TIMES - FAIL LINK ; L4TIM11: PUSH BX PUSH CX CALL L4CONNECTFAILED ; TELL OTHER PARTNER IT FAILED CALL CLEARSESSIONENTRY POP CX POP BX RET L4TIM12: PUSH BX PUSH CX CALL SENDL4CONNECT POP CX POP BX RET L4TIM30: ; ; STATE 5 OR ABOVE - RETRY INFO ; ; AND FLAGS[BX],NOT L4BUSY ; CANCEL CHOKE INC L4RETRIES[BX] MOV AL,L4N2 CMP L4RETRIES[BX],AL JL L4TIM40 ; PUSH BX PUSH CX CALL CLOSESESSIONPARTNER POP CX POP BX RET ; L4TIM40: ; PUSH BX PUSH CX ; ; RESEND ALL OUTSTANDING FRAMES ; AND FLAGS[BX],7FH ; CLEAR CHOKED MOV SI,L4HOLD_Q[BX] L4TIM45: CMP SI,0 JE L4TIM049 ; NO MORE MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; RESTART TIMER PUSH SI CALL GETBUFF POP SI JZ L4TIM049 ; CANT - NO BUFFERS ; PUSH SI PUSH DI MOV CX,MSGLENGTH[SI] REP MOVSB ; COPY MESSAGE - LEAVE STATE ALONE POP DI ; MESSAGE PUSH BX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD ; QUEUE ON DEST INC L4FRAMESRETRIED JNZ INC004 INC L4FRAMESRETRIED+2 INC004: POP BX POP SI MOV SI,[SI] ; NEXT MESSAGE IN CHAIN JMP L4TIM45 ; SEND NEXT L4TIM049: POP CX POP BX RET SENDL4CONNECT: CALL GETBUFF JNZ SENDL4C00 ; OK RET SENDL4C00: MOV L3PID[DI],0CFH ; NET MESSAGE PUSH DI LEA SI,L4MYCALL[BX] LEA DI,L3SRCE[DI] MOV CX,7 REP MOVSB MOV SI,L4TARGET[BX] ; FAR END NODE LEA SI,DEST_CALL[SI] MOV CX,7 REP MOVSB POP DI PUSH DI MOV AL,L3LIVES MOV L3MONR[DI],AL MOV AX,WORD PTR CIRCUITINDEX[BX] MOV WORD PTR L4INDEX[DI],AX MOV WORD PTR L4TXNO[DI],0 MOV L4FLAGS[DI],L4CREQ MOV AL,L4DEFAULTWINDOW MOV L4DATA[DI],AL ; PROPOSED WINDOW LEA DI,L4DATA+1[DI] ; TO ORIG CALL LEA SI,L4USER[BX] MOV CX,7 REP MOVSB LEA SI,L4MYCALL[BX] MOV CX,7 REP MOVSB MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; START TIMER STOSW ; AND PUT IN MSG CMP SPYFLAG[BX],0 JE NOTSPY MOV AL,'Z' ; ADD SPY ON BBS FLAG STOSB NOTSPY: MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD RET SENDL4DISC: CMP L4STATE[BX],4 JAE OKTODIS ; ; CIRCUIT NOT UP OR CLOSING - PROBABLY NOT YET SET UP - JUST ZAP IT ; CALL L4TIM06 RET OKTODIS: MOV AX,SESSIONT1[BX] MOV L4TIMER[BX],AX ; START TIMER MOV L4STATE[BX],4 ; SET DISCONNECTING MOV L4ACKREQ[BX],0 ; CANCEL ACK NEEDED CALL GETBUFF JNZ SENDL4D00 ; OK RET SENDL4D00: MOV L3PID[DI],0CFH ; NET MESSAGE PUSH DI LEA SI,L4MYCALL[BX] ; CALL WE ARE USING LEA DI,L3SRCE[DI] MOV CX,7 REP MOVSB MOV SI,L4TARGET[BX] ; FAR END NODE LEA SI,DEST_CALL[SI] MOV CX,7 REP MOVSB POP DI PUSH DI MOV AL,L3LIVES MOV L3MONR[DI],AL MOV AX,WORD PTR FARINDEX[BX] MOV WORD PTR L4INDEX[DI],AX MOV WORD PTR L4TXNO[DI],0 MOV L4FLAGS[DI],L4DREQ LEA DI,L4DATA[DI] MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD RET SENDL4IACK: ; ; SEND INFO ACK ; CALL GETBUFF JNZ SENDL4A00 ; OK MOV L4ACKREQ[BX],10 ; TRY AGAIN LATER RET SENDL4A00: MOV L4ACKREQ[BX],0 ; CLEAR ACK NEEDED MOV L3PID[DI],0CFH ; NET MESSAGE PUSH DI LEA SI,L4MYCALL[BX] ; CALL WE ARE USING LEA DI,L3SRCE[DI] MOV CX,7 REP MOVSB MOV SI,L4TARGET[BX] ; FAR END NODE LEA SI,DEST_CALL[SI] MOV CX,7 REP MOVSB POP DI PUSH DI MOV AL,L3LIVES MOV L3MONR[DI],AL MOV AX,WORD PTR FARINDEX[BX] MOV WORD PTR L4INDEX[DI],AX MOV L4TXNO[DI],0 MOV AL,RXSEQNO[BX] MOV L4RXNO[DI],AL MOV L4LASTACKED[BX],AL ; SAVE LAST NUMBER ACKED CALL GETBUSYBIT ; SEE IF CROSSSESSION IS BUSY MOV AL,L4IACK OR AL,NAKBITS[BX] ; PUT IN NAK/CHOKE BITS MOV L4FLAGS[DI],AL LEA DI,L4DATA[DI] MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,L4TARGET[BX] ; LINK ENTRY LEA SI,DEST_Q[BX] CALL Q_ADD RET GETBUSYBIT: ; ; SEE IF CROSSSESSION IS BUSY ; AND NAKBITS[BX],0FFH-L4BUSY CALL CHECKIFBUSY ; RETURNS AL WITH BUSY BIT SET IF CROSSSESSION IS BUSY OR NAKBITS[BX],AL RET L4CONNECTFAILED: ; ; CONNECT HAS TIMED OUT - SEND MESSAGE TO OTHER END ; CMP L4CROSSLINK[BX],0 JE L4CONF00 ; NO LINK? CALL GETBUFF JNZ L4CONF10 L4CONF00: RET L4CONF10: PUSH BX PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID CALL SETUPNODEHEADER ; PUT IN NODE ID MOV SI,OFFSET FAILEDMSG MOV CX,LFAILEDMSG REP MOVSB PUSH DI MOV SI,L4TARGET[BX] ; ADDR OF DEST ENTRY LEA SI,DEST_CALL[SI] CALL DECODENODENAME ; CONVET TO ALIAS:CALL POP DI MOV CX,17 REP MOVSB MOV AL,0DH STOSB MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX MOV BX,L4CROSSLINK[BX] MOV L4CROSSLINK[BX],0 ; SET BACK TO COMMAND LEVEL LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER POP BX ; ORIGINAL CIRCUIT TABLE RET AUTOTIMER: ; ; SEND MESSAGE TO USER TO KEEP CIRCUIT OPEN ; CALL GETBUFF JNZ KEEP00 RET ; CANT KEEP00: PUSH DI ADD DI,5 MOV AL,0F0H STOSB ; PID XOR AX,AX STOSW ; A COUPLE OF NULLS MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX LEA SI,L4TX_Q[BX] CALL Q_ADD ; SEND MESSAGE TO CALLER MOV L4KILLTIMER[BX],0 PUSH BX MOV BX,L4CROSSLINK[BX] ; TO PARTNER SESSION OR BX,BX JZ L4TIM201 ; NO CROSSLINK?? MOV L4KILLTIMER[BX],0 ; ITS TIMES IS ALSO ABOUT TO EXPIRE L4TIM201: POP BX RET IF TNC2 SETUPCONSOLESESSION: ; ; SET UP A SESSION FOR INTERNAL TNC SUPPORT ; MOV AL,APPLICATION[BX] ENDIF SETUPBPQCONSOLESESSION: ; APPL ALREADY IN AL PUSH BX ; SAVE TNC POINTER CALL GETFREECIRCUIT ; GET AN ENTRY JZ SETUPCON00 ; OK ADD SP,2 ; CLEAR STACK MOV BX,0 ; RETURN PORTER = 0 RET SETUPCON00: ; ; IF BBS PORT USE BBS CALL, ELSE NODE CALL ; LEA SI,BBSCALL ; BBS CALLSIGN TEST AL,1 ; APPL FLAG JNZ CCTFORBBS LEA SI,MYCALL CCTFORBBS: PUSH SI LEA DI,L4USER[BX] MOV CX,7 REP MOVSB ; PUT IN CALL ; POP SI LEA DI,L4MYCALL[BX] ; NODE CALL IN USE MOV CX,7 REP MOVSB ; PUT IN CALL ; MOV CIRCUITINDEX[BX],DL ; OUR INDEX MOV AL,NEXTID MOV CIRCUITID[BX],AL ; OUR ID CALL INC_ID POP AX MOV L4TARGET[BX],AX ; LINK POINTER - TO TNC CONTROL INFO IF TNC2 MOV L4CIRCUITTYPE[BX],HOST+UPLINK ; HOST ENDIF MOV L4STATE[BX],5 MOV AX,L4T1 MOV SESSIONT1[BX],AX ; DEFAULT TIMEOUT MOV AL,L4DEFAULTWINDOW MOV L4WINDOW[BX],AL ; SET WINDOW MOV AL,PACLEN MOV SESSPACLEN[BX],AL ; DEFAULT RET CODE ENDS END