Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Networking /
Chapter 5 - AppleTalk Data Stream Protocol (ADSP) / Using ADSP


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:

  1. Use the Device Manager's OpenDriver function to open the .MPP driver and then use the OpenDriver function to open the .DSP driver. The OpenDriver function returns the reference number for the .DSP driver. You must supply this reference number each time you call the .DSP driver.
  2. 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 the dspCLInit 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 the dspRemove routine to eliminate the connection end.
  3. 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 the localSocket parameter. ADSP returns the socket number when the dspCLInit routine completes execution.

  4. 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.
  5. Use the dspCLListen routine to cause the connection listener to wait for an open-
    connection request. Because the dspCLListen routine does not complete execution until it receives a connection request, you should call this routine asynchronously.
    You can specify a value for the filterAddress 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 the filterAddress parameter, it returns a noErr result code
    (if you executed the routine asynchronously, it places a noErr result code in the ioResult parameter) and places values in the parameter block for the remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters.

  6. 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 the dspCLListen 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 the dspDeny routine, specifying the CCB of the connection listener in the ccbRefNum parameter. Because the dspCLListen routine completes execution when it receives an open-connection request, you must return to step 5 to wait for another connection request.

  7. Call the dspOpen routine to open the connection. Specify the value ocAccept for the ocMode parameter and specify in the ccbRefNum parameter the reference number
    of the CCB for the connection end that you want to use. When you call the dspOpen routine, you must provide the values returned by the dspCLListen routine for
    the remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq 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 the noErr result code, then the connection is open.

  8. 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 or dspRemove routine, both of which are also described in the section "Creating and Using a Connection Control Block."
  9. When you are finished using the connection listener, you can use the dspCLRemove routine to eliminate it. Once you have called the dspCLRemove routine, you can release the memory you allocated for the connection listener's CCB.

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 dspCLInit routine to establish a connection listener, uses NBP to register the name of the connection end on the internet, and uses the dspCLListen routine to wait for a connection request. When the routine receives a connection request, it calls the dspOpen 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}

Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996