/** * @param claimedAddress an IP/port based RemoteHostId, or null if unknown * @param remoteHostId non-null, == claimedAddress if direct, or a hash-based one if indirect * @param addr non-null */ public OutboundEstablishState( RouterContext ctx, RemoteHostId claimedAddress, RemoteHostId remoteHostId, RouterIdentity remotePeer, SessionKey introKey, UDPAddress addr, DHSessionKeyBuilder.Factory dh) { _context = ctx; _log = ctx.logManager().getLog(OutboundEstablishState.class); if (claimedAddress != null) { _bobIP = claimedAddress.getIP(); _bobPort = claimedAddress.getPort(); } else { // _bobIP = null; _bobPort = -1; } _claimedAddress = claimedAddress; _remoteHostId = remoteHostId; _remotePeer = remotePeer; _introKey = introKey; _queuedMessages = new LinkedBlockingQueue<OutNetMessage>(); _establishBegin = ctx.clock().now(); _remoteAddress = addr; _introductionNonce = -1; _keyFactory = dh; if (addr.getIntroducerCount() > 0) { if (_log.shouldLog(Log.DEBUG)) _log.debug( "new outbound establish to " + remotePeer.calculateHash() + ", with address: " + addr); _currentState = OutboundState.OB_STATE_PENDING_INTRO; } else { _currentState = OutboundState.OB_STATE_UNKNOWN; } }
/** * 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.WARN)) _log.warn("Peer " + getRemoteHostId() + " sent us an invalid DH parameter", 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; } }
/** * BLOCKING if queue between here and PacketHandler is full. * * @return zero (was queue size) */ private final int doReceive(UDPPacket packet) { if (!_keepRunning) return 0; if (_log.shouldLog(Log.INFO)) _log.info("Received: " + packet); RemoteHostId from = packet.getRemoteHost(); if (_transport.isInDropList(from)) { if (_log.shouldLog(Log.INFO)) _log.info("Ignoring packet from the drop-listed peer: " + from); _context.statManager().addRateData("udp.ignorePacketFromDroplist", packet.getLifetime()); packet.release(); return 0; } // drop anything apparently from our IP (any port) if (Arrays.equals(from.getIP(), _transport.getExternalIP()) && !_transport.allowLocal()) { if (_log.shouldLog(Log.WARN)) _log.warn("Dropping (spoofed?) packet from ourselves"); packet.release(); return 0; } /** * ** packet.enqueue(); boolean rejected = false; int queueSize = 0; long headPeriod = 0; * * <p>UDPPacket head = _inboundQueue.peek(); if (head != null) { headPeriod = * head.getLifetime(); if (headPeriod > MAX_QUEUE_PERIOD) { rejected = true; } } if (!rejected) * { ** */ try { _handler.queueReceived(packet); } catch (InterruptedException ie) { packet.release(); _keepRunning = false; } // return queueSize + 1; return 0; /** * ** } * * <p>// rejected packet.release(); _context.statManager().addRateData("udp.droppedInbound", * queueSize, headPeriod); if (_log.shouldLog(Log.WARN)) { queueSize = _inboundQueue.size(); * StringBuilder msg = new StringBuilder(); msg.append("Dropping inbound packet with "); * msg.append(queueSize); msg.append(" queued for "); msg.append(headPeriod); msg.append(" * packet handlers: ").append(_transport.getPacketHandlerStatus()); _log.warn(msg.toString()); } * return queueSize; ** */ }