protected synchronized void punchHole() { if (!this.doHolePunching) return; if (this.lastSendDest == null) return; long curTime = System.currentTimeMillis(); long interval = this.config.getPunchingInterval(); if (curTime < this.lastSendTime + interval) return; // ask self exterior address to an other node Message reqMsg = UDPMessagingMessageFactory.getPunchHoleReqMessage( IDAddressPair.getIDAddressPair(null, this.selfAddr)); synchronized (this.punchingLock) { this.punchReplyReceived = false; try { this.sender.send(this.lastSendDest, reqMsg); } catch (IOException e) { logger.log( Level.WARNING, "Could not send an PUNCH_HOLE_REQ message for UDP hole punching: " + this.lastSendDest + " on " + this.selfAddr, e); return; } // wait for a reply if (!this.punchReplyReceived) { try { this.punchingLock.wait(this.config.getPunchingRepTimeout()); } catch (InterruptedException e) { // do nothing } } this.endFirstPunching(this.punchReplyReceived); if (!this.punchReplyReceived) { logger.log( Level.WARNING, "Could not receive an PUNCH_HOLE_REP message for UDP hole punching: " + this.lastSendDest + " on " + this.selfAddr); } } // synchronized (this.punchingLock) }
public void run() { Thread.currentThread().setName("UDPMessageHandler: " + this.srcAddr); // handling an incoming message int tag = msg.getTag(); Message ret = null; if (tag == Tag.PUNCH_HOLE_REQ.getNumber()) { // for UDP hole punching MessagingAddress src = provider.getMessagingAddress(this.srcAddr); ret = UDPMessagingMessageFactory.getPunchHoleRepMessage( IDAddressPair.getIDAddressPair(null, selfAddr), (InetMessagingAddress) src); } else if (tag == Tag.PUNCH_HOLE_REP.getNumber()) { // for UDP hole punching // notify synchronized (punchingLock) { punchReplyReceived = true; punchingLock.notifyAll(); } if (doHolePunching) { Serializable[] contents = msg.getContents(); InetMessagingAddress selfExteriorAddress = (InetMessagingAddress) contents[0]; logger.log( Level.INFO, "UDP hole punching: self exterior address is " + selfExteriorAddress); if (selfExteriorAddress.equals(selfAddr)) { // UDP hole punching is not required logger.log(Level.INFO, "UDP hole punching was *not* required."); } else { // set self address UDPMessageReceiver.this.selfAddr = selfExteriorAddress; synchronized (UDPMessageReceiver.this) { if (holePunchingDaemon == null) { logger.log(Level.INFO, "UDP hole punching is required."); // start punching daemon Runnable r = new UDPHolePunchingDaemon(); holePunchingDaemon = new Thread(r); holePunchingDaemon.setName("UDPHolePunchingDaemon"); holePunchingDaemon.setDaemon(true); holePunchingDaemon.start(); } } } } } else { // process the received message ret = processMessage(msg); } // return a Message (from the last handler) if (ret != null) { logger.log(Level.INFO, "Return a message."); MessagingAddress src = (msg.getSource() != null ? msg.getSource().getAddress() : null); try { ByteBuffer buf = sender.send(sock, this.srcAddr, src, ret, true); // notify statistics collector if (src != null) { msgReporter.notifyStatCollectorOfMessageSent(src, ret, buf.remaining()); } } catch (IOException e) { logger.log(Level.WARNING, "Could not return a message."); // notify statistics collector if (src != null) { msgReporter.notifyStatCollectorOfDeletedNode(ret.getSource(), src, ret.getTag()); } } } else { logger.log(Level.INFO, "Return no message."); } if (tag != Tag.PUNCH_HOLE_REQ.getNumber() && tag != Tag.PUNCH_HOLE_REP.getNumber()) { // not for UDP hole punching // post-process postProcessMessage(msg); } handlerThreads.remove(Thread.currentThread()); Thread.currentThread().setName(MessagingFactory.DEFAULT_POOLED_THREAD_NAME); }