/** * Wait for the username/password message and verify or throw SOCKSException on failure * * @since 0.8.2 */ private void verifyPassword(DataInputStream in, DataOutputStream out) throws IOException, SOCKSException { int c = in.readUnsignedByte(); if (c != AUTH_VERSION) throw new SOCKSException("Unsupported authentication version"); c = in.readUnsignedByte(); if (c <= 0) throw new SOCKSException("Bad authentication"); byte[] user = new byte[c]; in.readFully(user); c = in.readUnsignedByte(); if (c <= 0) throw new SOCKSException("Bad authentication"); byte[] pw = new byte[c]; in.readFully(pw); // Hopefully these are in UTF-8, since that's what our config file is in // these throw UnsupportedEncodingException which is an IOE String u = new String(user, "UTF-8"); String p = new String(pw, "UTF-8"); String configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_USER); String configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_PW); if ((!u.equals(configUser)) || (!p.equals(configPW))) { _log.error("SOCKS authorization failure"); sendAuthReply(AUTH_FAILURE, out); throw new SOCKSException("SOCKS authorization failure"); } if (_log.shouldLog(Log.INFO)) _log.info("SOCKS authorization success, user: " + u); sendAuthReply(AUTH_SUCCESS, out); }
/** * Not thread-safe. Blocking. Only used for external sockets. ClientWriterRunner thread is the * only caller. Others must use doSend(). */ void writeMessage(I2CPMessage msg) { // long before = _context.clock().now(); try { // We don't need synchronization here, ClientWriterRunner is the only writer. // synchronized (_out) { msg.writeMessage(_out); _out.flush(); // } // if (_log.shouldLog(Log.DEBUG)) // _log.debug("after writeMessage("+ msg.getClass().getName() + "): " // + (_context.clock().now()-before) + "ms"); } catch (I2CPMessageException ime) { _log.error("Error sending I2CP message to client", ime); stopRunning(); } catch (EOFException eofe) { // only warn if client went away if (_log.shouldLog(Log.WARN)) _log.warn("Error sending I2CP message - client went away", eofe); stopRunning(); } catch (IOException ioe) { if (_log.shouldLog(Log.ERROR)) _log.error("IO Error sending I2CP message to client", ioe); stopRunning(); } catch (Throwable t) { _log.log(Log.CRIT, "Unhandled exception sending I2CP message to client", t); stopRunning(); // } finally { // long after = _context.clock().now(); // long lag = after - before; // if (lag > 300) { // if (_log.shouldLog(Log.WARN)) // _log.warn("synchronization on the i2cp message send took too long (" + lag // + "ms): " + msg); // } } }
/** * Run an integrity check on the blockfile and all the skiplists in it * * @return true if the levels were modified. */ public boolean bfck(boolean fix) { if (log.shouldLog(Log.INFO)) { log.info("magic bytes " + magicBytes); log.info("fileLen " + fileLen); log.info("freeListStart " + freeListStart); log.info("mounted " + mounted); log.info("spanSize " + spanSize); log.info("Metaindex"); log.info("Checking meta index in blockfile " + file); } boolean rv = metaIndex.bslck(fix, true); if (rv) { if (log.shouldLog(Log.WARN)) log.warn("Repaired meta index in blockfile " + file); } else { if (log.shouldLog(Log.INFO)) log.info("No errors in meta index in blockfile " + file); } int items = 0; for (SkipIterator iter = metaIndex.iterator(); iter.hasNext(); ) { String slname = (String) iter.nextKey(); Integer page = (Integer) iter.next(); if (log.shouldLog(Log.INFO)) log.info("List " + slname + " page " + page); try { // This uses IdentityBytes, so the value class won't be right, but at least // it won't fail the out-of-order check Serializer keyser = slname.equals("%%__REVERSE__%%") ? new IntBytes() : new UTF8StringBytes(); BSkipList bsl = getIndex(slname, keyser, new IdentityBytes()); if (bsl == null) { log.error("Can't find list? " + slname); continue; } // The check is now done in getIndex(), no need to do here... // but we can't get the return value of the check here. items++; } catch (IOException ioe) { log.error("Error with list " + slname, ioe); } } log.info("Checked meta index and " + items + " skiplists"); if (freeListStart != 0) { try { if (flb == null) flb = new FreeListBlock(file, freeListStart); flb.flbck(true); } catch (IOException ioe) { log.error("Free list error", ioe); } } else { if (log.shouldLog(Log.INFO)) log.info("No freelist"); } return rv; }
@Override public int doEndTag() throws JspException { JspWriter out = pageContext.getOut(); Email email = new Email(includeSentTime); String statusMessage; if (recipients.isEmpty()) statusMessage = _t("Error: Please add at least one recipient."); else try { // set addresses InternetAddress ia = new InternetAddress(senderAddress); email.setFrom(ia); // We must continue to set "Sender:" even with only one mailbox // in "From:", which is against RFC 2822 but required for older // Bote versions to see a sender (and validate the signature). email.setSender(ia); email.setSubject(subject, "UTF-8"); for (Recipient recipient : recipients) email.addRecipient(recipient.type, recipient.address); // TODO: Comment out until we determine if this is necessary // email.fixAddresses(); // set the text and add attachments email.setContent(message, attachments); // send the email I2PBote.getInstance().sendEmail(email); // delete attachment temp files for (Attachment attachment : attachments) { if (!attachment.clean()) log.error("Can't clean up attachment: <" + attachment + ">"); } statusMessage = _t("The email has been queued for sending."); } catch (PasswordException e) { throw new JspException(e); } catch (Exception e) { statusMessage = _t("Error sending email: {0}", e.getLocalizedMessage()); log.error("Error sending email", e); } try { out.println(statusMessage); } catch (IOException e) { log.error("Can't write output to HTML page", e); } return EVAL_PAGE; }
public int allocPage() throws IOException { if (freeListStart != 0) { try { if (flb == null) flb = new FreeListBlock(file, freeListStart); if (!flb.isEmpty()) { if (log.shouldLog(Log.DEBUG)) log.debug("Alloc from " + flb); return flb.takePage(); } else { if (log.shouldLog(Log.DEBUG)) log.debug("Alloc returning empty " + flb); freeListStart = flb.getNextPage(); writeSuperBlock(); int rv = flb.page; flb = null; return rv; } } catch (IOException ioe) { log.error("Discarding corrupt free list block page " + freeListStart, ioe); freeListStart = 0; } } long offset = file.length(); fileLen = offset + PAGESIZE; file.setLength(fileLen); writeSuperBlock(); return (int) ((offset / PAGESIZE) + 1); }
private void connectWithPeers() { if (_peerDestFiles != null) { for (int i = 0; i < _peerDestFiles.length; i++) { try { FileInputStream fin = new FileInputStream(_peerDestFiles[i]); byte dest[] = new byte[1024]; int read = DataHelper.read(fin, dest); String remDest = new String(dest, 0, read); int con = 0; Flooder flooder = null; synchronized (_remotePeers) { con = _remotePeers.size() + 1; flooder = new Flooder(con, remDest); _remotePeers.put(new Integer(con), flooder); } byte msg[] = (DataHelper.getUTF8("STREAM CONNECT ID=" + con + " DESTINATION=" + remDest + "\n")); synchronized (_samOut) { _samOut.write(msg); _samOut.flush(); } I2PThread flood = new I2PThread(flooder, "Flood " + con); flood.start(); _log.debug("Starting flooder with peer from " + _peerDestFiles[i] + ": " + con); } catch (IOException ioe) { _log.error("Unable to read the peer from " + _peerDestFiles[i]); } } } }
/** Send a search to the given peer */ protected void sendSearch(RouterInfo router) { if (router.getIdentity().equals(getContext().router().getRouterInfo().getIdentity())) { // don't search ourselves if (_log.shouldLog(Log.ERROR)) _log.error(getJobId() + ": Dont send search to ourselves - why did we try?"); return; } else { if (_log.shouldLog(Log.INFO)) _log.info( getJobId() + ": Send search to " + router.getIdentity().getHash().toBase64() + " for " + _state.getTarget().toBase64() + " w/ timeout " + getPerPeerTimeoutMs(router.getIdentity().calculateHash())); } getContext().statManager().addRateData("netDb.searchMessageCount", 1, 0); // if (_isLease || true) // always send searches out tunnels sendLeaseSearch(router); // else // sendRouterSearch(router); }
/** * Verifies the DSA signature of a signed update file. * * @param signedFile The signed update file to check. * @param signingPublicKey An instance of {@link net.i2p.data.SigningPublicKey} to use for * verification. * @return <code>true</code> if the file has a valid signature, otherwise <code>false</code>. */ public boolean verify(File signedFile, SigningPublicKey signingPublicKey) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(signedFile); Signature signature = new Signature(); signature.readBytes(fileInputStream); return _context.dsa().verifySignature(signature, fileInputStream, signingPublicKey); } catch (IOException ioe) { if (_log.shouldLog(Log.WARN)) _log.warn("Error reading " + signedFile + " to verify", ioe); return false; } catch (DataFormatException dfe) { if (_log.shouldLog(Log.ERROR)) _log.error("Error reading the signature", dfe); return false; } finally { if (fileInputStream != null) try { fileInputStream.close(); } catch (IOException ioe) { } } }
/** Search totally failed */ protected void fail() { if (isLocal()) { if (_log.shouldLog(Log.ERROR)) _log.error( getJobId() + ": why did we fail if the target is local?: " + _state.getTarget().toBase64(), new Exception("failure cause")); succeed(); return; } if (_log.shouldLog(Log.INFO)) _log.info(getJobId() + ": Failed search for key " + _state.getTarget()); if (_log.shouldLog(Log.DEBUG)) _log.debug(getJobId() + ": State of failed search: " + _state); long time = getContext().clock().now() - _state.getWhenStarted(); int attempted = _state.getAttempted().size(); getContext().statManager().addRateData("netDb.failedAttemptedPeers", attempted, time); if (_keepStats) { getContext().statManager().addRateData("netDb.failedTime", time, 0); // _facade.fail(_state.getTarget()); } if (_onFailure != null) getContext().jobQueue().addJob(_onFailure); _facade.searchComplete(_state.getTarget()); handleDeferred(false); }
/** * Blocking call (run in the establisher thread) to determine if the session was created properly. * If it wasn't, all the SessionCreated remnants are dropped (perhaps they were spoofed, etc) so * that we can receive another one * * <p>Generates session key and mac key. * * @return true if valid */ public synchronized boolean validateSessionCreated() { if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) { if (_log.shouldLog(Log.WARN)) _log.warn("Session created already failed"); return false; } if (_receivedSignature != null) { if (_log.shouldLog(Log.WARN)) _log.warn("Session created already validated"); return true; } boolean valid = true; try { generateSessionKey(); } catch (DHSessionKeyBuilder.InvalidPublicParameterException ippe) { if (_log.shouldLog(Log.ERROR)) _log.error( "Peer " + getRemoteHostId() + " sent us an invalid DH parameter (or were spoofed)", ippe); valid = false; } if (valid) decryptSignature(); if (valid && verifySessionCreated()) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Session created passed validation"); return true; } else { if (_log.shouldLog(Log.WARN)) _log.warn( "Session created failed validation, clearing state for " + _remoteHostId.toString()); fail(); return false; } }
/** * Add the page to the free list. The file is never shrunk. TODO: Reclaim free pages at end of * file, or even do a full compaction. Does not throw exceptions; logs on failure. */ public void freePage(int page) { if (page <= METAINDEX_PAGE) { log.error("Bad page free attempt: " + page); return; } try { if (freeListStart == 0) { freeListStart = page; FreeListBlock.initPage(file, page); writeSuperBlock(); if (log.shouldLog(Log.DEBUG)) log.debug("Freed page " + page + " as new FLB"); return; } try { if (flb == null) flb = new FreeListBlock(file, freeListStart); if (flb.isFull()) { // Make the free page a new FLB if (log.shouldLog(Log.DEBUG)) log.debug("Full: " + flb); FreeListBlock.initPage(file, page); if (flb.getNextPage() == 0) { // Put it at the tail. // Next free will make a new FLB at the head, // so we have one more FLB than we need. flb.setNextPage(page); } else { // Put it at the head flb = new FreeListBlock(file, page); flb.setNextPage(freeListStart); freeListStart = page; writeSuperBlock(); } if (log.shouldLog(Log.DEBUG)) log.debug("Freed page " + page + " to full " + flb); return; } flb.addPage(page); if (log.shouldLog(Log.DEBUG)) log.debug("Freed page " + page + " to " + flb); } catch (IOException ioe) { log.error("Discarding corrupt free list block page " + freeListStart, ioe); freeListStart = page; FreeListBlock.initPage(file, page); writeSuperBlock(); flb = null; } } catch (IOException ioe) { log.error("Error freeing page: " + page, ioe); } }
/** * Start up the socket listener, listens for connections, and fires those connections off via * {@link #runConnection runConnection}. This only returns if the socket cannot be opened or there * is a catastrophic failure. */ public void startup() { _running = true; int curDelay = 0; while ((_running) && (curDelay < MAX_FAIL_DELAY)) { try { _log.info("Starting up listening for connections on port " + _port); _socket = new ServerSocket(_port); curDelay = 0; while (_running && (_socket != null)) { try { Socket socket = _socket.accept(); _log.debug("Connection received"); runConnection(socket); } catch (IOException ioe) { _log.error("Server error accepting", ioe); } catch (Throwable t) { _log.error("Fatal error running client listener - killing the thread!", t); return; } } } catch (IOException ioe) { _log.error("Error listening on port " + _port, ioe); } if (_socket != null) { try { _socket.close(); } catch (IOException ioe) { } _socket = null; } _log.error("Error listening, waiting " + _nextFailDelay + "ms before we try again"); try { Thread.sleep(_nextFailDelay); } catch (InterruptedException ie) { } curDelay += _nextFailDelay; _nextFailDelay *= 5; } _log.error( "CANCELING ADMIN LISTENER. delay = " + curDelay, new Exception("ADMIN LISTENER cancelled!!!")); _running = false; }
/** Aborts program abnormally. */ private void fatal(String s, Throwable t) { _log.error(s, t); // System.err.println("snark: " + s + ((t == null) ? "" : (": " + t))); // if (debug >= INFO && t != null) // t.printStackTrace(); stopTorrent(); if (t != null) s += ": " + t; if (completeListener != null) completeListener.fatal(this, s); throw new RuntimeException(s, t); }
public void notifyStreamSendBufferFree(int id) throws IOException { if (getStreamSession() == null) { _log.error("BUG! Stream outgoing buffer is free, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } if (!writeString("STREAM READY_TO_SEND ID=" + id + "\n")) { throw new IOException("Error notifying connection to SAM client"); } }
public void notifyStreamIncomingConnection(Destination d) throws IOException { if (getStreamSession() == null) { _log.error("BUG! Received stream connection, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } if (!writeString(d.toBase64() + "\n")) { throw new IOException("Error notifying connection to SAM client"); } }
/** this shouldn't throw anything */ static void startPlugins(RouterContext ctx) { Log log = ctx.logManager().getLog(PluginStarter.class); Properties props = pluginProperties(); for (Map.Entry<Object, Object> e : props.entrySet()) { String name = (String) e.getKey(); if (name.startsWith(PREFIX) && name.endsWith(ENABLED)) { if (Boolean.parseBoolean((String) e.getValue())) { String app = name.substring(PREFIX.length(), name.lastIndexOf(ENABLED)); // plugins could have been started after update if (isPluginRunning(app, ctx)) continue; try { if (!startPlugin(ctx, app)) log.error("Failed to start plugin: " + app); } catch (Throwable t) { log.error("Failed to start plugin: " + app, t); } } } } }
/** * @return true on success * @throws just about anything, caller would be wise to catch Throwable */ public static boolean stopPlugin(RouterContext ctx, String appName) throws Exception { Log log = ctx.logManager().getLog(PluginStarter.class); File pluginDir = new File(ctx.getConfigDir(), PLUGIN_DIR + '/' + appName); if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) { log.error("Cannot stop nonexistent plugin: " + appName); return false; } // stop things in clients.config File clientConfig = new File(pluginDir, "clients.config"); if (clientConfig.exists()) { Properties props = new Properties(); DataHelper.loadProps(props, clientConfig); List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig); runClientApps(ctx, pluginDir, clients, "stop"); } // stop console webapps in console/webapps // ContextHandlerCollection server = WebAppStarter.getConsoleServer(); // if (server != null) { /* File consoleDir = new File(pluginDir, "console"); Properties props = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath()); File webappDir = new File(consoleDir, "webapps"); String fileNames[] = webappDir.list(RouterConsoleRunner.WarFilenameFilter.instance()); if (fileNames != null) { for (int i = 0; i < fileNames.length; i++) { String warName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war")); if (Arrays.asList(STANDARD_WEBAPPS).contains(warName)) { continue; } WebAppStarter.stopWebApp(server, warName); } } */ if (pluginWars.containsKey(appName)) { Iterator<String> wars = pluginWars.get(appName).iterator(); while (wars.hasNext()) { String warName = wars.next(); WebAppStarter.stopWebApp(warName); } pluginWars.get(appName).clear(); } // } // remove summary bar link Properties props = pluginProperties(ctx, appName); String name = ConfigClientsHelper.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(ctx)); if (name == null) name = ConfigClientsHelper.stripHTML(props, "consoleLinkName"); if (name != null && name.length() > 0) NavHelper.unregisterApp(name); if (log.shouldLog(Log.WARN)) log.warn("Stopping plugin: " + appName); return true; }
/** @return null if no valid elements */ private static URL[] classpathToURLArray(String classpath, String clientName, Log log) { StringTokenizer tok = new StringTokenizer(classpath, ","); List<URL> urls = new ArrayList<URL>(); while (tok.hasMoreTokens()) { String elem = tok.nextToken().trim(); File f = new File(elem); if (!f.isAbsolute()) { log.error("Plugin client " + clientName + " classpath element is not absolute: " + f); continue; } try { urls.add(f.toURI().toURL()); if (log.shouldLog(Log.WARN)) log.warn("INFO: Adding plugin to classpath: " + f); } catch (Exception e) { log.error("Plugin client " + clientName + " bad classpath element: " + f, e); } } if (urls.isEmpty()) return null; return urls.toArray(new URL[urls.size()]); }
private boolean connect() { try { _samSocket = new Socket(_samHost, Integer.parseInt(_samPort)); _samOut = _samSocket.getOutputStream(); _samIn = _samSocket.getInputStream(); return true; } catch (Exception e) { _log.error("Unable to connect to SAM at " + _samHost + ":" + _samPort, e); return false; } }
private boolean writeDest(String dest) { try { FileOutputStream fos = new FileOutputStream(_destFile); fos.write(DataHelper.getASCII(dest)); fos.close(); return true; } catch (Exception e) { _log.error("Error writing to " + _destFile, e); return false; } }
public void streamSendAnswer(int id, String result, String bufferState) throws IOException { if (getStreamSession() == null) { _log.error("BUG! Want to answer to stream SEND, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } if (!writeString( "STREAM SEND ID=" + id + " RESULT=" + result + " STATE=" + bufferState + "\n")) { throw new IOException("Error notifying connection to SAM client"); } }
/** * move the cursor to the next known stat, returning true if a valid * stat is available. * * @return true if a valid stat is available, otherwise false */ public boolean hasMoreStats() { if (_stats.isEmpty()) return false; _currentIsGraphed = false; _currentStatName = (String)_stats.remove(0); RateStat rs = _context.statManager().getRate(_currentStatName); if (rs != null) { _currentStatDescription = rs.getDescription(); if (_currentGroup == null) _currentIsFirstInGroup = true; else if (!rs.getGroupName().equals(_currentGroup)) _currentIsFirstInGroup = true; else _currentIsFirstInGroup = false; _currentGroup = rs.getGroupName(); long period = rs.getPeriods()[0]; // should be the minimum if (period <= 10*60*1000) { Rate r = rs.getRate(period); _currentCanBeGraphed = r != null; if (_currentCanBeGraphed) { // see above //_currentIsGraphed = r.getSummaryListener() != null; _currentGraphName = _currentStatName + "." + period; _currentIsGraphed = _graphs.contains(_currentGraphName); } } else { _currentCanBeGraphed = false; } } else { FrequencyStat fs = _context.statManager().getFrequency(_currentStatName); if (fs != null) { _currentStatDescription = fs.getDescription(); if (_currentGroup == null) _currentIsFirstInGroup = true; else if (!fs.getGroupName().equals(_currentGroup)) _currentIsFirstInGroup = true; else _currentIsFirstInGroup = false; _currentGroup = fs.getGroupName(); _currentCanBeGraphed = false; } else { if (_log.shouldLog(Log.ERROR)) _log.error("Stat does not exist?! [" + _currentStatName + "]"); return false; } } if (_filters.contains("*") || _filters.contains(_currentStatName)) _currentIsLogged = true; else _currentIsLogged = false; return true; }
private byte[] getBytes() { if (_destination == null) return null; if (_options == null) return null; if (_creationDate == null) return null; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { // _log.debug("PubKey size for destination: " + _destination.getPublicKey().getData().length); // _log.debug("SigningKey size for destination: " + // _destination.getSigningPublicKey().getData().length); _destination.writeBytes(out); DataHelper.writeProperties(out, _options, true); // UTF-8 DataHelper.writeDate(out, _creationDate); } catch (IOException ioe) { _log.error("IOError signing", ioe); return null; } catch (DataFormatException dfe) { _log.error("Error writing out the bytes for signing/verification", dfe); return null; } return out.toByteArray(); }
public void stopRawReceiving() { _log.debug("stopRawReceiving() invoked"); if (getRawSession() == null) { _log.error("BUG! Got raw receiving stop, but session is null!"); throw new NullPointerException("BUG! RAW session is null!"); } try { closeClientSocket(); } catch (IOException e) { if (_log.shouldLog(Log.WARN)) _log.warn("Error closing socket", e); } }
public void stopStreamReceiving() { _log.debug("stopStreamReceiving() invoked", new Exception("stopped")); if (getStreamSession() == null) { _log.error("BUG! Got stream receiving stop, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } try { closeClientSocket(); } catch (IOException e) { if (_log.shouldLog(Log.WARN)) _log.warn("Error closing socket", e); } }
public void notifyStreamOutgoingConnection(int id, String result, String msg) throws IOException { if (getStreamSession() == null) { _log.error("BUG! Received stream connection, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } String msgString = ""; if (msg != null) msgString = " MESSAGE=\"" + msg + "\""; if (!writeString("STREAM STATUS RESULT=" + result + " ID=" + id + msgString + "\n")) { throw new IOException("Error notifying connection to SAM client"); } }
/** * Duplicate keys or names rejected, except that duplicate empty names are allowed * * @param key 172 character base64 string * @param name non-null but "" ok * @since 0.7.12 * @return true if successful */ public boolean addKey(String key, String name) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Adding " + name + ": " + key); SigningPublicKey signingPublicKey = new SigningPublicKey(); try { // fromBase64() will throw a DFE if length is not right signingPublicKey.fromBase64(key); } catch (DataFormatException dfe) { _log.error("Invalid signing key for " + name + " : " + key, dfe); return false; } String oldName = _trustedKeys.get(signingPublicKey); // already there? if (name.equals(oldName)) return true; if (oldName != null && !oldName.equals("")) { _log.error("Key for " + name + " already stored for different name " + oldName + " : " + key); return false; } if ((!name.equals("")) && _trustedKeys.containsValue(name)) { _log.error("Key mismatch for " + name + ", spoof attempt? : " + key); return false; } _trustedKeys.put(signingPublicKey, name); return true; }
private String handshake() { synchronized (_samOut) { try { _samOut.write(DataHelper.getASCII("HELLO VERSION MIN=1.0 MAX=1.0\n")); _samOut.flush(); _log.debug("Hello sent"); String serverVersion = _eventHandler.waitForHelloReply(); _log.debug("Hello reply found: " + serverVersion); if (serverVersion == null) throw new IOException("hello failed?"); String req = "SESSION CREATE STYLE=STREAM DESTINATION=" + _destFile + " " + _conOptions + "\n"; _samOut.write(DataHelper.getUTF8(req)); _samOut.flush(); _log.debug("Session create sent"); boolean ok = _eventHandler.waitForSessionCreateReply(); _log.debug("Session create reply found: " + ok); req = "NAMING LOOKUP NAME=ME\n"; _samOut.write(DataHelper.getASCII(req)); _samOut.flush(); _log.debug("Naming lookup sent"); String destination = _eventHandler.waitForNamingReply("ME"); _log.debug("Naming lookup reply found: " + destination); if (destination == null) { _log.error("No naming lookup reply found!"); return null; } else { _log.info(_destFile + " is located at " + destination); } return destination; } catch (Exception e) { _log.error("Error handshaking", e); return null; } } }
/** * Blocking, may take a while */ public synchronized void start() { if (_log.shouldLog(Log.DEBUG)) _log.debug("UPnP Start"); _shouldBeRunning = true; if (!_isRunning) { long b = _context.clock().now(); try { _isRunning = _upnp.runPlugin(); if (_log.shouldLog(Log.INFO)) _log.info("UPnP runPlugin took " + (_context.clock().now() - b)); } catch (Exception e) { // NPE in UPnP (ticket #728), can't let it bring us down if (!_errorLogged) { _log.error("UPnP error, please report", e); _errorLogged = true; } } } if (_isRunning) { _rescanner.schedule(RESCAN_LONG_DELAY); if (_log.shouldLog(Log.DEBUG)) _log.debug("UPnP Start Done"); } else { _rescanner.schedule(RESCAN_SHORT_DELAY); // Do we have a non-loopback, non-broadcast address? // If not, that's why it failed (HTTPServer won't start) if (!Addresses.isConnected()) { if (!_disconLogged) { _log.logAlways(Log.WARN, "UPnP start failed - no network connection?"); _disconLogged = true; } } else { _log.error("UPnP start failed - port conflict?"); } } }
/** @return true on success - caller should call stopPlugin() first */ static boolean deletePlugin(RouterContext ctx, String appName) throws Exception { Log log = ctx.logManager().getLog(PluginStarter.class); File pluginDir = new File(ctx.getConfigDir(), PLUGIN_DIR + '/' + appName); if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) { log.error("Cannot delete nonexistent plugin: " + appName); return false; } // uninstall things in clients.config File clientConfig = new File(pluginDir, "clients.config"); if (clientConfig.exists()) { Properties props = new Properties(); DataHelper.loadProps(props, clientConfig); List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig); runClientApps(ctx, pluginDir, clients, "uninstall"); } // unregister themes, and switch to default if we are unregistering the current theme File dir = new File(pluginDir, "console/themes"); File[] tfiles = dir.listFiles(); if (tfiles != null) { String current = ctx.getProperty(CSSHelper.PROP_THEME_NAME); Map<String, String> changes = new HashMap<String, String>(); List<String> removes = new ArrayList<String>(); for (int i = 0; i < tfiles.length; i++) { String name = tfiles[i].getName(); if (tfiles[i].isDirectory() && (!Arrays.asList(STANDARD_THEMES).contains(tfiles[i]))) { removes.add(ConfigUIHelper.PROP_THEME_PFX + name); if (name.equals(current)) changes.put(CSSHelper.PROP_THEME_NAME, CSSHelper.DEFAULT_THEME); } } ctx.router().saveConfig(changes, removes); } boolean deleted = FileUtil.rmdir(pluginDir, false); Properties props = pluginProperties(); for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { String name = (String) iter.next(); if (name.startsWith(PREFIX + appName + '.')) iter.remove(); } if (!deleted) { // This happens on Windows when there are plugin jars in classpath // Mark it as deleted, we will try again after restart log.logAlways(Log.WARN, "Deletion of " + pluginDir + " failed, will try again at restart"); props.setProperty(PREFIX + appName + ENABLED, DELETED); } storePluginProperties(props); return true; }