Author: zothar
Date: 2006-08-20 22:55:18 +0000 (Sun, 20 Aug 2006)
New Revision: 10219

Modified:
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/PacketSender.java
   trunk/freenet/src/freenet/node/PeerNode.java
Log:
Now N2NTMs can be sent to multiple peers at once and N2NTMs to disconnected 
peers are queued until they connect.  Theme owners should take a look as this 
and my last commit probably need some fiddling to look right, etc.  Calling 
maybeOnConnect() from PacketSender seems like a hack, but calling onConnect() 
from the end of completedHandshake() seemed unreliable, in that the queued 
N2NTM didn't go through, but repeating the disconnect/connect cycle caused it 
to go through.  Perhaps another dev can improve on things.

Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-08-20 20:57:44 UTC (rev 10218)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-08-20 22:55:18 UTC (rev 10219)
@@ -339,7 +339,7 @@
                                peerRow.addChild("td", "class", 
"peer-status").addChild("span", "class", peerNodeStatus.getStatusCSSName(), 
statusString + (peerNodeStatus.isFetchingARK() ? "*" : ""));

                                // name column
-                               if (peerNodeStatus.isConnected() && 
(Integer.parseInt(peerNodeStatus.getSimpleVersion()) > 476)) {
+                               if 
(Integer.parseInt(peerNodeStatus.getSimpleVersion()) > 476) {
                                        peerRow.addChild("td", "class", 
"peer-name").addChild("a", "href", "/send_n2ntm/?peernode_hashcode=" + 
peerNodeStatus.hashCode(), peerNodeStatus.getName());
                                } else {
                                        peerRow.addChild("td", "class", 
"peer-name").addChild("#", peerNodeStatus.getName());  // TODO: This branch can 
probably be removed at some point
@@ -447,7 +447,7 @@

                        HTMLNode actionSelect = peerForm.addChild("select", 
"name", "action");
                        actionSelect.addChild("option", "value", "", "-- Select 
action --");
-                       //actionSelect.addChild("option", "value", 
"send_n2ntm", "Send N2NTM to selected peers");  // Disabled until we have 
queue-for-send-on-connect
+                       actionSelect.addChild("option", "value", "send_n2ntm", 
"Send N2NTM to selected peers");
                        actionSelect.addChild("option", "value", 
"update_notes", "Update changed private notes");
                        if(advancedEnabled) {
                                actionSelect.addChild("option", "value", 
"enable", "Enable selected peers");

Modified: trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-08-20 
20:57:44 UTC (rev 10218)
+++ trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-08-20 
22:55:18 UTC (rev 10219)
@@ -13,9 +13,11 @@
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
 import freenet.node.PeerNode;
+import freenet.support.Base64;
 import freenet.support.HTMLNode;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.SimpleFieldSet;
 import freenet.support.io.Bucket;

 public class N2NTMToadlet extends Toadlet {
@@ -130,9 +132,16 @@
                                        try {
                                                Message n2ntm = 
DMT.createNodeToNodeTextMessage(Node.N2N_TEXT_MESSAGE_TYPE_USERALERT, 
node.getMyName(), pn.getName(), message);
                                                if(!pn.isConnected()) {
-                                                       sendStatusShort = 
"Failed";
-                                                       sendStatusLong = "Not 
connected: Message not sent to peer";
-                                                       sendStatusClass = 
"n2ntm-send-failed";
+                                                       sendStatusShort = 
"Queued";
+                                                       sendStatusLong = 
"Queued: Peer not connected, so message queued for when it connects";
+                                                       sendStatusClass = 
"n2ntm-send-queued";
+                                                       SimpleFieldSet fs = new 
SimpleFieldSet();
+                                                       fs.put("type", 
Integer.toString(Node.N2N_TEXT_MESSAGE_TYPE_USERALERT));
+                                                       
fs.put("source_nodename", Base64.encode(node.getMyName().getBytes()));
+                                                       
fs.put("target_nodename", Base64.encode(pn.getName().getBytes()));
+                                                       fs.put("text", 
Base64.encode(message.getBytes()));
+                                                       pn.queueN2NTM(fs);
+                                                       Logger.normal(this, 
"Queued N2NTM to '"+pn.getName()+"': "+message);
                                                } else 
if(pn.getPeerNodeStatus() == Node.PEER_NODE_STATUS_ROUTING_BACKED_OFF) {
                                                        sendStatusShort = 
"Delayed";
                                                        sendStatusLong = 
"Backed off: Sending of message possibly delayed to peer";

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-08-20 20:57:44 UTC (rev 
10218)
+++ trunk/freenet/src/freenet/node/Node.java    2006-08-20 22:55:18 UTC (rev 
10219)
@@ -394,6 +394,7 @@
        public static final int N2N_TEXT_MESSAGE_TYPE_USERALERT = 1;
        public static final int EXTRA_PEER_DATA_TYPE_N2NTM = 1;
        public static final int EXTRA_PEER_DATA_TYPE_PEER_NOTE = 2;
+       public static final int EXTRA_PEER_DATA_TYPE_QUEUED_TO_SEND_N2NTM = 3;
        public static final int PEER_NOTE_TYPE_PRIVATE_DARKNET_COMMENT = 1;

        public final long bootID;

Modified: trunk/freenet/src/freenet/node/PacketSender.java
===================================================================
--- trunk/freenet/src/freenet/node/PacketSender.java    2006-08-20 20:57:44 UTC 
(rev 10218)
+++ trunk/freenet/src/freenet/node/PacketSender.java    2006-08-20 22:55:18 UTC 
(rev 10219)
@@ -158,6 +158,7 @@
             PeerNode pn = nodes[i];
             lastReceivedPacketFromAnyNode =
                 Math.max(pn.lastReceivedPacketTime(), 
lastReceivedPacketFromAnyNode);
+                       pn.maybeOnConnect();
             if(pn.isConnected()) {

                if(pn.isRoutable() && pn.shouldDisconnectNow()) {

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2006-08-20 20:57:44 UTC 
(rev 10218)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2006-08-20 22:55:18 UTC 
(rev 10219)
@@ -127,6 +127,10 @@
      */
     private boolean isConnected;
     private boolean isRoutable;
+
+    /** Used by maybeOnConnect */
+    private boolean wasDisconnected;
+    
     /**
      * ARK fetcher.
      */
@@ -277,6 +281,9 @@
     /** Private comment on the peer for /darknet/ page's extra peer data file 
number */
     private int privateDarknetCommentFileNumber;

+    /** Queued-to-send N2NTM extra peer data file numbers */
+    private Vector queuedToSendN2NTMExtraPeerDataFileNumbers;
+    
     /**
      * Create a PeerNode from a SimpleFieldSet containing a
      * node reference for one. This must contain the following
@@ -515,12 +522,17 @@
         // status may have changed from PEER_NODE_STATUS_DISCONNECTED to 
PEER_NODE_STATUS_NEVER_CONNECTED
         setPeerNodeStatus(now);

+               // Setup the private darknet comment note
         privateDarknetComment = new String();
         privateDarknetCommentFileNumber = -1;

                // Setup the extraPeerDataFileNumbers
                extraPeerDataFileNumbers = new Vector();
                extraPeerDataFileNumbers.removeAllElements();
+               
+               // Setup the queuedToSendN2NTMExtraPeerDataFileNumbers
+               queuedToSendN2NTMExtraPeerDataFileNumbers = new Vector();
+               queuedToSendN2NTMExtraPeerDataFileNumbers.removeAllElements();
     }

     private boolean parseARK(SimpleFieldSet fs, boolean onStartup) {
@@ -1378,6 +1390,9 @@
                synchronized(this) {
                        sentInitialMessages = false;
                }
+               if(isConnected()) {
+                       onConnect();
+               }
                return true;
     }

@@ -2387,6 +2402,25 @@
                return !gotError;
        }

+       public boolean rereadExtraPeerDataFile(int fileNumber) {
+               String extraPeerDataDirPath = node.getExtraPeerDataDir();
+               File extraPeerDataPeerDir = new 
File(extraPeerDataDirPath+File.separator+getIdentityString());
+               if(!extraPeerDataPeerDir.exists()) {
+                       Logger.error(this, "Extra peer data directory for peer 
does not exist: "+extraPeerDataPeerDir.getPath());
+                       return false;
+               }
+               if(!extraPeerDataPeerDir.isDirectory()) {
+                       Logger.error(this, "Extra peer data directory for peer 
not a directory: "+extraPeerDataPeerDir.getPath());
+                       return false;
+               }
+               File extraPeerDataFile = new 
File(extraPeerDataDirPath+File.separator+getIdentityString()+File.separator+fileNumber);
+               if(!extraPeerDataFile.exists()) {
+                       Logger.error(this, "Extra peer data file for peer does 
not exist: "+extraPeerDataFile.getPath());
+                       return false;
+               }
+               return readExtraPeerDataFile(extraPeerDataFile, fileNumber);
+       }
+
        public boolean readExtraPeerDataFile(File extraPeerDataFile, int 
fileNumber) {
                boolean gotError = false;
                if(!extraPeerDataFile.exists()) {
@@ -2465,6 +2499,41 @@
                        }
                        Logger.error(this, "Read unknown peer note type 
'"+peerNoteType+"' from file "+extraPeerDataFile.getPath());
                        return false;
+               } else if(extraPeerDataType == 
Node.EXTRA_PEER_DATA_TYPE_QUEUED_TO_SEND_N2NTM) {
+                       boolean sendSuccess = false;
+                       if(isConnected()) {
+                               String source_nodename = null;
+                               String target_nodename = null;
+                               String text = null;
+                               try {
+                                       source_nodename = new 
String(Base64.decode(fs.get("source_nodename")));
+                                       target_nodename = new 
String(Base64.decode(fs.get("target_nodename")));
+                                       text = new 
String(Base64.decode(fs.get("text")));
+                               } catch (IllegalBase64Exception e) {
+                                       Logger.error(this, "Bad Base64 encoding 
when decoding a N2NTM SimpleFieldSet", e);
+                                       return false;
+                               }
+                               Message n2ntm = 
DMT.createNodeToNodeTextMessage(Node.N2N_TEXT_MESSAGE_TYPE_USERALERT, 
source_nodename, target_nodename, text);
+                               try {
+                                       node.usm.send(this, n2ntm, null);
+                                       Logger.normal(this, "Sent N2NTM to 
'"+getName()+"': "+text);
+                                       sendSuccess = true;
+                                       
synchronized(queuedToSendN2NTMExtraPeerDataFileNumbers) {
+                                               
if(queuedToSendN2NTMExtraPeerDataFileNumbers.contains(new Integer(fileNumber))) 
{
+                                                       
queuedToSendN2NTMExtraPeerDataFileNumbers.addElement(new Integer(fileNumber));
+                                               }
+                                       }
+                                       deleteExtraPeerDataFile(fileNumber);
+                               } catch (NotConnectedException e) {
+                                       sendSuccess = false;  // redundant, but 
clear
+                               }
+                       }
+                       if(!sendSuccess) {
+                               
synchronized(queuedToSendN2NTMExtraPeerDataFileNumbers) {
+                                       
queuedToSendN2NTMExtraPeerDataFileNumbers.addElement(new Integer(fileNumber));
+                               }
+                       }
+                       return true;
                }
                Logger.error(this, "Read unknown extra peer data type 
'"+extraPeerDataType+"' from file "+extraPeerDataFile.getPath());
                return false;
@@ -2617,4 +2686,42 @@
                        rewriteExtraPeerDataFile(fs, 
Node.EXTRA_PEER_DATA_TYPE_PEER_NOTE, localFileNumber);
                }
        }
+
+       public void queueN2NTM(SimpleFieldSet fs) {
+               int fileNumber = writeNewExtraPeerDataFile( fs, 
Node.EXTRA_PEER_DATA_TYPE_QUEUED_TO_SEND_N2NTM);
+               synchronized(queuedToSendN2NTMExtraPeerDataFileNumbers) {
+                       
queuedToSendN2NTMExtraPeerDataFileNumbers.addElement(new Integer(fileNumber));
+               }
+       }
+
+       public void sendQueuedN2NTMs() {
+               Integer[] localFileNumbers = null;
+               synchronized(queuedToSendN2NTMExtraPeerDataFileNumbers) {
+                       localFileNumbers = (Integer[]) 
queuedToSendN2NTMExtraPeerDataFileNumbers.toArray(new 
Integer[queuedToSendN2NTMExtraPeerDataFileNumbers.size()]);
+               }
+               Arrays.sort(localFileNumbers);
+               for (int i = 0; i < localFileNumbers.length; i++) {
+                       rereadExtraPeerDataFile(localFileNumbers[i].intValue());
+               }
+       }
+
+       public void maybeOnConnect() {
+               if(wasDisconnected && isConnected()) {
+                       synchronized(this) {
+                               wasDisconnected = false;
+                       }
+                       onConnect();
+               } else if(!isConnected()) {
+                       synchronized(this) {
+                               wasDisconnected = true;
+                       }
+               }
+       }
+
+       /**
+        * A method to be called once at the beginning of every time 
isConnected() is true
+        */
+       private void onConnect() {
+               sendQueuedN2NTMs();
+       }
 }


Reply via email to