PAGE 56,132 ; .386 ; ; SEGMENT definitions and order ; ;* 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 extrn _BTLENGTH:DWORD,_BTEXTFLD:DWORD,_BTHDDR:DWORD D10 DB 10 D16 DB 16 NEWVALUE DB 0 SWITCHSP DB 'SWITCH ' BADRAWMSG DB 'BPQ32 Corrupt Raw Message len=' BADRAWCOUNT DB 'xxxx',0 COMPAREFIELD DB 14 DUP (0) ; FOR FINDING LINK TABLE ENTRIES COMPAREPORT DB 0 ; PORT FOR ABOVE _ENDOFDATA DD 0 ; For DUMP ROUTINE PUBLIC SWITCHSP,_ENDOFDATA EVEN EXTRN _PORTTABLE:DWORD,_NUMBEROFPORTS:DWORD, _pgm:BYTE IF BLACKBITS EXTRN BLACKLIST:BYTE ENDIF EXTRN _APPLCALLTABLE:BYTE,_IDMSG:DWORD,_NORMCALL:BYTE EXTRN _QCOUNT:WORD,_IDMSG_Q:DWORD, _Semaphore:DWORD EXTRN _BPQHOSTVECTOR:BYTE,_BPQVECLENGTH:BYTE EXTRN _REALTIMETICKS:WORD,_BUFFERWAITS:DWORD extern _SemHeldByAPI:DWORD extern _Sem_eax:DWORD extern _Sem_ebx:DWORD extern _Sem_ecx:DWORD extern _Sem_edx:DWORD extern _Sem_esi:DWORD extern _Sem_edi:DWORD extern _AuthorisedProgram:BYTE _BPQDATA ENDS _TEXT SEGMENT ; EXTRN _PUT_ON_PORT_Q:NEAR,_SENDNODESMSG:NEAR PUBLIC COUNT_QUEUED_FRAMES,COUNT_Q PUBLIC COUNT_AT_L2,_SENDNETFRAME EXTRN _CloseSessionPartner:NEAR EXTRN _SENDSABM:NEAR extrn _Sleep@4:near CR EQU 0DH LF EQU 0AH extern _LINKS:DWORD extern _MAXLINKS:WORD FINDLINKXX: ; ; FIND LINK FOR AN ADDRESS PAIR (OUR CALL - FAR CALL) IN EDI ; MOV EBX,0 MOV ESI,_LINKS MOVZX ECX,_MAXLINKS PUBLIC FINDLK00 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 JMP SHORT FINDLK10 ; TRY NEXT ENTRY PUBLIC FINDLK05 FINDLK05: MOV eax,LINKPORT[ESI] ; PORT mov al, PORTNUMBER[eax] CMP AL,COMPAREPORT JNE SHORT FINDLK10 ; WRONG PORT PUSH ESI PUSH EDI PUSH ECX LEA EDI,7[EDI] ; ORIGIN FROM MESSAGE CALL COMPARECALLS ; COMPARE WITH LINKCALL POP ECX POP EDI POP ESI JNE SHORT FINDLK10 PUSH ESI PUSH EDI PUSH ECX ADD ESI,7 ; OURCALL IN TABLE CALL COMPARECALLS ; COMPARE WITH DESTINATON IN MSG POP ECX POP EDI POP ESI JE SHORT FINDLKRET ; YES FINDLK10: ADD ESI,TYPE LINKTABLE LOOP FINDLK00 ; ; ENTRY NOT FOUND - BX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 ; SET NZ RET FINDLKRET: MOV EBX,ESI XOR AL,AL RET COMPARECALLS: ; ; COMPARE AX25 CALLSIGNS IN ESI, EDI IGNORING EXTRA BITS IN SSID ; MOV ECX,6 REP CMPSB ; COMPARE JNE SHORT COMPCALLRET ; DONT MATCH LODSB MOV AH,[EDI] AND AX,0001111000011110B ; MASK NON-SSID BITS CMP AL,AH COMPCALLRET: RET PUBLIC _COUNT_QUEUED_FRAMES _COUNT_QUEUED_FRAMES: COUNT_QUEUED_FRAMES: ; ; COUNT NUMBER OF FRAMES QUEUED ON A SESSION (IN ESI) ; RETURN TOTAL IN AL, NUMBER QUEUED ABOVE LINK IN AH (FOR HOST MODE TESTS) ; PUSH EBX TEST L4CIRCUITTYPE[ESI],BPQHOST JZ SHORT CQF00 LEA EBX,L4TX_Q[ESI] CALL COUNT_Q MOV AH,AL POP EBX RET PUBLIC CQF00 CQF00: TEST L4CIRCUITTYPE[ESI],SESSION JZ SHORT CQF10 ; ; L4 SESSION - GET NUMBER UNACKED, AND ADD NUMBER ON TX QUEUE ; LEA EBX,L4TX_Q[ESI] CALL COUNT_Q MOV AH,AL MOV AL,TXSEQNO[ESI] SUB AL,L4WS[ESI] ; LAST FRAME ACKED - GIVES NUMBER OUTSTANING ; ADD AL,AH POP EBX RET PUBLIC CQF10 CQF10: TEST L4CIRCUITTYPE[ESI],PACTOR JZ SHORT CQF20 ; MUST BE L2 SESSION ; ; PACTOR Type - Frames are queued on the Port Entry ; MOV EBX,L4TARGET[ESI] ; TO PORT LEA EBX,PORTTX_Q[EBX] CALL COUNT_Q pop EBX RET CQF20: ; ; L2 CIRCUIT ; LEA EBX,L4TX_Q[ESI] CALL COUNT_Q MOV AH,AL ; NUMBER ON SESSION MOV EBX,L4TARGET[ESI] ; TO LINK CALL COUNT_AT_L2 POP EBX RET COUNT_AT_L2: ; ; COUNTS FRAMES QUEUED ON AN L2 SESSION (IN BX) ; CMP EBX,0 ; NO SESSION?? JE C_L2_RET PUSH EBX LEA EBX,TX_Q[EBX] CALL COUNT_Q ADD AH,AL ; NUMBER ON L2 TX QUEUE POP EBX ; LINK ; ; COUNT FRAMES IN TSLOTS ; PUSH ECX MOV AL,0 MOV ECX,8 PUBLIC TSLOOP TSLOOP: CMP FRAMES[EBX],0 ; FRAME THERE? JE SHORT TSLOOP2 ; NO INC AL PUBLIC TSLOOP2 TSLOOP2: ADD EBX,4 LOOP TSLOOP POP ECX PUBLIC C_L2_RET C_L2_RET: ADD AL,AH ; TOTAL IN AL, NUMBER ABOVE LINK IN AH RET COUNT_Q: ; ; SEE HOW MANY BUFFERS ATTACHED TO Q HEADER IN BX ; XOR EAX,EAX COUNT_Q_LOOP: CMP DWORD PTR [EBX],0 JE SHORT COUNT_RET INC EAX MOV EBX,[EBX] ; FOLLOW CHAIN JNZ SHORT COUNT_Q_LOOP ; JUST IN CASE! PUBLIC COUNT_RET COUNT_RET: RET JUMPVECTOR LABEL DWORD DD OFFSET32 CHECKLOADED ; 0 DD OFFSET32 SETAPPLFLAGS ; 1 DD OFFSET32 SENDBPQFRAME ; 2 DD OFFSET32 GETBPQFRAME ; 3 DD OFFSET32 GETSTREAMSTATUS ; 4 DD OFFSET32 CLEARSTREAMSTATUS ; 5 DD OFFSET32 BPQCONDIS ; 6 DD OFFSET32 GETBUFFERSTATUS ; 7 DD OFFSET32 GETCONNECTIONINFO ; 8 DD OFFSET32 BPQRETURN ; 9 - GETCALLS DD OFFSET32 RAWTX ; 10 IE KISS TYPE DATA DD OFFSET32 GETRAWFRAME ; 11 DD OFFSET32 UPDATESWITCH ; 12 DD OFFSET32 BPQALLOC ; 13 DD OFFSET32 _SENDNETFRAME ; 14 DD OFFSET32 GETTIME ; 15 MARKER DB 'G8BPQ' ; MUST BE JUST BEFORE INT 7F ENTRY DB 4 ; MAJORVERSION DB 9 ; MINORVERSION PUBLIC _BPQHOSTAPI PUBLIC _BPQHOSTAPI _BPQHOSTAPI: ; ; SPECIAL INTERFACE, MAINLY FOR EXTERNAL HOST MODE SUPPORT PROGS ; ; COMMANDS SUPPORTED ARE ; ; AH = 0 Get node/switch version number and description. On return ; AH = major version number and AL = minor version number, ; and user's buffer pointed to by ES:ESI is set to the text ; string normally output by the USERS command, eg: ; "G8BPQ Packet Switch Version 4.01 Dev". CX is set to the ; length of the text string. ; ; ; AH = 1 Set application mask to value in DL (or even DX if 16 ; applications are ever to be supported). ; ; Set application flag(s) to value in CL (or CX). ; whether user gets connected/disconnected messages issued ; by the node etc. ; ; ; AH = 2 Send frame in ES:ESI (length CX) ; ; ; AH = 3 Receive frame into buffer at ES:ESI, length of frame returned ; in CX. BX returns the number of outstanding frames still to ; be received (ie. after this one) or zero if no more frames ; (ie. this is last one). ; ; ; ; AH = 4 Get stream status. Returns: ; ; CX = 0 if stream disconnected or CX = 1 if stream connected ; DX = 0 if no change of state since last read, or DX = 1 if ; the connected/disconnected state has changed since ; last read (ie. delta-stream status). ; ; ; ; AH = 6 Session control. ; ; CX = 0 Conneect - _APPLMASK in DL ; CX = 1 connect ; CX = 2 disconnect ; CX = 3 return user to node ; ; ; AH = 7 Get buffer counts for stream. Returns: ; ; AX = number of status change messages to be received ; BX = number of frames queued for receive ; CX = number of un-acked frames to be sent ; DX = number of buffers left in node ; SI = number of trace frames queued for receive ; ;AH = 8 Port control/information. Called with a stream number ; in AL returns: ; ; AL = Radio port on which channel is connected (or zero) ; AH = SESSION TYPE BITS ; BX = L2 paclen for the radio port ; CX = L2 maxframe for the radio port ; DX = L4 window size (if L4 circuit, or zero) ; ES:EDI = CALLSIGN ;AH = 9 Fetch node/application callsign & alias. AL = application ; number: ; ; 0 = node ; 1 = BBS ; 2 = HOST ; 3 = SYSOP etc. etc. ; ; Returns string with alias & callsign or application name in ; user's buffer pointed to by ES:ESI length CX. For example: ; ; "WORCS:G8TIC" or "TICPMS:G8TIC-10". ; ; ; AH = 10 Unproto transmit frame. Data pointed to by ES:ESI, of ; length CX, is transmitted as a HDLC frame on the radio ; port (not stream) in AL. ; ; ; AH = 11 Get Trace (RAW Data) Frame into ES:EDI, ; Length to CX, Timestamp to AX ; ; ; AH = 12 Update Switch. At the moment only Beacon Text may be updated ; DX = Function ; 1=update BT. ES:ESI, Len CX = Text ; 2=kick off nodes broadcast ; ; AH = 14 Internal Interface for IP Router ; ; Send frame - to NETROM L3 if DL=0 ; to L2 Session if DL<>0 ; ; ; AH = 15 Get interval timer ; ; CALCULATE AND STACK ROUTINE ADDRESS ; extrn _GetSemaphore:near extrn _FreeSemaphore:near extrn _Check_Timer:near pushad call _Check_Timer push offset _Semaphore call _GetSemaphore add esp, 4 popad mov _SemHeldByAPI,1 mov _Sem_eax,eax mov _Sem_ebx,ebx mov _Sem_ecx,ecx mov _Sem_edx,edx mov _Sem_esi,esi mov _Sem_edi,edi call API pushad push offset _Semaphore call _FreeSemaphore add esp, 4 popad ret PUBLIC API API: ; MOV BL,AH ; AND EBX,0FH MOVZX EBX,AH SHL EBX,2 ; COMMAND * 4 ADD EBX,OFFSET32 JUMPVECTOR PUSH CS:[EBX] ; ROUTINE TO STACK CMP AH,11 JE SHORT NEEDHOSTPORT CMP AH,13 JE SHORT NEEDHOSTPORT CMP AH,10 JAE SHORT HOSTNOPORT ; CMP AH,2 JNE NEEDHOSTPORT ; SEND ALLOWS ZERO STREAM, MEANING UNPROTO OR AL,AL JNZ NEEDHOSTPORT JMP SHORT HOSTNOPORT ; BROADCAST STREAM PUBLIC NEEDHOSTPORT NEEDHOSTPORT: ; ; CALCULATE PORT VECTOR ADDDRESS ; PUSH EAX AND EAX,0FFH JZ short ALBAD ; in case of duff call DEC AL CMP AL,64 JBE SHORT ALOK PUBLIC ALBAD ALBAD: MOV AL,64 ; PROTECT US! PUBLIC ALOK ALOK: MUL _BPQVECLENGTH ADD EAX,OFFSET32 _BPQHOSTVECTOR ; POINT TO VECTOR FOR STREAM IN AL XCHG EAX,EBX ; VECTOR TO BX GOTPORT: POP EAX PUBLIC HOSTNOPORT HOSTNOPORT: RET ; ENTER STACKED ROUTINE ; PUBLIC _SENDNETFRAME _SENDNETFRAME: ; ; ATTACH FRAME TO OUTBOUND L3 QUEUES (ONLY USED FOR IP ROUTER) ; ; ESI, CX INCLUDE THE L2 SESSION INFO (15 BYTES) ; MOVZX ECX,CX CMP ECX,MAXDATA JA SHORT NETEXIT ; IGNORE CMP _QCOUNT,100 ; PLENTY FREE? JB SHORT NETEXIT ; NO PUSH ESI ; USERS BUFFER CALL GETBUFF POP ESI JZ SHORT NETEXIT ; WOT? PUSH EDI ; SAVE BUFFER ADD EDI,7 PUSH ESI ADD ESI,15 ; REMOVE HEADER INFO SUB ECX,15 REP MOVSB POP ESI PUSH EDI MOV EDI,OFFSET32 COMPAREFIELD+7; IN CASE L2 MOV ECX,7 REP MOVSB ; GET L2 INFO MOV EDI,OFFSET32 COMPAREFIELD ; IN CASE L2 MOV ECX,7 REP MOVSB ; GET L2 INFO POP ECX ; END OF DATA POP EDI ; START OF DATA SUB ECX,EDI ; LENGTH MOV MSGLENGTH[EDI],CX ; ; SEE IF L2 OR L3 ; CMP DL,0 JNE SHORT NETSENDL2 PUSH EDI LEA ESI,L3DEST[EDI] CALL _FINDDESTINATION POP EDI JZ SHORT L3OK PUBLIC NETCANTSEND NETCANTSEND: CALL RELBUFF JMP SHORT NETEXIT1 PUBLIC L3OK L3OK: LEA ESI,DEST_Q[EBX] CALL _Q_ADD PUBLIC NETEXIT1 NETEXIT1: PUBLIC NETEXIT NETEXIT: RET PUBLIC NETSENDL2 NETSENDL2: ; ; SEND FRAME TO L2 DEST, CREATING A LINK ENTRY IF NECESSARY ; PUSH EDI ; SAVE BUFFER MOV COMPAREPORT,DL CALL GETPORTTABLEENTRY MOV EBP,EBX MOV EDI,OFFSET32 COMPAREFIELD CALL FINDLINKXX ; GET LINK FOR THIS ADDRESS PAIR (IN BX) ; ; SET UP NEW SESSION (OR RESET EXISTING ONE) ; JZ SHORT GOTLINK CMP EBX,0 JE NETCANTSEND ; TABLES FULL ; ; COPY ADDRESS INFO TO LINK TABLE ; LEA ESI,COMPAREFIELD+7 LEA EDI,LINKCALL[EBX] MOV ECX,7 REP MOVSB LEA ESI,COMPAREFIELD LEA EDI,OURCALL[EBX] MOV ECX,7 REP MOVSB ; MOV LINKPORT[EBX],EBP ; PUT IN PORT MOV AL,PORTT1[EBP] MOV L2TIME[EBX],AL ; SET STANDARD TIMER VALUE MOV LINKTYPE[EBX],2 ; DOWNLINK mov al,PORTWINDOW[ebp] MOV LINKWINDOW[EBX],AL MOV L2STATE[EBX],2 ; CONNECTING CALL _SENDSABM ; KICK IT OFF PUBLIC GOTLINK GOTLINK: POP EDI LEA ESI,TX_Q[EBX] CALL _Q_ADD ; QUEUE ON LINK JMP NETEXIT1 extrn _GetCurrentProcessId@0:near PUBLIC SETAPPLFLAGS SETAPPLFLAGS: MOV HOSTAPPLMASK[EBX],EDX ; APPL MASK MOV HOSTAPPLFLAGS[EBX],CL ; APPL FLAGS ; If either is non-zero, set allocated and Process. This gets round problem with ; stations that don't call allocate stream movzx eax,cl or eax,edx jz short BPQRETURN OR HOSTFLAGS[EBX],80H ; SET ALLOCATED BIT push ebx call _GetCurrentProcessId@0 pop ebx mov STREAMOWNER[EBX],EAX ; Set Program Name pushad lea esi, _pgm; lea edi, HOSTPGMNAME[EBX]; mov ecx, 31 rep movsb popad PUBLIC BPQRETURN BPQRETURN: RET PUBLIC BPQALLOC BPQALLOC: CMP AL,0 JE SHORT ALLOC_FIND ; ; ALLOC OR RELEASE ; CMP CL,1 JE SHORT ALLOC CMP CL,2 JNE SHORT BPQRETURN ; ; RELEASE STREAM ; AND HOSTFLAGS[EBX],7FH ; CLEAR ALLOCATED BIT mov STREAMOWNER[EBX],0 MOV HOSTAPPLMASK[EBX],0 ; APPL MASK MOV HOSTAPPLFLAGS[EBX],0 ; APPL FLAGS MOV HOSTPGMNAME[EBX], 0; JMP SHORT BPQRETURN PUBLIC ALLOC ALLOC: TEST HOSTFLAGS[EBX],80H JZ SHORT ALLOC_OK MOV ECX,1 JMP SHORT BPQRETURN PUBLIC ALLOC_OK ALLOC_OK: OR HOSTFLAGS[EBX],80H ; SET ALLOCATED BIT push eax push ebx call _GetCurrentProcessId@0 pop ebx mov STREAMOWNER[EBX],EAX ; Set Program Name pushad lea esi, _pgm; lea edi, HOSTPGMNAME[EBX]; mov ecx, 31 rep movsb popad pop eax MOV ECX,0 JMP SHORT BPQRETURN PUBLIC ALLOC_FIND ALLOC_FIND: ; ; LOOK FOR FIRST FREE SESSION ; MOV EBX,OFFSET32 _BPQHOSTVECTOR MOV EAX,1 PUBLIC ALLOC_LOOP ALLOC_LOOP: TEST HOSTFLAGS[EBX],80H JZ SHORT OK_TO_ALLOC ADD EBX,VECTORLENGTH INC AL CMP AL,65 JNE SHORT ALLOC_LOOP MOV AL,0FFH JMP SHORT BPQRETURN PUBLIC OK_TO_ALLOC OK_TO_ALLOC: OR HOSTFLAGS[EBX],80H ; SET ALLOCATED BIT push eax push ebx call _GetCurrentProcessId@0 pop ebx mov STREAMOWNER[EBX],EAX ; Set Program Name pushad lea esi, _pgm; lea edi, HOSTPGMNAME[EBX]; mov ecx, 31 rep movsb popad pop eax JMP BPQRETURN PUBLIC CHECKLOADED CHECKLOADED: MOV AX,'PB' MOV BX,' Q' MOV DH,4 ; MAJORVERSION MOV DL,9 ; MINORVERSION ; MOV SI,OFFSET SESSIONHDDR ; MOV CX,SESSHDDRLEN-2 ; PUSH CX ; REP MOVSB ; POP CX RET PUBLIC GETTIME GETTIME: MOV AX,_REALTIMETICKS MOV EBX,0 IF BLACKBITS MOV EBX,OFFSET32 BLACKLIST ENDIF RET PUBLIC GETSTREAMSTATUS GETSTREAMSTATUS: ; ; AH = 4 Get stream status. Returns: ; ; CX = 0 if stream disconnected or CX = 1 if stream connected ; DX = 0 if no change of state since last read, or DX = 1 if ; the connected/disconnected state has changed since ; last read (ie. delta-stream status). ; ; MOVZX EDX,HOSTFLAGS[EBX] ; STATE CHANGE BITS TEST DL,3 MOV DL,0 JZ SHORT @F MOV DL,1 @@: MOV ECX,HOSTSESSION[EBX] ; LOCAL SESSION OR ECX,ECX JZ SHORT @F ; NO SESSION MOV ECX,1 @@: RET PUBLIC CLEARSTREAMSTATUS CLEARSTREAMSTATUS: ; ; AH = 5 Ack stream status change ; ; AND HOSTFLAGS[EBX],0FCH ; CLEAR IT RET PUBLIC GETBUFFERSTATUS PUBLIC _GETBUFFERSTATUS GETBUFFERSTATUS: _GETBUFFERSTATUS: ; ; AH = 7 Get buffer counts for stream. Returns: ; ; BX = number of frames queued for receive ; CX = number of un-acked frames to be sent ; DX = number of buffers left in node ; SI = number of monitor frames queued for receive XOR ECX,ECX ; unacked frames PUSH EBX LEA EBX,HOSTTRACEQ[EBX] XOR EAX,EAX CALL COUNT_Q ; POP EBX ; PUSH EAX ; SAVE ; MOV ESI,HOSTSESSION[EBX] ; LOCAL SESSION CMP ESI,0 JNE SHORT BPQSTATE01 ; CONNECTED ; ; NOT CONNECTED - JUST RETURN FREE Q COUNT AND CHANGE BITS ; MOV EBX,0 ; NOTHING QUEUED JMP SHORT BPQSTATUSEND PUBLIC BPQSTATE01 BPQSTATE01: ; ; CONNECTED ; LEA EBX,L4TX_Q[ESI] XOR EAX,EAX CALL COUNT_Q MOV EBX,EAX ; QUEUED RX FRAMES PUBLIC BPQSTATE02 BPQSTATE02: CMP L4CROSSLINK[ESI],0 JE SHORT BPQSTATUSEND ; NOT CONNECTED BEYOND SWITCH MOV ESI,L4CROSSLINK[ESI] XOR EAX,EAX CALL COUNT_QUEUED_FRAMES MOVZX ECX,AL ; QUEUED TO SEND PUBLIC BPQSTATUSEND BPQSTATUSEND: MOVZX EDX,_QCOUNT ; FREE BUFFERS POP ESI RET ; public GETCONNECTIONINFO PUBLIC _GETCONNECTIONINFO _GETCONNECTIONINFO: PUBLIC GETCONNECTIONINFO GETCONNECTIONINFO: ; ; PACLEN IN BX ; PUSH EBP MOV EAX,0 ; PORT MOV EBP,EAX ; PACLEN MOV ECX,EAX ; MAXFRAME MOV EDX,-1 ; ERROR FLAG IF NO CONNECTION MOV EBX,HOSTSESSION[EBX] ; SESSION CMP EBX,0 JE NO_INFO ; NOT CONNECTED MOV EDX,EAX ; L4 WINDOW MOVZX EBP,SESSPACLEN[EBX] MOV ESI,OFFSET32 SWITCHSP CMP L4CROSSLINK[EBX],0 JE SHORT CALLCOPY ; ; CONNECTED OUT - GET TARGET SESSION ; MOV ESI,L4CROSSLINK[EBX] MOV DL,L4WINDOW[ESI] MOV AH,L4CIRCUITTYPE[ESI] ; UPLINK SESSION TYPE TEST AH,BPQHOST JNZ SHORT HOST_ENTRY TEST AH,L2LINK JNZ SHORT L2_ENTRY TEST AH,PACTOR JZ SHORT @f ; MUST BE NODE SESSION ; ; PACTOR Type - Frames are queued on the Port Entry ; MOV EBX, L4TARGET[ESI] MOV AL, PORTNUMBER[EBX] push EAX MOVZX EAX, KAMSESSION[ESI] SHL EAX,2 ADD EAX, L4TARGET[ESI] MOV ESI, ATTACHEDSESSIONS[EAX] pop EAX JMP SHORT RETURNCALL @@: ; ANOTHER NODE ; ; IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL ; TEST L4CIRCUITTYPE[EBX],UPLINK; GET SESSION TYPE JZ SHORT RETURNCALL ; MOV ESI,L4TARGET[ESI] ; NODE LEA ESI,DEST_CALL[ESI] ; NODE CALLSIGN JMP SHORT RETURNCALL PUBLIC L2_ENTRY L2_ENTRY: PUSH ESI ; SAVE SESSION MOV ESI,L4TARGET[ESI] ; ; ESI IS LINK ENTRY - EXTRACT PORT AND MAXFRAME ; push esi mov esi, LINKPORT[ESI] mov al, PORTNUMBER[esi] pop esi MOV CL,LINKWINDOW[ESI] MOV DL,0 ; NO L4 WINDOW ; LEA ESI,LINKCALL[ESI] TEST AH,UPLINK JZ SHORT L2_DOWN ; DOWNLINK, SO WE HAVE THE RIGHT CALL ; ; IF UPLINK, SHOULD USE SESSION CALL, IN CASE *** LINKED HAS BEEN USED ; POP ESI ; BACK TO SESSION JMP SHORT HOST_ENTRY PUBLIC L2_DOWN L2_DOWN: ADD ESP,4 ; LOOSE SAVED ESI JMP SHORT RETURNCALL HOST_ENTRY: LEA ESI,L4USER[ESI] PUBLIC RETURNCALL RETURNCALL: PUSH EDI ; USERS BUFFER PUSH EAX PUSH ECX CALL CONVFROMAX25 ; CONVERT CALL TO NORMAL POP ECX POP EAX POP EDI MOV ESI,OFFSET32 _NORMCALL PUBLIC CALLCOPY CALLCOPY: PUSH ECX MOV ECX,10 REP MOVSB ; RETURN CALL POP ECX PUBLIC NO_INFO NO_INFO: MOV EBX,EBP POP EBP RET PUBLIC BPQCONDIS BPQCONDIS: ; ; CL=0 CONNECT USING APPL MASK IN EDX ; CL=1, CONNECT. CL=2 - DISCONNECT. CL=3 RETURN TO NODE ; CMP CL,1 JA SHORT BPQDIS CMP HOSTSESSION[EBX],0 JNE SHORT BPQCONRET ; ALREADY CONNECTED?? ; ; SET UP A SESSION FOR THE CONSOLE ; OR HOSTFLAGS[EBX],80H ; SET ALLOCATED BIT PUSH EBX MOV EAX,EDX CMP CL,0 JE SHORT GOTMASK MOV EAX,HOSTAPPLMASK[EBX] ; SO WE GET CORRECT CALLSIGN PUBLIC GOTMASK GOTMASK: ;NewSess = SETUPBPQCONSOLESESSION(Session, HOSTSESS, Mask); CALL SETUPBPQCONSOLESESSION ; MOV ESI,EBX POP EBX ; ; ESI=SESSION, EBX=VECTOR ; CMP ESI,0 JE SHORT BPQDIS00 ; RETURN DISCONNECTED?? MOV HOSTSESSION[EBX],ESI MOV L4CIRCUITTYPE[ESI],BPQHOST+UPLINK MOV AL,_AuthorisedProgram ; // Secure Host Session MOV Authorised_Session[ESI],AL BPQCONRET: OR HOSTFLAGS[EBX],1 ; STATE CHANGE CALL POSTSTATECHANGE RET ; PUBLIC BPQDIS BPQDIS: CMP HOSTSESSION[EBX],0 JE SHORT BPQCONRET ; NOT CONNECTED?? CMP CL,3 JNE SHORT DO_DISC OR HOSTFLAGS[EBX],20H ; SET 'STAY' FLAG PUBLIC DO_DISC DO_DISC: OR HOSTFLAGS[EBX],40H ; SET 'DISC REQ' FLAG RET PUBLIC BPQDIS00 BPQDIS00: MOV HOSTSESSION[EBX],0 OR HOSTFLAGS[EBX],3 ; STATE CHANGE ; CALL POSTSTATECHANGE RET PUBLIC SENDBPQFRAME SENDBPQFRAME: ; ; ES:ESI = MESSAGE, CX = LENGTH, BX = VECTOR ; MOVZX ECX,CX CMP ECX,256 JA SHORT SENDHOSTRET ; IGNORE CMP AL,0 JE SHORT BPQHOSTUNPROTO OR HOSTFLAGS[EBX],80H ; SET ALLOCATED BIT MOV EBX,HOSTSESSION[EBX] CMP EBX,0 JE SHORT SENDHOSTRET ; NO SESSION ; ; GET A BUFFER ; PUBLIC BWAITFORBUFFER BWAITFORBUFFER: CMP _QCOUNT,40 ; PLENTY FREE? JB SHORT SENDHOSTERR ; NO PUSH ESI ; USERS BUFFER CALL GETBUFF POP ESI JZ SHORT SENDHOSTERR ; ?? PUSH EDI ; SAVE BUFFER ADD EDI,7 MOV AL,0F0H ; PID STOSB REP MOVSB MOV ECX,EDI POP EDI SUB ECX,EDI ; LENGTH MOV MSGLENGTH[EDI],CX ; ; IF CONNECTED, PASS MESSAGE TO TARGET CIRCUIT - FLOW CONTROL AND ; DELAYED DISC ONLY WORK ON ONE SIDE ; LEA ESI,L4RX_Q[EBX] MOV L4KILLTIMER[EBX],0 ; RESET SESSION TIMEOUT CMP L4CROSSLINK[EBX],0 ; CONNECTED? JE SHORT SENDF50 ; NO, SO QUEUE NORMALLY MOV EBX,L4CROSSLINK[EBX] ; TO SESSION PARTNER CMP L4STATE[EBX],5 JNE SHORT SENDF50 ; NOT UP YET - AGAIN QUEUE NORAMLLY LEA ESI,L4TX_Q[EBX] CALL _Q_ADD ; PUT ON QUEUE CALL _POSTDATAAVAIL MOV EAX,0 RET PUBLIC SENDF50 SENDF50: CALL _Q_ADD ; PUT ON QUEUE PUBLIC SENDHOSTRET SENDHOSTRET: MOV EAX,0 RET ; PUBLIC SENDHOSTERR SENDHOSTERR: MOV EAX,1 RET PUBLIC BPQHOSTUNPROTO BPQHOSTUNPROTO: CMP AH,2 JNE SHORT UNPROTORET ; ONLY USED FOR SEND DATA ; MOVZX ECX,CX CMP ECX,256 JA SHORT UNPROTORET ; IGNORE ; SEND FRAME TO ALL RADIO PORTS ; ; COPY DATA TO A BUFFER IN OUR SEGMENTS - SIMPLFIES THINGS LATER ; CMP _QCOUNT,20 ; PLENTY FREE? JB SHORT UNPROTORET ; DONT BOTHER IF VERY LOW PUSH ESI ; USERS BUFFER CALL GETBUFF POP ESI JZ SHORT UNPROTORET ; ?? PUSH EDI ; SAVE BUFFER ADD EDI,7 MOV AL,0F0H ; PID STOSB REP MOVSB MOV ECX,EDI POP EDI SUB ECX,EDI ; LENGTH MOV MSGLENGTH[EDI],CX ; PUSH EDI ; SAVE FOR RELEASE MOV ESI,EDI pushad push esi CALL _SENDUIMESSAGE pop esi popad POP EDI CALL RELBUFF PUBLIC UNPROTORET UNPROTORET: MOV ECX,0 MOV EDX,0 RET extern _SENDUIMESSAGE:NEAR PUBLIC GETBPQFRAME PUBLIC GETBPQFRAME GETBPQFRAME: MOV ECX,0 ; FRAME LENGTH MOV EBX,HOSTSESSION[EBX] ; SESSION OR EBX,EBX JZ SHORT GETF10 ; NO SESSION LEA ESI,L4TX_Q[EBX] CMP DWORD PTR [ESI],0 JNE SHORT GETF20 PUBLIC GETF10 GETF10: XOR EBX,EBX ; NO MORE RET PUBLIC GETF20 GETF20: MOV L4KILLTIMER[EBX],0 ; RESET SESSION TIMEOUT MOV EDX,EDI ; SAVE USERS BUFFER CALL Q_REM MOVZX ECX,MSGLENGTH[EDI] LEA ESI,L3PID+1[EDI] SUB ECX,8 ; HEADER LENGTH JZ SHORT GETBPQEND ; ZERO LENGTH TEXT CMP ECX,257 JB SHORT BPQLENOK MOV ECX,256 ; PROTECTION PUBLIC BPQLENOK BPQLENOK: PUSH EDI ; SAVE BUFFER MOV EDI,EDX ; RESTORE USERS BUFFER PUSH ECX REP MOVSB ; COPY TO SUPPLIED BUFFER POP ECX POP EDI ; MSG BUFFER PUBLIC GETBPQEND GETBPQEND: CALL RELBUFF LEA EBX,L4TX_Q[EBX] CALL COUNT_Q MOV EBX,0 MOV BL,AL ; FRAMES WAITING MOV EDI,EDX RET PUBLIC GETRAWFRAME GETRAWFRAME: MOV ECX,0 ; FRAME LENGTH LEA ESI,HOSTTRACEQ[EBX] CMP DWORD PTR [ESI],0 JNE SHORT GETRF20 XOR EBX,EBX ; NO MORE RET PUBLIC GETRF20 GETRF20: MOV EDX,EDI ; SAVE USERS BUFFER CALL Q_REM MOVZX ECX,MSGLENGTH[EDI] CMP ECX,400 JA GETX cmp ecx,0 jne getxx PUBLIC GETX GETX: XOR EBX,EBX ; NO MORE XOR ECX,ECX RET getxx: PUSH EDI ; SAVE BUFFER MOV EAX,BUFFLEN-8[EDI] ; GET TIMESTAMP MOV ESI,EDI MOV EDI,EDX ; RESTORE USERS BUFFER PUSH ECX REP MOVSB ; COPY TO SUPPLIED BUFFER POP ECX POP EDI PUBLIC GETRAWEND GETRAWEND: PUSH EAX ; SAVE TIMESTAMP CALL RELBUFF ; ; COUNT THOSE LEFT ON QUEUE ; LEA EBX,HOSTTRACEQ[EBX] CALL COUNT_Q XOR AH,AH ; FRAMES WAITING XOR EBX,EBX MOV BX,AX MOV EDI,EDX POP EAX RET RAWTX: ; ; ESI = MESSAGE, CX = LENGTH, AL = PORT ; ; GET A BUFFER ; MOVZX ECX,CX CMP ECX,MAXDATA JA SHORT RAWEXIT ; IGNORE CMP _QCOUNT,50 ; PLENTY FREE? JB SHORT RAWERROR ; no CALL GETPORTTABLEENTRY PUSH ESI ; USERS BUFFER CALL GETBUFF POP ESI JZ SHORT RAWERROR PUSH EDI ; SAVE BUFFER ADD EDI,7 REP MOVSB MOV ECX,EDI POP EDI SUB ECX,EDI ; LENGTH MOV MSGLENGTH[EDI],CX ; CMP PROTOCOL[EBX],10 ; PACTOR/WINMOR Style JNE SHORT RAWNOTPACTOR ; Pactor Style. Probably will only be used for Tracker uneless we do APRS over V4 or WINMOR ; Attach to UI_Q LEA ESI,UI_Q[EBX] CALL _Q_ADD ; PUT ON QUEUE mov eax,0 RET RAWNOTPACTOR: MOV AL,PORTNUMBER[EBX] MOV MSGPORT[EDI],AL pushad push edi push ebx CALL _PUT_ON_PORT_Q add esp,8 popad PUBLIC RAWEXIT RAWEXIT: mov eax,0 RET PUBLIC RAWERROR RAWERROR: mov eax,1 RET PUBLIC UPDATESWITCH UPDATESWITCH: CMP DX,2 JNE SHORT NOTNODES CALL _SENDNODESMSG JMP RAWEXIT PUBLIC NOTNODES NOTNODES: CMP DX,1 JNE SHORT RAWEXIT ; ; UPDATE BT ; MOVZX ECX, CX MOV _BTLENGTH,ECX ADD _BTLENGTH,7 MOV EDI,OFFSET32 _BTEXTFLD REP MOVSB JMP RAWEXIT extrn _PostMessageA@16:near extrn _BPQMsg:dword PUBLIC POSTSTATECHANGE PUBLIC POSTSTATECHANGE POSTSTATECHANGE: ; ; Post a message if requested ; MOV EAX,HOSTHANDLE[EBX] or eax,eax jz short nopost push ecx ; save push 4 movzx ecx,HOSTSTREAM[EBX] push ecx push _BPQMsg PUSH EAX call _PostMessageA@16 pop ecx nopost: 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 NOPOST ; NOT BPQ HOST MODE MOV EAX,L4TARGET[EBX] OR EAX,EAX JZ NOPOST cmp HOSTHANDLE[EAX],0 je nopost push ecx push 2 movzx ecx,HOSTSTREAM[EAX] push ecx push _BPQMsg PUSH HOSTHANDLE[EAX] call _PostMessageA@16 pop ecx RET GETFREECIRCUIT: MOV EBX,_L4TABLE MOVZX ECX,_MAXCIRCUITS MOV DL,0 GETFREE00: CMP BYTE PTR [EBX],0 JNE SHORT GETFREE05 ; NOT A SPARE ENTRY RET GETFREE05: ADD EBX,TYPE TRANSPORTENTRY INC DL ; INDEX LOOP GETFREE00 ; ; ENTRY NOT FOUND ; OR AL,1 RET EXTRN _L4T1:WORD,_L3LIVES:BYTE,_L4TABLE:DWORD,_MAXCIRCUITS:WORD EXTRN _L4LIMIT:WORD EXTRN _ALIASPTR:DWORD,_CMDALIAS:BYTE extern _NEXTID:byte ; DB 55H ; NEXT ID TO ALLOCATE extern _MYCALL:BYTE, _PACLEN:BYTE, _L4DEFAULTWINDOW:byte INC_ID: INC _NEXTID JNZ SHORT IDOK INC _NEXTID ; KEEP NONZERO IDOK: RET extern _DESTS:DWORD extern _MAXDESTS:WORD _FINDDESTINATION: MOV EBX,0 MOV EDI,_DESTS MOVZX ECX,_MAXDESTS PUBLIC FINDDE00 FINDDE00: CMP DEST_CALL[EDI],0 JNE SHORT FINDDE05 ; NOT A SPARE ENTRY CMP EBX,0 JNE SHORT FINDDE10 ; ALREADY FOUND A SPARE MOV EBX,EDI ; POINTER TO FIRST FREE JMP SHORT FINDDE10 ; TRY NEXT ENTRY PUBLIC FINDDE05 FINDDE05: PUSH ESI PUSH EDI PUSH ECX LEA EDI,DEST_CALL[EDI] CALL COMPARECALLS ; CORRECT ENTRY? POP ECX POP EDI POP ESI JE SHORT FINDDE99 ; YES PUBLIC FINDDE10 FINDDE10: ADD EDI,TYPE DEST_LIST LOOP FINDDE00 ; ; ENTRY NOT FOUND - BX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 RET PUBLIC FINDDE99 FINDDE99: MOV EBX,EDI XOR AL,AL RET CONVFROMAX25: ; ; CONVERT AX25 FORMAT CALL IN [ESI] TO NORMAL FORMAT IN _NORMCALL ; RETURNS LENGTH IN CX AND NZ IF LAST ADDRESS BIT IS SET ; PUSH ESI ; SAVE MOV EDI,OFFSET32 _NORMCALL MOV ECX,10 ; MAX ALPHANUMERICS MOV AL,20H REP STOSB ; CLEAR IN CASE SHORT CALL MOV EDI,OFFSET32 _NORMCALL MOV CL,6 PUBLIC CONVAX50 CONVAX50: LODSB CMP AL,40H JE SHORT CONVAX60 ; END IF CALL - DO SSID SHR AL,1 STOSB LOOP CONVAX50 PUBLIC CONVAX60 CONVAX60: POP ESI ADD ESI,6 ; TO SSID LODSB MOV AH,AL ; SAVE FOR LAST BIT TEST SHR AL,1 AND AL,0FH JZ SHORT CONVAX90 ; NO SSID - FINISHED ; MOV BYTE PTR [EDI],'-' INC EDI CMP AL,10 JB SHORT CONVAX70 SUB AL,10 MOV BYTE PTR [EDI],'1' INC EDI PUBLIC CONVAX70 CONVAX70: ADD AL,30H ; CONVERT TO DIGIT STOSB PUBLIC CONVAX90 CONVAX90: MOV ECX,EDI SUB ECX,OFFSET32 _NORMCALL TEST AH,1 ; LAST BIT SET? RET GETPORTTABLEENTRY: PUSH ECX MOV EBX,_PORTTABLE MOV ECX,_NUMBEROFPORTS JCXZ GETNOPORTS PUBLIC GETPORT10 GETPORT10: CMP AL,PORTNUMBER[EBX] JE SHORT GETPORT20 MOV EBX,PORTPOINTER[EBX] LOOP GETPORT10 PUBLIC GETNOPORTS GETNOPORTS: MOV EBX,_PORTTABLE ; TO FIRST IF NOT DEFINED PUBLIC GETPORT20 GETPORT20: POP ECX RET extern _FREE_Q:DWORD EXTRN _MINBUFFCOUNT:WORD,_NOBUFFCOUNT:WORD Q_REM: ; CALL CHECKBUFFERS MOV EDI,[ESI] ; GET ADDR OF FIRST BUFFER CMP EDI,0 JE SHORT Q_RET ; EMPTY ; CALL CHECKBUFFER_EDI ; MAKE SURE OK MOV EAX,[EDI] ; CHAIN FROM BUFFER MOV [ESI],EAX ; STORE IN HEADER ; POP [EDI] ; CALLERS ADDR ; PUSH [EDI] PUBLIC Q_RET Q_RET: RET GETBUFF: MOV ESI,OFFSET32 _FREE_Q CALL Q_REM JZ SHORT NOBUFFS DEC _QCOUNT MOV AX,_QCOUNT CMP AX,_MINBUFFCOUNT JA SHORT GETBUFFRET MOV _MINBUFFCOUNT,AX PUBLIC GETBUFFRET GETBUFFRET: OR AL,1 ; SET NZ ; ; FLAG BUFFER WITH ADDR OF CALLING ROUTINE (TRYING TO TRACK DOWN LOST BUFFERS!) ; ; POP [EDI] ; PUSH [EDI] RET PUBLIC NOBUFFS NOBUFFS: INC _NOBUFFCOUNT XOR AL,AL RET ; RELBUFF: MOV ESI,OFFSET32 _FREE_Q CALL _Q_ADDF ; RETURN BUFFER TO FREE QUEUE RET _Q_ADDF: INC _QCOUNT MOV EAX,[ESI] ; OLD FIRST IN CHAIN MOV [EDI],EAX MOV [ESI],EDI ; PUT NEW ON FRONT ; RET PUBLIC _Q_ADD _Q_ADD: _Q_ADD05: CMP DWORD PTR [ESI],0 ; END OF CHAIN JE SHORT _Q_ADD10 MOV ESI,[ESI] ; NEXT IN CHAIN JMP _Q_ADD05 _Q_ADD10: MOV DWORD PTR [EDI],0 ; CLEAR CHAIN ON NEW BUFFER MOV [ESI],EDI ; CHAIN ON NEW BUFFER RET ; _TEXT ENDS END