{$B-,V-,X+} UNIT nwSPX; { nwSPX unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk } { NOTE: These SPX calls are not documented in this version } INTERFACE Uses Dos,nwMisc,nwIPX; { Primary SPX calls: Subf: Comments: SPXabortConnection 14 SPXGetConnectionStatus 15 SPXestablishConnection 11 * SPXinitialize 10 SPXlistenForConnection 12 SPXlistenForSequencedPacket 17 SPXsendSequencedPacket 16 SPXTerminateConnection 13 Secondary calls: * SPXpresent Notes: (1) These functions use INT 21 and are not to be called from within an ESR. } Var Result:word; { unit errorcode variable } Type TspxHeader=Record IPXhdr :TipxHeader; { SPX will set packetType to 5 } connControl :byte; { rarely used, set to $00 } { ignored by SPX, but passed on to receiver: $10 End of message; $20 Attention packet } dataStreamType:Byte; { to be used by higher level protocols. nust be < $FE, passed on to receiver } sourceConnId, destConnId :Word; sequenceNbr, acknowledgeNbr, allocationNbr :Word; end; { Fields within IPX and SPX are high-low. Byte swapping will be done by the IPX functions, except network and node addresses. } Type TSPXconnectionInformation =record ConnectionState :Byte; { all fields are returned hi-lo } WatchDogState :Byte; LocalSPXConnectionId :Word; RemoteSPXConnectionId :Word; SequenceNumber :Word; LocalAcknowledgeNumber :Word; LocalAllocationNumber :Word; RemoteAcknowledgeNumber:Word; RemoteAllocationNumber :Word; LocalSocket :Word; ImmediateAddress :TnodeAddress; RemoteAddress :TinterNetworkAddress; RetransmissionCount :Word; EstimatedRoundTripDelay:Word; RetransmittedPackets :Word; SuppressedPackets :Word; end; Function SPXpresent:boolean; { Determines if SPX is installed. Calls SPXInitialize. } {IPX/SPX: 10h} Function SpxInitialize(Var SPXhiVer,SPXloVer:Byte; Var MaxConn,AvailConn:word):boolean; { Determines if SPX is loaded. (this function also tests the presence of IPX, } { as IPX is required for running SPX. Remember: Netware 2.2 allows IPX and SPX } { to be loaded seperately, so only IPX may be present. } {IPX/SPX: 11h} Function SPXestablishConnection(retryCount:byte; WatchdogFlag:Byte; {i/o} Var ECB:Tecb; {out} Var SPXconnectionID:Word):boolean; {IPX/SPX: 12h} Function SPXlistenForConnection(retryCount:Byte; WatchdogFlag: Byte; Var ECB:Tecb ):boolean; {IPX/SPX: 15h} Function SPXGetConnectionStatus(SPXconnectionID:word; Var connInfo:TSPXconnectionInformation):boolean; {IPX/SPX: 13h} Function SPXTerminateConnection(SPXconnectionID:Word; ECB:Tecb):boolean; {IPX/SPX: 14h} Function SPXabortConnection(SPXconnectionID:Word):boolean; {IPX/SPX: 16h} Function SPXsendSequencedPacket(SPXconnectionID:Word; Var ECB:Tecb):boolean; {IPX/SPX: 17h} Function SPXlistenForSequencedPacket(Var ECB:Tecb):boolean; {************** Secondary Procedures ***************************************} IMPLEMENTATION {==============================================================} CONST SPX_WATCHDOG_ENABLED =1; SPX_WATCHDOG_DISABLED =0; SPX_DEFAULT_RETRY_COUNT =0; SPX_POOL_SIZE =10; SPX_MAX_DATA_LENGTH =534; {IPX/SPX: 10 } Function SpxInitialize(Var SPXhiVer,SPXloVer:Byte; Var MaxConn,AvailConn:word):boolean; Var Regs:registers; begin With regs do begin al:=$00; bx:=$0010; IpxSpxSystemCall(Regs); result:=regs.al; if AL<>$FF then begin result:=$FF; SpxInitialize:=false end else begin SPXhiVer:=BH; SPXloVer:=BL; MaxConn:=CX; AvailConn:=DX; result:=$00; SpxInitialize:=true; end; end; {with} { resultcodes: $00 successfull (SPX installed); $FF SPX not installed } end; Function SpxPresent:boolean; Var SpxHi,SpxLo:Byte; MaxConn,AvConn:word; begin SpxPresent:=( IpxPresent and SpxInitialize(SpxHi,SpxLo,MaxConn,AvConn) ); end; {IPX/SPX: 11h} Function SPXestablishConnection(retryCount:byte; WatchdogFlag:Byte; {i/o} Var ECB:Tecb; {out} Var SPXconnectionID:Word):boolean; Var regs:registers; begin With regs do begin BX:=$0011; AL:=retryCount; AH:=WatchDogFlag; ES:=Seg(ECB); SI:=ofs(ECB); end; IpxSpxSystemCall(Regs); result:=regs.AL; SPXconnectionID:=regs.DX; SPXestablishConnection:=(result=$00); { resultcodes: $00 SPX Attempting to contact destination socket; $EF Local connection table full; $FD Fragment count not 1 AND/OR Buffer size not 42; $FF Send Socket not open OR IPX/SPX not initialized. } end; {IPX/SPX: 12h} Function SPXlistenForConnection(retryCount:Byte; WatchdogFlag: Byte; Var ECB:Tecb ):boolean; Var regs:Registers; begin With regs do begin BX:=$0012; AL:=retryCount; AH:=WatchdogFlag; ES:=Seg(ECB); SI:=Ofs(ECB); IpxSpxSystemCall(Regs); result:=AL; if result<>$FF then result:=$00; end; SPXlistenForConnection:=(result=$00); end; {IPX/SPX: 15h} Function SPXGetConnectionStatus(SPXconnectionID:word; Var connInfo:TSPXconnectionInformation):boolean; Var regs:Registers; begin With regs do begin BX:=$0015; DX:=SPXconnectionID; ES:=Seg(connInfo); SI:=Ofs(connInfo); IpxSpxSystemCall(Regs); Result:=AL; end; if result=0 then begin With ConnInfo do begin { force all returned words lo-hi } LocalSPXConnectionId :=Swap(LocalSPXconnectionID); RemoteSPXConnectionId :=Swap(RemoteSPXconnectionID); SequenceNumber :=swap(SequenceNumber); LocalAcknowledgeNumber :=swap(LocalAcknowledgeNumber); LocalAllocationNumber :=swap(LocalAllocationNumber); RemoteAcknowledgeNumber:=swap(RemoteAcknowledgeNumber); RemoteAllocationNumber :=swap(RemoteAllocationNumber); LocalSocket :=swap(LocalSocket); RemoteAddress.socket :=swap(remoteAddress.socket); RetransmissionCount :=swap(RetransmissionCount); EstimatedRoundTripDelay:=swap(EstimatedRoundTripDelay); RetransmittedPackets :=swap(RetransmittedPackets); SuppressedPackets :=swap(SuppressedPackets); end; end; SPXGetConnectionStatus:=(result=0); { Resulcodes: $00 Connection is active; $EE No such connection } end; {IPX/SPX: 13h} Function SPXTerminateConnection(SPXconnectionID:Word; ECB:Tecb):boolean; Var regs:Registers; begin with regs do begin BX:=$0013; DX:=SPXconnectionID; ES:=seg(ECB); SI:=Ofs(ECB); end; IpxSpxSystemCall(Regs); result:=regs.al; if result<>$FF then result:=$00; SPXterminateConnection:=(result=0); {resultcodes: $00 SPX attempting to break connection; $FF IPX/SPX not loaded. } end; {IPX/SPX: 14h} Function SPXabortConnection(SPXconnectionID:Word):boolean; Var regs:Registers; begin with regs do begin BX:=$0014; DX:=SPXconnectionID; end; IpxSpxSystemCall(Regs); result:=regs.al; if result<>$FF then result:=$00; SPXabortConnection:=(result=0); {resultcodes: $00 SPX trying to unilateral break the connection; $FF IPX/SPX not loaded. } end; {IPX/SPX: 16h} Function SPXsendSequencedPacket(SPXconnectionID:Word; Var ECB:Tecb):boolean; Var regs:Registers; begin with regs do begin BX:=$0016; DX:=SPXconnectionID; ES:=Seg(ECB); SI:=Ofs(ECB); end; IpxSpxSystemCall(Regs); result:=regs.al; if result<>$FF then result:=$00; SPXsendSequencedPacket:=(result=0); {resultcodes: $00 SPX will attempt to send packet; $FF IPX/SPX not loaded. } end; {IPX/SPX: 17h} Function SPXlistenForSequencedPacket(Var ECB:Tecb):boolean; Var regs:Registers; begin with regs do begin BX:=$0017; ES:=Seg(ECB); SI:=Ofs(ECB); end; IpxSpxSystemCall(Regs); result:=regs.al; if result<>$FF then result:=$00; SPXlistenForSequencedPacket:=(result=0); {resultcodes: $00 SPX waits for incoming packets; $FF IPX/SPX not loaded. } end; {************** Secondary Procedures ***************************************} end.