/** * Send a notification to the client that their message (id specified) was accepted for delivery * (but not necessarily delivered) Doesn't do anything if i2cp.messageReliability = "none" or if * the nonce is 0. * * @param id OUR id for the message * @param nonce HIS id for the message */ void ackSendMessage(MessageId id, long nonce) { if (_dontSendMSM || nonce == 0) return; SessionId sid = _sessionId; if (sid == null) return; if (_log.shouldLog(Log.DEBUG)) _log.debug("Acking message send [accepted]" + id + " / " + nonce + " for sessionId " + sid); MessageStatusMessage status = new MessageStatusMessage(); status.setMessageId(id.getMessageId()); status.setSessionId(sid.getSessionId()); status.setSize(0L); status.setNonce(nonce); status.setStatus(MessageStatusMessage.STATUS_SEND_ACCEPTED); try { doSend(status); _acceptedPending.remove(id); } catch (I2CPMessageException ime) { if (_log.shouldLog(Log.WARN)) _log.warn("Error writing out the message status message", ime); } }
/** * Note that this sends the Guaranteed status codes, even though we only support best effort. */ public void runJob() { if (_dead) return; MessageStatusMessage msg = new MessageStatusMessage(); msg.setMessageId(_messageId.getMessageId()); msg.setSessionId(_sessionId.getSessionId()); // has to be >= 0, it is initialized to -1 msg.setNonce(2); msg.setSize(0); msg.setStatus(_status); if (!alreadyAccepted(_messageId)) { if (_requeueCount++ > MAX_REQUEUE) { // bug requeueing forever? failsafe _log.error( "Abandon update for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) + " for session " + _sessionId.getSessionId()); } else { if (_log.shouldLog(Log.WARN)) _log.warn( "Almost send an update for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) + " for session " + _sessionId.getSessionId() + " before they knew the messageId! delaying .5s"); _lastTried = _context.clock().now(); requeue(REQUEUE_DELAY); } return; } boolean alreadyProcessed = false; long beforeLock = _context.clock().now(); long inLock = 0; synchronized (_alreadyProcessed) { inLock = _context.clock().now(); if (_alreadyProcessed.contains(_messageId)) { _log.warn("Status already updated"); alreadyProcessed = true; } else { _alreadyProcessed.add(_messageId); while (_alreadyProcessed.size() > 10) _alreadyProcessed.remove(0); } } long afterLock = _context.clock().now(); if (afterLock - beforeLock > 50) { _log.warn( "MessageDeliveryStatusUpdate.locking took too long: " + (afterLock - beforeLock) + " overall, synchronized took " + (inLock - beforeLock)); } if (alreadyProcessed) return; if (_lastTried > 0) { if (_log.shouldLog(Log.DEBUG)) _log.info( "Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) + " for session " + _sessionId.getSessionId() + " (with nonce=2), retrying after " + (_context.clock().now() - _lastTried)); } else { if (_log.shouldLog(Log.DEBUG)) _log.debug( "Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) + " for session " + _sessionId.getSessionId() + " (with nonce=2)"); } try { doSend(msg); } catch (I2CPMessageException ime) { if (_log.shouldLog(Log.WARN)) _log.warn("Error updating the status for message ID " + _messageId, ime); } }