;ProfiPacket - packet radio terminal program
;Copyright (C) 1999  Alexander Feigl
;
;This program is free software; you can redistribute it and/or modify
;it under the terms of the GNU General Public License as published by
;the Free Software Foundation; either version 2 of the License, or
;(at your option) any later version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
;
;Author:
;
;Alexander Feigl
;Burachstraße 51
;
;D-88250 Weingarten
;
;EMail : Alexander.Feigl@gmx.de

                CPU M68000
                SNMAOPT Q+,P+,A+,B-,S+,M+,E+
                nolist
                
AJUMP                   MACRO
                        dc.w $4ef9
                        dc.l \1
                        ENDM

                        incdir "sys:include/"
                        include "exec/exec_lib.i"
                        include "/global.i"
                        include "utility/utility_lib.i"

                                
_Nil                    moveq #0,d0
                        rts
                        dc.b "ProfServ"
                
                
CONN_Head               dc.l CONN_Name
                        dc.l 1
                        dc.l CONN_Init
                        dc.l 0
                        dc.l 8                ;Subtype (3=Miscellaneous)
                        
CONN_Name               dc.b "Connection",0
                        even
CONN_Init               movem.l a6/a2-a4/d2-d7,-(sp)
                        move.l a0,a4
                        move.l a1,d7
                        move.l d0,d6
                        move.l a3,a6
                        move.l #CONN_Functions-CONN_FunctionsBegin,d0
                        move.l #conn_Size,d1
                        lea CONN_Functions,a0
                        move.l ppb_Global(a6),a5
                        jsr _QVOCreateServerBase(A6)
                        tst.l d0
                        beq .Cannot_Serve
                        move.l d0,a6
                        move.l a3,a5
                        move.l a3,conn_QSOBase(a6)
                        move.l d7,conn_OldServer(A6)
                        move.l d6,conn_Channel(a6)
                        move.l a2,conn_Parameter(a6)
                        move.l a4,conn_ThisQSO(a6)
                        move.l a6,qso_Server(a4)
                        
                        clr.l conn_InLine(a6)
                        clr.l conn_DoHearme(a6)

                        move.l a2,a0
                        GOQSO ParseComLine
                        cmp.l #2,d0
                        blt .Invalid_Parameters
                        cmp.l #65,d0
                        bgt .Invalid_Parameters

                        move.l a2,a0
                        bsr CONN_ParseCommand
                        tst.l d0
                        bne .Invalid_Parameters

                        clr.l conn_ConnectionStep(a6)
                        move.l #-1,conn_ThisType(a6)
                        clr.l conn_ThisPort(a6)
                        clr.b conn_ThisCall(a6)

                        bsr CONN_NextStep
                        tst.l d0
                        bne .Server_Success
                        bsr CONN_LinkEstablished
                        bra .Exit


.Server_Success         bsr CONN_ReceivePacket
.Exit                   movem.l (sp)+,a6/a2-a4/d2-d7
                        moveq #0,d0
                        rts


.Cannot_Serve           movem.l (sp)+,a6/a2-a4/d2-d7
                        moveq #-1,d0
                        rts

.Invalid_Parameters     bsr CONN_Cleanup
                        movem.l (Sp)+,a6/a2-a4/d2-d7
                        moveq #-1,d0
                        rts
                        

CONN_LinkEstablished    lea conn_WishServer(a6),a0
                        GOQSO SearchSpecialServer
                        tst.l d0
                        beq .Error
                        move.l conn_OldServer(a6),d1
                        move.l conn_ThisQSO(a6),a0
                        move.l d1,qso_Server(a0)
                        move.l d0,a0
                        move.l conn_Channel(a6),d0
                        sub.l a1,a1
                        GOQSO StartServer
                        tst.l d0
                        beq .Good_Cleanme
                        move.l conn_ThisQSO(a6),a0
                        move.l a6,qso_Server(a0)
.Error                  rts
.Good_Cleanme           move.l a6,-(sp)
                        move.l conn_ThisQSO(a6),a0
                        move.l qso_Server(a0),d0
                        move.l d0,-(sp)
                        move.l conn_ThisQSO(a6),a0
                        GOQSO TestServBuffer
                        move.l (Sp)+,a6
                        cmpa.l #0,a6
                        beq .No_Service
                        jsr _SVOReceivePacket(A6)
.No_Service             move.l (sp)+,a6
                        move.l a6,a1
                        sub.l #CONN_Functions-CONN_FunctionsBegin,a1
                        move.l a6,-(Sp)
                        move.l ppb_ExecBase(a5),a6
                        jsr _LVOFreeVec(a6)
                        move.l (sp)+,a6
                        rts

CONN_Cleanup            move.l conn_OldServer(a6),d0
                        move.l conn_ThisQSO(a6),a0
                        move.l d0,qso_Server(a0)
                        move.l a6,a1
                        move.l ppb_ExecBase(a5),a6
                        sub.l #CONN_Functions-CONN_FunctionsBegin,a1
                        jsr _LVOFreeVec(A6)
                        moveq #0,d0
                        rts

CONN_ConnectProced      rts

CONN_ReceivePacket      movem.l d2-d7/a2-a6,-(sp)
.Loop                   tst.l conn_DoHearme(a6)
                        beq .Exit
                        move.l conn_ThisQSO(a6),a0
                        GOQSO TestServBufferLin
                        tst.l d0
                        beq .Exit
                        move.l d0,d1
                        add.l conn_InLine(a6),d1
                        cmp.l #1024,d1
                        ble .Good_Line
                        move.l #1024,d0
                        sub.l conn_InLine(a6),d0
                        tst.l d0
                        bne .Good_Line
                        clr.l conn_InLine(a6)
                        bra .Loop
.Good_Line              lea conn_ServerLine(a6),a0
                        add.l conn_InLine(a6),a0
                        move.l conn_ThisQSO(A6),a1
                        GOQSO ReadServBuffer
                        add.l d0,conn_InLine(a6)
                        move.l conn_InLine(a6),d0
                        tst.l d0
                        beq .Exit
                        move.l conn_InLine(a6),d0
                        lea conn_ServerLine(a6),a0
                        subq.l #1,d0
                        add.l d0,a0
                        cmp.b #$0d,(a0)
                        bne .Exit
                        move.l a0,-(sp)
                        sub.l a1,a1
                        lea conn_ServerLine(a6),a0
                        cmp.b #"[",(a0)
                        bne .No_Surpress
.Loop_Surpress          cmp.b #"]",(a0)
                        beq .Surpress_EndBracket
                        cmp.b #" ",(a0)
                        beq .No_Surpress
                        cmp.b #"-",(a0)+
                        bne .Loop_Surpress
                        move.l a0,a1
                        bra .Loop_Surpress
.Surpress_EndBracket    cmp.b #$d,1(a0)
                        bne .No_Surpress
                        cmpa.l #0,a1
                        beq .No_Surpress
                        clr.b 1(a0)
                        lea conn_ServerLine(a6),a0
                        lea conn_ReceivedSID(a6),a1
                        GOQSO ParseSID
                        tst.l d0
                        beq .No_GoodSID

                        move.l conn_ThisQSO(a6),a0
                        lea conn_ReceivedSID(a6),a1
                        GOQSO HandleSID
                        move.l (sp)+,a0
                        clr.l conn_InLine(a6)
                        bra .Loop
.No_GoodSID
.No_Surpress            move.l conn_InLine(a6),d0
                        move.l conn_Channel(a6),d1
                        lea conn_ServerLine(a6),a0
                        move.l d2,-(Sp)
                        moveq #2,d2
                        GOQSO WriteTerminalUni
                        move.l (sp)+,d2
                        move.l (sp)+,a0
                        clr.b (a0)
                        clr.l conn_InLine(a6)
                        lea conn_ServerLine(a6),a0
                        move.l conn_Channel(a6),d0
                        GOQSO TestForwardConnect
                        tst.l d0
                        beq .Loop

                        bsr CONN_CheckEstablish
                        bra .Exit



                        bra .Loop
.Exit                   movem.l (Sp)+,d2-d7/a2-a6
                        rts



CONN_TerminalInput      rts


CONN_WriteTerminal      move.l conn_Channel(a6),d1
                        moveq #2,d2
                        GOQSO WriteTerminalUni
                        rts

CONN_AbortServer        move.l a6,-(sp)
                        move.l conn_ThisQSO(a6),a0
                        GOQSO TestServBuffer
                        move.l d0,-(sp)
                        move.l conn_OldServer(a6),-(sp)
                        bsr CONN_Cleanup
                        move.l (sp)+,a6
                        move.l (Sp)+,d0
                        cmpa.l #0,a6
                        beq .Exit
                        jsr _SVOReceivePacket(A6)
.Exit                   move.l (sp)+,a6
                        rts

CONN_GetServerType      moveq #0,d0
                        rts




CONN_Nop                rts

CONN_DoPoll             bsr CONN_CheckEstablish
                        rts


CONN_CheckEstablish     lea conn_ThisCall(a6),a0
                        bsr .Go_AfterCol
                        move.l a0,a1
                        move.l conn_ThisQSO(A6),a0
                        lea qso_Call(a0),a0
.Compare                move.b (a0)+,d0
                        cmp.b (a1)+,d0
                        bne .Not_Equal
                        tst.b d0
                        bne .Compare
                        bsr CONN_NextStep
                        tst.l d0
                        bne .Is_InBuild
                        bsr CONN_LinkEstablished
.Is_InBuild
.Not_Equal              rts

.Go_AfterCol            move.l a0,-(sp)
.Go_AfterColL           tst.b (a0)
                        beq .No_Col
                        cmp.b #":",(a0)+
                        bne .Go_AfterColL
                        move.l (sp)+,d0
                        rts
.No_Col                 move.l (sp)+,a0
                        rts

;>A0 Param
;>D0 NumParam
CONN_ParseCommand
                        subq.l #1,d0
                        lea conn_WishServer(a6),a1
.Copy_Wish              move.b (a0)+,(a1)+
                        tst.b -1(a0)
                        bne .Copy_Wish
                        movem.l d2-d7/a2-a6,-(sp)
                        move.l a0,a4
                        moveq #0,d7
                        move.l d0,d6
.Main_Loop              cmp.l #1,d6
                        beq .Is_Final

                        moveq #0,d4
                        tst.b (a4)
                        beq .Invalid_Param
                        tst.b 1(a4)
                        beq .Is_Digi
                        cmp.b #"_",1(a4)
                        beq .Is_Complex
                        tst.b 2(a4)
                        beq .Is_Digi
                        cmp.b #"_",2(A4)
                        bne .Is_Digi
                        move.b 1(A4),d0
                        cmp.b #$31,d0
                        blt .Invalid_Param
                        cmp.b #$39,d0
                        bgt .Invalid_Param
                        and.l #$f,d0
                        move.l d0,d4
.Is_Complex             move.b (a4),d0
                        cmp.b #"P",d0
                        beq .Is_PPTerm
                        cmp.b #"T",d0
                        beq .Is_TopTerm
                        cmp.b #"N",d0
                        beq .Is_Node
                        bra .Invalid_Param
.Is_PPTerm              moveq #3,d5
                        bra .Skip_Complex
.Is_TopTerm             moveq #2,d5
                        bra .Skip_Complex
.Is_Node                moveq #4,d5
                        bra .Skip_Complex
.Skip_Complex           move.b (a4)+,d0
                        cmp.b #"_",d0
                        bne .Skip_Complex
                        bra .Copy_ThisParam
.Is_Digi                moveq #1,d5
                        moveq #0,d4
                        bra .Copy_ThisParam
.Is_Final               moveq #0,d5     ;Type
                        moveq #0,d4     ;Station
.Copy_ThisParam         lea conn_StationType(a6),a0
                        move.l d7,d0
                        asl.l #2,d0
                        add.l d0,a0
                        move.l d5,(a0)
                        lea conn_StationPort(a6),a0
                        add.l d0,a0
                        move.l d4,(a0)
                        lea conn_StationCall(a6),a0
                        move.l d7,d0
                        asl.l #4,d0
                        add.l d0,a0
                        moveq #15,d0
.Copy_ThisCall          move.b (a4)+,(a0)+
                        tst.b -1(a0)
                        beq .Copy_ThisCallE
                        dbf d0,.Copy_ThisCall
                        bra .Invalid_Param
.Copy_ThisCallE         addq.l #1,d7
                        subq.l #1,d6
                        tst.l d6
                        bgt .Main_Loop
                        lea conn_StationType(a6),a3
                        lea conn_StationCall(a6),a4
.Verify_Calls           move.l a4,a0
                        cmp.b #"-",(a0)
                        beq .Invalid_Param
.Verify_Calls_L         move.b (a0),d0
                        cmp.b #"-",d0
                        beq .Verify_Calls_SSID
                        tst.b (a0)
                        beq .Next_Call
                        cmp.b #"0",d0
                        blt .Invalid_Param
                        cmp.b #"9",d0
                        ble .Is_Valid_Char
                        cmp.b #":",d0
                        beq .Is_Valid_Char
                        cmp.b #"A",d0
                        blt .Invalid_Param
                        cmp.b #"Z",d0
                        ble .Is_Valid_Char
                        cmp.b #"a",d0
                        blt .Invalid_Param
                        cmp.b #"z",d0
                        bgt .Invalid_Param
                        sub.b #$20,d0
.Is_Valid_Char          move.b d0,(a0)+
                        bra .Verify_Calls_L
.Verify_Calls_SSID      addq.l #1,a0
                        move.b (a0)+,d0
                        cmp.b #$30,d0
                        blt .Invalid_Param
                        cmp.b #$39,d0
                        bgt .Invalid_Param
                        move.b (a0)+,d1
                        tst.b d1
                        beq .Next_Call
                        and.l #$f,d0
                        cmp.b #$30,d1
                        blt .Invalid_Param
                        cmp.b #$39,d1
                        bgt .Invalid_Param
                        and.l #$f,d1
                        mulu #10,d0
                        add.l d1,d0
                        cmp.l #15,d0
                        bgt .Invalid_Param
                        bra .Next_Call
.Next_Call              tst.l (a3)
                        beq .Good_Calls
                        addq.l #4,a3
                        add.l #16,a4
                        bra .Verify_Calls
.Good_Calls             moveq #0,d0
.Exit                   movem.l (sp)+,d2-d7/a2-a6
                        rts
.Invalid_Param          moveq #-1,d0
                        bra .Exit
                        
CONN_AskAudio           move.l a6,-(sp)
                        move.l conn_OldServer(a6),a6
                        cmpa.l #0,a6
                        beq .NoServer
                        jsr _SVOAskAudio(a6)
                        move.l (sp)+,a6
                        rts
.NoServer               moveq #-1,d0
                        move.l (sp)+,a6
                        rts



CONN_NextStep           movem.l d2-d7/a2-a6,-(sp)
                        move.l conn_ThisType(a6),d0
                        tst.l d0
                        beq .Is_RightStation
                        lea conn_OutputLine(a6),a4
                        move.l conn_ConnectionStep(a6),d7
                        move.l d7,d6

.Search_NoDigi          move.l d6,d0
                        asl.l #2,d0
                        lea conn_StationType(a6),a0
                        add.l d0,a0
                        cmp.l #1,(a0)
                        bne .NoDigi_Found
                        addq.l #1,d6
                        bra .Search_NoDigi
.NoDigi_Found

                        move.l conn_ThisType(a6),d0
                        cmp.l #-1,d0
                        beq .Root_Class_Pref
                        cmp.l #2,d0
                        beq .TOPXP_Pfx
                        cmp.l #3,d0
                        beq .PPT_Pfx
                        cmp.l #4,d0
                        beq .Node_Pfx
.PPT_Pfx                move.b #"/",(a4)+
                        move.b #"/",(a4)+
                        move.b #"C",(a4)+
                        move.b #" ",(a4)+
                        tst.l conn_ThisPort(a6)
                        beq .Prefixed
                        move.l conn_ThisPort(a6),d0
                        or.l #$30,d0
                        move.b d0,(a4)+
                        move.b #"_",(a4)+
                        bra .Prefixed
.TOPXP_Pfx              move.b #"/",(A4)+
                        move.b #"/",(a4)+
                        move.b #"C",(a4)+
                        move.b #" ",(a4)+
                        bra .Prefixed
.Node_Pfx               move.b #"C",(a4)+
                        move.b #" ",(A4)+
                        tst.l conn_ThisPort(a6)
                        beq .Prefixed
                        move.l conn_ThisPort(a6),d0
                        or.l #$30,d0
                        move.b d0,(a4)+
                        move.b #" ",(a4)+
                        bra .Prefixed
.Root_Class_Pref        move.b #"C",(a4)+
                        move.b #" ",(a4)+

.Prefixed               move.l d6,d0
                        asl.l #4,d0
                        lea conn_StationCall(a6),a0
                        add.l d0,a0
.Copy_Call              tst.b (a0)
                        beq .Copy_Call_End
                        move.b (a0)+,(a4)+
                        bra .Copy_Call
.Copy_Call_End
.Make_Digis             cmp.l d6,d7
                        beq .No_More_Digis
                        move.b #" ",(A4)+
                        move.l d7,d0
                        asl.l #4,d0
                        lea conn_StationCall(A6),a0
                        add.l d0,a0
                        addq.l #1,d7
.Copy_Digi              tst.b (a0)
                        beq .Make_Digis
                        move.b (a0)+,(a4)+
                        bra .Copy_Digi
.No_More_Digis          lea conn_StationType(a6),a0
                        move.l conn_ThisType(a6),d0
                        cmp.l #-1,d0
                        beq .Do_RootConnect
                        cmp.l #2,d0
                        beq .Do_TopConnect
                        cmp.l #3,d0
                        beq .Do_PPConnect
                        cmp.l #4,d0
                        beq .Do_NodeConnect
.Do_PPConnect           move.b #$0d,(a4)+
.Do_OutputLine          lea conn_OutputLine(a6),a0
                        sub.l a0,a4
                        move.l a4,d0
                        move.l conn_Channel(a6),d1
                        GOQSO TransmitData
                        move.l conn_Channel(a6),d0
                        GOQSO ForceTransmit
                        move.l #1,conn_DoHearme(a6)
                        bra .Is_Good
.Do_TopConnect          tst.l conn_ThisPort(a6)
                        beq .Do_TopConnectNoPort
                        move.l conn_ThisPort(a6),d0
                        or.l #$30,d0
                        move.b #" ",(a4)+
                        move.b d0,(a4)+
.Do_TopConnectNoPort    move.b #$0d,(a4)+
                        bra .Do_OutputLine
.Do_NodeConnect         move.b #$0d,(a4)+
                        bra .Do_OutputLine
.Do_RootConnect         lea conn_OutputLine(a6),a0
                        sub.l a0,a4
                        move.l a4,d0
                        move.l conn_Channel(a6),d1
                        GOQSO TransmitCommand
                        bra .Is_Good
.Is_Good                move.l d6,d1
                        asl.l #2,d1
                        lea conn_StationType(a6),a0
                        add.l d1,a0
                        move.l (a0),d0
                        move.l d0,conn_ThisType(a6)
                        lea conn_StationPort(a6),a0
                        add.l d1,a0
                        move.l (a0),d0
                        move.l d0,conn_ThisPort(a6)
                        lea conn_StationCall(a6),a0
                        move.l d6,d0
                        asl.l #4,d0
                        add.l d0,a0
                        lea conn_ThisCall(a6),a1
                        move.l (a0),(a1)
                        move.l 4(a0),4(a1)
                        move.l 8(a0),8(a1)
                        move.l 12(a0),12(a1)
                        addq.l #1,d6
                        move.l d6,conn_ConnectionStep(a6)
                        moveq #1,d0
                        bra .Exit
.Exit                   movem.l (sp)+,d2-d7/a2-a6
                        rts

.Is_RightStation        moveq #0,d0
                        bra .Exit

CONN_FunctionsBegin

                        AJUMP CONN_AskAudio
                        AJUMP CONN_AbortServer              ;-48
                        AJUMP CONN_GetServerType                ;-42
                        AJUMP CONN_TerminalInput                ;-36
                        AJUMP CONN_ReceivePacket                ;-30
                        AJUMP CONN_DoPoll                  ;-24
                        AJUMP CONN_ConnectProced                ;-18
                        AJUMP CONN_Cleanup              ;-12
                        AJUMP CONN_Init                 ;-6
CONN_Functions
                        
                        even
                        
                        
                        rsreset
conn_ThisQSO            rs.l 1
conn_Channel            rs.l 1
conn_OldServer          rs.l 1
conn_QSOBase            rs.l 1
conn_Parameter          rs.l 1
conn_InLine             rs.l 1
conn_DoHearme           rs.l 1
conn_ServerLine         rs.b 1024
conn_OutputLine         rs.b 1024
conn_ReceivedSID        rs.b sid_Size
conn_ThisType           rs.l 1
conn_ThisPort           rs.l 1
conn_ThisCall           rs.b 16
conn_ConnectionStep     rs.l 1
conn_StationType        rs.l 64         ;-1=RootClass 0=Final 1=Digi 2=TOP/XP 3=PP 4=Node
conn_StationPort        rs.l 64
conn_StationCall        rs.b 64*16
conn_WishServer         rs.b 256
conn_Size               rs.b 0
