PAGE 56,132 ; .386 ; ; SEGMENT definitions and order ; ; July 2008 ; Fix possible crash if L4DACK received out of sequence ;* 32 Bit code _TEXT SEGMENT DWORD USE32 PUBLIC 'CODE' _TEXT ENDS ;* Contains 32 Bit data _BPQDATA SEGMENT DWORD PUBLIC 'DATA' _BPQDATA ENDS ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:FLAT OFFSET32 EQU _BPQDATA SEGMENT INCLUDE STRUCS.INC APPLCALLTABLEPTR DD 0 ; APPLICAION BEING CONNECTED TO 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 DD 0 ; CURRENT LINK SAVEPORT DB 0 ; CURRENT PORT ; TEMPFIELD DB 7 DUP (0) ; TEMP STORAGE FOR CALL extern _NEXTID:byte ; DB 55H ; NEXT ID TO ALLOCATE ; FRAGFLAG DB 0 ; MESSAGE FRAGMENTATION FLAG CONNECTSESSION DD 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 W16 DW 16 CTPACLEN DD 0 _L3RTT DB 'L'+'L','3'+'3','R'+'R','T'+'T','T'+'T',40h,11100000B; L3RTT IN AX25 _L3KEEP DB 'K'+'K','E'+'E','E'+'E','P'+'P','L'+'L','I'+'I',11100000B; L3RTT IN AX25 ; ; FIRST WORD - L4 TIMEOUT ; NEXT BYTE - 'SPY FLAG' ; TRANSPORTLENGTH DB TYPE TRANSPORTENTRY PUBLIC SAVELINK,SAVEPORT, _L3RTT, _L3KEEP EXTRN L3FRAMES:WORD,L4FRAMESTX:WORD,L4FRAMESRX:WORD,HEADERCHAR:BYTE,ROUTEVECLEN:DWORD EXTRN L4FRAMESRETRIED:WORD,L4CONNECTSIN:DWORD,OLDFRAMES:WORD EXTRN L4DELAY:WORD,_L4DEFAULTWINDOW:BYTE,PACLEN:BYTE,APPLMASK:DWORD EXTRN _MYCALL:BYTE,APPLCALLTABLE:BYTE,AX25CALL:BYTE,NORMCALL:BYTE,QCOUNT:WORD EXTRN DECODEDNAME:BYTE,ROUTEQUAL:BYTE,BUFFER:DWORD,SAVENBOUR:DWORD EXTRN NORMLEN:WORD,SAVEDAPPLFLAGS:BYTE,DESTS:DWORD,_MAXDESTS:WORD EXTRN BPQHOSTVECTOR:DWORD,_NUMBEROFNODES:DWORD EXTRN IPHOSTVECTOR:BYTE EXTRN _L4T1:WORD,_L3LIVES:BYTE,_L4TABLE:DWORD,_MAXCIRCUITS:WORD EXTRN _L4LIMIT:WORD,L4N2:BYTE,NODE:BYTE,D10:BYTE EXTRN ALIASPTR:DWORD,CMDALIAS:BYTE EXTRN TNCTABLE:DWORD,NUMBEROFSTREAMS:WORD,DISCFLAG:BYTE EXTRN _FULL_CTEXT:BYTE,_CTEXTMSG:DWORD,_CTEXTLEN:WORD _BPQDATA ENDS _TEXT SEGMENT 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 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 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 EXTRN POSTSTATECHANGE:NEAR extrn _time:near, _NRRecordRoute:NEAR, _ProcessRTTMsg:near, _ProcessINP3RIF:NEAR PUBLIC L4BG L4BG: ; ; PROCESS DATA QUEUED ON SESSIONS ; MOV EBX,_L4TABLE MOVZX ECX,_MAXCIRCUITS PUBLIC L4BG00 L4BG00: CMP L4USER[EBX],0 JE L4BG99 ; SPARE ENTRY PUBLIC L4BG01 L4BG01: ; TEST L4CIRCUITTYPE[EBX],BPQHOST JNZ SHORT JMP_50 ; LEAVE HERE IF BPQ HOST MODE LEA ESI,L4TX_Q[EBX] ; FRAMES TO SEND? CMP WORD PTR [ESI],0 JE SHORT JMP_50 ; NO ; ; SEE IF BUSY - NEED DIFFERENT TESTS FOR EACH SESSION TYPE ; TEST L4CIRCUITTYPE[EBX],SESSION JZ SHORT L4BG06 ; ; L4 SESSION - WILL NEED BUFFERS FOR SAVING COPY, ; AND POSSIBLY FRAGMENTATION ; CMP QCOUNT,15 JB SHORT JMP_50 ; WAIT TILL THERE ARE MORE ; TEST FLAGS[EBX],L4BUSY JZ SHORT L4BG05 ; NOT CHOKED ; ; CHOKED - MAKE SURE TIMER IS RUNNING ; MOV AX,SESSIONT1[EBX] CMP L4TIMER[EBX],0 JNZ SHORT L4BG50 ; OK - TIMER IS RUNNING MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; RESTART TIMER PUBLIC JMP_50 JMP_50: JMP L4BG50 ; AND WAIT PUBLIC L4BG05 L4BG05: ; ; CHECK WINDOW ; MOV AL,TXSEQNO[EBX] SUB AL,L4WS[EBX] ; LAST FRAME ACKED - GIVES NUMBER OUTSTANING ; ; MOD 256, SO SHOULD HANDLE WRAP?? ; CMP AL,L4WINDOW[EBX] JB SHORT L4BG10 ; OK JMP L4BG50 ; BUSY PUBLIC L4BG06 L4BG06: TEST L4CIRCUITTYPE[EBX],L2LINK JZ SHORT L4BG10 ; NOT DEFINED?? ; ; L2 LINK - ESI IS POINTING TO Q HEADER, EBX TO SESSION ; PUSH EBX MOV EBX,L4TARGET[EBX] ; TO LINK MOV AH,0 CALL COUNT_AT_L2 ; SEE HOW MANY QUEUED POP EBX CMP AH,5 JA SHORT L4BG50 ; BUSY PUBLIC L4BG10 L4BG10: CALL Q_REM PUSH EBX PUSH ECX TEST L4CIRCUITTYPE[EBX],PACTOR ; NOT PACTOR JZ @F ; ; PACTOR-like - queue to Port ; ; Stream Number for KAM is in KAMSESSION MOV AL,KAMSESSION[EBX] MOV 4[EDI],AL MOV EBX,L4TARGET[EBX] ; PORT ENTRY LEA ESI,PORTTX_Q[EBX] JMP SHORT L4BG25 @@: ; ; IF CROSSLINK, QUEUE TO NEIGHBOUR, ELSE QUEUE ON LINK ENTRY ; TEST L4CIRCUITTYPE[EBX],SESSION ; NOT CROSSLINK JZ SHORT L4BG20 ; CALL SENDL4MESSAGE ; PUT IN LEVEL 4 HEADER JMP SHORT L4BG30 ; PUBLIC L4BG20 L4BG20: MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,TX_Q[EBX] PUBLIC L4BG25 L4BG25: CALL _Q_ADD PUBLIC L4BG30 L4BG30: POP ECX POP EBX MOV L4KILLTIMER[EBX],0 ; RESET SESSION TIMEOUT JMP L4BG01 ; SEE IF MORE PUBLIC L4BG50 L4BG50: LEA ESI,L4RX_Q[EBX] ; FRAMES RECEIVED? CALL Q_REM JZ SHORT L4BG55 ; NO PUSH EBX PUSH ECX ; MOV BUFFER,EDI CALL IFRM150 POP ECX POP EBX CMP L4USER[EBX],0 JE SHORT L4BG99 ; HAVE JUST CLOSED SESSION! JMP L4BG50 ; SEE IF NMORE PUBLIC L4BG55 L4BG55: ; ; IF ACK IS PENDING, AND WE ARE AT RX WINDOW, SEND ACK NOW ; MOV AL,RXSEQNO[EBX] SUB AL,L4LASTACKED[EBX] ; NUMBER TO ACK CMP AL,L4WINDOW[EBX] JB SHORT L4BG56 ; NOT AT WINDOW PUSH EBX PUSH ECX CALL SENDL4IACK POP ECX POP EBX PUBLIC L4BG56 L4BG56: PUBLIC L4BG99 L4BG99: ADD EBX,TYPE TRANSPORTENTRY LOOP L4BGXX RET PUBLIC L4BGXX L4BGXX: JMP L4BG00 ; TOO FAR FOR LOOP PUBLIC SENDL4MESSAGE SENDL4MESSAGE: CMP MSGLENGTH[EDI],8 JE SHORT NULLMESSAGE ; NO DATA - DISCARD IT MOV FRAGFLAG,0 ; NO FRAGMENTATION MOV BUFFER,EDI ; SAVE MESSAGE CALL GETBUFF JNZ SHORT 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 EDI,BUFFER MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; RESTART TIMER PUBLIC NULLMESSAGE NULLMESSAGE: CALL RELBUFF RET PUBLIC SENDL4M00 SENDL4M00: MOV L3PID[EDI],0CFH ; NET MESSAGE PUSH EDI LEA ESI,L4MYCALL[EBX] ; CALL WE ARE USING LEA EDI,L3SRCE[EDI] MOV ECX,7 REP MOVSB MOV ESI,L4TARGET[EBX] ; FAR END NODE LEA ESI,DEST_CALL[ESI] MOV ECX,7 REP MOVSB POP EDI PUSH EDI MOV AL,_L3LIVES MOV L3MONR[EDI],AL MOV AX,WORD PTR FARINDEX[EBX] MOV WORD PTR L4INDEX[EDI],AX MOV AL,TXSEQNO[EBX] MOV L4TXNO[EDI],AL INC TXSEQNO[EBX] ; ; SET UP RTT TIMER ; CMP RTT_TIMER[EBX],0 JNE SHORT RTT_RUNNING ; ALREADY TIMING MOV RTT_SEQ[EBX],AL ; ; GET TIME FROM BIOS DATA AREA OR RTC ; PUSH 0 CALL _time ADD ESP,4 MUL W16 MOV RTT_TIMER[EBX],AX ; SAVE PUBLIC RTT_RUNNING RTT_RUNNING: MOV AL,RXSEQNO[EBX] MOV L4RXNO[EDI],AL MOV L4LASTACKED[EBX],AL ; SAVE LAST NUMBER ACKED CALL GETBUSYBIT ; SEE IF CROSSSESSION IS BUSY MOV AL,L4INFO OR AL,NAKBITS[EBX] ; PUT IN NAK/CHOKE BITS MOV L4FLAGS[EDI],AL MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; SET TIMER MOV L4ACKREQ[EBX],0 ; CANCEL ACK NEEDED MOV ESI,BUFFER MOVZX ECX,MSGLENGTH[ESI] CMP ECX,244 ; 236 DATA + 8 HEADER JBE SETUPHOK ; ; MUST FRAGMENT MESSAGE ; OR L4FLAGS[EDI],L4MORE MOV FRAGFLAG,1 MOV ECX,244 PUBLIC SETUPHOK SETUPHOK: ADD ECX,20 MOV MSGLENGTH[EDI],CX SUB ECX,28 LEA EDI,L4DATA[EDI] LEA ESI,8[ESI] REP MOVSB ; ; CREATE COPY FOR POSSIBLE RETRY ; CALL GETBUFF POP ESI ; NEW MESSAGE JZ SHORT SETUPH99 ; SHOULD NEVER HAPPEN ; PUSH ESI ; SAVE PUSH EDI MOVZX ECX,MSGLENGTH[ESI] REP MOVSB LEA ESI,L4HOLD_Q[EBX] POP EDI ; COPY CALL _Q_ADD ; PUT ON QUEUE ; POP EDI ; MESSAGE PUSH EBX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD ; QUEUE ON DEST INC DEST_COUNT[EBX] ; COUNT THEM POP EBX INC L4FRAMESTX CMP FRAGFLAG,0 JE SHORT SETUPHEND ; NO FRAGMENTATION ; ; MESSAGE WAS TOO BIG - ADJUST IT AND LOOP BACK ; MOV EDI,BUFFER MOVZX ECX,MSGLENGTH[EDI] SUB ECX,244 JBE SETUPHEND ; WOT!! ; ; ECX = DATA TO SEND ; ADD ECX,8 ; HEADER MOV MSGLENGTH[EDI],CX LEA ESI,244[EDI] LEA EDI,8[EDI] SUB ECX,8 REP MOVSB ; MOVE DATA UP MOV EDI,BUFFER JMP SENDL4MESSAGE PUBLIC SETUPHEND SETUPHEND: PUBLIC SETUPH99 SETUPH99: MOV EDI,BUFFER CALL RELBUFF ; RELEASE ORIGINAL MESSAGE RET PUBLIC CHECKIFBUSY CHECKIFBUSY: ; ; RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY ; MOV AH,0 PUSH ESI MOV ESI,EBX ; COUNT QUEUED USES ESI CMP L4CROSSLINK[EBX],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 ; ; COUNT 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 ; PUBLIC CHECKBPARTNER CHECKBPARTNER: MOV ESI,L4CROSSLINK[EBX] ; TO PARTNER CALL COUNT_QUEUED_FRAMES ; FRAMES NOT ACKED PUBLIC CHECKBTEST CHECKBTEST: MOV AH,AL CMP L4WINDOW[EBX],AL JA SHORT CHECKBRET ; NOT BUSY ; ; NUMBER QUEUED = WINDOW - STOP SENDING ; MOV AL,L4BUSY POP ESI RET PUBLIC CHECKBRET CHECKBRET: MOV AL,0 POP ESI RET PUBLIC PROCESSIFRAME 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,EDI ; SAVE MOV SAVELINK,EBX ; SAVE LINK TABLE MOV AL,LINKPORT[EBX] MOV SAVEPORT,AL ; SAVE PORT ; ; IT IS POSSIBLE TO MULTIPLEX NETROM AND IP STUFF ON THE SAME LINK ; CMP L3PID[EDI],0CCH JE SHORT Q_IP_MSG CMP L3PID[EDI],0CDH JE SHORT Q_IP_MSG CMP L3PID[EDI],0CFH JE SHORT INTERNODE ; MUST BE INTERNODE! CMP LINKTYPE[EBX],3 JNE SHORT IFRM100 ; UP/DOWN PUBLIC INTERNODE INTERNODE: ; ; IF LINKTYPE IS NOT 3, MUST CHECK IF WE HAVE ACCIDENTALLY ATTACHED A ; BBS PORT TO THE NODE ; CMP LINKTYPE[EBX],3 JE SHORT ALREADY_L3 CMP CIRCUITPOINTER[EBX],0 ; ANY SESSION? JE SHORT MAKEIT_L3 ; NOTHING ATTACHED ; ; MUST KILL SESSION ; CALL INFORMPARTNER ; CLOSE IT MOV CIRCUITPOINTER[EBX],0 ; AND UNHOOK PUBLIC MAKEIT_L3 MAKEIT_L3: MOV LINKTYPE[EBX],3 ; NOW WE KNOW ITS A CROSSLINK PUBLIC ALREADY_L3 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[EDI],0CFH JE SHORT PIDOK JMP L3DISCARD PUBLIC Q_IP_MSG Q_IP_MSG: MOV EBX,OFFSET32 IPHOSTVECTOR ; ; VECTOR FORMAT IS: ; ; 0-3 2 BYTES - ADDRESS OF SESSION ENTRY ; 4 1 BYTE - STATE CHANGE FLAGS ; 5 1 BYTE - APPLICATION MASK ; 6 1 BYTE - APPLICATION FLAGS - TOP BIT ENABLES MONITORING ; 7-10 2 BYTES - RAW FRAME QUEUE ; TEST HOSTAPPLFLAGS[EBX],80H JZ SHORT NOSAVE ; NOT ENABLED ; ; CHECK WE ARENT USING TOO MANY BUFFERS ; PUSH EDI CMP HOSTTRACEQ[EBX],0 JE SHORT IPOK ; NONE QUEUED PUSH EBX LEA EBX,HOSTTRACEQ[EBX] ; TO HEADER CALL COUNT_Q POP EBX CMP AL,20 JB SHORT IPOK LEA ESI,HOSTTRACEQ[EBX] CALL Q_REM JZ SHORT IPOK ; WOT? CALL RELBUFF PUBLIC IPOK IPOK: POP EDI LEA ESI,HOSTTRACEQ[EBX] CALL _Q_ADD ; PUT ON QUEUE RET PUBLIC NOSAVE NOSAVE: CALL RELBUFF RET PUBLIC PIDOK PIDOK: CALL NETROMMSG RET PUBLIC IFRM100 IFRM100: CMP CIRCUITPOINTER[EBX],0 JE SHORT IFRM200 ; NOT CONNECTED ; ; UPLINK WITH CIRCUIT - PASS ACROSS ; MOV EBX,CIRCUITPOINTER[EBX] ; TO CIRCUIT ENTRY PUBLIC IFRM150 IFRM150: ; ; ENTER HERE WITH I FRAME FROM L4 - EBX IS INCOMING SESSION ; MOV L4KILLTIMER[EBX],0 ; RESET SESSION TIMEOUT CMP L4CROSSLINK[EBX],0 ; CONNECTED? JE SHORT IFRM250 ; NO, SO PASS TO COMMAND HANDLER MOV EDX,EBX ; SAVE MOV EBX,L4CROSSLINK[EBX] ; TO SESSION PARTNER CMP L4STATE[EBX],5 JE SHORT IFRM155 ; OK ; ; MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION ; AND PASS MESSAGE TO COMMAND HANDLER ; TEST L4CIRCUITTYPE[EBX],L2LINK ; L2 SESSION? JZ SHORT IFRM152 ; NO ; ; MUST CANCEL L2 SESSION ; PUSH EBX MOV EBX,L4TARGET[EBX] MOV CIRCUITPOINTER[EBX],0 ; CLEAR REVERSE LINK MOV L2STATE[EBX],4 ; DISCONNECTING MOV L2TIMER[EBX],1 ; USE TIMER TO KICK OFF DISC PUSH EBX MOV AL,LINKPORT[EBX] CALL GETPORTTABLEENTRY MOV AL,PORTN2[EBX] POP EBX SUB AL,2 MOV L2RETRIES[EBX],AL ; ONLY SEND DISC ONCE ; POP EBX PUBLIC IFRM152 IFRM152: CALL CLEARSESSIONENTRY MOV EBX,EDX ; RESTORE OLD SESSION MOV L4CROSSLINK[EBX],0 ; CLEAR CROSS LINK JMP SHORT IFRM250 PUBLIC IFRM155 IFRM155: LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; PASS TO DEST CALL _POSTDATAAVAIL RET ; PUBLIC IFRM200 IFRM200: ; ; UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE ; CALL GETPORTPACLEN ; PACLEN FOR THIS PORT PUSH EAX CALL SETUPUSERSESSION POP EAX JZ SHORT IFRM202 ; OK RET ; SEND BUSY?? PUBLIC IFRM202 IFRM202: MOV SESSPACLEN[EBX],AL PUBLIC IFRM250 IFRM250: MOV EDI,BUFFER CALL COMMANDHANDLER ; BUFFER USED FOR REPLY OR CONNECT RET PUBLIC SETUPUSERSESSION SETUPUSERSESSION: ; ; UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE ; PUSH EBX ; SAVE LINK ENTRY CALL GETFREECIRCUIT ; GET AN ENTRY JZ SHORT IFRM210 ; OK POP EBX RET PUBLIC IFRM210 IFRM210: MOV EAX,EBX POP EBX MOV CIRCUITPOINTER[EBX],EAX ; SETUP LINK-CIRCUIT CONNECTION LEA ESI,LINKCALL[EBX] ; CALLER'S CALLSIGN PUSH EBX ; SAVE LINK ENTRY MOV EBX,EAX LEA EDI,L4USER[EBX] MOV ECX,7 REP MOVSB ; PUT IN CALL ; MOV ESI,OFFSET32 _MYCALL ; ALWAYS USE NODE CALL LEA EDI,L4MYCALL[EBX] MOV ECX,7 REP MOVSB MOV CIRCUITINDEX[EBX],DL ; OUR INDEX MOV AL,_NEXTID MOV CIRCUITID[EBX],AL ; OUR ID CALL INC_ID POP EAX ; LINK MOV L4TARGET[EBX],EAX ; LINK POINTER MOV L4CIRCUITTYPE[EBX],L2LINK+UPLINK ; UPLINK MOV L4STATE[EBX],5 ; SET LINK ACTIVE MOV AX,_L4T1 MOV SESSIONT1[EBX],AX ; DEFAULT TIMEOUT MOV AL,_L4DEFAULTWINDOW MOV L4WINDOW[EBX],AL ; SET WINDOW XOR AL,AL RET PUBLIC INC_ID INC_ID: INC _NEXTID JNZ SHORT IDOK INC _NEXTID ; KEEP NONZERO PUBLIC IDOK IDOK: RET PUBLIC NETROMMSG NETROMMSG: ; ; MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT ; WE THINK IS A NODE-NODE LINK ; CMP L3PID[EDI],0CFH JNE SHORT DISC00 ; IGNORE IT ; ; MESSAGE ON NODE-NODE SESSION ; ; EBX = LINK, EDI = BUFFER ; CMP NEIGHBOUR[EBX],0 JNE SHORT NETMSG00 ; OK ; ; NO DESTINATION ASSOCIATED WITH THIS CIRCUIT - SET ONE UP ; CALL CHECKNEIGHBOUR CMP NEIGHBOUR[EBX],0 JNE SHORT NETMSG00 ; NOW OK ; ; COULDNT SET UP NEIGHBOUR - CAN ONLY THROW IT AWAY ; PUBLIC DISC00 DISC00: JMP L3DISCARD PUBLIC NETMSG00 NETMSG00: ; ; See if a INP3 RIF (first Byte 0xFF) ; MOV EDI,BUFFER CMP L3PID+1[EDI],0FFH JNE @F MOVZX EAX, BYTE PTR 4[EDI] ; Port PUSH EAX MOVZX EAX, WORD PTR 5[EDI] ; Length SUB EAX,9 PUSH EAX ADD EDI, 9 ; TO RIF PUSH EDI push NEIGHBOUR[EBX] CALL _ProcessINP3RIF ADD ESP,16 JMP L3DISCARD @@: CMP NODE,0 ; NODE SUPPORT INCLUDED? JE SHORT NONODECODE ; NO MOV APPLMASK,0 ; NOT APPLICATION MOV EDI,BUFFER LEA ESI,L3DEST[EDI] MOV EDI,OFFSET32 _MYCALL CALL COMPARECALLS JNE SHORT NONODECODE JMP FRAMEFORUS ; PUBLIC NONODECODE NONODECODE: MOV APPLMASK,1 ; APPLICATION (may not be 1) MOV ALIASPTR,OFFSET CMDALIAS MOV EDX,OFFSET32 APPLCALLTABLE ; CHECK ALL L4 CALLS @@: MOV APPLCALLTABLEPTR,EDX MOV EDI,BUFFER LEA ESI,L3DEST[EDI] LEA EDI,APPLCALL[EDX] CALL COMPARECALLS JE FRAMEFORUS ADD EDX,TYPE APPLCALLS ADD ALIASPTR,ALIASLEN SHL APPLMASK,1 JNZ @B PUBLIC NOTFORUS NOTFORUS: ; ; IS IT INP3 (L3RTT) ; MOV EDI,BUFFER LEA ESI,L3DEST[EDI] push esi MOV EDI,OFFSET32 _L3RTT CALL COMPARECALLS pop esi jnz short @f MOV ESI, BUFFER MOVZX EAX, BYTE PTR 4[ESI] ; Port PUSH EAX MOVZX EAX, WORD PTR 5[ESI] ; Length SUB EAX,8 PUSH EAX ADD ESI, 8 ; TO L3 Header PUSH ESI push NEIGHBOUR[EBX] CALL _ProcessRTTMsg ADD ESP, 16 JMP SHORT L3DISCARD @@: ; ; NOT FOR US - PASS TO DESTINATION ; MOV EDI,BUFFER DEC L3MONR[EDI] JNZ SHORT FRAMESTILLOK PUBLIC L3DISCARD L3DISCARD: MOV EDI,BUFFER CALL RELBUFF RET ; DISCARD IT PUBLIC FRAMESTILLOK FRAMESTILLOK: ; ; If it is a record route frame we should add our call to the list before sending on ; CMP L4FLAGS[EDI], 0 JNE @F CMP WORD PTR L4INDEX[EDI], 0100H JNE @F ; Add our call on end, and increase count MOVZX ECX,MSGLENGTH[EDI] cmp ecx,248 jae @f ; too full! push EDI add EDI,ECX mov al,-1[EDI] and al, 7fh ; Mask End of Route Bit mov esi, offset _MYCALL mov ecx,7 rep movsb dec al stosb pop edi jz @f add MSGLENGTH[EDI],8 @@: MOV AL,_L3LIVES CMP L3MONR[EDI],AL JB SHORT LIVESOK MOV L3MONR[EDI],AL ; ENFORCE LIMIT ON ALL FRAMES SENT PUBLIC LIVESOK LIVESOK: LEA ESI,L3DEST[EDI] CALL _FINDDESTINATION JNZ SHORT 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 EDI,BUFFER LEA ESI,L3SRCE[EDI] MOV EDI,OFFSET32 _MYCALL CALL COMPARECALLS JE SHORT ROUTE_LOOP ; MOV EDI,BUFFER LEA ESI,L3SRCE[EDI] MOV EDI,OFFSET32 APPLCALLTABLE LEA EDI,APPLCALL[EDI] CALL COMPARECALLS JNE SHORT OKTORELAY PUBLIC ROUTE_LOOP 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[EBX],0 JZ L3DISCARD ; ONLY ONE ROUTE INC DEST_ROUTE[EBX] ; TO NEXT CMP DEST_ROUTE[EBX],4 JNE SHORT OKTORELAY ; MOV DEST_ROUTE[EBX],1 ; TRY TO ACTIVATE FIRST ; PUBLIC OKTORELAY OKTORELAY: ; ; IF CURRENT ROUTE IS BACK THE WAY WE CAME, THEN ACTIVATE ; ANOTHER (IF POSSIBLE). ; ; EBX IS DEST ENTRY, SAVELINK HAS LINK FROM INCOMMING MESSAGE ; PUSH ESI PUSH EBX MOV ESI,SAVELINK MOV ESI,NEIGHBOUR[ESI] ; ROUTE TABLE ENTRY FOR SENDER ; OF THIS MSG MOVZX EAX,DEST_ROUTE[EBX] OR AL,AL JNZ SHORT GOT_ACTIVE ; ; DONT HAVE AN ACTIVE ROUTE ; POP EBX CMP ROUT1_NEIGHBOUR[EBX],ESI JNE SHORT NO_PROBLEM ; WILL ACTIVATE ANOTHER ROUTE ; ; FIRST ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE ; MOV DEST_ROUTE[EBX],2 ; WILL BE RESET BY L3 CODE IF ; THERE IS NOT OTHER ROUTE JMP SHORT NO_PROBLEM PUBLIC GOT_ACTIVE GOT_ACTIVE: DEC EAX MUL BYTE PTR ROUTEVECLEN ; 6 BYTE ENTRIES - VALUE CAN ONLY BE 0-2 ADD EBX,EAX ; TO ACTIVE ROUTE ENTRY CMP ROUT1_NEIGHBOUR[EBX],ESI ; IS ACTIVE ONE BACK VIA ORIGINATOR? POP EBX JNE SHORT NO_PROBLEM ; NO ; ; SET TO USE NEXT BEST ROUTE ; INC DEST_ROUTE[EBX] ; TO NEXT CMP DEST_ROUTE[EBX],4 JNE SHORT L4NEXT00 ; MOV DEST_ROUTE[EBX],1 ; TRY TO ACTIVATE FIRST PUBLIC L4NEXT00 L4NEXT00: PUBLIC NO_PROBLEM NO_PROBLEM: POP ESI 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 ESI,DEST_Q[EBX] MOV EDI,BUFFER CALL _Q_ADD INC L3FRAMES JNZ SHORT INC001 INC L3FRAMES+2 PUBLIC INC001 INC001: RET PUBLIC FRAMEFORUS FRAMEFORUS: ; ; INTERNODE LINK ; INC L4FRAMESRX JNZ SHORT INC002 INC L4FRAMESRX+2 PUBLIC INC002 INC002: MOV EDI,BUFFER MOV AL,L4FLAGS[EDI] AND AL,0FH CMP AL,0 JE SHORT ESCAPECODES CMP AL,L4CREQ ; CONNECT REQUEST JE SHORT L4REQUEST ; ; OTHERS NEED A SESSION ; MOVZX EAX,L4INDEX[EDI] ; OUR ID MUL TRANSPORTLENGTH MOV EBX,_L4TABLE ADD EBX,EAX ; POINT TO ENTRY MOV AL,L4ID[EDI] CMP AL,CIRCUITID[EBX] ; CORRECT ID JNE SHORT L4DISCARD ; IGNORE ; ; HAVE FOUND CORRECT SESSION ENTRY ; MOV EDI,BUFFER MOV AL,L4FLAGS[EDI] 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 PUBLIC L4DISCARD L4DISCARD: JMP L3DISCARD ; NO PUBLIC L4REQUEST L4REQUEST: INC L4CONNECTSIN CALL CONNECTREQUEST RET PUBLIC ESCAPECODES ESCAPECODES: ; OPCODE 0 is used for a variety of functions, using L4INDEX and L4ID as sualifiers ; 0c0c is used for IP CMP WORD PTR L4INDEX[EDI], 0C0CH JNE @F MOV MSGPORT[EDI],0CFH JMP Q_IP_MSG @@: ; 00 01 Seesm to be Netrom Record Route CMP WORD PTR L4INDEX[EDI], 0100H JNE @F movzx ecx, word ptr 5[edi] pushad PUSH ECX PUSH EDI CALL _NRRecordRoute POP EDI POP ECX popad @@: JMP L3DISCARD PUBLIC L4DISREQ L4DISREQ: MOV AX,WORD PTR FARINDEX[EBX] MOV WORD PTR L4INDEX[EDI],AX MOV L4FLAGS[EDI],L4DACK CALL L3SWAPADDRESSES ; EXCHANGE SOURCE AND DEST MOV EDI,BUFFER MOV AL,_L3LIVES MOV L3MONR[EDI],AL PUSH EBX MOV EBX,SAVELINK LEA ESI,TX_Q[EBX] ; SEND BACK TO ORIGINATOR CALL _Q_ADD POP EBX CALL CLOSESESSIONPARTNER ; SEND CLOSE TO PARTNER (IF PRESENT) RET PUBLIC L4CONNACK L4CONNACK: JMP CONNECTACK PUBLIC L4DISACK L4DISACK: CALL CLEARSESSIONENTRY ; DELETE SESSION JMP L4DISCARD PUBLIC L4INFOACK L4INFOACK: MOV AL,L4RXNO[EDI] ; SEQUENCE CALL ACKFRAMES CALL REFRESHROUTE ; INDICATE ROUTE STILL OK JMP L4DISCARD PUBLIC L4IFRAME L4IFRAME: ; ; MAKE SURE SESSION IS UP - FIRST I FRAME COULD ARRIVE BEFORE ; CONNECT ACK ; CMP L4STATE[EBX],5 JB L4DISCARD ; SHOULD SAVE - WILL AVOID NEED TO ; RETRANSMIT MOV AL,L4RXNO[EDI] ; SEQUENCE CALL ACKFRAMES ; ; IF STATE IS 4, THEN SESSION IS CLOSING - IGNORE ANY I FRAMES ; TEST FLAGS[EBX],DISCPENDING JNZ L4DISCARD ; WAITING FOR ALL TO BE ACKED CMP L4STATE[EBX],4 JE L4DISCARD ; ; CHECK RECEIVED SEQUENCE ; MOV AL,L4TXNO[EDI] ; WHAT WE GOT SUB AL,RXSEQNO[EBX] ; WHAT WE WANT JZ SHORT L4FRAME_OK ; ; AL IS THE NUMBER OF FRAMES MISSING. IF -VE, THEN IN FACT IT ; INDICATES A REPEAT ; CMP AL,128 JB SHORT FRAME_MISSING ; ; FRAME IS A REPEAT ; MOV L4ACKREQ[EBX],1 ; SEND INFO ACK IN 1 SEC(IN CASE LAST ACK WAS LOST) JMP L4DISCARD ; PUBLIC FRAME_MISSING FRAME_MISSING: ; ; EXPECTED FRAME HAS BEEN MISSED - ASK FOR IT AGAIN, ; AND KEEP THIS FRAME UNTIL MISSING ONE ARRIVES ; OR NAKBITS[EBX],L4NAK ; SET NAK REQUIRED PUSH EBX PUSH EDI ; CALL SENDL4IACK ; SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES ; POP EDI POP EBX ; ; SEE IF WE ALREADY HAVE A COPY OF THIS ONE ; MOV ESI,L4RESEQ_Q[EBX] MOV AL,L4TXNO[EDI] PUBLIC CHECK_FRAME_LOOP CHECK_FRAME_LOOP: CMP ESI,0 JE SHORT NOTONQUEUE CMP AL,L4TXNO[ESI] JE SHORT MSGONQUEUE MOV ESI,[ESI] ; FOLLOW CHAIN JMP CHECK_FRAME_LOOP PUBLIC NOTONQUEUE NOTONQUEUE: LEA ESI,L4RESEQ_Q[EBX] CALL _Q_ADD ; ADD TO CHAIN RET MSGONQUEUE: ; ; ALREADY HAVE A COPY - DISCARD IT ; JMP L4DISCARD ; PUBLIC L4FRAME_OK L4FRAME_OK: AND NAKBITS[EBX],0FFH-L4NAK ; CLEAR MESSAGE LOST STATE ; INC RXSEQNO[EBX] ; ; REMOVE HEADERS, AND QUEUE INFO ; MOVZX ECX,MSGLENGTH[EDI] SUB ECX,20 MOV MSGLENGTH[EDI],CX ; NEW LENGTH SUB ECX,8 JNC L4IFLENOK PUBLIC L4DISCARD_JMP L4DISCARD_JMP: CALL L4DISCARD ; NO PID! JMP SHORT CHECK_RESEQ PUBLIC L4IFLENOK L4IFLENOK: LEA EDI,L3PID[EDI] MOV ESI,EDI ADD ESI,21 ; FIRST DATA BYTE MOV AL,0F0H STOSB ; NORMAL PID JCXZ L4IFRM00 ; NO DATA REP MOVSB ; COPY DOWN PUBLIC L4IFRM00 L4IFRM00: ; ; QUEUE FRAME FOR TARGET ; CALL REFRESHROUTE ; SET ROUTE STILL OK MOV AX,L4DELAY MOV L4ACKREQ[EBX],AL ; SEND INFO ACK AFTER L4DELAY (UNLESS I FRAME SENT) MOV EDI,BUFFER PUSH EBX CALL IFRM150 ; CHECK IF SETTING UP AND PASS ON POP EBX CHECK_RESEQ: ; ; SEE IF ANYTHING ON RESEQ QUEUE TO PROCESS ; LEA ESI,L4RESEQ_Q[EBX] MOV EDI,[ESI] MOV AL,RXSEQNO[EBX] ; WHAT WE WANT FIND_FRAME_LOOP: CMP EDI,0 JE SHORT NOTFOUND CMP AL,L4TXNO[EDI] JE SHORT FOUNDMESSAGE MOV ESI,EDI ; SAVE PREVIOUS IN CHAIN MOV EDI,[EDI] ; FOLLOW CHAIN JMP FIND_FRAME_LOOP NOTFOUND: RET FOUNDMESSAGE: ; ; REMOVE IT FROM QUEUE,AND PROCESS IT ; ; ESI IS PREVIOUS IN QUEUE ; MOV EAX,[EDI] ; NEXT IN CHAIN MOV [ESI],EAX ; CHAIN TO PREVIOUS MOV BUFFER,EDI ; SAVE ADDRESS ADD OLDFRAMES,1 ADC OLDFRAMES+2,0 ; COUNT FOR STATS JMP L4FRAME_OK PUBLIC CLEARSESSIONENTRY CLEARSESSIONENTRY: PUSH ESI ; ; RETURN ANY QUEUED BUFFERS TO FREE QUEUE ; LEA ESI,L4TX_Q[EBX] CALL RELEASEQUEUE LEA ESI,L4RX_Q[EBX] CALL RELEASEQUEUE LEA ESI,L4HOLD_Q[EBX] CALL RELEASEQUEUE LEA ESI,L4RESEQ_Q[EBX] CALL RELEASEQUEUE MOV EDI,EBX MOV ECX,TYPE TRANSPORTENTRY XOR AL,AL REP STOSB ; CLEAR ENTRY POP ESI RET PUBLIC RELEASEQUEUE RELEASEQUEUE: PUSH ESI CALL Q_REM JZ SHORT RELQUEUERET CALL RELBUFF POP ESI JMP RELEASEQUEUE PUBLIC RELQUEUERET RELQUEUERET: POP ESI RET PUBLIC ACKFRAMES ACKFRAMES: PUSH EDI ; ; SEE HOW MANY FRAMES ARE ACKED - IF NEGATIVE, THAN THIS MUST BE A ; DELAYED REPEAT OF AN ACK ALREADY PROCESSED ; PUBLIC ACKFR00 ACKFR00: MOV AH,AL SUB AH,L4WS[EBX] ; LAST ACKED JE SHORT NO_NEW_ACK ; NOTHING HAS CHANGED ; ; THIS MAY BE A DELAYED REPEAT OF AN ACK ALREADY PROCESSED ; CMP AH,128 JB SHORT NEWACK ; ; REPEATED ACK ; POP EDI RET ; IGNORE COMPLETELY PUBLIC NEWACK NEWACK: ; ; FRAME L4WS HAS BEED ACKED - IT SHOULD BE FIRST ON HOLD QUEUE ; PUSH EAX ; SAVE LEA ESI,L4HOLD_Q[EBX] CALL Q_REM JZ SHORT ACKFR10 ; WOT !! CALL RELBUFF ; RELEASE IT PUBLIC ACKFR10 ACKFR10: ; ; CHECK RTT SEQUENCE ; MOV AL,L4WS[EBX] CMP RTT_SEQ[EBX],AL JNE SHORT NOT_RTT_ACK ; CMP RTT_TIMER[EBX],0 JE SHORT NOT_RTT_ACK ; TIMER NOT ACTIVE ; ; FRAME BEING TIMED HAS BEEN ACKED - UPDATE DEST TIMER ; ; GET TIME FROM BIOS DATA AREA OR RTC ; PUSH 0 CALL _time ADD ESP,4 MUL W16 SUB AX,RTT_TIMER[EBX] ; TIME IN 18THS/10THS ; MOV RTT_TIMER[EBX],0 PUSH EBX MOV EBX,L4TARGET[EBX] ; DEST ENTRY CMP DEST_RTT[EBX],0 JE SHORT FIRST_TIME ; ; TAKE 7/8TH OF OLD VLAUE AND 1/8 OF THIS ; SHR AX,3 ; /8 MOV CX,DEST_RTT[EBX] ; OLD VALUE SHR CX,3 ; 1/8 SUB DEST_RTT[EBX],CX ; GIVES 7/8 PUBLIC FIRST_TIME FIRST_TIME: ADD DEST_RTT[EBX],AX POP EBX PUBLIC NOT_RTT_ACK NOT_RTT_ACK: POP EAX INC L4WS[EBX] JMP ACKFR00 ; LOOP BACK TO SEE IF ANY MORE TO DO PUBLIC NO_NEW_ACK NO_NEW_ACK: MOV L4RETRIES[EBX],0 ; CLEAR RETRY COUNT MOV L4TIMER[EBX],0 CMP AL,TXSEQNO[EBX] ; NEXT TO SEND JE SHORT ALL_ACKED MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; RESTART TIMER JMP ACKFR15 PUBLIC ALL_ACKED ALL_ACKED: CMP L4TX_Q[EBX],0 JNE SHORT ACKFR15 ; STILL SOME TO SEND ; ; IF DISC PENDING, SEND IT ; TEST FLAGS[EBX],DISCPENDING JZ SHORT ACKFR15 PUSH EBX CALL SENDL4DISC POP EBX POP EDI RET PUBLIC ACKFR15 ACKFR15: ; ; SEE IF CHOKE SET ; POP EDI MOV AL,L4FLAGS[EDI] AND AL,L4BUSY ; EXTRACT BUSY BIT AND FLAGS[EBX],0FFH-L4BUSY OR FLAGS[EBX],AL ; SAVE IT TEST L4FLAGS[EDI],L4NAK JNZ SHORT NAKMSG ; REQUEST TO RETRANSMIT RET PUBLIC NAKMSG NAKMSG: ; ; RETRANSMIT REQUESTED MESSAGE - WILL BE FIRST ON HOLD QUEUE ; PUSH EDI ; INCOMING MSG CALL GETBUFF JZ SHORT L4NAKRET ; CANT - NO BUFFERS ; PUSH EDI MOV ESI,L4HOLD_Q[EBX] CMP ESI,0 JNE @F ; No Message??? POP EDI JMP SHORT L4NAKRET @@: MOVZX ECX,MSGLENGTH[ESI] REP MOVSB ; COPY MESSAGE - LEAVE STATE ALONE POP EDI ; MESSAGE PUSH EBX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD ; QUEUE ON DEST POP EBX PUBLIC L4NAKRET L4NAKRET: POP EDI RET PUBLIC CONNECTREQUEST CONNECTREQUEST: ; ; CONNECT REQUEST - SEE IF EXISTING SESSION ; IF NOT, GET AND FORMAT SESSION TABLE ENTRY ; SEND CONNECT ACK ; ; EDI = BUFFER, EBX = 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 EBX ; SAVE LINK CALL FINDCIRCUIT JZ L4CONN50 ; SESSION EXISTS - ASSUME RETRY AND SEND ACK ; OR EBX,EBX JZ L4CONN90 ; TABLES FULL - REJECT CALL SETUPNEWCIRCUIT CMP L4TARGET[EBX],0 JE SHORT KILLSESSION ; NODE NOT IN TABLE, AND TABLE FULL ; - CANCEL IT ; ; IF CONNECT TO BBS, ALLOCATE BBS PORT ; CMP APPLMASK,0 JE SHORT L4CONN50 ; NORMAL CONNECT ; CMP BPQPARAMS+2,'Z' JE SHORT L4CONN50 ; 'SPY' CONNECT TO NODE CMP APPLMASK,0 JE @F ;NOT APPL CONNECT ; IF APPL CONNECT, SEE IF APPL HAS AN ALIAS MOV ESI,ALIASPTR CMP BYTE PTR [ESI],20H JE @F ; NO ; ACCEPT THE CONNECT, THEN INVOKE THE ALIAS POP EAX ; LINK PUSH EBX PUSH ESI CALL SENDCONACK ; TELL USER, AND PASS COMMAND TO HANDLER CALL GETBUFF POP ESI POP EBX JZ SHORT APNOBUF ; NO BUFFERS MOV BUFFER,EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID MOV ECX,16 REP MOVSB MOV AL,0DH STOSB MOV ECX,EDI MOV EDI,BUFFER SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EDI,BUFFER CALL COMMANDHANDLER ; BUFFER USED FOR REPLY OR CONNECT APNOBUF: RET @@: MOV AL,PACLEN ; NETWORK ATTACH CALL ATTACHTOBBS ; FIND AND ATTACH FREE APPL SESSION - RETURN NZ IF FAILED JZ SHORT L4CONN50 ; OK PUBLIC KILLSESSION KILLSESSION: CALL CLEARSESSIONENTRY JMP L4CONN90 ; REJECT PUBLIC L4CONN50 L4CONN50: ; EBX = Session, on stack = incomming circuit ; POP EAX ; LINK CALL SENDCONACK RET PUBLIC SENDCONACK SENDCONACK: ; EBX = Session, EAX = incomming circuit PUSH EAX ; Link ; ; SEND CONNECT ACK ; MOV EDI,BUFFER MOV AL,CIRCUITINDEX[EBX] ; OUR INDEX MOV L4TXNO[EDI],AL ; INTO REPLY MOV AL,CIRCUITID[EBX] ; OUR ID MOV L4RXNO[EDI],AL ; TO REPLY MOV AL,L4WINDOW[EBX] MOV L4DATA[EDI],AL ; WINDOW MOV L4FLAGS[EDI],L4CACK ; ; IF CTEXT ON ALL CONNECTS IS REQUIRED, SEND IT ; ; IF CONNECT TO ALIAS, SEND CTEXT ; CMP _FULL_CTEXT,1 ; FOR ANY CONNECT? JNE L4CONN95 ; NO CMP APPLMASK,0 JNE SHORT L4CONN95 ; Dont Sent CTEXT to Appl Connects CMP _CTEXTLEN,0 JE SHORT L4CONN95 ; NOT DEFINED PUSH EDI MOV ESI,_CTEXTMSG MOVZX EDX,_CTEXTLEN MOVZX EAX,PACLEN mov CTPACLEN,EAX CTLOOP: push esi CALL GETBUFF pop esi JZ SHORT CTEXTRET ; NO BUFFERS push edi ADD EDI,7 MOV AL,0F0H STOSB ; PID MOV ECX,EDX CMP EDX,CTPACLEN JBE @F MOV ECX,CTPACLEN @@: push ecx REP MOVSB pop ecx sub edx,ecx ; edx = bytes still to send MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX push esi LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL pop esi cmp edx,0 JG CTLOOP CTEXTRET: POP EDI JMP SHORT L4CONN95 ; SEND RESPONSE PUBLIC L4CONN90 L4CONN90: MOV EDI,BUFFER MOV L4FLAGS[EDI],L4CACK+L4BUSY; REJECT MOV L4DATA[EDI],0 ; WINDOW PUBLIC L4CONN95 L4CONN95: CALL L3SWAPADDRESSES ; EXCHANGE SOURCE AND DEST MOV EDI,BUFFER MOV AL,_L3LIVES MOV L3MONR[EDI],AL LEA ECX,L4DATA+1[EDI] SUB ECX,EDI CMP BPQNODE,1 JNE SHORT L4CONN95A ; NOT BPQ MOV L4DATA+1[EDI],AL ; OUR TTL INC ECX PUBLIC L4CONN95A L4CONN95A: MOV MSGLENGTH[EDI],CX ; SET LENGTH POP EBX LEA ESI,TX_Q[EBX] ; SEND BACK TO ORIGINATOR CALL _Q_ADD RET PUBLIC L4CONN96 L4CONN96: ; ; TABLES FULL - SHOULD CANCEL SESSION AND SEND REPLY ( OR CHECK FIRST) ; POP EBX ; NEW LINK NENTY POP EBX ; LINK RET ; ????? PUBLIC ATTACHTOBBS ATTACHTOBBS: ; ; AL CONTAINS PACLEN FOR TNC SESSION ; PUSH EAX MOV CONNECTSESSION,EBX ; ; LOOK FOR A FREE HOST SESSION ; ; TRY BPQ HOST MODE PORTS FIRST ; MOV EBX,OFFSET32 BPQHOSTVECTOR MOV ECX,BPQHOSTSTREAMS MOV EAX,APPLMASK Mov EDX,0 ; Ports for this Appl PUBLIC BPQHOSTLOOP BPQHOSTLOOP: TEST HOSTAPPLMASK[EBX],EAX ; CORRECT APPLICATION? JZ SHORT NEXTBPQPORT ; NO ; INC EDX ; Count Defined CMP HOSTSESSION[EBX],0 ; SESSION ALREADY ATTACHED? JNE SHORT NEXTBPQPORT ; YES TEST HOSTFLAGS[EBX],3 ; STATUS CHANGE NOT YET REPORTED? JNZ SHORT NEXTBPQPORT ; ; WEVE GOT A FREE BPQ HOST PORT - USE IT ; MOV AL,HOSTAPPLFLAGS[EBX] MOV SAVEDAPPLFLAGS,AL PUSH EBX ; HOST PORT ENTRY MOV EAX,APPLMASK ; was HOSTAPPLMASK[EBX] CALL SETUPBPQCONSOLESESSION MOV ESI,EBX ; SESSION (OR ZERO) RETURNED IN EBX POP EBX MOV HOSTSESSION[EBX],ESI ; LINK SESSION TO HOST VECTOR MOV EDI,CONNECTSESSION ; INCOMING CIRCUIT CMP ESI,0 JE SHORT BBSBUSY ; CANT SET UP SESSION ; ; Convert APPLMASK to APPLNUM push edx MOV DH,0 MOV EAX,APPLMASK @@: OR EAX,EAX JZ @F INC DH TEST EAX,1 JNZ @F ; FOUND APPL SHR EAX,1 JMP SHORT @B @@: MOV BYTE PTR HOSTAPPLNUM[EBX],DH pop edx OR HOSTFLAGS[EBX],2 ; INDICATE STATE CHANGE CALL POSTSTATECHANGE MOV L4CIRCUITTYPE[ESI],BPQHOST+DOWNLINK MOV EDI,CONNECTSESSION ; INCOMING CIRCUIT MOV L4CROSSLINK[EDI],ESI ; POINTER FROM NEW TO OLD MOV L4CROSSLINK[ESI],EDI ; POINTER FROM OLD TO NEW ; MOV AL,SAVEDAPPLFLAGS MOV SESS_APPLFLAGS[EDI],AL ; SAVE IN SESSION ENTRY POP EAX ; GET PACLEN MOV SESSPACLEN[ESI],AL MOV EBX,CONNECTSESSION ; RETURN WITH INCOMING SESSION IN EBX XOR AL,AL RET PUBLIC NEXTBPQPORT NEXTBPQPORT: ADD EBX,VECTORLENGTH DEC ECX JNZ BPQHOSTLOOP ; TOO FAR FOR LOOP ; PUBLIC BBSBUSY BBSBUSY: POP EAX ; CLEAR PACLEN MOV EBX,CONNECTSESSION OR AL,1 RET ; WITH NZ SET PUBLIC SETUPNEWCIRCUIT SETUPNEWCIRCUIT: MOV ESI,BUFFER MOVZX ECX,MSGLENGTH[ESI] ; GET LENGTH MOV AX,WORD PTR L4INDEX[ESI] ; INDEX AND ID MOV WORD PTR FARINDEX[EBX],AX; COPY MOV CIRCUITINDEX[EBX],DL ; OUR INDEX MOV AL,_NEXTID MOV CIRCUITID[EBX],AL ; OUR ID CALL INC_ID LEA ESI,L4DATA[ESI] LODSB CMP AL,_L4DEFAULTWINDOW JB SHORT L4CONN05 ; REQUESTED LESS THAN 4 MOV AL,_L4DEFAULTWINDOW PUBLIC L4CONN05 L4CONN05: MOV L4WINDOW[EBX],AL ; SET WINDOW LEA EDI,L4USER[EBX] MOV ECX,7 REP MOVSB ; COPY ORIGINATING CALL ; ; GET BPQ EXTENDED CONNECT PARAMS IF PRESENT ; MOV ESI,BUFFER MOVZX ECX,MSGLENGTH[ESI] LEA ESI,L4_BPQ[ESI] ; TO MY EXTENDED PARAMS MOV EDI,OFFSET32 BPQPARAMS SUB ECX,L4_BPQ JCXZ NOT_THENODE ; ; MAKE SURE - OTHERS NOW USE EXTENDED CONNECTS ; CMP ECX,2 ; TIMER JE SHORT THENODE CMP ECX,3 ; SPY FLAG JNE SHORT NOT_THENODE PUBLIC THENODE THENODE: REP MOVSB ; GET THENODE EXTENDED CONNECT PARAMS MOV BPQNODE,1 ; A BPQ NODE PUBLIC NOT_THENODE NOT_THENODE: MOV L4CIRCUITTYPE[EBX],SESSION+UPLINK ; CROSS CIRCUIT MOV L4STATE[EBX],5 ; MOV ESI,OFFSET32 _MYCALL CMP APPLMASK,0 JE SHORT L4CONN06 ; NORMAL MOV ESI,APPLCALLTABLEPTR LEA ESI,APPLCALL[ESI] PUBLIC L4CONN06 L4CONN06: LEA EDI,L4MYCALL[EBX] MOV ECX,7 REP MOVSB MOV ECX,2 ; Just in case! TryAgain: push ecx CALL CHECKL3TABLES ; CHECK THAT FAR NODE IS IN 'NODES', pop ecx ; RETURNS NODE IN AX MOV L4TARGET[EBX],EAX ; SET LINK POINTER TO DEST CMP EAX,0 JNE SHORT L4CONN07 ; OK ; ; Node not it table. ; Replace worst quality node with session counts of zero push edi push ecx push ebx MOV EBX,0 MOV AL,255 ; Lowest qual found MOV EDI,DESTS MOVZX ECX,_MAXDESTS FN00: CMP DEST_COUNT[EDI],0 JNE SHORT @F ; Has been used cmp DEST_RTT[EDI],0 ; INP3 ROUTE? JNE SHORT @F CMP ROUT1_QUALITY[EDI], AL JAE @F ; Better MOV EBX,EDI MOV AL,ROUT1_QUALITY[EDI] @@: ADD EDI,TYPE DEST_LIST LOOP FN00 cmp ebx,0 je @f ; nothing to replace ???? ; ZAP the entry just found MOV EDI,EBX MOV ECX,TYPE DEST_LIST MOV AL,0 REP STOSB ; CLEAR ENTRY dec _NUMBEROFNODES pop ebx pop ecx pop edi loop TryAgain ; There is now a free one! ; ; just in case! xor eax,eax RET @@: pop ebx pop ecx pop edi xor eax,eax ret PUBLIC L4CONN07 L4CONN07: ; CMP BPQNODE,1 JNE SHORT L4CONN07A ; FAR END NOT BPQ PUSH EBX MOV EBX,EAX OR DEST_STATE[EBX],40H ; SET BPQ NODE BIT POP EBX PUBLIC L4CONN07A L4CONN07A: MOV AX,WORD PTR BPQPARAMS ; TIMEOUT FROM CONNECT CMP AX,300 ; CHECK IN CASE CORRUPT JBE @F MOV AX,_L4T1 ; TAKE DEFAULT @@: MOV SESSIONT1[EBX],AX ; DEFAULT TIMEOUT MOV AL,PACLEN ; L4 LINK - USE SYSTEM DEFAULT MOV SESSPACLEN[EBX],AL ; DEFAULT RET PUBLIC CONNECTACK CONNECTACK: ; ; EXTRACT EXTENDED PARAMS IF PRESENT ; CMP BYTE PTR MSGLENGTH[EDI],L4DATA+1 JE SHORT NOTBPQ MOV AL,L4DATA+1[EDI] SUB AL,L3MONR[EDI] ADD AL,41H ; HOPS TO DEST + 40H MOV ESI,L4TARGET[EBX] AND DEST_STATE[ESI],80H OR DEST_STATE[ESI],AL ; SAVE PUBLIC NOTBPQ NOTBPQ: ; ; SEE IF SUCCESS OR FAIL ; PUSH EDI MOV ESI,L4TARGET[EBX] ; ADDR OF LINK/DEST ENTRY LEA ESI,DEST_CALL[ESI] CALL DECODENODENAME ; CONVERT TO ALIAS:CALL MOV EDI,OFFSET32 CONACKCALL MOV ECX,17 REP MOVSB POP EDI TEST L4FLAGS[EDI],L4BUSY JNZ SHORT L4CONNFAILED CMP L4STATE[EBX],5 JE SHORT CONNACK05 ; MUST BE REPEAT MSG - DISCARD MOV AX,WORD PTR L4TXNO[EDI] ; HIS INDEX MOV WORD PTR FARINDEX[EBX],AX MOV L4STATE[EBX],5 ; ACTIVE MOV L4TIMER[EBX],0 ; CANCEL TIMER MOV L4RETRIES[EBX],0 ; CLEAR RETRY COUNT MOV AL,L4DATA[EDI] ; WINDOW MOV L4WINDOW[EBX],AL ; SET WINDOW MOV EDX,L4CROSSLINK[EBX] ; POINT TO PARTNER ; MOV ESI,OFFSET32 CONNECTEDMSG MOV ECX,LCONNECTEDMSG JMP SHORT L4CONNCOMM PUBLIC L4CONNFAILED L4CONNFAILED: ; MOV EDX,L4CROSSLINK[EBX] ; SAVE PARTNER CALL CLEARSESSIONENTRY ; CLEAR OUT THE SESSION PUSH EBX MOV EBX,EDX MOV L4CROSSLINK[EBX],0 ; CLEAR CROSSLINK POP EBX MOV ESI,OFFSET32 BUSYMSG ; ?? BUSY MOV ECX,LBUSYMSG PUBLIC L4CONNCOMM L4CONNCOMM: OR EDX,EDX JNZ SHORT L4CONNOK10 ; ; CROSSLINK HAS GONE?? - JUST CHUCK MESSAGE ; PUBLIC CONNACK05 CONNACK05: JMP L4DISCARD PUBLIC L4CONNOK10 L4CONNOK10: PUSH EBX PUSH ESI PUSH ECX MOV EDI,BUFFER ADD EDI,7 MOV AL,0F0H STOSB ; PID CALL _SETUPNODEHEADER ; PUT IN NODE ID POP ECX POP ESI REP MOVSB MOV ESI,OFFSET32 CONACKCALL MOV ECX,17 ; MAX LENGTH ALIAS:CALL REP MOVSB MOV AL,0DH STOSB MOV ECX,EDI MOV EDI,BUFFER SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,EDX ; CALLER'S SESSION LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL POP EBX ; ORIGINAL CIRCUIT TABLE RET PUBLIC CONNECTREFUSED CONNECTREFUSED: ; ; L2 CONNECTION REQUEST REJECTED ; ; IF DOWNLINK, TELL PARTNER ; IF CROSSLINK, TELL ROUTE CONTROL ; CMP LINKTYPE[EBX],3 JNE SHORT CONNECTR00 ; ; FAILURE TO SET UP CROSSLINK - TELL LEVEL 3 ; CALL L3CONNECTFAILED ; REPORT TO LEVEL 3 RET PUBLIC CONNECTR00 CONNECTR00: CMP CIRCUITPOINTER[EBX],0 JNE SHORT CONNECTR01 RET ; NO CROSS LINK PUBLIC CONNECTR01 CONNECTR01: CALL GETBUFF JZ CONNECTF10 ; NO BUFFERS ?? WHAT SHOULD WE DO ?? PUSH EBX PUSH EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID CALL _SETUPNODEHEADER MOV ESI,OFFSET32 BUSYMSG MOV ECX,LBUSYMSG JMP SHORT CONNECTF05 ; PUBLIC CONNECTFAILED CONNECTFAILED: ; ; CONNECTION REQUEST FAILED ; IF DOWNLINK, TELL PARTNER ; IF CROSSLINK, TELL ROUTE CONTROL ; CMP LINKTYPE[EBX],3 JNE SHORT CONNECTF00 ; ; FAILURE TO SET UP CROSSLINK - TELL LEVEL 3 ; CALL L3CONNECTFAILED ; REPORT TO LEVEL 3 RET PUBLIC CONNECTF00 CONNECTF00: CMP CIRCUITPOINTER[EBX],0 JNE SHORT CONNECTF01 RET ; NO CROSS LINK PUBLIC CONNECTF01 CONNECTF01: CALL GETBUFF JZ SHORT CONNECTF10 ; NO BUFFERS ?? WHAT SHOULD WE DO ?? PUSH EBX PUSH EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID CALL _SETUPNODEHEADER MOV ESI,OFFSET32 FAILEDMSG MOV ECX,LFAILEDMSG PUBLIC CONNECTF05 CONNECTF05: REP MOVSB LEA ESI,LINKCALL[EBX] PUSH EDI ; SAVE CALL CONVFROMAX25 ; ADDR OF CALLED STATION POP EDI MOV ESI,OFFSET32 NORMCALL MOV ECX,10 REP MOVSB MOV AL,0DH STOSB MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,CIRCUITPOINTER[EBX] ; GET CIRCUIT TABLE ENTRY MOV EDX,L4CROSSLINK[EBX] ; TO INCOMMONG SESSION PUSH EDI CALL CLEARSESSIONENTRY ; CANCEL OUTWARD LINK POP EDI MOV EBX,EDX MOV L4CROSSLINK[EBX],0 ; CLEAR REVERSE LINK ; LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL POP EBX PUBLIC CONNECTF10 CONNECTF10: RET ; PUBLIC RETURNEDTONODE RETURNEDTONODE: ; ; SEND RETURNED TO ALIAS:CALL ; CALL GETBUFF JNZ SHORT RETURNED00 RET ; CANT PUBLIC RETURNED00 RETURNED00: PUSH EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID MOV ESI,OFFSET32 RETURNEDMSG MOV ECX,LRETURNED REP MOVSB MOV ESI,OFFSET32 _MYCALL CALL DECODENODENAME MOV ECX,20 PUBLIC RETURNED10 RETURNED10: LODSB CMP AL,HEADERCHAR JE SHORT RETURNED20 ; STOSB LOOP RETURNED10 PUBLIC RETURNED20 RETURNED20: MOV AL,0DH STOSB MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL RET PUBLIC SENDCONNECTREPLY SENDCONNECTREPLY: ; ; LINK SETUP COMPLETE - EBX = LINK, EDI = BUFFER ; CMP LINKTYPE[EBX],3 JNE SHORT CONNECTED00 ; ; NODE - NODE SESSION SET UP - DONT NEED TO DO ANYTHING (I THINK!) ; CALL RELBUFF RET ; ; UP/DOWN LINK ; PUBLIC CONNECTED00 CONNECTED00: CMP CIRCUITPOINTER[EBX],0 JNE SHORT CONNECTED01 CALL RELBUFF ; UP/DOWN WITH NO SESSION - NOONE TO TELL RET ; NO CROSS LINK PUBLIC CONNECTED01 CONNECTED01: MOV BUFFER,EDI PUSH EBX PUSH ESI PUSH ECX ADD EDI,7 MOV AL,0F0H STOSB ; PID CALL _SETUPNODEHEADER ; PUT IN NODE ID LEA ESI,LINKCALL[EBX] PUSH EDI CALL CONVFROMAX25 ; ADDR OF CALLED STATION POP EDI MOV EBX,CIRCUITPOINTER[EBX] MOV L4STATE[EBX],5 ; SET LINK UP MOV EBX,L4CROSSLINK[EBX] ; TO INCOMING LINK cmp ebx,0 jne xxx ; ; NO LINK ??? ; MOV EDI,BUFFER CALL RELBUFF POP ECX POP ESI POP EBX RET PUBLIC xxx xxx: POP ECX POP ESI REP MOVSB MOV ESI,OFFSET32 NORMCALL MOVZX ECX,NORMLEN REP MOVSB MOV AL,0DH STOSB MOV ECX,EDI MOV EDI,BUFFER SUB ECX,EDI MOV MSGLENGTH[EDI],CX LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL POP EBX RET PUBLIC INFORMPARTNER INFORMPARTNER: ; ; LINK IS DISCONNECTING - IF THERE IS A CROSSLINK, SEND DISC TO IT ; CMP LINKTYPE[EBX],3 JNE SHORT INFORMP00 ; CALL L3LINKCLOSED ; REPORT TO LEVEL 3 RET PUBLIC INFORMP00 INFORMP00: CMP CIRCUITPOINTER[EBX],0 JNE SHORT INFORMP01 RET ; NO CROSS LINK PUBLIC INFORMP01 INFORMP01: PUSH EBX ; SAVE L2 LINK MOV EBX,CIRCUITPOINTER[EBX] CALL CLOSESESSIONPARTNER POP EBX RET PUBLIC CLOSESESSIONPARTNER CLOSESESSIONPARTNER: ; ; SEND CLOSE TO CROSSLINKED SESSION AND CLEAR LOCAL SESSION ; CMP EBX,0 JE SHORT @F ; No Session?? CMP L4CROSSLINK[EBX],0 JNE SHORT INFORMP0X ; NO CROSSLINK CALL CLEARSESSIONENTRY ; CLEAR INCOMING L4 ENTRY @@: RET PUBLIC INFORMP0X INFORMP0X: PUSH EBX ; SAVE MOV EBX,L4CROSSLINK[EBX] ; TO PARTNER SESSION CALL CLOSECURRENTSESSION POP EBX CALL CLEARSESSIONENTRY ; CLEAR INCOMING L4 ENTRY RET PUBLIC CLOSECURRENTSESSION CLOSECURRENTSESSION: ; ; SHUT DOWN SESSION IN EBX, AND UNLINK IF CROSSLINKED ; MOV L4CROSSLINK[EBX],0 ; REMOVE CROSSLINK ; ; IF STAY FLAG SET, KEEP SESSION, AND SEND MESSAGE ; CMP DISCFLAG,'S' JE SHORT STAYHERE ; HOST MODE STAY TEST L4CIRCUITTYPE[EBX],BPQHOST JNZ SHORT BPQHOSTCLOSE ; DONT HAVE A STAYFLAG CMP STAYFLAG[EBX],0 JE SHORT DONTSTAY PUBLIC STAYHERE STAYHERE: CALL RETURNEDTONODE RET PUBLIC BPQHOSTCLOSE BPQHOSTCLOSE: ; ; BPQ HOST MODE SESSION - INDICATE STATUS CHANGE ; PUSH EBX MOV EBX,L4TARGET[EBX] ; ESI IS HOST CONTROL VECTOR MOV HOSTSESSION[EBX],0 ; CLEAR SESSION POINTER OR HOSTFLAGS[EBX],3 ; HOSTSTATECHANGE CALL POSTSTATECHANGE POP EBX JMP INFORMP05C ; CLEAR SESSION PUBLIC DONTSTAY DONTSTAY: TEST L4CIRCUITTYPE[EBX],PACTOR JZ @F ; ; PACTOR-type (Session linked to Port) ; MOVZX EAX, KAMSESSION[EBX] SHL EAX,2 ; ; If any data is queued, move it to the port entry, so it can be sent before the disconnect ; ADD EAX, L4TARGET[EBX] ; ; EAX is the port record ; SEEIFMORE: PUSH EAX LEA ESI,L4TX_Q[EBX] CALL Q_REM JZ NOMORE POP EAX PUSH EAX PUSH ECX PUSH EDI ; Msg for 'c' Routines PUSH EBX ; VECTOR for 'c' Routines MOV EBX,L4TARGET[EBX] CALL PORTTXROUTINE[EBX] ; LEVEL 2 PROCESS POP EBX POP EDI POP ECX POP EAX JMP SHORT SEEIFMORE NOMORE: POP EAX MOV ATTACHEDSESSIONS[EAX],0 CALL CLEARSESSIONENTRY ; CLEAR L4 ENTRY RET @@: TEST L4CIRCUITTYPE[EBX],SESSION JNZ SHORT INFORMP03 JMP INFORMP05 PUBLIC INFORMP03 INFORMP03: ; ; L4 SESSION TO CLOSE ; CMP L4HOLD_Q[EBX],0 JNE SHORT INFORMP03A ; WAITING FOR ACK - SEND DISC LATER CMP L4TX_Q[EBX],0 JNE SHORT INFORMP03A ; STILL MORE TO SEND - SEND DISC LATER CALL SENDL4DISC RET PUBLIC INFORMP03A INFORMP03A: OR FLAGS[EBX],DISCPENDING ; SEND DISC WHEN ALL DATA ACKED RET PUBLIC INFORMP05 INFORMP05: ; ; LEVEL 2 SESSION TO CLOSE ; ; COPY ANY PENDING DATA TO L2 TX Q, THEN GET RID OF SESSION ; LEA ESI,L4TX_Q[EBX] CALL Q_REM JZ SHORT NOWT_ON_SESSION PUSH EBX ; SAVE SESSION MOV EBX,L4TARGET[EBX] ; GET LINK LEA ESI,TX_Q[EBX] CALL _Q_ADD ; MOVE MESSAGE TO LINK LEVEL POP EBX JMP INFORMP05 ; SEE IF MORE PUBLIC NOWT_ON_SESSION NOWT_ON_SESSION: ; ; NOTHING LEFT AT SESSION LEVEL ; PUSH EBX ; SAVE SESSION MOV EBX,L4TARGET[EBX] ; GET LINK CMP EBX,0 JE @F ; No Cross??? MOV CIRCUITPOINTER[EBX],0 ; CLEAR REVERSE LINK ; MOV AL,LINKWS[EBX] ; NEW WINDOW START CMP AL,LINKNS[EBX] ; IS N(S) = NEW WINDOW START? JNE SHORT INFORMP05A ; STILL SOME TO ACK ; CMP TX_Q[EBX],0 JNE SHORT INFORMP05A ; STILL MORE TO SEND - SEND DISC LATER ; ; NOTHING QUEUED - CAN SEND DISC NOW ; MOV L2STATE[EBX],4 ; DISCONNECTING MOV L2TIMER[EBX],1 ; USE TIMER TO KICK OFF DISC JMP SHORT INFORMP05B PUBLIC INFORMP05A INFORMP05A: OR L2FLAGS[EBX],DISCPENDING ; SEND DISC WHEN ALL DATA ACKED PUBLIC INFORMP05B INFORMP05B: @@: POP EBX PUBLIC INFORMP05C INFORMP05C: CALL CLEARSESSIONENTRY ; CLEAR L4 ENTRY RET PUBLIC GETFREECIRCUIT GETFREECIRCUIT: MOV EBX,_L4TABLE MOVZX ECX,_MAXCIRCUITS MOV DL,0 PUBLIC GETFREE00 GETFREE00: CMP BYTE PTR [EBX],0 JNE SHORT GETFREE05 ; NOT A SPARE ENTRY RET PUBLIC GETFREE05 GETFREE05: ADD EBX,TYPE TRANSPORTENTRY INC DL ; INDEX LOOP GETFREE00 ; ; ENTRY NOT FOUND ; OR AL,1 RET PUBLIC FINDCIRCUIT FINDCIRCUIT: ; ; FIND CIRCUIT FOR AN INCOMING MESSAGE ; ; MESSAGE ADDR IN EDI ; MOV EBX,0 MOV DL,0 ; INDEX MOV ESI,_L4TABLE MOVZX ECX,_MAXCIRCUITS FINDLK00: CMP BYTE PTR [ESI],0 JNE SHORT FINDLK05 ; NOT A SPARE ENTRY CMP EBX,0 JNE SHORT FINDLK10 ; ALREADY FOUND A SPARE MOV EBX,ESI ; POINTER TO FIRST FREE MOV DH,DL JMP SHORT FINDLK10 ; TRY NEXT ENTRY FINDLK05: PUSH ESI PUSH EDI PUSH ECX MOV ESI,L4TARGET[ESI] ; POINTER TO DEST ENTRY LEA ESI,DEST_CALL[ESI] LEA EDI,L3SRCE[EDI] ; ORIGIN FROM MESSAGE CALL COMPARECALLS ; COMPARE WITH LINKCALL POP ECX POP EDI POP ESI JNE SHORT FINDLK10 ; WRONG NODE MOV AX,WORD PTR L4INDEX[EDI] ; ID AND INDEX CMP AX,WORD PTR FARINDEX[ESI] JE SHORT FINDLKRET ; CORRECT CIRCUIT FINDLK10: ADD ESI,TYPE TRANSPORTENTRY INC DL ; INDEX LOOP FINDLK00 ; ; ENTRY NOT FOUND - EBX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 MOV DL,DH ; FIRST FREE INDEX RET FINDLKRET: MOV EBX,ESI XOR AL,AL RET PUBLIC L4TIMERPROC L4TIMERPROC: ; ; CHECK FOR TIMER EXPIRY ; MOVZX ECX,_MAXCIRCUITS MOV EBX,_L4TABLE PUBLIC L4TIM00 L4TIM00: CMP L4USER[EBX],0 JNE SHORT L4TIM01 ; ; SPARE ENTRY ; PUBLIC L4TIM300 L4TIM300: ADD EBX,TYPE TRANSPORTENTRY LOOP L4TIM00 RET PUBLIC L4TIM01 L4TIM01: ; ; CHECK FOR L4BUSY SET AND NO LONGER BUSY ; TEST NAKBITS[EBX],L4BUSY JZ SHORT L4NOTBUSY CALL CHECKIFBUSY TEST AL,L4BUSY JNZ SHORT L4NOTBUSY ; STILL BUSY AND NAKBITS[EBX],NOT L4BUSY MOV L4ACKREQ[EBX],1 ; SEND ACK PUBLIC L4NOTBUSY L4NOTBUSY: MOV AX,L4TIMER[EBX] OR AX,AX JZ SHORT L4TIM100 ; NOT RUNNING DEC AX MOV L4TIMER[EBX],AX ; DECREMENT JNZ SHORT L4TIM100 ; NOT EXPIRED CALL L4TIMEOUT ; TIMEOUT HAS OCCURED PUBLIC L4TIM100 L4TIM100: CMP L4ACKREQ[EBX],0 ; DELAYED ACK TIMER JE SHORT L4TIM200 ; NOT RUNNING DEC L4ACKREQ[EBX] JNZ SHORT L4TIM200 ; STILL OK ; PUSH EBX PUSH ECX ; CALL SENDL4IACK ; SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES ; POP ECX POP EBX PUBLIC L4TIM200 L4TIM200: INC L4KILLTIMER[EBX] ; ; IF BIT 6 OF APPLFLAGS SET, SEND MSG EVERY 11 MINS TO KEEP SESSION OPEN ; CMP L4CROSSLINK[EBX],0 ; CONNECTED? JE SHORT L4TIM202 ; NO TEST SESS_APPLFLAGS[EBX],40H JZ SHORT L4TIM202 ; AUTOTIMER MODE NOT SELECTED CMP L4KILLTIMER[EBX],11*60 ; 11 MINS JB SHORT L4TIM202 CALL AUTOTIMER PUBLIC L4TIM202 L4TIM202: MOV AX,_L4LIMIT OR AX,AX JZ SHORT L4TIM300 ; IF ZERO, RUN FOR EVER CMP L4KILLTIMER[EBX],AX JB SHORT L4TIM300 ; MOV L4KILLTIMER[EBX],0 ; ; CLOSE THIS SESSION, AND ITS PARTNER (IF ANY) ; PUSH EBX PUSH ECX PUSH L4CROSSLINK[EBX] ; SAVE PARTNER SESSION MOV STAYFLAG[EBX],0 CALL CLOSECURRENTSESSION ; CLOSE THIS ONE POP EBX OR EBX,EBX JZ SHORT L4TIM250 ; NO CROSSLINK MOV L4KILLTIMER[EBX],0 ; ITS TIMES IS ALSO ABOUT TO EXPIRE MOV STAYFLAG[EBX],0 CALL CLOSECURRENTSESSION ; CLOSE IT AS WELL PUBLIC L4TIM250 L4TIM250: POP ECX POP EBX JMP L4TIM300 PUBLIC L4TIMEOUT L4TIMEOUT: ; ; TIMER EXPIRED ; ; IF LINK UP REPEAT TEXT ; IF S2, REPEAT CONNECT REQUEST ; IF S4, REPEAT DISCONNECT REQUEST ; CMP L4STATE[EBX],1 ; NO IDLE STATE JLE L4TIMRET CMP L4STATE[EBX],4 JA SHORT L4TIM30 ; LINK UP JE SHORT L4TIM05 ; SEND DISC AGAIN CMP L4STATE[EBX],2 JE SHORT L4TIM10 ; SEND CONNECT AGAIN PUBLIC L4TIMRET L4TIMRET: RET PUBLIC L4TIM05 L4TIM05: ; ; RETRY DISCONNECT ; INC L4RETRIES[EBX] MOV AL,L4N2 CMP L4RETRIES[EBX],AL JL SHORT L4TIM08 ; ; RETRIED N2 TIMES - FAIL LINK ; PUBLIC L4TIM06 L4TIM06: PUSH EBX PUSH ECX CALL CLEARSESSIONENTRY POP ECX POP EBX RET PUBLIC L4TIM08 L4TIM08: PUSH EBX PUSH ECX CALL SENDL4DISC POP ECX POP EBX RET ; ; RETRY CONNECT ; PUBLIC L4TIM10 L4TIM10: INC L4RETRIES[EBX] MOV AL,L4N2 CMP L4RETRIES[EBX],AL JL SHORT L4TIM12 ; ; RETRIED N2 TIMES - FAIL LINK ; PUBLIC L4TIM11 L4TIM11: PUSH EBX PUSH ECX CALL L4CONNECTFAILED ; TELL OTHER PARTNER IT FAILED CALL CLEARSESSIONENTRY POP ECX POP EBX RET PUBLIC L4TIM12 L4TIM12: PUSH EBX PUSH ECX CALL SENDL4CONNECT POP ECX POP EBX RET PUBLIC L4TIM30 L4TIM30: ; ; STATE 5 OR ABOVE - RETRY INFO ; ; AND FLAGS[EBX],NOT L4BUSY ; CANCEL CHOKE INC L4RETRIES[EBX] MOV AL,L4N2 CMP L4RETRIES[EBX],AL JL SHORT L4TIM40 ; PUSH EBX PUSH ECX CALL CLOSESESSIONPARTNER POP ECX POP EBX RET ; PUBLIC L4TIM40 L4TIM40: ; PUSH EBX PUSH ECX ; ; RESEND ALL OUTSTANDING FRAMES ; AND FLAGS[EBX],7FH ; CLEAR CHOKED MOV ESI,L4HOLD_Q[EBX] PUBLIC L4TIM45 L4TIM45: CMP ESI,0 JE SHORT L4TIM049 ; NO MORE MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; RESTART TIMER PUSH ESI CALL GETBUFF POP ESI JZ SHORT L4TIM049 ; CANT - NO BUFFERS ; PUSH ESI PUSH EDI MOVZX ECX,MSGLENGTH[ESI] REP MOVSB ; COPY MESSAGE - LEAVE STATE ALONE POP EDI ; MESSAGE PUSH EBX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD ; QUEUE ON DEST INC L4FRAMESRETRIED JNZ SHORT INC004 INC L4FRAMESRETRIED+2 PUBLIC INC004 INC004: POP EBX POP ESI MOV ESI,[ESI] ; NEXT MESSAGE IN CHAIN JMP L4TIM45 ; SEND NEXT PUBLIC L4TIM049 L4TIM049: POP ECX POP EBX RET PUBLIC SENDL4CONNECT SENDL4CONNECT: CALL GETBUFF JNZ SHORT SENDL4C00 ; OK RET PUBLIC SENDL4C00 SENDL4C00: MOV L3PID[EDI],0CFH ; NET MESSAGE PUSH EDI LEA ESI,L4MYCALL[EBX] LEA EDI,L3SRCE[EDI] MOV ECX,7 REP MOVSB MOV ESI,L4TARGET[EBX] ; FAR END NODE LEA ESI,DEST_CALL[ESI] MOV ECX,7 REP MOVSB POP EDI PUSH EDI MOV AL,_L3LIVES MOV L3MONR[EDI],AL MOV AX,WORD PTR CIRCUITINDEX[EBX] MOV WORD PTR L4INDEX[EDI],AX MOV WORD PTR L4TXNO[EDI],0 MOV L4FLAGS[EDI],L4CREQ MOV AL,_L4DEFAULTWINDOW MOV L4DATA[EDI],AL ; PROPOSED WINDOW LEA EDI,L4DATA+1[EDI] ; TO ORIG CALL LEA ESI,L4USER[EBX] MOV ECX,7 REP MOVSB LEA ESI,L4MYCALL[EBX] MOV ECX,7 REP MOVSB MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; START TIMER STOSW ; AND PUT IN MSG CMP SPYFLAG[EBX],0 JE SHORT NOTSPY MOV AL,'Z' ; ADD SPY ON BBS FLAG STOSB PUBLIC NOTSPY NOTSPY: MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD RET PUBLIC SENDL4DISC SENDL4DISC: CMP L4STATE[EBX],4 JAE OKTODIS ; ; CIRCUIT NOT UP OR CLOSING - PROBABLY NOT YET SET UP - JUST ZAP IT ; CALL L4TIM06 RET PUBLIC OKTODIS OKTODIS: MOV AX,SESSIONT1[EBX] MOV L4TIMER[EBX],AX ; START TIMER MOV L4STATE[EBX],4 ; SET DISCONNECTING MOV L4ACKREQ[EBX],0 ; CANCEL ACK NEEDED CALL GETBUFF JNZ SHORT SENDL4D00 ; OK RET PUBLIC SENDL4D00 SENDL4D00: MOV L3PID[EDI],0CFH ; NET MESSAGE PUSH EDI LEA ESI,L4MYCALL[EBX] ; CALL WE ARE USING LEA EDI,L3SRCE[EDI] MOV ECX,7 REP MOVSB MOV ESI,L4TARGET[EBX] ; FAR END NODE LEA ESI,DEST_CALL[ESI] MOV ECX,7 REP MOVSB POP EDI PUSH EDI MOV AL,_L3LIVES MOV L3MONR[EDI],AL MOV AX,WORD PTR FARINDEX[EBX] MOV WORD PTR L4INDEX[EDI],AX MOV WORD PTR L4TXNO[EDI],0 MOV L4FLAGS[EDI],L4DREQ LEA EDI,L4DATA[EDI] MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD RET PUBLIC SENDL4IACK SENDL4IACK: ; ; SEND INFO ACK ; CALL GETBUFF JNZ SHORT SENDL4A00 ; OK MOV L4ACKREQ[EBX],10 ; TRY AGAIN LATER RET PUBLIC SENDL4A00 SENDL4A00: MOV L4ACKREQ[EBX],0 ; CLEAR ACK NEEDED MOV L3PID[EDI],0CFH ; NET MESSAGE PUSH EDI LEA ESI,L4MYCALL[EBX] ; CALL WE ARE USING LEA EDI,L3SRCE[EDI] MOV ECX,7 REP MOVSB MOV ESI,L4TARGET[EBX] ; FAR END NODE LEA ESI,DEST_CALL[ESI] MOV ECX,7 REP MOVSB POP EDI PUSH EDI MOV AL,_L3LIVES MOV L3MONR[EDI],AL MOV AX,WORD PTR FARINDEX[EBX] MOV WORD PTR L4INDEX[EDI],AX MOV L4TXNO[EDI],0 MOV AL,RXSEQNO[EBX] MOV L4RXNO[EDI],AL MOV L4LASTACKED[EBX],AL ; SAVE LAST NUMBER ACKED CALL GETBUSYBIT ; SEE IF CROSSSESSION IS BUSY MOV AL,L4IACK OR AL,NAKBITS[EBX] ; PUT IN NAK/CHOKE BITS MOV L4FLAGS[EDI],AL LEA EDI,L4DATA[EDI] MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,L4TARGET[EBX] ; LINK ENTRY LEA ESI,DEST_Q[EBX] CALL _Q_ADD RET PUBLIC GETBUSYBIT GETBUSYBIT: ; ; SEE IF CROSSSESSION IS BUSY ; AND NAKBITS[EBX],0FFH-L4BUSY CALL CHECKIFBUSY ; RETURNS AL WITH BUSY BIT SET IF CROSSSESSION IS BUSY OR NAKBITS[EBX],AL RET PUBLIC L4CONNECTFAILED L4CONNECTFAILED: ; ; CONNECT HAS TIMED OUT - SEND MESSAGE TO OTHER END ; CMP L4CROSSLINK[EBX],0 JE SHORT L4CONF00 ; NO LINK? CALL GETBUFF JNZ SHORT L4CONF10 PUBLIC L4CONF00 L4CONF00: RET PUBLIC L4CONF10 L4CONF10: PUSH EBX PUSH EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID CALL _SETUPNODEHEADER ; PUT IN NODE ID MOV ESI,OFFSET32 FAILEDMSG MOV ECX,LFAILEDMSG REP MOVSB PUSH EDI MOV ESI,L4TARGET[EBX] ; ADDR OF DEST ENTRY LEA ESI,DEST_CALL[ESI] CALL DECODENODENAME ; CONVET TO ALIAS:CALL POP EDI MOV ECX,17 REP MOVSB MOV AL,0DH STOSB MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX MOV EBX,L4CROSSLINK[EBX] MOV L4CROSSLINK[EBX],0 ; SET BACK TO COMMAND LEVEL LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL POP EBX ; ORIGINAL CIRCUIT TABLE RET PUBLIC AUTOTIMER AUTOTIMER: ; ; SEND MESSAGE TO USER TO KEEP CIRCUIT OPEN ; CALL GETBUFF JNZ SHORT KEEP00 RET ; CANT PUBLIC KEEP00 KEEP00: PUSH EDI ADD EDI,7 MOV AL,0F0H STOSB ; PID XOR AX,AX STOSW ; A COUPLE OF NULLS MOV ECX,EDI POP EDI SUB ECX,EDI MOV MSGLENGTH[EDI],CX LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; SEND MESSAGE TO CALLER CALL _POSTDATAAVAIL MOV L4KILLTIMER[EBX],0 PUSH EBX MOV EBX,L4CROSSLINK[EBX] ; TO PARTNER SESSION OR EBX,EBX JZ SHORT L4TIM201 ; NO CROSSLINK?? MOV L4KILLTIMER[EBX],0 ; ITS TIMES IS ALSO ABOUT TO EXPIRE PUBLIC L4TIM201 L4TIM201: POP EBX RET PUBLIC SETUPBPQCONSOLESESSION SETUPBPQCONSOLESESSION: ; APPL ALREADY IN AL PUSH EBX ; SAVE TNC POINTER CALL GETFREECIRCUIT ; GET AN ENTRY JZ SHORT SETUPCON00 ; OK ADD ESP,4 ; CLEAR STACK MOV EBX,0 ; RETURN POINTER = 0 RET PUBLIC SETUPCON00 SETUPCON00: ; ; IF BBS PORT USE BBS CALL, ELSE NODE CALL ; LEA ESI,_MYCALL AND EAX,0FFFFFFFFH ; APPL FLAG JZ SHORT CCTFORNODE MOV ESI,OFFSET32 APPLCALLTABLE @@: TEST EAX,1 JNZ @F ; GOT APPL NUMBER ADD ESI,TYPE APPLCALLS SHR EAX,1 JMP SHORT @B @@: LEA ESI,APPLCALL[ESI] ; BBS CALLSIGN CMP BYTE PTR [ESI],40H JA CCTFORNODE ; CALL PRESENT LEA ESI,_MYCALL ; NO APPL CALL DEFINED, SO USE NODE CALL PUBLIC CCTFORNODE CCTFORNODE: PUSH ESI LEA EDI,L4USER[EBX] MOV ECX,7 REP MOVSB ; PUT IN CALL ; POP ESI LEA EDI,L4MYCALL[EBX] ; NODE CALL IN USE MOV ECX,7 REP MOVSB ; PUT IN CALL ; MOV CIRCUITINDEX[EBX],DL ; OUR INDEX MOV AL,_NEXTID MOV CIRCUITID[EBX],AL ; OUR ID CALL INC_ID POP EAX MOV L4TARGET[EBX],EAX ; LINK POINTER - TO TNC CONTROL INFO MOV L4STATE[EBX],5 MOV AX,_L4T1 MOV SESSIONT1[EBX],AX ; DEFAULT TIMEOUT MOV AL,_L4DEFAULTWINDOW MOV L4WINDOW[EBX],AL ; SET WINDOW MOV AL,PACLEN MOV SESSPACLEN[EBX],AL ; DEFAULT RET extrn _PostMessageA@16:near extrn _BPQMsg:dword PUBLIC _POSTDATAAVAIL PUBLIC _POSTDATAAVAIL _POSTDATAAVAIL: ; ; Post a message if requested ; TEST L4CIRCUITTYPE[EBX],BPQHOST JZ SHORT NOPOST ; NOT BPQ HOST MODE MOV EAX,L4TARGET[EBX] OR EAX,EAX JZ SHORT NOPOST cmp HOSTHANDLE[EAX],0 je short nopost push ecx push 2 movzx ecx,HOSTSTREAM[EAX] push ecx push _BPQMsg PUSH HOSTHANDLE[EAX] call _PostMessageA@16 pop ecx nopost: RET _TEXT ENDS END