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 PUBLIC BTLENGTH,BTEXTFLD BTHDDR DD 0 ; CHAIN DB 0 ; PORT BTLENGTH DW 9 ; LENGTH DB 0F0H ; PID BTEXTFLD DB 0DH,256 DUP (0) D10 DB 10 D16 DB 16 NEWVALUE DB 0 SWITCHSP DB 'SWITCH ' DISCFLAG DB 0 ; HOST MODE DISCONNECT PARAM (FOR STAY CHECK) BADRAWMSG DB 'BPQ32 Corrupt Raw Message len=' BADRAWCOUNT DB 'xxxx',0 _ENDOFDATA DD 0 ; For DUMP ROUTINE PUBLIC SWITCHSP,_ENDOFDATA EVEN EXTRN PORTTABLE:DWORD,NUMBEROFPORTS:WORD IF BLACKBITS EXTRN BLACKLIST:BYTE ENDIF EXTRN APPLCALLTABLE:BYTE,IDMSG:DWORD,NORMCALL:BYTE EXTRN QCOUNT:WORD,IDMSG_Q:DWORD EXTRN COMPAREFIELD:BYTE,COMPAREPORT:BYTE 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 PUBLIC DISCFLAG _BPQDATA ENDS _TEXT SEGMENT ; PUBLIC TNCTIMERPROC EXTRN PUT_ON_PORT_Q:NEAR,SENDNODESMSG:NEAR,_FINDDESTINATION:NEAR PUBLIC COUNT_QUEUED_FRAMES,SENDIDMSG,SENDBTMSG,COUNT_Q PUBLIC COUNT_AT_L2,_RAWTX,_SENDNETFRAME EXTRN CLOSESESSIONPARTNER:NEAR,CONVFROMAX25:NEAR EXTRN GETBUFF:NEAR,RELBUFF:NEAR,_Q_ADD:NEAR,Q_REM:NEAR EXTRN SETUPBPQCONSOLESESSION:NEAR EXTRN FINDLINKXX:NEAR,GETPORTWINDOW:NEAR,SENDSABM:NEAR EXTRN RETURNEDTONODE:NEAR,GETPORTTABLEENTRY:NEAR EXTRN _POSTDATAAVAIL:NEAR extrn _Sleep@4:near CR EQU 0DH LF EQU 0AH PUBLIC TNCTIMERPROC TNCTIMERPROC: ; ; CALLED AT 10 HZ ; MOV ECX,BPQHOSTSTREAMS MOV EBX,OFFSET32 BPQHOSTVECTOR ; ; VECTOR FORMAT IS: ; ; 0-3 4 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 4 BYTES - RAW FRAME QUEUE ; TNCTIMERLOOP: ; Action any DISC Requests (must be done in timer owning process) TEST HOSTFLAGS[EBX],40H ; DISC REQUEST JZ short CheckTraceQ TEST HOSTFLAGS[EBX],20H ; STAY? JZ short @F MOV DISCFLAG,'S' @@: AND HOSTFLAGS[EBX],10011111B ; Clear Flags PUSH EBX PUSH ECX MOV EBX,HOSTSESSION[EBX] ; TO SESSION CALL CLOSESESSIONPARTNER POP ECX POP EBX MOV DISCFLAG,0 ; CLEAR STAY FLAG MOV HOSTSESSION[EBX],0 OR HOSTFLAGS[EBX],3 ; STATE CHANGE CALL POSTSTATECHANGE CheckTraceQ: TEST HOSTAPPLFLAGS[EBX],80H JZ SHORT NOTRACE ; NOT ENABLED ; @@: ; CHECK LENGTH OF HOST MODE RAW DATA QUEUES CMP HOSTTRACEQ[EBX],0 JE SHORT NOTRACE ; NONE QUEUED PUSH EBX LEA EBX,HOSTTRACEQ[EBX] ; TO HEADER CALL COUNT_Q POP EBX CMP AL,100 ; MAX LENGTH JB SHORT NOTRACE LEA ESI,HOSTTRACEQ[EBX] CALL Q_REM JZ SHORT NOTRACE ; WOT? CALL RELBUFF JMP @B NOTRACE: ADD EBX,VECTORLENGTH LOOP TNCTIMERLOOP RET PUBLIC SENDIDMSG SENDIDMSG: PUSH EBX MOV EBX,PORTTABLE MOVZX ECX,NUMBEROFPORTS PUBLIC SENDID10 SENDID10: MOV ESI,IDMSG PUSH ECX CMP PROTOCOL[EBX],10 JE @F ; PACTOR STYLE CALL SENDIDMSG00 @@: POP ECX MOV EBX,PORTPOINTER[EBX] LOOP SENDID10 POP EBX RET PUBLIC SENDIDMSG00 SENDIDMSG00: PUSH ESI ; SAVE MESSAGE ADDR CALL GETBUFF POP ESI JZ SHORT SENDIDRET PUSH EDI MOVZX ECX,MSGLENGTH[ESI] REP MOVSB POP EDI MOV AL,PORTNUMBER[EBX] MOV MSGPORT[EDI],AL ; ; IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD ; CMP PORTCALL[EBX],20H JBE SHORT NOPORTCALL PUSH ESI PUSH EDI LEA ESI,PORTCALL[EBX] LEA EDI,14[EDI] ; COPY TO ID MESSAGE MOV ECX,7 REP MOVSB OR BYTE PTR -1[EDI],1 ; SET END OF CALL BIT POP EDI POP ESI PUBLIC NOPORTCALL NOPORTCALL: MOV ESI,OFFSET32 IDMSG_Q ; Q FOR SENDING LATER (AT INTERVALS) CALL _Q_ADD PUBLIC SENDIDRET SENDIDRET: RET PUBLIC SENDBTMSG SENDBTMSG: MOV ESI,OFFSET32 BTHDDR MOV EDX,PORTTABLE ; FIRST HDLC LINK MOVZX ECX,NUMBEROFPORTS PUBLIC SENDBT10 SENDBT10: PUSH ESI ; MESSAGE PUSH ECX CMP PROTOCOL[EDX],10 JE @F ; PACTOR STYLE CALL SENDBTMSG00 @@: POP ECX MOV ESI,EDX MOV EDX,PORTPOINTER[ESI] POP ESI LOOP SENDBT10 RET PUBLIC SENDBTMSG00 SENDBTMSG00: PUSH ESI ; SAVE MESSAGE ; MOV ESI,EDX MOV ESI,PORTUNPROTO[ESI] CMP ESI,0 JE SKIP_UI ; IGNORE PUSH ESI ; SAVE UNPROTO ADDR CALL GETBUFF POP ESI JZ SKIP_UI ; NO BUFFERS MOV EAX,EDI ; BUFFER LEA EDI,MSGDEST[EDI] MOV ECX,7 REP MOVSB OR BYTE PTR -1[EDI],0C0H ; SET COMMAND BITS PUSH ESI ; SAVE POSSIBLE DIGIS ; Send from BBSCALL unless PORTBCALL defined MOV ESI,OFFSET32 APPLCALLTABLE LEA ESI,APPLCALL[ESI] ; IF PORT HAS A BCALL DEFINED, SEND THAT INSTEAD ; CMP PORTBCALL[EDX],20H JBE SHORT NOBCALL LEA ESI,PORTBCALL[EDX] NOBCALL: MOV ECX,7 REP MOVSB POP ESI @@: CMP BYTE PTR [ESI],0 JE SHORT @F ; END OF DIGIS MOV ECX,7 REP MOVSB JMP SHORT @B @@: OR BYTE PTR -1[EDI],1 ; SET LAST CALL MOV BYTE PTR [EDI],3 ; UI INC EDI POP ESI ; MESSAGE MOVZX ECX,MSGLENGTH[ESI] ADD ESI,7 SUB ECX,7 REP MOVSB ; COPY IN MESSAGE MOV ECX,EDI MOV EDI,EAX ; BUFFER SUB ECX,EDI MOV MSGLENGTH[EDI],CX PUSH EBX MOV EBX,EDX ; PORT TABLE ENTRY MOV AL,PORTNUMBER[EBX] MOV MSGPORT[EDI],AL MOV ESI,OFFSET32 IDMSG_Q ; Q FOR SENDING LATER (AT INTERVALS) CALL _Q_ADD POP EBX RET PUBLIC SENDUIMESSAGE SENDUIMESSAGE: MOV EDX,PORTTABLE ; FIRST HDLC LINK MOVZX ECX,NUMBEROFPORTS PUBLIC SENDUI10 SENDUI10: PUSH ESI ; MESSAGE PUSH ECX CALL SENDUIMSG00 POP ECX MOV ESI,EDX MOV EDX,PORTPOINTER[ESI] POP ESI LOOP SENDUI10 RET PUBLIC SENDUIMSG00 SENDUIMSG00: PUSH ESI ; SAVE MESSAGE ; MOV ESI,EDX MOV ESI,PORTUNPROTO[ESI] CMP ESI,0 JE SHORT SKIP_UI ; IGNORE PUSH ESI ; SAVE UNPROTO ADDR CALL GETBUFF POP ESI JZ SHORT SKIP_UI ; NO BUFFERS MOV EAX,EDI ; BUFFER LEA EDI,MSGDEST[EDI] MOV ECX,7 REP MOVSB OR BYTE PTR -1[EDI],0C0H ; SET COMMAND BITS PUSH ESI ; SAVE POSSIBLE DIGIS MOV ESI,OFFSET32 APPLCALLTABLE LEA ESI,APPLCALL[ESI] MOV ECX,7 REP MOVSB POP ESI PUBLIC SENDUILOOP SENDUILOOP: CMP BYTE PTR [ESI],0 JE SHORT SENDUIEND ; END OF DIGIS MOV ECX,7 REP MOVSB JMP SENDUILOOP PUBLIC SENDUIEND SENDUIEND: OR BYTE PTR -1[EDI],1 ; SET LAST CALL MOV BYTE PTR [EDI],3 ; UI INC EDI POP ESI ; MESSAGE MOVZX ECX,MSGLENGTH[ESI] ADD ESI,7 SUB ECX,7 REP MOVSB ; COPY IN MESSAGE MOV ECX,EDI MOV EDI,EAX ; BUFFER SUB ECX,EDI MOV MSGLENGTH[EDI],CX PUSH EBX MOV EBX,EDX ; PORT TABLE ENTRY MOV AL,PORTNUMBER[EBX] MOV MSGPORT[EDI],AL MOV ESI,OFFSET32 IDMSG_Q ; Q FOR SENDING LATER (AT INTERVALS) CALL _Q_ADD POP EBX RET PUBLIC SKIP_UI SKIP_UI: POP ESI 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 PUBLIC COUNT_AT_L2 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 call _GetSemaphore 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 call _FreeSemaphore 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],DL ; PUT IN PORT MOV AL,PORTT1[EBP] MOV L2TIME[EBX],AL ; SET STANDARD TIMER VALUE MOV LINKTYPE[EBX],2 ; DOWNLINK CALL GETPORTWINDOW 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 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 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 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 pop eax JMP SHORT 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: ; ; 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 ; MOV AL,LINKPORT[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: 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 CALL SENDUIMESSAGE POP EDI CALL RELBUFF PUBLIC UNPROTORET UNPROTORET: MOV ECX,0 MOV EDX,0 RET 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 extern _OutputDebugStringA@4:near, BYTE_TO_HEX:NEAR 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: mov edi,offset32 BADRAWCOUNT MOV AL,CH CALL BYTE_TO_HEX MOV AL,CL CALL BYTE_TO_HEX push OFFSET32 BADRAWMSG call _OutputDebugStringA@4 XOR EBX,EBX ; NO MORE RET PUBLIC getxx 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 PUBLIC _RAWTX _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 CALL PUT_ON_PORT_Q 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 ; MOV BTLENGTH,CX 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 _TEXT ENDS END