2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * ident "%Z%%M% %I% %E% SMI" 2N/A * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A// network transaction. 2N/A * Transact performs the low level details for transacting an SLP network 2N/A * query. Note that, in the future, this class may spin separate threads 2N/A * for DA requests as well. 2N/A // Cache of open TCP sockets. 2N/A // SLP config object. 2N/A // Vector of return values. 2N/A // Timeout for multicast convergence. Varies if it's DA discovery or 2N/A // request multicast. 2N/A // Maximum results desired for multicast. 2N/A // Exception to throw. 2N/A // Multicast address to use. 2N/A // If this is true, continue multicast after the first set of stuff 2N/A // is found. Exit when three tries have happened without finding 2N/A * Perform a query to the SLP network. The multicast query is performed 2N/A * in a separate thread for performance reasons. DAs having the 2N/A * same scope set are queried until one answers. These DAs form 2N/A * an equivalence class. 2N/A * @param daEquivClasses Vector of DATable.DARecord objects in the 2N/A * same equivalence clase w.r.t. scopes. 2N/A * @param uniMsg A unicast message to send. 2N/A * @param multiMsg A multicast message to send. 2N/A * @param address Multicast address to use. 2N/A * @return Vector of SrvLocMsg objects with results. 2N/A // If we need to multicast, then start the multicast thread. 2N/A // Create a new Transact multicast thread. 2N/A // The final argument to the constructor of Transact determines 2N/A // whether to return after the first result or to continue to 2N/A // gather more than one result. The value to this field 2N/A // continueAfterFound MUST be set to 'true' or else multicast 2N/A // based discovery will find the first result, not all results, 2N/A true);
// continueAfterFound 2N/A // Go through the msgTable doing all the DAs. 2N/A // Wait until the TransactConverge thread is done, if necessary. 2N/A // If there was a problem in either the multicast thread or in 2N/A // the unicast call, throw an exception, but *only* if no 2N/A // results came back. 2N/A // Return the result to the client. 2N/A * Transact a message with DAs. Put the returned SrvLocMsg 2N/A * object into the Vector ret. 2N/A * @param daEquivClasses Vector of DATable.DARecord objects in the 2N/A * same equivalence clase w.r.t. scopes. 2N/A * @param msg SrvLocMsg Message to send. 2N/A * @param ret Vector for returns. 2N/A * @param maxResults Maximum results expected. 2N/A * @return A ServiceLocationException object if an exception occured. 2N/A * @exception ServiceLocationException 2N/A * If results cannot be obtained in the timeout interval 2N/A * specified in the 'config.' or 2N/A * If networking resources cannot be obtained or used 2N/A // Get the config object if we need it. 2N/A // Go through the DA address equivalence classes we need 2N/A // Get a new outgoing socket. 2N/A // Go through the DA addresses until we get a reply from one. 2N/A // Get the reply message if any. 2N/A // If overflow, try TCP. 2N/A // Increment number of replies we received. 2N/A // Add to return vector. 2N/A // Break out of the loop, since we only need one in 2N/A // this equivalence class. 2N/A // In case we are querying more than one DA, we 2N/A // save th exception, returning it to the caller to 2N/A // decide if it should be thrown. We ignore DA_BUSY, 2N/A // though, since the DA may free up later. 2N/A // If the error code is NETWORK_TIMED_OUT, then remove 2N/A // this DA from the DA table. If it's just down 2N/A // temporarily, we'll get it next time we go to 2N/A // the server to get the DA addresses. 2N/A "socket_creation_failure",
2N/A * Transact a message via. UDP. Try a maximum of three times if 2N/A * @param ds The datagram socket to use. 2N/A * @param addr The DA to contact. 2N/A * @param msg The message to send. 2N/A * @return The SrvLocMsg returned or null if none. 2N/A * @exception ServiceLocationException Due to errors in parsing message. 2N/A // Construct the datagram packet to send. 2N/A // Resend for number of timeouts in timeout interval. 2N/A // Catch timeout and IO errors. 2N/A // Process result into a reply object. 2N/A // Did not get it on the first timeout, try again. 2N/A "datagram_io_error",
2N/A // If nothing, then we've timed out. DAs with no matching 2N/A // info should at least return a reply. 2N/A * Transact a message using TCP, since the reply was too big. 2N/A * @parameter addr Address of the DA to contact. 2N/A * @parameter msg The message object to use. 2N/A * @parameter cacheIt Cache socket, if new. 2N/A * @return The SrvLocMsg returned if any. 2N/A * @exception ServiceLocationException 2N/A * If results cannot be obtained in the timeout interval 2N/A * specified in the 'config.' 2N/A * If networking resources cannot be obtained or used 2N/A // Get the config object if we need it. 2N/A // Transact the message, taking care of socket caching. 2N/A // Filter reply for nulls, invalid xid. 2N/A // Uncache a socket. 2N/A // Get a (possibly cached) TCP socket, cache it if cache is on. 2N/A // We use the cached socket if we've got it. 2N/A // Set it so the socket will block for fixed timeout. 2N/A // We cache it if we're supposed to. 2N/A // Transact the message, using cached socket if necessary. Retry if 2N/A // In case the server cuts us off... 2N/A // Only one thread at a time gets to use this socket, in case 2N/A // it was cached. Otherwise, we *may* get interleaved i/o. 2N/A // Send the request. 2N/A // Uncache it, get a new one. If that one doesn't work, we're 2N/A // Recursively call ourselves to take care of this, but 2N/A // Externalize the message into bytes. 2N/A // Check if it excceds the output buffer length. 2N/A // Filter the reply to make sure the xid matches and that it's not null. 2N/A static protected boolean 2N/A // Check for invalid xid. 2N/A * Internalize the byte array in the input stream into a SrvLocMsg 2N/A * subclass. It will be an appropriate subclass for the client agent. 2N/A * If an exception comes out of this method, it is converted into 2N/A * a SrvLocMsg with error code. 2N/A * @param dis The input stream containing the packet. 2N/A * @param addr The address of the replying agent (for error reporting). 2N/A * @return The right SrvLocMsg subclass appropriate for the Client Agent. 2N/A * If null is returned, the function code wasn't recognized, 2N/A * and so it may be appropriate for another agent. 2N/A * @exception ServiceLocationException If the character set was not valid 2N/A * or an error occured during parsing. 2N/A * @exception IOException If DataInputStream throws it. 2N/A byte[] b =
new byte[
2];
2N/A ver = (
int) ((
char)b[
0] &
0XFF);
2N/A fun = (
int) ((
char)b[
1] &
0XFF);
2N/A // Unrecognized version number if header not returned. 2N/A "version_number_error",
2N/A // Create the header. Note that we only need to create a 2N/A // client side header here, because that is all that 2N/A // will be expected by the client side code. Note that we 2N/A // *can't* use the SrvLocHeader.newInstance() mechanism 2N/A // because Transact lives in the server as well, and 2N/A // SrvLocHeader can only handle one header class per 2N/A // Parse options, if any. 2N/A // During parsing, this can be thrown if syntax errors occur. 2N/A // If version code is zero, then we suspect a network error, 2N/A // otherwise, it is probably a parse error. 2N/A // During parsing, this can be thrown if the message stream 2N/A // is improperly formatted. 2N/A "ioexception_parsing",
2N/A // Add the address of the replying agent. 2N/A // Send out the message. 2N/A static protected void 2N/A // Check the response and add the previous responder if it is OK. 2N/A static protected boolean 2N/A // Add incoming result to the vector. 2N/A // Transact an active request for DA or SA adverts. 2N/A // Perform active advertisement. 2N/A // Create Transact object and start. 2N/A // Wait until the TransactConverge thread is done, if necessary. 2N/A // Process the results. 2N/A for (i =
0; i < n; i++) {
2N/A // Let DA table handle it if it`s a DAAdvert. 2N/A // Add scopes from the SAAdvert if not already there. 2N/A for (j =
0; j < m; j++) {
2N/A // Construct a Transact object to run a convergence transaction in 2N/A // a separate thread. 2N/A // Run the multicast convergence algorithm. 2N/A // Get the config object if we need it. 2N/A // Multicast out on the default interface only. 2N/A // Perform convergence. 2N/A // Ignore DA_BUSY, the DA may free up later. 2N/A // Create new exception to be thrown. 2N/A // Close the socket if it's been opened. 2N/A * Send the message using multicast and use convergence to gather the 2N/A * results. Note that this routine must be synchronized because 2N/A * only one multicast can be active at a time; othewise, the client 2N/A * may get back an unexpected result. However, there can be many unicast 2N/A * requests active along with a multicast request, hence the separate 2N/A * thread for multicast. 2N/A * The subtlety of the timing routine is that it will only resend the 2N/A * message when one of the multicast convergence timeout intervals 2N/A * elapses. Further, for efficiency, it will give up after a complete 2N/A * interval has gone by without receiving any results. This may mean 2N/A * that the intervals have to be extended in larger networks. In the 2N/A * common case, multicast convergence will complete under 3 seconds 2N/A * as all results will arrive during the first interval (1 second long) 2N/A * and none will arrive during the second interval. 2N/A * @param ds The datagram socket to send on. 2N/A * @param msg The message to send. 2N/A * @param vResult A vector in which to put the returns. 2N/A * @param msTimeouts Array of timeout values for multicast convergence. 2N/A * @param maxResults Maximum replies desired. 2N/A * @param continueAfterFound If true, continue after something is 2N/A * found. Try three times if nothing was 2N/A * found. If false, exit at the first 2N/A * timeout. DA discovery should set this 2N/A * to true so as many DAs as possible are 2N/A * found, otherwise, it should be false. 2N/A * @exception ServiceLocationException 2N/A * If results cannot be obtained in the timeout interval 2N/A * specified in the 'config.' or 2N/A * if networking resources cannot be obtained or used 2N/A // Get the config object if we need it. 2N/A // Send the request for the 1st iteration. It will be sent again 2N/A // only when the timeout intervals elapse. 2N/A // Continue collecting results only as long as we need more for 2N/A // the 'max results' configuration. 2N/A // Set up the reply buffer. 2N/A // Block on receive (no longer than max timeout - time spent). 2N/A break;
// we have no time left! 2N/A // We try sending at least three times, unless there was 2N/A // a timeout. If continueAfterFound is false, we exit 2N/A // after the first timeout if something was found. 2N/A // Now resend the request... 2N/A continue;
// since we did not receive anything, continue... 2N/A // Data was received without timeout or fail. 2N/A // Add this responder to previous responders. If the message 2N/A // was already received but the SA resent because it isn't 2N/A // doing multicast convergence correctly, then ignore it. 2N/A // Handle any overflow thru TCP. 2N/A // Add response to list. 2N/A // Increment the number of results returned. 2N/A // Exit if we should not continue. 2N/A // If we broke off because the previous responder's list is too 2N/A // long, then return, otherwise throw the exception again. 2N/A // Calculate the multicast timeout depending on where we are in the loop. 2N/A return -
1;
// if we get here we have waited past all of the timeouts