Author: zothar
Date: 2006-05-27 00:53:10 +0000 (Sat, 27 May 2006)
New Revision: 8879

Added:
   trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
   trunk/freenet/src/freenet/node/useralerts/N2NTMUserAlert.java
Modified:
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/io/comm/DMT.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeDispatcher.java
Log:
Added very basic, unthemed local node to node text message support.  Feel free 
to make it look better. :)

Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-05-26 19:30:28 UTC (rev 8878)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-05-27 00:53:10 UTC (rev 8879)
@@ -33,8 +33,8 @@
                        Integer stat1 = (Integer) row1[2];
                        int x = stat0.compareTo(stat1);
                        if(x != 0) return x;
-                       String name0 = (String) row0[3];  // 3 = node name
-                       String name1 = (String) row1[3];
+                       String name0 = (String) row0[9];  // 9 = node name
+                       String name1 = (String) row1[9];
                        return 
name0.toLowerCase().compareTo(name1.toLowerCase());
                }

@@ -114,7 +114,7 @@
                                long idle = pn.lastReceivedPacketTime();

                                // Elements must be HTML encoded.
-                               Object[] row = new Object[9];  // where [0] is 
the pn object!
+                               Object[] row = new Object[10];  // where [0] is 
the pn object and 9 is the node name only for sorting!
                                rows[i] = row;

                                Object status = new 
Integer(pn.getPeerNodeStatus());
@@ -132,18 +132,24 @@
                                        VersionPrefixString = "<span 
class=\"peer_version_problem\">";
                                        VersionSuffixString = "</span>";
                                }
+                               String NamePrefixString = "";
+                               String NameSuffixString = "";
+                               if(pn.isConnected()) {
+                                 NamePrefixString = "<a 
href=\"/send_n2ntm/?peernode_hashcode="+pn.hashCode()+"\">";
+                                 NameSuffixString = "</a>";
+                               }

                                row[0] = pn;
                                row[1] = "<input type=\"checkbox\" 
name=\"delete_node_"+pn.hashCode()+"\" />";
                                row[2] = status;
-                               row[3] = HTMLEncoder.encode(pn.getName());
+                               row[3] = 
NamePrefixString+HTMLEncoder.encode(pn.getName())+NameSuffixString;
                                row[4] = ( pn.getDetectedPeer() != null ? 
HTMLEncoder.encode(pn.getDetectedPeer().toString()) : "(address unknown)" ) + 
avgPingTimeString;
                                row[5] = 
VersionPrefixString+HTMLEncoder.encode(pn.getVersion())+VersionSuffixString;
                                row[6] = new 
Double(pn.getLocation().getValue());
                                row[7] = backoff/1000 + "/" + 
pn.getRoutingBackoffLength()/1000+lastBackoffReasonOutputString;
                                if (idle == -1) row[8] = " ";
                                else row[8] = new Long((now - idle) / 60000);
-                               
+                               row[9] = HTMLEncoder.encode(pn.getName());
                        }

                        // Sort array
@@ -180,6 +186,8 @@
                                Object[] row = rows[i];
                                buf2.append("<tr>");
                                for(int j=1;j<row.length;j++) {  // skip index 
0 as it's the PeerNode object
+                                 if(j == 9) // skip index 9 as it's used for 
sorting purposes only
+                                   continue;
                                        buf2.append("<td>"+row[j]+"</td>");
                                }
                                buf2.append("</tr>\n");
@@ -393,7 +401,7 @@
                        headers.put("Location", "/darknet/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
-               }else{
+               } else {
                        this.handleGet(uri, ctx);
                }
        }

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-05-26 
19:30:28 UTC (rev 8878)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-05-27 
00:53:10 UTC (rev 8879)
@@ -355,6 +355,9 @@
                        DarknetConnectionsToadlet darknetToadlet = new 
DarknetConnectionsToadlet(node, client);
                        server.register(darknetToadlet, "/darknet/", true);

+                       N2NTMToadlet n2ntmToadlet = new N2NTMToadlet(node, 
client);
+                       server.register(n2ntmToadlet, "/send_n2ntm/", true);
+                       
                        QueueToadlet queueToadlet = new 
QueueToadlet(node.getFCPServer(), client);
                        server.register(queueToadlet, "/queue/", true);


Added: trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-05-26 
19:30:28 UTC (rev 8878)
+++ trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-05-27 
00:53:10 UTC (rev 8879)
@@ -0,0 +1,158 @@
+package freenet.clients.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.io.comm.DMT;
+import freenet.io.comm.Message;
+import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.UdpSocketManager;
+import freenet.node.FSParseException;
+import freenet.node.Node;
+import freenet.node.PeerNode;
+import freenet.node.Version;
+import freenet.support.Bucket;
+import freenet.support.HTMLEncoder;
+import freenet.support.Logger;
+import freenet.support.MultiValueTable;
+import freenet.support.SimpleFieldSet;
+
+public class N2NTMToadlet extends Toadlet {
+
+  private Node node;
+  private UdpSocketManager usm;
+  
+  protected N2NTMToadlet(Node n, HighLevelSimpleClient client) {
+    super(client);
+    this.node = n;
+    this.usm = n.getUSM();
+  }
+
+  public String supportedMethods() {
+    return "GET, POST";
+  }
+
+  public void handleGet(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
+    
+    HTTPRequest request = new HTTPRequest(uri, null, ctx);
+    StringBuffer buf = new StringBuffer(1024);
+    if (request.isParameterSet("peernode_hashcode")) {
+      ctx.getPageMaker().makeHead(buf, "Send Node To Node Text Message");
+      String peernode_name = null;
+      String input_hashcode_string = request.getParam("peernode_hashcode");
+      int input_hashcode = -1;
+      try {
+        input_hashcode = (new Integer(input_hashcode_string)).intValue();
+      } catch (NumberFormatException e) {
+        // ignore here, handle below
+      }
+      if(input_hashcode != -1) {
+        PeerNode[] peerNodes = node.getDarknetConnections();
+        for(int i = 0; i < peerNodes.length; i++) {
+          int peer_hashcode = peerNodes[i].hashCode();
+          if(peer_hashcode == input_hashcode) {
+            peernode_name = peerNodes[i].getName();
+            break;
+          }
+        }
+      }
+      if(peernode_name == null) {
+        buf.append("PeerNode.hashCode '"+input_hashcode_string+"' not 
found.<br /><br />\n");
+        buf.append("<a href=\"/darknet/\">Back to Darknet page</a>\n");
+        ctx.getPageMaker().makeTail(buf);
+        this.writeReply(ctx, 200, "text/html", "OK", buf.toString());
+        return;
+      }
+      buf.append("<b>Sending Node To Node Text Message to 
"+HTMLEncoder.encode(peernode_name)+":</b><br />\n");
+      buf.append("<form action=\".\" method=\"post\" 
enctype=\"multipart/form-data\">\n");
+      buf.append("<input type=\"hidden\" name=\"hashcode\" 
value=\""+input_hashcode_string+"\" />\n");
+      buf.append("<textarea id=\"n2ntmtext\" name=\"message\" rows=\"8\" 
cols=\"74\"></textarea><br />\n");
+      buf.append("<input type=\"submit\" name=\"send\" value=\"Send message to 
"+HTMLEncoder.encode(peernode_name)+"\" />\n");
+      buf.append("</form>\n");
+      ctx.getPageMaker().makeTail(buf);
+      this.writeReply(ctx, 200, "text/html", "OK", buf.toString());
+      return;
+    }
+    MultiValueTable headers = new MultiValueTable();
+    headers.put("Location", "/darknet/");
+    ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+  }
+  
+  public void handlePost(URI uri, Bucket data, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
+    if(data.size() > 1024*1024) {
+      this.writeReply(ctx, 400, "text/plain", "Too big", "Too much data, 
darknet toadlet limited to 1MB");
+      return;
+    }
+    
+    HTTPRequest request = new HTTPRequest(uri, data, ctx);
+    StringBuffer buf = new StringBuffer(1024);
+    
+    if (request.isPartSet("send")) {
+      String message = request.getPartAsString("message", 2000);
+      message = message.trim();
+      PeerNode pn = null;
+      String input_hashcode_string = request.getPartAsString("hashcode", 2000);
+      request.freeParts();
+                       input_hashcode_string = input_hashcode_string.trim();
+      int input_hashcode = -1;
+      try {
+        input_hashcode = (new Integer(input_hashcode_string)).intValue();
+      } catch (NumberFormatException e) {
+        // ignore here, handle below
+      }
+      if(input_hashcode != -1) {
+        PeerNode[] peerNodes = node.getDarknetConnections();
+        for(int i = 0; i < peerNodes.length; i++) {
+          int peer_hashcode = peerNodes[i].hashCode();
+          if(peer_hashcode == input_hashcode) {
+            pn = peerNodes[i];
+            break;
+          }
+        }
+      }
+      if(pn == null) {
+        buf.append("PeerNode.hashCode '"+input_hashcode_string+"' not 
found.<br /><br />\n");
+        buf.append("<a href=\"/darknet/\">Back to Darknet page</a>\n");
+        ctx.getPageMaker().makeTail(buf);
+        this.writeReply(ctx, 200, "text/html", "OK", buf.toString());
+        return;
+      }
+      try {
+        Message n2ntm = 
DMT.createNodeToNodeTextMessage(Node.N2N_TEXT_MESSAGE_TYPE_USERALERT, 
node.getMyName(), pn.getName(), message);
+        if(pn == null) {
+          buf.append("PeerNode.hashCode '"+request.getParam("hashcode")+"' not 
found.<br /><br />\n");
+        } else if(!pn.isConnected()) {
+          buf.append("Peer '"+HTMLEncoder.encode(pn.getName())+"' is not 
connected.  Not sending N2NTM.<br /><br />\n");
+        } else if(pn.getPeerNodeStatus() == 
Node.PEER_NODE_STATUS_ROUTING_BACKED_OFF) {
+          buf.append("Peer '"+HTMLEncoder.encode(pn.getName())+"' is \"backed 
off\".  N2NTM receipt may be significantly delayed.<br /><br />\n");
+          usm.send(pn, n2ntm);
+          buf.append("Message should be on it's way.<br /><br />\n");
+        } else {
+          buf.append("Sending N2NTM to peer 
'"+HTMLEncoder.encode(pn.getName())+"'.<br /><br />\n");
+          usm.send(pn, n2ntm);
+          buf.append("Message should be on it's way.<br /><br />\n");
+        }
+      } catch (NotConnectedException e) {
+        buf.append("Got NotConnectedException sending message to Peer 
'"+HTMLEncoder.encode(pn.getName())+"'.  Can't send N2NTM.<br /><br />\n");
+        Logger.error(this, "Caught NotConnectedException while trying to send 
n2ntm: "+e);
+      }
+      buf.append("<a href=\"/darknet/\">Back to Darknet page</a>\n");
+      ctx.getPageMaker().makeTail(buf);
+      this.writeReply(ctx, 200, "text/html", "OK", buf.toString());
+      return;
+    }
+    MultiValueTable headers = new MultiValueTable();
+    headers.put("Location", "/darknet/");
+    ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+  }
+}

Modified: trunk/freenet/src/freenet/io/comm/DMT.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/DMT.java  2006-05-26 19:30:28 UTC (rev 
8878)
+++ trunk/freenet/src/freenet/io/comm/DMT.java  2006-05-27 00:53:10 UTC (rev 
8879)
@@ -84,6 +84,10 @@
     public static final String PUBKEY_HASH = "pubkeyHash";
     public static final String NEED_PUB_KEY = "needPubKey";
     public static final String PUBKEY_AS_BYTES = "pubkeyAsBytes";
+    public static final String SOURCE_NODENAME = "sourceNodename";
+    public static final String TARGET_NODENAME = "targetNodename";
+    public static final String NODE_TO_NODE_MESSAGE_TYPE = 
"nodeToNodeMessageType";
+    public static final String NODE_TO_NODE_MESSAGE_TEXT = 
"nodeToNodeMessageText";

        //Diagnostic
        public static final MessageType ping = new MessageType("ping") {{
@@ -343,6 +347,23 @@
         return msg;
     }

+    // Node-To-Node Instant Message
+    public static final MessageType nodeToNodeTextMessage = new 
MessageType("nodeToNodeTextMessage", false) {{
+        addField(NODE_TO_NODE_MESSAGE_TYPE, Integer.class);
+        addField(SOURCE_NODENAME, String.class);
+        addField(TARGET_NODENAME, String.class);
+        addField(NODE_TO_NODE_MESSAGE_TEXT, String.class);
+    }};
+
+    public static final Message createNodeToNodeTextMessage(int type, String 
source, String target, String message) {
+        Message msg = new Message(nodeToNodeTextMessage);
+        msg.set(NODE_TO_NODE_MESSAGE_TYPE, type);
+        msg.set(SOURCE_NODENAME, source);
+        msg.set(TARGET_NODENAME, target);
+        msg.set(NODE_TO_NODE_MESSAGE_TEXT, message);
+        return msg;
+    }
+
     // FNP messages
     public static final MessageType FNPCHKDataRequest = new 
MessageType("FNPCHKDataRequest") {{
         addField(UID, Long.class);

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-05-26 19:30:28 UTC (rev 
8878)
+++ trunk/freenet/src/freenet/node/Node.java    2006-05-27 00:53:10 UTC (rev 
8879)
@@ -92,6 +92,7 @@
 import freenet.node.useralerts.BuildOldAgeUserAlert;
 import freenet.node.useralerts.IPUndetectedUserAlert;
 import freenet.node.useralerts.MeaningfulNodeNameUserAlert;
+import freenet.node.useralerts.N2NTMUserAlert;
 import freenet.node.useralerts.UserAlertManager;
 import freenet.pluginmanager.PluginManager;
 import freenet.store.BerkeleyDBFreenetStore;
@@ -536,6 +537,7 @@
     public static final int PEER_NODE_STATUS_TOO_NEW = 3;
     public static final int PEER_NODE_STATUS_TOO_OLD = 4;
     public static final int PEER_NODE_STATUS_DISCONNECTED = 5;
+    public static final int N2N_TEXT_MESSAGE_TYPE_USERALERT = 1;

     public final long bootID;
     public final long startupTime;
@@ -2889,4 +2891,30 @@
         nextPeerNodeStatusLogTime = now + peerNodeStatusLogInterval;
       }
     }
+
+    /**
+     * Handle a received node to node text message
+     */
+    public void receivedNodeToNodeTextMessage(Message m) {
+      PeerNode source = (PeerNode)m.getSource();
+      int type = ((Integer) 
m.getObject(DMT.NODE_TO_NODE_MESSAGE_TYPE)).intValue();
+      if(type == Node.N2N_TEXT_MESSAGE_TYPE_USERALERT) {
+        String source_nodename = (String) m.getObject(DMT.SOURCE_NODENAME);
+        String target_nodename = (String) m.getObject(DMT.TARGET_NODENAME);
+        String text = (String) m.getObject(DMT.NODE_TO_NODE_MESSAGE_TEXT);
+        Logger.normal(this, "Received N2NTM from '"+source_nodename+"' to 
'"+target_nodename+"': "+text);
+        N2NTMUserAlert userAlert = new N2NTMUserAlert(source_nodename, 
target_nodename, text);
+                   alerts.register(userAlert);
+      } else {
+        Logger.error(this, "Received unknown node to node message type 
'"+type+"' from "+source.getPeer());
+      }
+    }
+
+    public String getMyName() {
+      return myName;
+    }
+
+    public UdpSocketManager getUSM() {
+      return usm;
+    }
 }

Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeDispatcher.java  2006-05-26 19:30:28 UTC 
(rev 8878)
+++ trunk/freenet/src/freenet/node/NodeDispatcher.java  2006-05-27 00:53:10 UTC 
(rev 8879)
@@ -40,7 +40,8 @@
     public boolean handleMessage(Message m) {
         PeerNode source = (PeerNode)m.getSource();
         Logger.minor(this, "Dispatching "+m);
-        if(m.getSpec() == DMT.FNPPing) {
+        MessageType spec = m.getSpec();
+        if(spec == DMT.FNPPing) {
             // Send an FNPPong
             Message reply = DMT.createFNPPong(m.getInt(DMT.PING_SEQNO));
             try {
@@ -50,7 +51,6 @@
             }
             return true;
         }
-        MessageType spec = m.getSpec();
         if(spec == DMT.FNPLocChangeNotification) {
             double newLoc = m.getDouble(DMT.LOCATION);
             source.updateLocation(newLoc);
@@ -94,6 +94,9 @@
                node.redetectAddress();
         } else if(spec == DMT.FNPVoid) {
                return true;
+        } else if(spec == DMT.nodeToNodeTextMessage) {
+               node.receivedNodeToNodeTextMessage(m);
+               return true;
         }
         return false;
     }

Added: trunk/freenet/src/freenet/node/useralerts/N2NTMUserAlert.java
===================================================================
--- trunk/freenet/src/freenet/node/useralerts/N2NTMUserAlert.java       
2006-05-26 19:30:28 UTC (rev 8878)
+++ trunk/freenet/src/freenet/node/useralerts/N2NTMUserAlert.java       
2006-05-27 00:53:10 UTC (rev 8879)
@@ -0,0 +1,45 @@
+package freenet.node.useralerts;
+
+import freenet.support.HTMLEncoder;
+
+// Node To Node Text Message User Alert
+public class N2NTMUserAlert implements UserAlert {
+       private boolean isValid=true;
+       public int lastGoodVersion = 0;
+       private String source_nodename;
+       private String target_nodename;
+       private String message_text;
+
+       public N2NTMUserAlert(String source, String target, String message) {
+               this.source_nodename = source;
+               this.target_nodename = target;
+               this.message_text = message;
+               isValid=true;
+       }
+       
+       public boolean userCanDismiss() {
+               return true;
+       }
+
+       public String getTitle() {
+               return "Node To Node Text Message";
+       }
+       
+       public String getText() {
+               String s;
+               s = "You, as nodename 
'"+HTMLEncoder.encode(target_nodename)+"', have received a node to node text 
message from nodename '"+HTMLEncoder.encode(source_nodename)+"':<br /><br 
/>"+HTMLEncoder.encode(message_text);
+               return s;
+       }
+
+       public short getPriorityClass() {
+               return UserAlert.MINOR;
+       }
+
+       public boolean isValid() {
+               return isValid;
+       }
+       
+       public void isValid(boolean b){
+               if(userCanDismiss()) isValid=b;
+       }
+}


Reply via email to