package jade.core; import jade.core.MainDetectionManager.MulticastParams; import jade.mtp.TransportAddress; import jade.util.Logger; import jade.util.leap.ArrayList; import jade.util.leap.Iterator; import jade.util.leap.List; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.UnknownHostException; //#J2ME_EXCLUDE_FILE class MulticastMainDetectionListener implements Runnable { private final static Logger logger = Logger.getMyLogger(MulticastMainDetectionListener.class.getName()); private final static int DGRAM_BUF_LEN = 1024; private ProfileImpl profile; private IMTPManager manager; private MulticastParams mcast; private InetAddress mcastGroupAddress; private MulticastSocket socket; private boolean active; public MulticastMainDetectionListener(ProfileImpl profile, IMTPManager manager) throws ProfileException { active = false; this.profile = profile; this.manager = manager; mcast = new MainDetectionManager.MulticastParams(profile); try { mcastGroupAddress = InetAddress.getByName(mcast.address); } catch (UnknownHostException e) { throw new ProfileException("Cannot resolve address "+mcast.address, e); } if (!mcastGroupAddress.isMulticastAddress()) { throw new ProfileException("Address "+mcast.address+" is not a multicast address"); } try { socket = new MulticastSocket(mcast.port); socket.joinGroup(mcastGroupAddress); socket.setTimeToLive(mcast.ttl); } catch (IOException ioe) { throw new ProfileException("Error setting up multicast socket", ioe); } } private String errorResponse(String code, String msg) { return code+" "+msg; } void stop() { if (active) { active = false; if (socket != null) { try { socket.leaveGroup(mcastGroupAddress); } catch (IOException e) { logger.log(Logger.FINER, "Error leaving multicast group", e); } socket.close(); } } } private String serveGetMain(String request) throws IMTPException { logger.log(Logger.FINER, "MulticastMainDetectionListener::serveGetMain(request=\""+request+"\")"); String response = null; int i; String proto = null; String platformName = null; // request is in form: // get-main[@platform_name][:protocol_name] // does request contain a desired protocol? i = request.indexOf(':'); if (i > 0) { proto = request.substring(i+1); request = request.substring(0, i); logger.log(Logger.FINER, "MulticastMainDetectionListener::serveGetMain(): desired proto is \""+proto+"\""); } // does request contain a platform name? i = request.indexOf('@'); if (i > 0) { platformName = request.substring(i+1); request = request.substring(0, i); logger.log(Logger.FINER, "MulticastMainDetectionListener::serveGetMain(): request is for platform \""+platformName+"\""); } String myPlatform = profile.getParameter(Profile.PLATFORM_ID, null); if (platformName != null && !platformName.equals(myPlatform)) { // not my platform, bail out with no response logger.log(Logger.FINER, "MulticastMainDetectionListener::serveGetMain(): my platform is \""+myPlatform+"\" while request is for platform \""+platformName+"\" --> Do not reply"); return null; } List addresses = manager.getLocalAddresses(); List responseAddresses = new ArrayList(addresses.size()); Iterator iter = addresses.iterator(); TransportAddress addr; while (iter.hasNext()) { addr = (TransportAddress)iter.next(); if (proto != null) { if (proto.equals(addr.getProto())) { responseAddresses.add(addr); break; } } else { responseAddresses.add(addr); } } if (responseAddresses.size() < 1) { response = errorResponse(MainDetectionManager.PROTO_RESP_NOTFOUND, "Cannot manage protocol "+proto); } else { response = MainDetectionManager.PROTO_RESP_OK; iter = responseAddresses.iterator(); while (iter.hasNext()) { addr = (TransportAddress)iter.next(); // FIXME use toString() //response += addr.toString(); response += addr.getProto()+MainDetectionManager.PROTO_ADDR_SEPARATOR+addr.getHost()+MainDetectionManager.PROTO_ADDR_SEPARATOR+addr.getPort(); if (iter.hasNext()) { response += MainDetectionManager.PROTO_ADDRESSES_SEPARATOR; } } } return response; } private String executeRequest(String request) throws Exception { logger.log(Logger.FINER, "MulticastMainDetectionListener::executeRequest(request=\""+request+"\")"); String result = null; if (request.indexOf(MainDetectionManager.PROTO_CMD_GETMAIN) == 0) { // command [get main] if (profile.isFirstMain()) { // only master main replies to [get main] commands result = serveGetMain(request); } else { logger.log(Logger.FINER, "MulticastMainDetectionListener::executeRequest(): I'm not master --> Do not reply"); } } else if (request.indexOf(MainDetectionManager.PROTO_CMD_PING) == 0) { throw new Exception("Command not implemented yet"); } else { throw new Exception("Command not implemented"); } return result; } private String manageRequest(byte[] requestBuffer) { logger.log(Logger.FINER, "MulticastMainDetectionListener::manageRequest(...)"); String result = null; String request; request = MainDetectionManager.decodeData(requestBuffer); if (request == null) { throw new RuntimeException("Error decoding request"); } try { logger.log(Logger.FINER, "MulticastMainDetectionListener::manageRequest(): request.length()="+request.length()); if (request.length() <= MainDetectionManager.PROTO_VERSION.length()) { throw new Exception("Bad request [request=\""+request+"\""); } int i = MainDetectionManager.checkProtocolVersion(request); request = request.substring(0, i); result = executeRequest(request); } catch (Exception e) { throw new RuntimeException("Error managing request \""+request+"\"", e); } return result; } public void run() { logger.log(Logger.FINE, "MulticastMainDetectionListener::run()"); try { String response; InetAddress clientAddr; int responsePort; active = true; while (true) { try { byte[] buf = new byte[DGRAM_BUF_LEN]; DatagramPacket packet = new DatagramPacket(buf, buf.length); try { socket.receive(packet); } catch (IOException ioe) { /* * when stop() is called, we get here with a * SocketException: Socket closed and active == false */ if (active) { /* * if active is still true, then something went wrong */ logger.log(Logger.SEVERE, "Error in receive()", ioe); } // in both cases, it's better to get outta here break; } logger.log(Logger.FINER, "MulticastMainDetectionListener::run(): "+packet.getLength()+" bytes received"); try { response = manageRequest(packet.getData()); } catch (Exception e) { logger.log(Logger.WARNING, "MulticastMainDetectionListener::run(): error managing request", e); response = errorResponse(MainDetectionManager.PROTO_RESP_ERR, e.getMessage()); } if (response != null) { response += MainDetectionManager.PROTO_VERSION; buf = response.getBytes(MainDetectionManager.PROTO_ENCODING); // get client info clientAddr = packet.getAddress(); responsePort = packet.getPort(); // prepare packet to be sent back return to client packet = new DatagramPacket(buf, buf.length, clientAddr, responsePort); logger.log(Logger.FINER, "MulticastMainDetectionListener::run(): sending response \""+response+"\" to "+clientAddr+":"+responsePort); socket.send(packet); } else { logger.log(Logger.FINE, "MulticastMainDetectionListener::run(): discarded request, sending no response"); } } catch(IOException ioe) { logger.log(Logger.WARNING, "Input-output error", ioe); } } } catch (Exception e) { logger.log(Logger.SEVERE, "Error in listener thread, MulticastMainDetectionListener is no more active", e); } } }