Socket: 3.1 Addresses: Letting the User Choose an Address

Up: GEOS SDK TechDocs| Up | Prev: 3 Addresses | Next: 3.2 Managing Addresses
SocketAddressControllerClass, SocketGetDomains(), SocketGetAddressController(), SocketCreateResolvedAddress(), SocketResolve(), SocketInterruptResolve()

Given a domain, you can request the Socket library to provide UI gadgetry so that the user can choose an address within that domain. Many programs only support socket connections over one domain. However, if you need a list of all domains supported in the user's environment, call SocketGetDomains() .

The SocketGetDomains() routine takes the optr of a chunk array and fills in that array with elements. Each element contains a (non-null-terminated) string which is the name of a supported domain. This chunk array has a standard ChunkArrayHeader header and variable-sized elements.

If you want the routine to allocate the chunk array for you, pass an optr that contains a NullChunk ( i.e. , a null ChunkHandle):

MemHandle	myHandle;
Optr	myOptr;
myHandle = OptrToHandle(myHandle);
myOptr = ConstructOptr(myHandle, NULL);

For more information about working with chunk arrays, see the Local Memory chapter. In short, to manage the chunk array of domain names:

  1. Lock down the local memory heap with MemLock() .
  2. Use LMemDerefHandles() to get a pointer to the chunk array.
  3. To get the number of domains, call ChunkArrayGetCount() .
  4. To get a pointer to the nth string in the chunk array, call ChunkArrayElementToPtr() or ChunkArrayElementToPtrHandles() .
  5. When finished reading domain strings, call MemUnlock() on the local memory heap.

Given a domain name, you can create some UI gadgetry for choosing addresses within that domain. As shown in the Appl/SDK_C/Talk example, call SocketGetAddressController() to get the class of an appropriate controller. This class is guaranteed to support the messages shown in SocketAddressControllerClass.

Code Display 23-1 SocketAddressControllerClass

/* Domain-specific subclasses of SocketAddressControllerClass all support 
 * the following messages. MSG_SOCKET_ADDRESS_CONTROL_GET_ADDRESSES is probably 
 * the most commonly used message. */
/*
 * Build the block of data that holds the addresses selected by the user
 * to pass to the transport driver. If OK, returns ChunkArray of SACAddress
 * structures in same block as controller. Else, returns 0.
 * As of this writing, all address controllers return at most one address 
 * in the list of addresses. 
 * The returned address(es) are not in its primitive form; use 
 * SocketResolve() to transform the address into something usable.
 */
 @message word MSG_SOCKET_ADDRESS_CONTROL_GET_ADDRESSES();
  typedef struct {
	word 		SACA_opaqueSize;
	/* label byte 		SACA_opaque;    Pass this to SocketResolve */ 
	/* after the opaque address, there is a null-terminated
	 *  human-readable form of the address. */
} SACAddress;
/*
 * Inform the subclass of the type of medium selected by the user
 * so it can customize its appearance appropriately, should the controller
 * handle media that have different ways of addressing.
 */
@message void MSG_SOCKET_ADDRESS_CONTROL_SET_MEDIUM (
				MediumType mediumType);
/*
 * Set the current user-editable address to the passed address.
 */
@message void MSG_SOCKET_ADDRESS_CONTROL_SET_ADDRESSES(optr addr);
/*
 * Inform the controller of the message and destination object it should use to
 * notify the invoker that a valid address exists.
 */
@message void MSG_SOCKET_ADDRESS_CONTROL_SET_ACTION (
				optr dest,
				word actionMsg);
/*
 * Let the containing dialog know whether the address we've got is a
 * valid one, so it can decide whether to allow the user to send the
 * message.
 */
@message void MSG_SOCKET_ADDRESS_CONTROL_SET_VALID_STATE(Boolean valid);

You cannot use an address with Socket library routines unless that address is in its primitive form. This primitive form is created by taking a higher-level form of the address and passing it to the SocketCreateResolvedAddress() routine or the SocketResolve() routine. Exactly how the Socket library resolves the address depends upon the domain.

Recall that addresses returned by the address controller are not in their primitive form. The primitive form of an address can be volatile: feel free to re-use them if making several connections over a short period of time, but re-resolve the address if it's been a long time since it was last resolved. Note that there can be a large overhead when it comes to resolving addresses. Also note that IRLAP numeric addresses are especially volatile, changing every time the protocol connection starts, i.e., every time the IRLAP driver is loaded, either for the first time or after more than a minute of inactivity.

The SocketCreateResolvedAddress() routine takes a pointer to a domain name and raw address data and returns a buffer with a SocketAddress structure and the address data. Depending on what you're going to use the address for, you may need to fill in the structure's SA_port field.

SocketResolve() is the same as SocketCreateResolvedAddress() except that SocketResolve() takes a buffer to hold the resolved address data. If the buffer isn't big enough, SocketResolve() returns SE_BUFFER_TOO_SMALL. Depending on the domain, calling SocketResolve() on an address already in its primitive form may have undesired results.

The resolution process may or may not require network access, depending on the domain and the input format. Depending on the domain, the addressing system may be volatile. Under these conditions, put off resolving the address as long as possible, until just before using the address; there will be less time for the address to go bad. If the network goes down, the Socket library might not be able to resolve addresses. In this case, SocketCreateResolvedAddress() or SocketResolve() returns SE_TEMPORARY_ERROR.

If you wish to interrupt the resolution process (perhaps you allow the user to cancel the operation), use the SocketInterruptResolve() function. This function attempts to halt the resolution process. It is, however, unreliable. It may not succeed in interrupting the resolution process; it may also interrupt other resolves happening at the same time.


Up: GEOS SDK TechDocs| Up | Prev: 3 Addresses | Next: 3.2 Managing Addresses