Important: The information in this document is obsolete and should not be used for new development.
Creating and Using a Connection Listener
A connection listener is a special sort of ADSP connection end that cannot receive or transmit data streams or attention messages. The sole function of a connection listener
is to wait passively to receive an open-connection request and to inform its client, the connection server, when it receives one. The connection server can then accept or deny the open-connection request. If it accepts the request, the connection server selects a socket to use as a connection end, establishes a connection end on that socket, and sends an acknowledgment and connection request back to the requesting connection end. The connection server can use the same socket as it used for the connection listener, or it
can select a different socket as the connection end.Use the following procedure to establish a connection listener and to use that connection listener to open a connection with a remote connection end:
Listing 5-2 illustrates the use of ADSP to establish and use a connection listener. It opens the .MPP and .DSP drivers and allocates memory for the CCB. Then it uses the
- Use the Device Manager's
OpenDriver
function to open the .MPP driver and then use theOpenDriver
function to open the .DSP driver. TheOpenDriver
function returns the reference number for the .DSP driver. You must supply this reference number each time you call the .DSP driver.- Allocate nonrelocatable memory for a connection control block, which is described
in "Connections, Connection Ends, and Connection States" on page 5-6. The CCB
is 242 bytes. A connection listener does not need send and receive queues or an attention-message buffer. The memory that you allocate becomes the property of ADSP when you call thedspCLInit
routine to establish a connection listener. You cannot write any data to this memory except by calling ADSP, and you must ensure that the memory remains locked until you call thedspRemove
routine to eliminate the connection end.- Call the
dspCLInit
routine to establish a connection listener. You must provide a pointer to the CCB.If there is a specific socket that you want to use for the connection listener, you can specify the socket number in the
localSocket
parameter. If you want ADSP to assign the socket for you, specify 0 for thelocalSocket
parameter. ADSP returns the socket number when thedspCLInit
routine completes execution.- If you wish, you can use the NBP routines to add the name and address of your connection listener to the node's names table. See the chapter "Name-Binding Protocol (NBP)" in this book for information on NBP.
- Use the
dspCLListen
routine to cause the connection listener to wait for an open-
connection request. Because thedspCLListen
routine does not complete execution until it receives a connection request, you should call this routine asynchronously.
You can specify a value for thefilterAddress
parameter to restrict the network number, node ID, or socket number from which you will accept an open-connection request.When the
dspCLListen
routine receives an open-connection request that meets
the restrictions of thefilterAddress
parameter, it returns anoErr
result code
(if you executed the routine asynchronously, it places anoErr
result code in theioResult
parameter) and places values in the parameter block for theremoteCID
,remoteAddress
,sendSeq
,sendWindow
, andattnSendSeq
parameters.- If you want to open the connection, call the
dspInit
routine to establish a connection end. You can use any available socket on the node for the connection end, including the socket that you used for the connection listener. Because a single socket can have more than one CCB connected with it, the socket can function simultaneously as a connection end and a connection listener.You can check the address of the remote socket to determine if it meets your criteria for a connection end. Although the
filterAddress
parameter to thedspCLListen
routine provides some screening of socket addresses, it cannot check for network number ranges, for example, or for a specific set of socket numbers. If for some reason you want to deny the connection request, call thedspDeny
routine, specifying the CCB of the connection listener in theccbRefNum
parameter. Because thedspCLListen
routine completes execution when it receives an open-connection request, you must return to step 5 to wait for another connection request.- Call the
dspOpen
routine to open the connection. Specify the valueocAccept
for theocMode
parameter and specify in theccbRefNum
parameter the reference number
of the CCB for the connection end that you want to use. When you call thedspOpen
routine, you must provide the values returned by thedspCLListen
routine for
theremoteCID
,remoteAddress
,sendSeq
,sendWindow
, andattnSendSeq
parameters.You can poll the state field in the CCB to determine when the connection is open. Alternatively, you can check the result code for the
dspOpen
routine when the routine completes execution. If the routine returns thenoErr
result code, then the connection is open.- You can now send and receive data and attention messages over the connection, as described in "Opening and Maintaining an ADSP Connection" beginning on page 5-13. When you are ready to close the connection, you can use the
dspClose
ordspRemove
routine, both of which are also described in the section "Creating and Using a Connection Control Block."- When you are finished using the connection listener, you can use the
dspCLRemove
routine to eliminate it. Once you have called thedspCLRemove
routine, you can release the memory you allocated for the connection listener's CCB.
dspCLInit
routine to establish a connection listener, uses NBP to register the name of the connection end on the internet, and uses thedspCLListen
routine to wait for a connection request. When the routine receives a connection request, it calls thedspOpen
routine to complete the connection.Listing 5-2 Using ADSP to establish and use a connection listener
VAR dspCCBPtr: TPCCB; myDSPPBPtr: DSPPBPtr; myMPPPBPtr: MPPPBPtr; myNTEName: NamesTableEntry; drvrRefNum: Integer; mppRefNum: Integer; connRefNum: Integer; myErr: OSErr; BEGIN myErr := OpenDriver('.MPP', mppRefNum); {open .MPP driver} IF myErr <> noErr THEN DoErr(myErr); {check and handle error} myErr := OpenDriver('.DSP', drvrRefNum); {open .DSP driver} IF myErr <> noErr THEN DoErr(myErr); {check and handle error} {Allocate memory for data buffers.} dspCCBPtr := TPCCB(NewPtr(SizeOf(TRCCB))); myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock))); myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock))); WITH myDSPPBPtr^ DO {set up dspCLInit parameters} BEGIN ioCRefNum := drvrRefNum; {ADSP driver ref num} csCode := dspCLInit; ccbPtr := dspCCBPtr; {pointer to CCB} localSocket := 0; {local socket number} END; myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE); {establish a connection listener} IF myErr <> noErr THEN DoErr(myErr); {check and handle error} connRefNum := myDSPPBPtr^.ccbRefNum; {save CCB ref num for later} NBPSetNTE(@myNTEName, 'The Object', 'The Type', '*', myDSPPBPtr^.localSocket); {set up NBP names table entry} WITH myMPPPBPtr^ DO {set up PRegisterName parameters} BEGIN interval := 7; {retransmit every 7*8=56 ticks } count := 3; { and retry 3 times} entityPtr := @myNTEname; {name to register} verifyFlag := 1; {verify this name} END; myErr := PRegisterName(myMPPPBPtr, FALSE); {register this name} IF myErr <> noErr THEN DoErr(myErr); {check and handle error} WITH myDSPPBPtr^ DO {set up dspCLListen parameters} BEGIN ioCRefNum := drvrRefNum; {ADSP driver ref num} csCode := dspCLListen; ccbRefNum := connRefNum; {connection ref num} filterAddress := AddrBlock(0); {connect with anybody} END; myErr := PBControl(ParmBlkPtr(myDSPPBPtr), TRUE); {listen for connection requests} WHILE myDSPPBPtr^.ioResult = 1 DO BEGIN {Return control to user while waiting for a connection } { request.} GoDoSomething; END; IF myErr <> noErr THEN DoErr(myErr); {check and handle error} WITH myDSPPBPtr^ DO {set up dspInit parameters} BEGIN ioCRefNum := drvrRefNum; {ADSP driver ref num} csCode := dspInit; ccbPtr := @dspCCB; {pointer to CCB} userRoutine := @myConnectionEvtUserRoutine; sendQSize := qSize; {size of send queue} sendQueue := dspSendQPtr; {send-queue buffer} recvQSize := qSize; {size of receive queue} recvQueue := dspRecvQPtr; {receive-queue buffer} attnPtr := dspAttnBufPtr; {receive-attention buffer} localSocket := 0; {let ADSP assign socket} END; dspCCB.myA5 := SetCurrentA5; {save A5 for the user routine} {Establish a connection end.} myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE); IF myErr <> noErr THEN DoErr(myErr); {check and handle error} connRefNum := myDSPPBPtr^.ccbRefNum; {save CCB ref num for later} {You received a connection request: now open a connection. } { The dspCLListen call has returned values into the } { remoteCID, remoteAddress, sendSeq, sendWindow, } { and attnSendSeq fields of the parameter block.} WITH myDSPPBPtr^ DO {set up dspOpen parameters} BEGIN ioCRefNum := drvrRefNum; {ADSP driver ref num} csCode := dspOpen; ccbRefNum := connRefNum; {connection ref num} ocMode := ocAccept; {open connection mode} ocInterval := 0; {use default retry interval} ocMaximum := 0; {use default retry maximum} END; myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE); {open a connection} IF myErr <> noErr THEN DoErr(myErr) {check and handle error} END; {MyCLADSP}