{$DOUBLE}
Program NEWLNK;
 {$nomain}

{ 
  Description: Module for AMI Message Router to process net Link Request 
         File: [AMIRTR]NEWLNK.PAS
       Author: Jim Bostwick 
    Last Edit: 20-DEC-1989 23:51:02 
      History:
         10-OCT-1989 - JMB - major happy munging...
         3-AUG-1989 - JMB - Add $DOUBLE compiler switch


}
 {$Nolist}
 {[a+,b+,l-,k+,r+] Pasmat }
 %INCLUDE 'AMIRTR.PKG';
 %INCLUDE 'Signal.ext';
 {$List }
 {*CALL*}


  PROCEDURE NEWLNK;
    EXTERNAL;

{*USER*

This procedure processes net link requests. Called from DoMail, it determines
if a slot is available, and either accepts (and initializes) the link for
that slot, or rejects the link if none is available. 

A future version will employ least-recently-used techniques to always 
accept a (non-duplicating) link by dropping a 'stale' link when necessary. 
This version simply rejects the request. 

Note that one link per remote node/router pair is required for all message 
traffic. This procedure will reject a link request for which an active link
exists. 
 }

{*WIZARD*

The link request lives in the mailbox structures - Links[0]. 
 }



  PROCEDURE NEWLNK;

    LABEL
      999; { error exit shortcut }

    VAR
      Lnk: Integer; { slot number }
      Slot: Integer; { number of open slot (which we'll use for new link)}
      new_node: CH6; { the node asking for service }
      new_task: CH16; { task asking for service }
      NetDat: CH16; { net mbx data }
      found: Boolean; { a flag }
      IOSB: Io_Status_Block; { For internal net IO }


    Function Find_empty_link:Integer;
    { Return first inactive link number, or zero if none available }
    
    VAR
    	L: Integer;
    
    BEGIN 
      L := 1;
      WHILE (Link[L].Active) AND (L <= Max_links)
              DO L := L + 1;
      If L > Max_links THEN L := 0;
      Find_empty_link := L
    END;  

    
    
    BEGIN
      { Check for duplicate link and open slot }
      New_Node := Conb.Src_Desc.Src_Node;
      New_Task := Conb.Src_desc.Src_task;
      { Check for active link. }
      Found := false;
      For Lnk := 1 to Max_links DO
	if Link[Lnk].Active 
	  THEN found := ( SEqual(Link[Lnk].node, New_Node) AND
		SEqual(link[Lnk].Task, Conb.Src_desc.Src_task));
      IF found THEN
        BEGIN { Reject the link as a duplicate }
        SAssign(NetDat, 'DUPLNK - Duplicate Link');
        Signal(Sig_DUPLNK, 0, Null_IOSB, 'NEWLNK - link already exists. ');
        NTREJ(Mbx_Lun, Aux_Efn, NetDat, Conb, IOSB);
        IF (IOSB.int[1] < 1) THEN Signal(Sig_NtRejF, 0, IOSB, 'NEWLNK');
        GOTO 999 { exit procedure }
        END;

      { Find an open slot }
      Slot := Find_Empty_link;
      IF (Slot = 0) THEN
        BEGIN { nope - reject with no-slots error }
        SAssign(NetDat, 'NOSLOT - No Slots Open');
        NTREJ(Mbx_Lun, Aux_Efn, NetDat, Conb, IOSB);
        Signal(Sig_NOSLOT, 0, IOSB, 'NEWLNK ');
        NTREJ(Mbx_Lun, Aux_Efn, NetDat, Conb, IOSB);
        IF (IOSB.int[1] < 1) THEN Signal(Sig_NtRejF, 0, IOSB, 'NEWLNK');
        GOTO 999 { exit procedure }
        END;

      { Accept the link request }
      Lnk := Slot;
      SClear(NetDat);
      NTACC(Link[Lnk].Lun, Aux_Efn, Conb, NetDat, IOSB);
      IF (IOSB.int[1] = 1) AND ($DSW = 1) THEN
        BEGIN
        Signal(Sig_NTAcc, Link[Lnk].Lun, IOSB, 'NEWLNK');
        { Post first (nowait) net read }
        NTREC(Link[Lnk].Lun, Net_EFN, Loophole(address, ref(Link[Lnk].Msg)),
              size(Message_rec), Link[Lnk].Read_IOSB);
        IF ($DSW <> 1) THEN Signal(Sig_NTRECF, Link[Lnk].Lun, IOSB, 'NEWLNK')
        ELSE
          WITH Link[Lnk] DO
            BEGIN
            Active := TRUE;
            node := new_node;
      	    Task := New_task; 
            WITH Stats DO
		BEGIN 
		Connects := Connects + 1;
		Reads := 0;
		Writes := 0
		END { with stats }
            END { with link }
        END
      ELSE Signal(Sig_NTAccF, Link[Lnk].Lun, IOSB, 'NEWLNK');

    999: ;
    END; { newlnk }
