├── CCNx ├── lib │ ├── ccn.jar │ └── bcprov-jdk16-143.jar ├── src │ ├── org │ │ └── json │ │ │ ├── zip │ │ │ ├── README │ │ │ ├── None.java │ │ │ ├── BitReader.java │ │ │ ├── BitWriter.java │ │ │ ├── PostMortem.java │ │ │ ├── Keep.java │ │ │ ├── BitOutputStream.java │ │ │ ├── BitInputStream.java │ │ │ ├── MapKeep.java │ │ │ ├── JSONzip.java │ │ │ ├── Decompressor.java │ │ │ ├── Huff.java │ │ │ └── TrieKeep.java │ │ │ ├── JSONString.java │ │ │ ├── JSONException.java │ │ │ ├── README │ │ │ ├── HTTPTokener.java │ │ │ ├── Property.java │ │ │ ├── JSONStringer.java │ │ │ ├── CookieList.java │ │ │ ├── HTTP.java │ │ │ ├── Cookie.java │ │ │ ├── CDL.java │ │ │ ├── JSONWriter.java │ │ │ ├── XMLTokener.java │ │ │ ├── Kim.java │ │ │ └── JSONTokener.java │ ├── ContentProps.java │ └── ClientManager.java ├── tools │ ├── ClientManager │ └── compile.sh ├── config.properties └── README ├── .gitmodules ├── CITATION ├── POX ├── __init__.py ├── startup.py ├── README ├── CCNxPlugin.py └── forwarding.py └── README /CCNx/lib/ccn.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TUDelftNAS/SDN-NDNFlow/HEAD/CCNx/lib/ccn.jar -------------------------------------------------------------------------------- /CCNx/lib/bcprov-jdk16-143.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TUDelftNAS/SDN-NDNFlow/HEAD/CCNx/lib/bcprov-jdk16-143.jar -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/README: -------------------------------------------------------------------------------- 1 | FOR EVALUATION PURPOSES ONLY. THIS PACKAGE HAS NOT BEEN TESTED ADEQUATELY FOR 2 | PRODUCTION USE. 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "POX/pox"] 2 | path = POX/pox 3 | url = git://github.com/noxrepo/pox.git 4 | [submodule "CCNx/ccnx"] 5 | path = CCNx/ccnx 6 | url = git://github.com/ProjectCCNx/ccnx.git 7 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | When using NDNFlow please refer to the accompanying article: 2 | Niels L. M. van Adrichem and Fernando A. Kuipers, NDNFlow: Software-Defined Named Data Networking, IEEE Conference on Network Softwarization (IEEE NetSoft), London, UK, April 13-17, 2015 3 | http://www.nas.ewi.tudelft.nl/people/Fernando/papers/NDNflow.pdf 4 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/None.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | /** 4 | * None is an interface that makes the constant none (short for 5 | * negative one or long for -1) available to any class that implements it. 6 | * The none value is used to stand for an integer that is not an integer, 7 | * such as the negative result of a search. 8 | */ 9 | public interface None { 10 | /** 11 | * Negative One. 12 | */ 13 | public static final int none = -1; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /CCNx/src/org/json/JSONString.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | /** 3 | * The JSONString interface allows a toJSONString() 4 | * method so that a class can change the behavior of 5 | * JSONObject.toString(), JSONArray.toString(), 6 | * and JSONWriter.value(Object). The 7 | * toJSONString method will be used instead of the default behavior 8 | * of using the Object's toString() method and quoting the result. 9 | */ 10 | public interface JSONString { 11 | /** 12 | * The toJSONString method allows a class to produce its own JSON 13 | * serialization. 14 | * 15 | * @return A strictly syntactically correct JSON text. 16 | */ 17 | public String toJSONString(); 18 | } 19 | -------------------------------------------------------------------------------- /POX/__init__.py: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | -------------------------------------------------------------------------------- /CCNx/src/org/json/JSONException.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /** 4 | * The JSONException is thrown by the JSON.org classes when things are amiss. 5 | * 6 | * @author JSON.org 7 | * @version 2013-02-10 8 | */ 9 | public class JSONException extends RuntimeException { 10 | private static final long serialVersionUID = 0; 11 | private Throwable cause; 12 | 13 | /** 14 | * Constructs a JSONException with an explanatory message. 15 | * 16 | * @param message 17 | * Detail about the reason for the exception. 18 | */ 19 | public JSONException(String message) { 20 | super(message); 21 | } 22 | 23 | /** 24 | * Constructs a new JSONException with the specified cause. 25 | */ 26 | public JSONException(Throwable cause) { 27 | super(cause.getMessage()); 28 | this.cause = cause; 29 | } 30 | 31 | /** 32 | * Returns the cause of this exception or null if the cause is nonexistent 33 | * or unknown. 34 | * 35 | * @returns the cause of this exception or null if the cause is nonexistent 36 | * or unknown. 37 | */ 38 | public Throwable getCause() { 39 | return this.cause; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/BitReader.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.io.IOException; 4 | 5 | public interface BitReader { 6 | /** 7 | * Read one bit. 8 | * 9 | * @return true if it is a 1 bit. 10 | */ 11 | public boolean bit() throws IOException; 12 | 13 | /** 14 | * Returns the number of bits that have been read from this bitreader. 15 | * 16 | * @return The number of bits read so far. 17 | */ 18 | public long nrBits(); 19 | 20 | /** 21 | * Check that the rest of the block has been padded with zeroes. 22 | * 23 | * @param factor 24 | * The size in bits of the block to pad. This will typically be 25 | * 8, 16, 32, 64, 128, 256, etc. 26 | * @return true if the block was zero padded, or false if the the padding 27 | * contained any one bits. 28 | * @throws IOException 29 | */ 30 | public boolean pad(int factor) throws IOException; 31 | 32 | /** 33 | * Read some bits. 34 | * 35 | * @param width 36 | * The number of bits to read. (0..32) 37 | * @throws IOException 38 | * @return the bits 39 | */ 40 | public int read(int width) throws IOException; 41 | } 42 | -------------------------------------------------------------------------------- /CCNx/tools/ClientManager: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 4 | # 5 | # This file is part of NDNFlow. 6 | # 7 | # NDNFlow is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # NDNFlow is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with NDNFlow. If not, see . 19 | 20 | JAR_FILE=ccn.jar 21 | JAVA_HOME=${JAVA_HOME:=/usr} 22 | JAVA=$JAVA_HOME/bin/java 23 | SCRIPT_DIR=`dirname $0` 24 | 25 | CP1=$SCRIPT_DIR/../lib/*.jar 26 | CP1=`echo $CP1 | sed "s/ /:/g"` 27 | CP2=$SCRIPT_DIR/../bin 28 | 29 | echo $CP1 30 | echo $CP2 31 | 32 | JAVA_RUN="$JAVA -cp $CP1:$CP2 ClientManager" 33 | echo $JAVA_RUN 34 | $JAVA_RUN 35 | -------------------------------------------------------------------------------- /CCNx/src/ContentProps.java: -------------------------------------------------------------------------------- 1 | /** 2 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 3 | # 4 | # This file is part of NDNFlow. 5 | # 6 | # NDNFlow is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # NDNFlow is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with NDNFlow. If not, see . 18 | **/ 19 | 20 | 21 | public class ContentProps { 22 | 23 | private int _cost; 24 | private int _priority; 25 | 26 | public ContentProps(int tCost, int tPriority) { 27 | _cost = tCost; 28 | _priority = tPriority; 29 | } 30 | 31 | public int getCost() { 32 | return _cost; 33 | } 34 | 35 | public int getPriority() { 36 | return _priority; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CCNx/tools/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 4 | # 5 | # This file is part of NDNFlow. 6 | # 7 | # NDNFlow is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # NDNFlow is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with NDNFlow. If not, see . 19 | 20 | JAR_FILE=ccn.jar 21 | JAVA_HOME=${JAVA_HOME:=/usr} 22 | JAVAC=$JAVA_HOME/bin/javac 23 | SCRIPT_DIR=`dirname $0` 24 | 25 | CP1=$SCRIPT_DIR/../lib/*.jar 26 | CP1=`echo $CP1 | sed "s/ /:/g"` 27 | CP2=$SCRIPT_DIR/../src 28 | MAIN_CLASS=$CP2/ClientManager.java 29 | DP=$SCRIPT_DIR/../bin 30 | 31 | echo $CP1 32 | echo $CP2 33 | 34 | rm -R $DP 35 | mkdir $DP 36 | 37 | JAVAC_RUN="$JAVAC -cp $CP1:$CP2 -d $DP $MAIN_CLASS" 38 | 39 | 40 | echo $JAVAC_RUN 41 | $JAVAC_RUN 42 | 43 | 44 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/BitWriter.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * A bitwriter is a an interface that allows for doing output at the bit level. 7 | * Most IO interfaces only allow for writing at the byte level or higher. 8 | */ 9 | public interface BitWriter { 10 | /** 11 | * Returns the number of bits that have been written to this bitwriter. 12 | */ 13 | public long nrBits(); 14 | 15 | /** 16 | * Write a 1 bit. 17 | * 18 | * @throws IOException 19 | */ 20 | public void one() throws IOException; 21 | 22 | /** 23 | * Pad the rest of the block with zeros and flush. 24 | * 25 | * @param factor 26 | * The size in bits of the block to pad. This will typically be 27 | * 8, 16, 32, 64, 128, 256, etc. 28 | * @return true if the block was zero padded, or false if the the padding 29 | * contains any one bits. 30 | * @throws IOException 31 | */ 32 | public void pad(int factor) throws IOException; 33 | 34 | /** 35 | * Write some bits. Up to 32 bits can be written at a time. 36 | * 37 | * @param bits 38 | * The bits to be written. 39 | * @param width 40 | * The number of bits to write. (0..32) 41 | * @throws IOException 42 | */ 43 | public void write(int bits, int width) throws IOException; 44 | 45 | /** 46 | * Write a 0 bit. 47 | * 48 | * @throws IOException 49 | */ 50 | public void zero() throws IOException; 51 | } 52 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | SDN-NDNFlow 19 | =========== 20 | 21 | NDNFlow offers POX and CCNx plugins to enable Information Centric Networking (a.k.a. Named Data Networking) in OpenFlow networks using CCNx, POX and Open vSwitch. 22 | 23 | When using NDNFlow please refer to the accompanying article: 24 | Niels L. M. van Adrichem and Fernando A. Kuipers, NDNFlow: Software-Defined Named Data Networking, IEEE Conference on Network Softwarization (IEEE NetSoft), London, UK, April 13-17, 2015 25 | http://www.nas.ewi.tudelft.nl/people/Fernando/papers/NDNflow.pdf 26 | 27 | The installation process and usage of NDNFlow is divided in two switch- and controller-specific READMEs, which can be found in the subfolders CCNx and POX. 28 | 29 | 30 | -------------------------------------------------------------------------------- /POX/startup.py: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | def launch (): 19 | from log.level import launch 20 | launch(DEBUG=True) 21 | 22 | from samples.pretty_log import launch 23 | launch() 24 | 25 | from openflow.keepalive import launch 26 | launch(interval=15) # 15 seconds 27 | 28 | from openflow.discovery import launch 29 | launch() 30 | 31 | #we solved the flooding-problem in l2_multi_withstate 32 | #from openflow.spanning_tree import launch 33 | #launch(no_flood = True, hold_down = True) 34 | 35 | from ccnxflow.forwarding import launch 36 | launch(l3_matching=False) 37 | 38 | from ccnxflow.CCNxPlugin import launch 39 | launch() 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /CCNx/config.properties: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | 19 | #client datapathid, compulsory 20 | dpid = 0x010000000025 21 | ip = 10.0.0.25 22 | 23 | #server ip or hostname, compulsory 24 | server = 10.10.2.25 25 | #optional port, defaults to 6635, as 6633 is the default OpenFlow port and 6634 is the default openflow passive listening port for switches 26 | #port = 6635 27 | 28 | 29 | #x is number from 0 to X, where X is number of entries-1 30 | #entry.x = content prefix 31 | #entry.x.cost = is cost in terms of additional link cost / hop count on top of regular shortest path computation. Defaults to 0. 32 | #entry.x.priority = absolute priority over other, equally named, routes. Lowest value takes precedence, note that longest-prefix match always has highest priority. Defaults to 0. 33 | 34 | entry.0 = ccnx:/myTestNode 35 | entry.0.cost = 10 36 | entry.0.priority = 0 37 | 38 | entry.1 = ccnx:/myBackupTestNode 39 | entry.1.cost = 20 40 | entry.1.priority = 100 41 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/PostMortem.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | /* 4 | Copyright (c) 2013 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * The PostMortem interface allows for testing the internal state of JSONzip 29 | * processors. Testing that JSONzip can compress an object and reproduce a 30 | * corresponding object is not sufficient. Complete testing requires that the 31 | * same internal data structures were constructed on both ends. If those 32 | * structures are not equivalent, then it is likely that the implementations 33 | * are not correct, even if convention tests are passed. 34 | * 35 | * PostMortem allows for testing of deep structures without breaking 36 | * encapsulation. 37 | */ 38 | public interface PostMortem { 39 | /** 40 | * Determine if two objects are equivalent. 41 | * 42 | * @param pm 43 | * Another object of the same type. 44 | * @return true if they match. 45 | */ 46 | public boolean postMortem(PostMortem pm); 47 | } 48 | -------------------------------------------------------------------------------- /POX/README: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | SDN-NDNFlow POX Controller module 19 | ================================= 20 | 21 | This subdirectory and README involve the installation of the POX OpenFlow controller and the corresponding modules from NDNFlow to enable ICN from the controller perspective. 22 | 23 | Step 1) 24 | After initially cloning this complete repository somewhere on your system, CD into this directory. 25 | # cd POX 26 | 27 | Step 2) 28 | Either checkout the pox submodule we used during experimentation (in the sample below), or install pox yourself according to: https://openflow.stanford.edu/display/ONL/POX+Wiki#POXWiki-InstallingPOX (n.b. we have only tested on the betta branch). 29 | # cd pox 30 | # git submodule init 31 | # git submodule update 32 | 33 | Step 3) 34 | You now have a folder ~/pox containing the working directory of pox, make sure you have `cd`ed into it. In the pox working directory is a folder `ext`, meant to contain files that should not be modified by upgrading POX or checking out another branch. 35 | 36 | Creat e new folder `ccnxflow` into the `ext` directory and copy or move the code into it. 37 | 38 | # mkdir ext/ccnxflow 39 | # cp ../*.py ext/ccnxflow 40 | 41 | Run POX with the NDNFlow modules 42 | # ./pox.py ccnxflow.startup 43 | 44 | From here on, you are good to go to run experiments and get a feeling of NDNFlow's capabilities. 45 | The NDNFlow module contains a forwarding module capable of finding shortest paths in multipath networks and starts all depending modules from the `ccnxflow/startup.py` script. 46 | -------------------------------------------------------------------------------- /CCNx/src/org/json/README: -------------------------------------------------------------------------------- 1 | JSON in Java [package org.json] 2 | 3 | Douglas Crockford 4 | douglas@crockford.com 5 | 6 | 2011-02-02 7 | 8 | 9 | JSON is a light-weight, language independent, data interchange format. 10 | See http://www.JSON.org/ 11 | 12 | The files in this package implement JSON encoders/decoders in Java. 13 | It also includes the capability to convert between JSON and XML, HTTP 14 | headers, Cookies, and CDL. 15 | 16 | This is a reference implementation. There is a large number of JSON packages 17 | in Java. Perhaps someday the Java community will standardize on one. Until 18 | then, choose carefully. 19 | 20 | The license includes this restriction: "The software shall be used for good, 21 | not evil." If your conscience cannot live with that, then choose a different 22 | package. 23 | 24 | The package compiles on Java 1.2 thru Java 1.4. 25 | 26 | 27 | JSONObject.java: The JSONObject can parse text from a String or a JSONTokener 28 | to produce a map-like object. The object provides methods for manipulating its 29 | contents, and for producing a JSON compliant object serialization. 30 | 31 | JSONArray.java: The JSONObject can parse text from a String or a JSONTokener 32 | to produce a vector-like object. The object provides methods for manipulating 33 | its contents, and for producing a JSON compliant array serialization. 34 | 35 | JSONTokener.java: The JSONTokener breaks a text into a sequence of individual 36 | tokens. It can be constructed from a String, Reader, or InputStream. 37 | 38 | JSONException.java: The JSONException is the standard exception type thrown 39 | by this package. 40 | 41 | 42 | JSONString.java: The JSONString interface requires a toJSONString method, 43 | allowing an object to provide its own serialization. 44 | 45 | JSONStringer.java: The JSONStringer provides a convenient facility for 46 | building JSON strings. 47 | 48 | JSONWriter.java: The JSONWriter provides a convenient facility for building 49 | JSON text through a writer. 50 | 51 | 52 | CDL.java: CDL provides support for converting between JSON and comma 53 | delimited lists. 54 | 55 | Cookie.java: Cookie provides support for converting between JSON and cookies. 56 | 57 | CookieList.java: CookieList provides support for converting between JSON and 58 | cookie lists. 59 | 60 | HTTP.java: HTTP provides support for converting between JSON and HTTP headers. 61 | 62 | HTTPTokener.java: HTTPTokener extends JSONTokener for parsing HTTP headers. 63 | 64 | XML.java: XML provides support for converting between JSON and XML. 65 | 66 | JSONML.java: JSONML provides support for converting between JSONML and XML. 67 | 68 | XMLTokener.java: XMLTokener extends JSONTokener for parsing XML text. 69 | -------------------------------------------------------------------------------- /CCNx/src/org/json/HTTPTokener.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * The HTTPTokener extends the JSONTokener to provide additional methods 29 | * for the parsing of HTTP headers. 30 | * @author JSON.org 31 | * @version 2012-11-13 32 | */ 33 | public class HTTPTokener extends JSONTokener { 34 | 35 | /** 36 | * Construct an HTTPTokener from a string. 37 | * @param string A source string. 38 | */ 39 | public HTTPTokener(String string) { 40 | super(string); 41 | } 42 | 43 | 44 | /** 45 | * Get the next token or string. This is used in parsing HTTP headers. 46 | * @throws JSONException 47 | * @return A String. 48 | */ 49 | public String nextToken() throws JSONException { 50 | char c; 51 | char q; 52 | StringBuffer sb = new StringBuffer(); 53 | do { 54 | c = next(); 55 | } while (Character.isWhitespace(c)); 56 | if (c == '"' || c == '\'') { 57 | q = c; 58 | for (;;) { 59 | c = next(); 60 | if (c < ' ') { 61 | throw syntaxError("Unterminated string."); 62 | } 63 | if (c == q) { 64 | return sb.toString(); 65 | } 66 | sb.append(c); 67 | } 68 | } 69 | for (;;) { 70 | if (c == 0 || Character.isWhitespace(c)) { 71 | return sb.toString(); 72 | } 73 | sb.append(c); 74 | c = next(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /CCNx/src/org/json/Property.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.util.Enumeration; 28 | import java.util.Iterator; 29 | import java.util.Properties; 30 | 31 | /** 32 | * Converts a Property file data into JSONObject and back. 33 | * @author JSON.org 34 | * @version 2013-05-23 35 | */ 36 | public class Property { 37 | /** 38 | * Converts a property file object into a JSONObject. The property file object is a table of name value pairs. 39 | * @param properties java.util.Properties 40 | * @return JSONObject 41 | * @throws JSONException 42 | */ 43 | public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException { 44 | JSONObject jo = new JSONObject(); 45 | if (properties != null && !properties.isEmpty()) { 46 | Enumeration enumProperties = properties.propertyNames(); 47 | while(enumProperties.hasMoreElements()) { 48 | String name = (String)enumProperties.nextElement(); 49 | jo.put(name, properties.getProperty(name)); 50 | } 51 | } 52 | return jo; 53 | 54 | } 55 | 56 | /** 57 | * Converts the JSONObject into a property file object. 58 | * @param jo JSONObject 59 | * @return java.util.Properties 60 | * @throws JSONException 61 | */ 62 | public static Properties toProperties(JSONObject jo) throws JSONException { 63 | Properties properties = new Properties(); 64 | if (jo != null) { 65 | Iterator keys = jo.keys(); 66 | 67 | while (keys.hasNext()) { 68 | String name = keys.next().toString(); 69 | properties.put(name, jo.getString(name)); 70 | } 71 | } 72 | return properties; 73 | } 74 | } -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/Keep.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | 4 | /* 5 | Copyright (c) 2013 JSON.org 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | The Software shall be used for Good, not Evil. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | /** 29 | * A keep is a data structure that associates strings (or substrings) with 30 | * numbers. This allows the sending of small integers instead of strings. 31 | * 32 | * @author JSON.org 33 | * @version 2013-04-18 34 | */ 35 | abstract class Keep implements None, PostMortem { 36 | protected int capacity; 37 | protected int length; 38 | protected int power; 39 | protected long[] uses; 40 | 41 | public Keep(int bits) { 42 | this.capacity = JSONzip.twos[bits]; 43 | this.length = 0; 44 | this.power = 0; 45 | this.uses = new long[this.capacity]; 46 | } 47 | 48 | /** 49 | * When an item ages, its use count is reduced by at least half. 50 | * 51 | * @param use 52 | * The current use count of an item. 53 | * @return The new use count for that item. 54 | */ 55 | public static long age(long use) { 56 | return use >= 32 ? 16 : use / 2; 57 | } 58 | 59 | /** 60 | * Return the number of bits required to contain an integer based on the 61 | * current length of the keep. As the keep fills up, the number of bits 62 | * required to identify one of its items goes up. 63 | */ 64 | public int bitsize() { 65 | while (JSONzip.twos[this.power] < this.length) { 66 | this.power += 1; 67 | } 68 | return this.power; 69 | } 70 | 71 | /** 72 | * Increase the usage count on an integer value. 73 | */ 74 | public void tick(int integer) { 75 | this.uses[integer] += 1; 76 | } 77 | 78 | /** 79 | * Get the value associated with an integer. 80 | * @param integer The number of an item in the keep. 81 | * @return The value. 82 | */ 83 | abstract public Object value(int integer); 84 | } 85 | -------------------------------------------------------------------------------- /CCNx/src/org/json/JSONStringer.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2006 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.io.StringWriter; 28 | 29 | /** 30 | * JSONStringer provides a quick and convenient way of producing JSON text. 31 | * The texts produced strictly conform to JSON syntax rules. No whitespace is 32 | * added, so the results are ready for transmission or storage. Each instance of 33 | * JSONStringer can produce one JSON text. 34 | *

35 | * A JSONStringer instance provides a value method for appending 36 | * values to the 37 | * text, and a key 38 | * method for adding keys before values in objects. There are array 39 | * and endArray methods that make and bound array values, and 40 | * object and endObject methods which make and bound 41 | * object values. All of these methods return the JSONWriter instance, 42 | * permitting cascade style. For example,

43 |  * myString = new JSONStringer()
44 |  *     .object()
45 |  *         .key("JSON")
46 |  *         .value("Hello, World!")
47 |  *     .endObject()
48 |  *     .toString();
which produces the string
49 |  * {"JSON":"Hello, World!"}
50 | *

51 | * The first method called must be array or object. 52 | * There are no methods for adding commas or colons. JSONStringer adds them for 53 | * you. Objects and arrays can be nested up to 20 levels deep. 54 | *

55 | * This can sometimes be easier than using a JSONObject to build a string. 56 | * @author JSON.org 57 | * @version 2008-09-18 58 | */ 59 | public class JSONStringer extends JSONWriter { 60 | /** 61 | * Make a fresh JSONStringer. It can be used to build one JSON text. 62 | */ 63 | public JSONStringer() { 64 | super(new StringWriter()); 65 | } 66 | 67 | /** 68 | * Return the JSON text. This method is used to obtain the product of the 69 | * JSONStringer instance. It will return null if there was a 70 | * problem in the construction of the JSON text (such as the calls to 71 | * array were not properly balanced with calls to 72 | * endArray). 73 | * @return The JSON text. 74 | */ 75 | public String toString() { 76 | return this.mode == 'd' ? this.writer.toString() : null; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /CCNx/src/org/json/CookieList.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.util.Iterator; 28 | 29 | /** 30 | * Convert a web browser cookie list string to a JSONObject and back. 31 | * @author JSON.org 32 | * @version 2010-12-24 33 | */ 34 | public class CookieList { 35 | 36 | /** 37 | * Convert a cookie list into a JSONObject. A cookie list is a sequence 38 | * of name/value pairs. The names are separated from the values by '='. 39 | * The pairs are separated by ';'. The names and the values 40 | * will be unescaped, possibly converting '+' and '%' sequences. 41 | * 42 | * To add a cookie to a cooklist, 43 | * cookielistJSONObject.put(cookieJSONObject.getString("name"), 44 | * cookieJSONObject.getString("value")); 45 | * @param string A cookie list string 46 | * @return A JSONObject 47 | * @throws JSONException 48 | */ 49 | public static JSONObject toJSONObject(String string) throws JSONException { 50 | JSONObject jo = new JSONObject(); 51 | JSONTokener x = new JSONTokener(string); 52 | while (x.more()) { 53 | String name = Cookie.unescape(x.nextTo('=')); 54 | x.next('='); 55 | jo.put(name, Cookie.unescape(x.nextTo(';'))); 56 | x.next(); 57 | } 58 | return jo; 59 | } 60 | 61 | 62 | /** 63 | * Convert a JSONObject into a cookie list. A cookie list is a sequence 64 | * of name/value pairs. The names are separated from the values by '='. 65 | * The pairs are separated by ';'. The characters '%', '+', '=', and ';' 66 | * in the names and values are replaced by "%hh". 67 | * @param jo A JSONObject 68 | * @return A cookie list string 69 | * @throws JSONException 70 | */ 71 | public static String toString(JSONObject jo) throws JSONException { 72 | boolean b = false; 73 | Iterator keys = jo.keys(); 74 | String string; 75 | StringBuffer sb = new StringBuffer(); 76 | while (keys.hasNext()) { 77 | string = keys.next().toString(); 78 | if (!jo.isNull(string)) { 79 | if (b) { 80 | sb.append(';'); 81 | } 82 | sb.append(Cookie.escape(string)); 83 | sb.append("="); 84 | sb.append(Cookie.escape(jo.getString(string))); 85 | b = true; 86 | } 87 | } 88 | return sb.toString(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /CCNx/README: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | SDN-NDNFlow CCNx switch module 19 | ================================= 20 | 21 | 1. Prerequisites 22 | 2. Building 23 | 3. Configuration and Usage 24 | 25 | 1. Prerequisites 26 | - This software has been build and tested using the CCNx architecture version 0.8.2., first of all make sure you have a working installation of version 0.8.2. Also see the submodule ccnx. 27 | - Make sure you have a properly configure JDK and JRE to compile and run the program, for example I use the Sun JRE and JDK 1.7. 28 | - Install Open vSwitch (OVS) which connects to exactly the same controller as where you run the POX module. Apart from running OVS, there is no further configuration or building necessary. We used stock Open vSwitch 2.0.2 from the Ubuntu 14.04.1 repositories during our experiments. 29 | 30 | 2. Building 31 | Download the source of NDNFlow and place it in a folder of your preference (e.g. use /home/username/tools/NDNFlow, from here on I assume you have a console open in this directory). 32 | The compilation and running of NDNFlow depends on a few jar-files carried along with CCNx-0.8.2 which should be in the folder lib. 33 | You can either: 34 | 1) Extract the folder from this repository if you use CCNx 0.8.2. 35 | 2) create the folder lib (mkdir lib) 36 | copy the files ccn.jar, bcprov-jzdk16-143.jar from $CCNX_HOME/lib (cp $CCNX_HOME/lib/ccn.jar $CCNX_HOME/lib/bcprov-jdk16-143.jar lib) 37 | 3) create a symlink to your $CCNX_HOME/lib folder (in case you frequently patch your CCNx) (ln -s $CCNX_HOME/lib lib) 38 | 39 | Run tools/compile.sh to build the source. 40 | A folder named bin holding the class-files is created automatically 41 | 42 | 3. Configuration and Usage 43 | Configuration occurs by editing the `config.properties` file found in the home folder of the plugin using your favourite editor. Have a look at the sample file. 44 | In the configuration file, a number of configuration parameters are of importance: 45 | dpid: Compulsory, the dpid must contain the hexadecimal representation of the Datapath Identifier of your OpenFlow capable switch. The controller module uses this parameter to couple the parrellel CCNx specific communication channel to the generic OpenFlow channel. 46 | ip: Compulsory, the ip MUST contain the internal (datapath) IP address of the OpenFlow LOCAL-port, or the IP address by which the CCNx daemon may be reached. This IP address is used to set up IP encapsulated tunnels between nodes that are disconnected by native means of CCNx. 47 | server: Compulsory, the IP address or hostname of the listening socket of the POX module. 48 | port: Optional, in case the plugin should connect to the POX module using a TCP port different from 6635. 49 | 50 | At this point, configuration is complete for an NDN node that provides caching. Additionally, routing for content providers can be provided by adding content entries. Each content entry should be numbered incrementally from x={0, 1, 2, 3, 4..MAX_INTEGER} onwards. 51 | entry.x: Contains the name prefix of the published content. Alike to IP forwarding rules, gateways may publish a default forwarding rule using a zero name component name of "ccnx:/". 52 | entry.x.cost: The additional routing cost from this node to the content in terms of additional link cost / hop count on top of regular shortest path computation. This cost is used in the routing algorithm as initial cost value, it may be used to steer load balancing between multiple locations publishing the same content prefix at the same priority. Defaults to 0. 53 | entry.x.priority: Absolute priority over other, equally named, routes. Lowest value takes precedence, note that longest-prefix match always has highest priority. Defaults to 0. 54 | 55 | 56 | To run the plugin, make sure a local CCNx daemon is running. 57 | The plugin can then be started by running `tools/ClientManager`. 58 | 59 | 60 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/BitOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | /* 7 | Copyright (c) 2013 JSON.org 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | The Software shall be used for Good, not Evil. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | 30 | /** 31 | * This is a big endian bit writer. It writes its bits to an OutputStream. 32 | * 33 | * @version 2013-04-18 34 | * 35 | */ 36 | public class BitOutputStream implements BitWriter { 37 | 38 | /** 39 | * The number of bits written. 40 | */ 41 | private long nrBits = 0; 42 | 43 | /** 44 | * The destination of the bits. 45 | */ 46 | private OutputStream out; 47 | 48 | /** 49 | * Holder of bits not yet written. 50 | */ 51 | private int unwritten; 52 | 53 | /** 54 | * The number of unused bits in this.unwritten. 55 | */ 56 | private int vacant = 8; 57 | 58 | /** 59 | * Use an OutputStream to produce a BitWriter. The BitWriter will send its 60 | * bits to the OutputStream as each byte is filled. 61 | * 62 | * @param out 63 | * An Output Stream 64 | */ 65 | public BitOutputStream(OutputStream out) { 66 | this.out = out; 67 | } 68 | 69 | /** 70 | * Returns the number of bits that have been written to this 71 | * bitOutputStream. This may include bits that have not yet been written 72 | * to the underlying outputStream. 73 | */ 74 | public long nrBits() { 75 | return this.nrBits; 76 | } 77 | 78 | /** 79 | * Write a 1 bit. 80 | * 81 | * @throws IOException 82 | */ 83 | public void one() throws IOException { 84 | write(1, 1); 85 | } 86 | 87 | /** 88 | * Pad the rest of the block with zeroes and flush. pad(8) flushes the last 89 | * unfinished byte. The underlying OutputStream will be flushed. 90 | * 91 | * @param factor 92 | * The size of the block to pad. This will typically be 8, 16, 93 | * 32, 64, 128, 256, etc. 94 | * @return this 95 | * @throws IOException 96 | */ 97 | public void pad(int factor) throws IOException { 98 | int padding = factor - (int) (nrBits % factor); 99 | int excess = padding & 7; 100 | if (excess > 0) { 101 | this.write(0, excess); 102 | padding -= excess; 103 | } 104 | while (padding > 0) { 105 | this.write(0, 8); 106 | padding -= 8; 107 | } 108 | this.out.flush(); 109 | } 110 | 111 | /** 112 | * Write some bits. Up to 32 bits can be written at a time. 113 | * 114 | * @param bits 115 | * The bits to be written. 116 | * @param width 117 | * The number of bits to write. (0..32) 118 | * @throws IOException 119 | */ 120 | public void write(int bits, int width) throws IOException { 121 | if (bits == 0 && width == 0) { 122 | return; 123 | } 124 | if (width <= 0 || width > 32) { 125 | throw new IOException("Bad write width."); 126 | } 127 | while (width > 0) { 128 | int actual = width; 129 | if (actual > this.vacant) { 130 | actual = this.vacant; 131 | } 132 | this.unwritten |= ((bits >>> (width - actual)) & 133 | BitInputStream.mask[actual]) << (this.vacant - actual); 134 | width -= actual; 135 | nrBits += actual; 136 | this.vacant -= actual; 137 | if (this.vacant == 0) { 138 | this.out.write(this.unwritten); 139 | this.unwritten = 0; 140 | this.vacant = 8; 141 | } 142 | } 143 | } 144 | 145 | /** 146 | * Write a 0 bit. 147 | * 148 | * @throws IOException 149 | */ 150 | public void zero() throws IOException { 151 | write(0, 1); 152 | 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/BitInputStream.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /* 7 | Copyright (c) 2013 JSON.org 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | The Software shall be used for Good, not Evil. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | 30 | /** 31 | * This is a big endian bit reader. It reads its bits from an InputStream. 32 | * 33 | * @version 2013-04-18 34 | * 35 | */ 36 | public class BitInputStream implements BitReader { 37 | /** 38 | * 2^n - 1 39 | */ 40 | static final int[] mask = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; 41 | 42 | /** 43 | * The number of bits remaining in the current byte. 44 | */ 45 | private int available = 0; 46 | 47 | /** 48 | * Up to a byte's worth of unread bits. 49 | */ 50 | private int unread = 0; 51 | 52 | /** 53 | * The source of the bits. 54 | */ 55 | private InputStream in; 56 | 57 | /** 58 | * The number of bits read so far. This is used in padding. 59 | */ 60 | private long nrBits = 0; 61 | 62 | /** 63 | * Make a BitReader from an InputStream. The BitReader will take bytes from 64 | * the InputStream and unpack them into bits. 65 | * 66 | * @param in 67 | * An InputStream. 68 | */ 69 | public BitInputStream(InputStream in) { 70 | this.in = in; 71 | } 72 | 73 | /** 74 | * Make a BitReader. The first byte is passed in explicitly, the remaining 75 | * bytes are obtained from the InputStream. This makes it possible to look 76 | * at the first byte of a stream before deciding that it should be read as 77 | * bits. 78 | * 79 | * @param in 80 | * An InputStream 81 | * @param firstByte 82 | * The first byte, which was probably read from in. 83 | */ 84 | public BitInputStream(InputStream in, int firstByte) { 85 | this.in = in; 86 | this.unread = firstByte; 87 | this.available = 8; 88 | } 89 | 90 | /** 91 | * Read one bit. 92 | * 93 | * @return true if it is a 1 bit. 94 | */ 95 | public boolean bit() throws IOException { 96 | return read(1) != 0; 97 | } 98 | 99 | /** 100 | * Get the number of bits that have been read from this BitInputStream. 101 | * This includes pad bits that have been skipped, but might not include 102 | * bytes that have been read from the underlying InputStream that have not 103 | * yet been delivered as bits. 104 | * 105 | * @return The number of bits read so far. 106 | */ 107 | public long nrBits() { 108 | return this.nrBits; 109 | } 110 | 111 | /** 112 | * Check that the rest of the block has been padded with zeroes. 113 | * 114 | * @param factor 115 | * The size of the block to pad. This will typically be 8, 16, 116 | * 32, 64, 128, 256, etc. 117 | * @return true if the block was zero padded, or false if the the padding 118 | * contains any one bits. 119 | * @throws IOException 120 | */ 121 | public boolean pad(int factor) throws IOException { 122 | int padding = factor - (int) (this.nrBits % factor); 123 | boolean result = true; 124 | 125 | for (int i = 0; i < padding; i += 1) { 126 | if (bit()) { 127 | result = false; 128 | } 129 | } 130 | return result; 131 | } 132 | 133 | /** 134 | * Read some bits. 135 | * 136 | * @param width 137 | * The number of bits to read. (0..32) 138 | * @throws IOException 139 | * @return the bits 140 | */ 141 | public int read(int width) throws IOException { 142 | if (width == 0) { 143 | return 0; 144 | } 145 | if (width < 0 || width > 32) { 146 | throw new IOException("Bad read width."); 147 | } 148 | int result = 0; 149 | while (width > 0) { 150 | if (this.available == 0) { 151 | this.unread = this.in.read(); 152 | if (this.unread < 0) { 153 | throw new IOException("Attempt to read past end."); 154 | } 155 | this.available = 8; 156 | } 157 | int take = width; 158 | if (take > this.available) { 159 | take = this.available; 160 | } 161 | result |= ((this.unread >>> (this.available - take)) & mask[take]) 162 | << (width - take); 163 | this.nrBits += take; 164 | this.available -= take; 165 | width -= take; 166 | } 167 | return result; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/MapKeep.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.util.HashMap; 4 | 5 | import org.json.Kim; 6 | 7 | /* 8 | Copyright (c) 2013 JSON.org 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | The Software shall be used for Good, not Evil. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | /** 32 | * A keep is an associative data structure that maintains usage counts of each 33 | * of the associations in its keeping. When the keep becomes full, it purges 34 | * little used associations, and ages the survivors. Each key is assigned an 35 | * integer value. When the keep is compacted, each key can be given a new 36 | * value. 37 | */ 38 | class MapKeep extends Keep { 39 | private Object[] list; 40 | private HashMap map; 41 | 42 | /** 43 | * Create a new Keep. 44 | * @param bits 45 | * The capacity of the keep expressed in the number of bits 46 | * required to hold an integer. 47 | */ 48 | public MapKeep(int bits) { 49 | super(bits); 50 | this.list = new Object[this.capacity]; 51 | this.map = new HashMap(this.capacity); 52 | } 53 | 54 | /** 55 | * Compact the keep. A keep may contain at most this.capacity elements. 56 | * The keep contents can be reduced by deleting all elements with low use 57 | * counts, and by reducing the use counts of the survivors. 58 | */ 59 | private void compact() { 60 | int from = 0; 61 | int to = 0; 62 | while (from < this.capacity) { 63 | Object key = this.list[from]; 64 | long usage = age(this.uses[from]); 65 | if (usage > 0) { 66 | this.uses[to] = usage; 67 | this.list[to] = key; 68 | this.map.put(key, new Integer(to)); 69 | to += 1; 70 | } else { 71 | this.map.remove(key); 72 | } 73 | from += 1; 74 | } 75 | if (to < this.capacity) { 76 | this.length = to; 77 | } else { 78 | this.map.clear(); 79 | this.length = 0; 80 | } 81 | this.power = 0; 82 | } 83 | 84 | /** 85 | * Find the integer value associated with this key, or nothing if this key 86 | * is not in the keep. 87 | * 88 | * @param key 89 | * An object. 90 | * @return An integer 91 | */ 92 | public int find(Object key) { 93 | Object o = this.map.get(key); 94 | return o instanceof Integer ? ((Integer) o).intValue() : none; 95 | } 96 | 97 | public boolean postMortem(PostMortem pm) { 98 | MapKeep that = (MapKeep) pm; 99 | if (this.length != that.length) { 100 | JSONzip.log(this.length + " <> " + that.length); 101 | return false; 102 | } 103 | for (int i = 0; i < this.length; i += 1) { 104 | boolean b; 105 | if (this.list[i] instanceof Kim) { 106 | b = ((Kim) this.list[i]).equals(that.list[i]); 107 | } else { 108 | Object o = this.list[i]; 109 | Object q = that.list[i]; 110 | if (o instanceof Number) { 111 | o = o.toString(); 112 | } 113 | if (q instanceof Number) { 114 | q = q.toString(); 115 | } 116 | b = o.equals(q); 117 | } 118 | if (!b) { 119 | JSONzip.log("\n[" + i + "]\n " + this.list[i] + "\n " 120 | + that.list[i] + "\n " + this.uses[i] + "\n " 121 | + that.uses[i]); 122 | return false; 123 | } 124 | } 125 | return true; 126 | } 127 | 128 | /** 129 | * Register a value in the keep. Compact the keep if it is full. The next 130 | * time this value is encountered, its integer can be sent instead. 131 | * @param value A value. 132 | */ 133 | public void register(Object value) { 134 | if (JSONzip.probe) { 135 | int integer = find(value); 136 | if (integer >= 0) { 137 | JSONzip.log("\nDuplicate key " + value); 138 | } 139 | } 140 | if (this.length >= this.capacity) { 141 | compact(); 142 | } 143 | this.list[this.length] = value; 144 | this.map.put(value, new Integer(this.length)); 145 | this.uses[this.length] = 1; 146 | if (JSONzip.probe) { 147 | JSONzip.log("<" + this.length + " " + value + "> "); 148 | } 149 | this.length += 1; 150 | } 151 | 152 | /** 153 | * Return the value associated with the integer. 154 | * @param integer The number of an item in the keep. 155 | * @return The value. 156 | */ 157 | public Object value(int integer) { 158 | return this.list[integer]; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /CCNx/src/org/json/HTTP.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.util.Iterator; 28 | 29 | /** 30 | * Convert an HTTP header to a JSONObject and back. 31 | * @author JSON.org 32 | * @version 2010-12-24 33 | */ 34 | public class HTTP { 35 | 36 | /** Carriage return/line feed. */ 37 | public static final String CRLF = "\r\n"; 38 | 39 | /** 40 | * Convert an HTTP header string into a JSONObject. It can be a request 41 | * header or a response header. A request header will contain 42 | *

{
 43 |      *    Method: "POST" (for example),
 44 |      *    "Request-URI": "/" (for example),
 45 |      *    "HTTP-Version": "HTTP/1.1" (for example)
 46 |      * }
47 | * A response header will contain 48 | *
{
 49 |      *    "HTTP-Version": "HTTP/1.1" (for example),
 50 |      *    "Status-Code": "200" (for example),
 51 |      *    "Reason-Phrase": "OK" (for example)
 52 |      * }
53 | * In addition, the other parameters in the header will be captured, using 54 | * the HTTP field names as JSON names, so that
 55 |      *    Date: Sun, 26 May 2002 18:06:04 GMT
 56 |      *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
 57 |      *    Cache-Control: no-cache
58 | * become 59 | *
{...
 60 |      *    Date: "Sun, 26 May 2002 18:06:04 GMT",
 61 |      *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
 62 |      *    "Cache-Control": "no-cache",
 63 |      * ...}
64 | * It does no further checking or conversion. It does not parse dates. 65 | * It does not do '%' transforms on URLs. 66 | * @param string An HTTP header string. 67 | * @return A JSONObject containing the elements and attributes 68 | * of the XML string. 69 | * @throws JSONException 70 | */ 71 | public static JSONObject toJSONObject(String string) throws JSONException { 72 | JSONObject jo = new JSONObject(); 73 | HTTPTokener x = new HTTPTokener(string); 74 | String token; 75 | 76 | token = x.nextToken(); 77 | if (token.toUpperCase().startsWith("HTTP")) { 78 | 79 | // Response 80 | 81 | jo.put("HTTP-Version", token); 82 | jo.put("Status-Code", x.nextToken()); 83 | jo.put("Reason-Phrase", x.nextTo('\0')); 84 | x.next(); 85 | 86 | } else { 87 | 88 | // Request 89 | 90 | jo.put("Method", token); 91 | jo.put("Request-URI", x.nextToken()); 92 | jo.put("HTTP-Version", x.nextToken()); 93 | } 94 | 95 | // Fields 96 | 97 | while (x.more()) { 98 | String name = x.nextTo(':'); 99 | x.next(':'); 100 | jo.put(name, x.nextTo('\0')); 101 | x.next(); 102 | } 103 | return jo; 104 | } 105 | 106 | 107 | /** 108 | * Convert a JSONObject into an HTTP header. A request header must contain 109 | *
{
110 |      *    Method: "POST" (for example),
111 |      *    "Request-URI": "/" (for example),
112 |      *    "HTTP-Version": "HTTP/1.1" (for example)
113 |      * }
114 | * A response header must contain 115 | *
{
116 |      *    "HTTP-Version": "HTTP/1.1" (for example),
117 |      *    "Status-Code": "200" (for example),
118 |      *    "Reason-Phrase": "OK" (for example)
119 |      * }
120 | * Any other members of the JSONObject will be output as HTTP fields. 121 | * The result will end with two CRLF pairs. 122 | * @param jo A JSONObject 123 | * @return An HTTP header string. 124 | * @throws JSONException if the object does not contain enough 125 | * information. 126 | */ 127 | public static String toString(JSONObject jo) throws JSONException { 128 | Iterator keys = jo.keys(); 129 | String string; 130 | StringBuffer sb = new StringBuffer(); 131 | if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { 132 | sb.append(jo.getString("HTTP-Version")); 133 | sb.append(' '); 134 | sb.append(jo.getString("Status-Code")); 135 | sb.append(' '); 136 | sb.append(jo.getString("Reason-Phrase")); 137 | } else if (jo.has("Method") && jo.has("Request-URI")) { 138 | sb.append(jo.getString("Method")); 139 | sb.append(' '); 140 | sb.append('"'); 141 | sb.append(jo.getString("Request-URI")); 142 | sb.append('"'); 143 | sb.append(' '); 144 | sb.append(jo.getString("HTTP-Version")); 145 | } else { 146 | throw new JSONException("Not enough material for an HTTP header."); 147 | } 148 | sb.append(CRLF); 149 | while (keys.hasNext()) { 150 | string = keys.next().toString(); 151 | if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && 152 | !"Reason-Phrase".equals(string) && !"Method".equals(string) && 153 | !"Request-URI".equals(string) && !jo.isNull(string)) { 154 | sb.append(string); 155 | sb.append(": "); 156 | sb.append(jo.getString(string)); 157 | sb.append(CRLF); 158 | } 159 | } 160 | sb.append(CRLF); 161 | return sb.toString(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /CCNx/src/org/json/Cookie.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * Convert a web browser cookie specification to a JSONObject and back. 29 | * JSON and Cookies are both notations for name/value pairs. 30 | * @author JSON.org 31 | * @version 2010-12-24 32 | */ 33 | public class Cookie { 34 | 35 | /** 36 | * Produce a copy of a string in which the characters '+', '%', '=', ';' 37 | * and control characters are replaced with "%hh". This is a gentle form 38 | * of URL encoding, attempting to cause as little distortion to the 39 | * string as possible. The characters '=' and ';' are meta characters in 40 | * cookies. By convention, they are escaped using the URL-encoding. This is 41 | * only a convention, not a standard. Often, cookies are expected to have 42 | * encoded values. We encode '=' and ';' because we must. We encode '%' and 43 | * '+' because they are meta characters in URL encoding. 44 | * @param string The source string. 45 | * @return The escaped result. 46 | */ 47 | public static String escape(String string) { 48 | char c; 49 | String s = string.trim(); 50 | StringBuffer sb = new StringBuffer(); 51 | int length = s.length(); 52 | for (int i = 0; i < length; i += 1) { 53 | c = s.charAt(i); 54 | if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { 55 | sb.append('%'); 56 | sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); 57 | sb.append(Character.forDigit((char)(c & 0x0f), 16)); 58 | } else { 59 | sb.append(c); 60 | } 61 | } 62 | return sb.toString(); 63 | } 64 | 65 | 66 | /** 67 | * Convert a cookie specification string into a JSONObject. The string 68 | * will contain a name value pair separated by '='. The name and the value 69 | * will be unescaped, possibly converting '+' and '%' sequences. The 70 | * cookie properties may follow, separated by ';', also represented as 71 | * name=value (except the secure property, which does not have a value). 72 | * The name will be stored under the key "name", and the value will be 73 | * stored under the key "value". This method does not do checking or 74 | * validation of the parameters. It only converts the cookie string into 75 | * a JSONObject. 76 | * @param string The cookie specification string. 77 | * @return A JSONObject containing "name", "value", and possibly other 78 | * members. 79 | * @throws JSONException 80 | */ 81 | public static JSONObject toJSONObject(String string) throws JSONException { 82 | String name; 83 | JSONObject jo = new JSONObject(); 84 | Object value; 85 | JSONTokener x = new JSONTokener(string); 86 | jo.put("name", x.nextTo('=')); 87 | x.next('='); 88 | jo.put("value", x.nextTo(';')); 89 | x.next(); 90 | while (x.more()) { 91 | name = unescape(x.nextTo("=;")); 92 | if (x.next() != '=') { 93 | if (name.equals("secure")) { 94 | value = Boolean.TRUE; 95 | } else { 96 | throw x.syntaxError("Missing '=' in cookie parameter."); 97 | } 98 | } else { 99 | value = unescape(x.nextTo(';')); 100 | x.next(); 101 | } 102 | jo.put(name, value); 103 | } 104 | return jo; 105 | } 106 | 107 | 108 | /** 109 | * Convert a JSONObject into a cookie specification string. The JSONObject 110 | * must contain "name" and "value" members. 111 | * If the JSONObject contains "expires", "domain", "path", or "secure" 112 | * members, they will be appended to the cookie specification string. 113 | * All other members are ignored. 114 | * @param jo A JSONObject 115 | * @return A cookie specification string 116 | * @throws JSONException 117 | */ 118 | public static String toString(JSONObject jo) throws JSONException { 119 | StringBuffer sb = new StringBuffer(); 120 | 121 | sb.append(escape(jo.getString("name"))); 122 | sb.append("="); 123 | sb.append(escape(jo.getString("value"))); 124 | if (jo.has("expires")) { 125 | sb.append(";expires="); 126 | sb.append(jo.getString("expires")); 127 | } 128 | if (jo.has("domain")) { 129 | sb.append(";domain="); 130 | sb.append(escape(jo.getString("domain"))); 131 | } 132 | if (jo.has("path")) { 133 | sb.append(";path="); 134 | sb.append(escape(jo.getString("path"))); 135 | } 136 | if (jo.optBoolean("secure")) { 137 | sb.append(";secure"); 138 | } 139 | return sb.toString(); 140 | } 141 | 142 | /** 143 | * Convert %hh sequences to single characters, and 144 | * convert plus to space. 145 | * @param string A string that may contain 146 | * + (plus) and 147 | * %hh sequences. 148 | * @return The unescaped string. 149 | */ 150 | public static String unescape(String string) { 151 | int length = string.length(); 152 | StringBuffer sb = new StringBuffer(); 153 | for (int i = 0; i < length; ++i) { 154 | char c = string.charAt(i); 155 | if (c == '+') { 156 | c = ' '; 157 | } else if (c == '%' && i + 2 < length) { 158 | int d = JSONTokener.dehexchar(string.charAt(i + 1)); 159 | int e = JSONTokener.dehexchar(string.charAt(i + 2)); 160 | if (d >= 0 && e >= 0) { 161 | c = (char)(d * 16 + e); 162 | i += 2; 163 | } 164 | } 165 | sb.append(c); 166 | } 167 | return sb.toString(); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /CCNx/src/ClientManager.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 5 | # 6 | # This file is part of NDNFlow. 7 | # 8 | # NDNFlow is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # NDNFlow is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with NDNFlow. If not, see . 20 | **/ 21 | 22 | import java.io.BufferedReader; 23 | import java.io.DataInputStream; 24 | import java.io.DataOutputStream; 25 | import java.io.FileInputStream; 26 | import java.io.FileNotFoundException; 27 | import java.io.IOException; 28 | import java.io.InputStreamReader; 29 | import java.net.Inet4Address; 30 | import java.net.InetAddress; 31 | import java.net.Socket; 32 | import java.net.UnknownHostException; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.Properties; 36 | 37 | import org.ccnx.ccn.CCNHandle; 38 | import org.ccnx.ccn.CCNInterestHandler; 39 | import org.ccnx.ccn.config.ConfigurationException; 40 | import org.ccnx.ccn.impl.CCNNetworkManager.NetworkProtocol; 41 | import org.ccnx.ccn.profiles.ccnd.CCNDaemonException; 42 | import org.ccnx.ccn.profiles.ccnd.FaceManager; 43 | import org.ccnx.ccn.profiles.ccnd.PrefixRegistrationManager; 44 | import org.ccnx.ccn.protocol.ContentName; 45 | import org.ccnx.ccn.protocol.Interest; 46 | import org.ccnx.ccn.protocol.MalformedContentNameStringException; 47 | import org.json.*; 48 | 49 | import static java.lang.System.out; 50 | 51 | 52 | 53 | public class ClientManager implements CCNInterestHandler { 54 | 55 | private CCNHandle ccnHandle; 56 | private Socket sock; 57 | private DataOutputStream os; 58 | private BufferedReader is; 59 | 60 | private String controller; 61 | private int controller_port; 62 | private long dpid; 63 | private InetAddress ip; 64 | 65 | private Map content; 66 | private FaceManager fHandle; 67 | private PrefixRegistrationManager prfxMgr; 68 | 69 | 70 | 71 | 72 | 73 | public static void main(String[] args) { 74 | new ClientManager().run(); 75 | } 76 | 77 | public void run() { 78 | try { 79 | 80 | getConfig(); 81 | 82 | connectCCNx(); 83 | connectController(); 84 | 85 | out.println("Connected to CCNx and Controller"); 86 | 87 | announceContent(); 88 | 89 | readInput(); 90 | 91 | 92 | } catch (MalformedContentNameStringException e) { 93 | // TODO Auto-generated catch block 94 | e.printStackTrace(); 95 | } catch (ConfigurationException e) { 96 | // TODO Auto-generated catch block 97 | e.printStackTrace(); 98 | } catch (IOException e) { 99 | // TODO Auto-generated catch block 100 | e.printStackTrace(); 101 | } catch (CCNDaemonException e) { 102 | // TODO Auto-generated catch block 103 | e.printStackTrace(); 104 | } 105 | 106 | 107 | 108 | } 109 | 110 | private void readInput() throws JSONException, IOException { 111 | String input; 112 | while((input = is.readLine()) != null) { 113 | out.println(input); 114 | JSONObject jo = new JSONObject(input); 115 | String Type = jo.getString("Type"); 116 | if (Type == null) { 117 | out.println("Received message without Type: " + input); 118 | } else if(Type.equals("Rule")) { 119 | 120 | try { 121 | 122 | ContentName prefix = ContentName.fromURI(jo.getString("Name")); 123 | String action = jo.getString("Action"); 124 | JSONArray actionParams = jo.getJSONArray("ActionParams"); 125 | 126 | out.println("Add rule for prefix ccnx:"+prefix+", action: "+action+", "+actionParams); 127 | Integer faceID = fHandle.createFace(NetworkProtocol.valueOf(action), actionParams.getString(0), 9695); 128 | prfxMgr.registerPrefix(prefix, faceID, null); 129 | out.println("Added rule for prefix ccnx:"+prefix+", action: "+action+", "+actionParams); 130 | 131 | } catch (MalformedContentNameStringException e) { 132 | // TODO Auto-generated catch block 133 | e.printStackTrace(); 134 | } catch (JSONException e) { 135 | // TODO Auto-generated catch block 136 | e.printStackTrace(); 137 | } catch (CCNDaemonException e) { 138 | // TODO Auto-generated catch block 139 | e.printStackTrace(); 140 | } 141 | 142 | 143 | } else { 144 | out.println("Received incorrect Type: " + Type); 145 | } 146 | } 147 | } 148 | 149 | private void announceContent() { 150 | JSONObject jo = new JSONObject(); 151 | jo.put("Type", "AvailableContent"); 152 | jo.put("Content", content); 153 | try { 154 | send(jo); 155 | } catch (IOException e) { 156 | // TODO Auto-generated catch block 157 | e.printStackTrace(); 158 | } 159 | out.println("Announced available content "+jo); 160 | } 161 | 162 | private void connectController() throws UnknownHostException, IOException { 163 | sock = new Socket(controller, controller_port); 164 | os = new DataOutputStream( sock.getOutputStream() ); 165 | is = new BufferedReader(new InputStreamReader( sock.getInputStream() )); 166 | 167 | JSONObject jo = new JSONObject(); 168 | jo.put("Type", "Announce"); 169 | jo.put("DPID", dpid); 170 | jo.put("IP", ip.getHostAddress()); 171 | 172 | send(jo); 173 | out.println("Sent "+jo); 174 | } 175 | 176 | private void connectCCNx() throws ConfigurationException, IOException, MalformedContentNameStringException, CCNDaemonException { 177 | ccnHandle = CCNHandle.open(); 178 | //incomingCCNHandle.registerFilter(ContentName.fromURI("/"), this); 179 | int _flags = PrefixRegistrationManager.CCN_FORW_ACTIVE | PrefixRegistrationManager.CCN_FORW_LAST; //We only want to search for new mappings if no other mappings exist. 180 | ccnHandle.getNetworkManager().setInterestFilter(ContentName.fromURI("/"), this, _flags); 181 | 182 | fHandle = new FaceManager(ccnHandle); 183 | prfxMgr = new PrefixRegistrationManager(ccnHandle); 184 | 185 | 186 | } 187 | 188 | private void getConfig() throws IOException, MalformedContentNameStringException { 189 | Properties confFile = new Properties(); 190 | FileInputStream confStream = new FileInputStream("config.properties"); 191 | confFile.load(confStream); 192 | 193 | dpid = Long.decode( confFile.getProperty("dpid") ); 194 | ip = InetAddress.getByName( confFile.getProperty("ip") ); 195 | 196 | out.println("Datapath ID dpid="+ Long.toHexString(dpid) ); 197 | controller = confFile.getProperty("server"); 198 | controller_port = Integer.decode( confFile.getProperty("port", "6635") ); 199 | out.println("Found server address: "+ controller + ":" + controller_port); 200 | 201 | content = new HashMap(); 202 | 203 | String entrypoint; 204 | for(int i = 0; (entrypoint = confFile.getProperty("entry."+i)) != null; i++) 205 | { 206 | int cost = Integer.parseInt( confFile.getProperty("entry."+i+".cost", "0") ); 207 | int priority = Integer.parseInt( confFile.getProperty("entry."+i+".priority", "0") ); 208 | 209 | content.put(ContentName.fromURI(entrypoint), new ContentProps(cost, priority)); 210 | 211 | out.println("Found entrypoint "+entrypoint+" @ cost="+cost+" and priority="+priority); 212 | } 213 | } 214 | 215 | @Override 216 | public boolean handleInterest(Interest intrst) { 217 | out.println("Received Interest: " + intrst.name()); 218 | 219 | try { 220 | 221 | JSONObject jo = new JSONObject(); 222 | jo.put("Type", "Interest"); 223 | jo.put("Name", intrst.name().toString()); 224 | out.println(jo); 225 | 226 | send(jo); 227 | 228 | } catch (IOException e) { 229 | // TODO Auto-generated catch block 230 | e.printStackTrace(); 231 | } 232 | 233 | return false; 234 | } 235 | 236 | public void send(JSONObject jo) throws IOException { 237 | synchronized (os) { 238 | os.writeBytes(jo.toString()+"\n"); 239 | os.flush(); 240 | } 241 | } 242 | 243 | } 244 | -------------------------------------------------------------------------------- /POX/CCNxPlugin.py: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | from pox.core import core 19 | from pox.lib.util import * 20 | import pox.openflow.libopenflow_01 as of 21 | import threading 22 | import json 23 | from collections import defaultdict 24 | import forwarding 25 | 26 | log = core.getLogger() 27 | enabledSwitches = {} 28 | availableContentByDPID = {} 29 | availableContentByName = {} 30 | 31 | class Content: 32 | def __init__ (self, dpid, name, cost, priority): 33 | self.dpid = dpid 34 | self.name = name 35 | self.cost = cost 36 | self.priority = priority 37 | 38 | class Switch: 39 | def __init__ (self, dpid, conn, ip): 40 | self.dpid = dpid 41 | self.conn = conn 42 | self.ip = ip 43 | 44 | def _get_path(src, dsts): 45 | ##Copy original adjacency 46 | #adj = defaultdict(lambda: defaultdict(lambda: None) ) 47 | #for (key, value) in forwarding.adj: 48 | # adj[key] = value.copy() 49 | 50 | #Reference original adjacency matrix 51 | adj = forwarding.adj 52 | 53 | #Bellman-Ford algorithm 54 | keys = forwarding.switches.keys() 55 | distance = {} 56 | previous = {} 57 | 58 | for dpid in keys: 59 | distance[dpid] = float("+inf") 60 | previous[dpid] = None 61 | 62 | distance[src] = 0 63 | for i in range(len(keys)-1): 64 | for u in adj.keys(): #nested dict 65 | for v in adj[u].keys(): 66 | w = 1 67 | if distance[u] + w < distance[v]: 68 | distance[v] = distance[u] + w 69 | previous[v] = u 70 | 71 | for u in adj.keys(): #nested dict 72 | for v in adj[u].keys(): 73 | w = 1 74 | if distance[u] + w < distance[v]: 75 | log.error("Graph contains a negative-weight cycle") 76 | return None 77 | 78 | #Determine cheapest destination from set of destinations 79 | dst = None 80 | cost = float("+inf") 81 | for _dst in dsts: 82 | if (_dst.cost + distance[_dst.dpid]) < cost: 83 | cost = _dst.cost + distance[_dst.dpid] 84 | dst = _dst.dpid 85 | 86 | first_port = None 87 | v = dst 88 | u = previous[v] 89 | while u is not None: 90 | if u == src: 91 | first_port = adj[u][v] 92 | 93 | v = u 94 | u = previous[v] 95 | 96 | return forwarding.Path(src, dst, previous, first_port) #path 97 | 98 | class CCNxPlugin (object): 99 | 100 | 101 | def SockClient(self, conn): 102 | log.debug("Client connection thread started") 103 | buffer = '' 104 | data = True 105 | while data: #Created our own buffered reader 106 | data = conn.recv(4096) 107 | buffer += data 108 | 109 | while buffer.find('\n') != -1: 110 | msg, buffer = buffer.split('\n', 1) 111 | 112 | #Actual \n delimited messages 113 | log.debug("Received message: "+ msg) 114 | tMsg = json.loads(msg) 115 | if tMsg["Type"] == "Interest": 116 | log.debug("%s received Interest message for name %s"%(dpid, tMsg["Name"])) 117 | prefix = tMsg["Name"] 118 | 119 | #Do prefix match, also check if resulting list is actually filled 120 | while prefix != "" and (prefix not in availableContentByName or not availableContentByName[prefix]): 121 | log.debug("Could not find prefix %s"%(prefix)) 122 | prefix = prefix[:prefix.rfind("/")] 123 | 124 | if prefix == "": 125 | log.debug("Could not find any prefix matches for Interest name") 126 | continue #with next message 127 | 128 | log.debug("Found %d elements for prefix %s"%(len(availableContentByName[prefix]), prefix)) 129 | 130 | #select exclusively highest prio (thus minimal value) content elements) 131 | #Might want to look into a priority queue for this, as theoretical number of requests exceeds number of inserts, updates and deletes 132 | minPrio = min([ci.priority for ci in availableContentByName[prefix].values()]) 133 | prioContent = [ci for ci in availableContentByName[prefix].values() if ci.priority == minPrio] 134 | 135 | log.debug("Found %d remaining elements for prio = %d"%(len(prioContent), minPrio)) 136 | 137 | prev_path = _get_path(dpid, prioContent) 138 | 139 | if prev_path is None: 140 | log.warn( "No path found from %s to %s"%(dpid_to_str(prev_path.src), dpid_to_str(prev_path.dst)) ) 141 | continue #with next message 142 | 143 | log.debug( "Path found from %s to %s over path %s"%(dpid_to_str(prev_path.src), dpid_to_str(prev_path.dst), prev_path) ) 144 | 145 | #Assume src and dst to be enabled, technically has to be, else the complete thing would not go through, but still. 146 | assert prev_path.dst in enabledSwitches 147 | assert prev_path.src in enabledSwitches 148 | 149 | subdst = prev_path.dst 150 | subsrc = prev_path.prev[subdst] 151 | while subsrc != None: 152 | if subsrc in enabledSwitches: 153 | log.debug("Found subpath %s to %s"%(dpid_to_str(subsrc), dpid_to_str(subdst)) ) 154 | nMsg = json.dumps ( { 'Type' : 'Rule', 155 | 'Name' : prefix, 156 | 'Action' : 'TCP', 157 | 'ActionParams' : [ enabledSwitches[subdst].ip ] } ) 158 | 159 | enabledSwitches[subsrc].conn.send ( nMsg + '\n' ) 160 | log.debug("Send %s to %s"%(nMsg, dpid_to_str(subsrc)) ) 161 | subdst = subsrc 162 | subsrc = prev_path.prev[subsrc] 163 | 164 | 165 | 166 | #log.debug("Name can be found on DPIDs %s"%(dpids)) 167 | #nMsg = json.dumps( { 'Type' : 'Rule', 168 | # 'Name' : '/test/ping', 169 | # 'Action' : 'TCP', 170 | # 'ActionParams' : ['10.0.0.7'] } ) 171 | #log.debug ( nMsg ) 172 | #conn.send( nMsg + '\n' ) 173 | 174 | elif tMsg["Type"] == "Announce": 175 | assert dpid == None #You cannot change the DPID of an already connected switch as it would invalidate path computations, available content, etc. 176 | assert ip == None #Same here 177 | 178 | dpid = int(tMsg["DPID"]) 179 | ip = tMsg["IP"] 180 | 181 | enabledSwitches[dpid] = Switch(dpid, conn, ip) 182 | log.debug("Switch with dpid announced itself %s" % (dpid_to_str(dpid)) ) 183 | 184 | elif tMsg["Type"] == "AvailableContent": 185 | #availableContentByDPID[dpid] = tMsg["Content"] 186 | availableContentByDPID[dpid] = {} 187 | for (name, value) in tMsg["Content"].items(): 188 | log.debug("Add %s : %s"%(name, json.dumps(value)) ) 189 | availableContentByDPID[dpid][name] = Content(dpid, name, value["cost"], value["priority"]) 190 | 191 | if name not in availableContentByName: 192 | availableContentByName[name] = {} 193 | availableContentByName[name][dpid] = Content(dpid, name, value["cost"], value["priority"]) 194 | 195 | log.debug("%s updated AvailableContent to %d items"%(dpid_to_str(dpid), len(availableContentByDPID[dpid]))) 196 | else: 197 | log.debug("Unknown message: " + tMsg["Type"]) 198 | 199 | conn.close() 200 | 201 | #Remove dpid from enabledSwitches 202 | del enabledSwitches[dpid] 203 | 204 | #Still need to clean availableContent 205 | ### 206 | 207 | log.debug("End of thread") 208 | 209 | def SockListener(self,sock): 210 | log.debug("I am your SockListener thread") 211 | while 1: 212 | (clientsock, address) = sock.accept() 213 | log.debug("New connection accepted") 214 | threading.Thread(target=self.SockClient, args=(clientsock,)).start() 215 | 216 | def __init__(self, *args, **kwargs): 217 | core.openflow.addListeners(self) 218 | log.debug("Added Openflow Listeners") 219 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 220 | sock.bind( ('', 6635) ) 221 | sock.listen(5) 222 | log.debug("Created Socket") 223 | threading.Thread(target=self.SockListener, args=(sock,)).start() 224 | log.debug("Gave socket to async thread") 225 | 226 | def _handle_ConnectionUp (self, event): 227 | if event.dpid in enabledSwitches : 228 | log.debug("NDN overlay enabled switch %s has come up.", dpid_to_str(event.dpid)) 229 | 230 | else: 231 | log.debug("Switch %s has come up.", dpid_to_str(event.dpid)) 232 | 233 | def launch (): 234 | 235 | log.debug("Registering CCNxPlugin") 236 | 237 | core.registerNew(CCNxPlugin) 238 | 239 | log.debug("Registered CCNxPlugin") 240 | 241 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/JSONzip.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | 4 | /* 5 | Copyright (c) 2013 JSON.org 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | The Software shall be used for Good, not Evil. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | /** 29 | * JSONzip is a binary-encoded JSON dialect. It is designed to compress the 30 | * messages in a session. It is adaptive, so with each message seen, it should 31 | * improve its compression. It minimizes JSON's overhead, reducing punctuation 32 | * to a small number of bits. It uses Huffman encoding to reduce the average 33 | * size of characters. It uses caches (or Keeps) to keep recently seen strings 34 | * and values, so repetitive content (such as object keys) can be 35 | * substantially reduced. It uses a character encoding called Kim (Keep it 36 | * minimal) that is smaller than UTF-8 for most East European, African, and 37 | * Asian scripts. 38 | * 39 | * JSONzip tends to reduce most content by about half. If there is a lot of 40 | * recurring information, the reduction can be much more dramatic. 41 | * 42 | * FOR EVALUATION PURPOSES ONLY. THIS PACKAGE HAS NOT YET BEEN TESTED 43 | * ADEQUATELY FOR PRODUCTION USE. 44 | * 45 | * @author JSON.org 46 | * @version 2013-04-18 47 | */ 48 | public abstract class JSONzip implements None, PostMortem { 49 | /** 50 | * Powers of 2. 51 | */ 52 | public static final int[] twos = { 53 | 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 54 | 1024, 2048, 4096, 8192, 16384, 32768, 65536 55 | }; 56 | 57 | /** 58 | * The characters in JSON numbers can be reduced to 4 bits each. 59 | */ 60 | public static final byte[] bcd = { 61 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-', '+', 'E' 62 | }; 63 | 64 | /** 65 | * The number of integers that can be encoded in 4 bits. 66 | */ 67 | public static final long int4 = 16; 68 | 69 | /** 70 | * The number of integers that can be encoded in 7 bits. 71 | */ 72 | public static final long int7 = 128; 73 | 74 | /** 75 | * The number of integers that can be encoded in 14 bits. 76 | */ 77 | public static final long int14 = 16384; 78 | 79 | /** 80 | * The end of string code. 81 | */ 82 | public static final int end = 256; 83 | 84 | /** 85 | * The end of number code. 86 | */ 87 | public static final int endOfNumber = bcd.length; 88 | 89 | /** 90 | * The maximum substring length when registering many. The registration of 91 | * one substring may be longer. 92 | */ 93 | public static final int maxSubstringLength = 10; 94 | 95 | /** 96 | * The minimum substring length. 97 | */ 98 | public static final int minSubstringLength = 3; 99 | 100 | /** 101 | * The package supports tracing for debugging. 102 | */ 103 | public static final boolean probe = false; 104 | 105 | /** 106 | * The maximum number of substrings added to the substrings keep per 107 | * string. 108 | */ 109 | public static final int substringLimit = 40; 110 | 111 | /** 112 | * The value code for an empty object. 113 | */ 114 | public static final int zipEmptyObject = 0; 115 | 116 | /** 117 | * The value code for an empty array. 118 | */ 119 | public static final int zipEmptyArray = 1; 120 | 121 | /** 122 | * The value code for true. 123 | */ 124 | public static final int zipTrue = 2; 125 | 126 | /** 127 | * The value code for false. 128 | */ 129 | public static final int zipFalse = 3; 130 | 131 | /** 132 | * The value code for null. 133 | */ 134 | public static final int zipNull = 4; 135 | 136 | /** 137 | * The value code for a non-empty object. 138 | */ 139 | public static final int zipObject = 5; 140 | 141 | /** 142 | * The value code for an array with a string as its first element. 143 | */ 144 | public static final int zipArrayString = 6; 145 | 146 | /** 147 | * The value code for an array with a non-string value as its first element. 148 | */ 149 | public static final int zipArrayValue = 7; 150 | 151 | /** 152 | * A Huffman encoder for names. 153 | */ 154 | protected final Huff namehuff; 155 | 156 | /** 157 | * A place to keep the names (keys). 158 | */ 159 | protected final MapKeep namekeep; 160 | 161 | /** 162 | * A place to keep the strings. 163 | */ 164 | protected final MapKeep stringkeep; 165 | 166 | /** 167 | * A Huffman encoder for string values. 168 | */ 169 | protected final Huff substringhuff; 170 | 171 | /** 172 | * A place to keep the strings. 173 | */ 174 | protected final TrieKeep substringkeep; 175 | 176 | /** 177 | * A place to keep the values. 178 | */ 179 | protected final MapKeep values; 180 | 181 | /** 182 | * Initialize the data structures. 183 | */ 184 | protected JSONzip() { 185 | this.namehuff = new Huff(end + 1); 186 | this.namekeep = new MapKeep(9); 187 | this.stringkeep = new MapKeep(11); 188 | this.substringhuff = new Huff(end + 1); 189 | this.substringkeep = new TrieKeep(12); 190 | this.values = new MapKeep(10); 191 | 192 | // Increase the weights of the ASCII letters, digits, and special characters 193 | // because they are highly likely to occur more frequently. The weight of each 194 | // character will increase as it is used. The Huffman encoder will tend to 195 | // use fewer bits to encode heavier characters. 196 | 197 | this.namehuff.tick(' ', '}'); 198 | this.namehuff.tick('a', 'z'); 199 | this.namehuff.tick(end); 200 | this.namehuff.tick(end); 201 | this.substringhuff.tick(' ', '}'); 202 | this.substringhuff.tick('a', 'z'); 203 | this.substringhuff.tick(end); 204 | this.substringhuff.tick(end); 205 | } 206 | 207 | /** 208 | * 209 | */ 210 | protected void begin() { 211 | this.namehuff.generate(); 212 | this.substringhuff.generate(); 213 | } 214 | 215 | /** 216 | * Write an end-of-line to the console. 217 | */ 218 | static void log() { 219 | log("\n"); 220 | } 221 | 222 | /** 223 | * Write an integer to the console. 224 | * 225 | * @param integer 226 | */ 227 | static void log(int integer) { 228 | log(integer + " "); 229 | } 230 | 231 | /** 232 | * Write two integers, separated by ':' to the console. 233 | * 234 | * @param integer 235 | * @param width 236 | */ 237 | static void log(int integer, int width) { 238 | log(integer + ":" + width + " "); 239 | } 240 | 241 | /** 242 | * Write a string to the console. 243 | * 244 | * @param string 245 | */ 246 | static void log(String string) { 247 | System.out.print(string); 248 | } 249 | 250 | /** 251 | * Write a character or its code to the console. 252 | * 253 | * @param integer 254 | * @param width 255 | */ 256 | static void logchar(int integer, int width) { 257 | if (integer > ' ' && integer <= '}') { 258 | log("'" + (char) integer + "':" + width + " "); 259 | } else { 260 | log(integer, width); 261 | } 262 | } 263 | 264 | /** 265 | * This method is used for testing the implementation of JSONzip. It is not 266 | * suitable for any other purpose. It is used to compare a Compressor and a 267 | * Decompressor, verifying that the data structures that were built during 268 | * zipping and unzipping were the same. 269 | * 270 | * @return true if the structures match. 271 | */ 272 | public boolean postMortem(PostMortem pm) { 273 | JSONzip that = (JSONzip) pm; 274 | return this.namehuff.postMortem(that.namehuff) 275 | && this.namekeep.postMortem(that.namekeep) 276 | && this.stringkeep.postMortem(that.stringkeep) 277 | && this.substringhuff.postMortem(that.substringhuff) 278 | && this.substringkeep.postMortem(that.substringkeep) 279 | && this.values.postMortem(that.values); 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/Decompressor.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | import org.json.JSONArray; 6 | import org.json.JSONException; 7 | import org.json.JSONObject; 8 | import org.json.Kim; 9 | 10 | /* 11 | Copyright (c) 2012 JSON.org 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | The Software shall be used for Good, not Evil. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | */ 33 | 34 | /** 35 | * JSONzip is a compression scheme for JSON text. 36 | * 37 | * @author JSON.org 38 | * @version 2013-04-18 39 | */ 40 | 41 | public class Decompressor extends JSONzip { 42 | 43 | /** 44 | * A decompressor reads bits from a BitReader. 45 | */ 46 | BitReader bitreader; 47 | 48 | /** 49 | * Create a new compressor. It may be used for an entire session or 50 | * subsession. 51 | * 52 | * @param bitreader 53 | * The bitreader that this decompressor will read from. 54 | */ 55 | public Decompressor(BitReader bitreader) { 56 | super(); 57 | this.bitreader = bitreader; 58 | } 59 | 60 | /** 61 | * Read one bit. 62 | * 63 | * @return true if 1, false if 0. 64 | * @throws JSONException 65 | */ 66 | private boolean bit() throws JSONException { 67 | boolean value; 68 | try { 69 | value = this.bitreader.bit(); 70 | if (probe) { 71 | log(value ? 1 : 0); 72 | } 73 | return value; 74 | } catch (Throwable e) { 75 | throw new JSONException(e); 76 | } 77 | 78 | } 79 | 80 | /** 81 | * Read enough bits to obtain an integer from the keep, and increase that 82 | * integer's weight. 83 | * 84 | * @param keep 85 | * @param bitreader 86 | * @return 87 | * @throws JSONException 88 | */ 89 | private Object getAndTick(Keep keep, BitReader bitreader) 90 | throws JSONException { 91 | try { 92 | int width = keep.bitsize(); 93 | int integer = bitreader.read(width); 94 | Object value = keep.value(integer); 95 | if (JSONzip.probe) { 96 | JSONzip.log("\"" + value + "\""); 97 | JSONzip.log(integer, width); 98 | } 99 | if (integer >= keep.length) { 100 | throw new JSONException("Deep error."); 101 | } 102 | keep.tick(integer); 103 | return value; 104 | } catch (Throwable e) { 105 | throw new JSONException(e); 106 | } 107 | } 108 | 109 | /** 110 | * The pad method skips the bits that padded a stream to fit some 111 | * allocation. pad(8) will skip over the remainder of a byte. 112 | * 113 | * @param factor 114 | * @return true if all of the padding bits were zero. 115 | * @throws JSONException 116 | */ 117 | public boolean pad(int factor) throws JSONException { 118 | try { 119 | return this.bitreader.pad(factor); 120 | } catch (Throwable e) { 121 | throw new JSONException(e); 122 | } 123 | } 124 | 125 | /** 126 | * Read an integer, specifying its width in bits. 127 | * 128 | * @param width 129 | * 0 to 32. 130 | * @return An unsigned integer. 131 | * @throws JSONException 132 | */ 133 | private int read(int width) throws JSONException { 134 | try { 135 | int value = this.bitreader.read(width); 136 | if (probe) { 137 | log(value, width); 138 | } 139 | return value; 140 | } catch (Throwable e) { 141 | throw new JSONException(e); 142 | } 143 | } 144 | 145 | /** 146 | * Read a JSONArray. 147 | * 148 | * @param stringy 149 | * true if the first element is a string. 150 | * @return 151 | * @throws JSONException 152 | */ 153 | private JSONArray readArray(boolean stringy) throws JSONException { 154 | JSONArray jsonarray = new JSONArray(); 155 | jsonarray.put(stringy ? readString() : readValue()); 156 | while (true) { 157 | if (probe) { 158 | log("\n"); 159 | } 160 | if (!bit()) { 161 | if (!bit()) { 162 | return jsonarray; 163 | } 164 | jsonarray.put(stringy ? readValue() : readString()); 165 | } else { 166 | jsonarray.put(stringy ? readString() : readValue()); 167 | } 168 | } 169 | } 170 | 171 | /** 172 | * Read a JSON value. The type of value is determined by the next 3 bits. 173 | * 174 | * @return 175 | * @throws JSONException 176 | */ 177 | private Object readJSON() throws JSONException { 178 | switch (read(3)) { 179 | case zipObject: 180 | return readObject(); 181 | case zipArrayString: 182 | return readArray(true); 183 | case zipArrayValue: 184 | return readArray(false); 185 | case zipEmptyObject: 186 | return new JSONObject(); 187 | case zipEmptyArray: 188 | return new JSONArray(); 189 | case zipTrue: 190 | return Boolean.TRUE; 191 | case zipFalse: 192 | return Boolean.FALSE; 193 | default: 194 | return JSONObject.NULL; 195 | } 196 | } 197 | 198 | private String readName() throws JSONException { 199 | byte[] bytes = new byte[65536]; 200 | int length = 0; 201 | if (!bit()) { 202 | while (true) { 203 | int c = this.namehuff.read(this.bitreader); 204 | if (c == end) { 205 | break; 206 | } 207 | bytes[length] = (byte) c; 208 | length += 1; 209 | } 210 | if (length == 0) { 211 | return ""; 212 | } 213 | Kim kim = new Kim(bytes, length); 214 | this.namekeep.register(kim); 215 | return kim.toString(); 216 | } 217 | return getAndTick(this.namekeep, this.bitreader).toString(); 218 | } 219 | 220 | private JSONObject readObject() throws JSONException { 221 | JSONObject jsonobject = new JSONObject(); 222 | while (true) { 223 | if (probe) { 224 | log("\n"); 225 | } 226 | String name = readName(); 227 | jsonobject.put(name, !bit() ? readString() : readValue()); 228 | if (!bit()) { 229 | return jsonobject; 230 | } 231 | } 232 | } 233 | 234 | private String readString() throws JSONException { 235 | Kim kim; 236 | int from = 0; 237 | int thru = 0; 238 | int previousFrom = none; 239 | int previousThru = 0; 240 | if (bit()) { 241 | return getAndTick(this.stringkeep, this.bitreader).toString(); 242 | } 243 | byte[] bytes = new byte[65536]; 244 | boolean one = bit(); 245 | this.substringkeep.reserve(); 246 | while (true) { 247 | if (one) { 248 | from = thru; 249 | kim = (Kim) getAndTick(this.substringkeep, this.bitreader); 250 | thru = kim.copy(bytes, from); 251 | if (previousFrom != none) { 252 | this.substringkeep.registerOne(new Kim(bytes, previousFrom, 253 | previousThru + 1)); 254 | } 255 | previousFrom = from; 256 | previousThru = thru; 257 | one = bit(); 258 | } else { 259 | from = none; 260 | while (true) { 261 | int c = this.substringhuff.read(this.bitreader); 262 | if (c == end) { 263 | break; 264 | } 265 | bytes[thru] = (byte) c; 266 | thru += 1; 267 | if (previousFrom != none) { 268 | this.substringkeep.registerOne(new Kim(bytes, 269 | previousFrom, previousThru + 1)); 270 | previousFrom = none; 271 | } 272 | } 273 | if (!bit()) { 274 | break; 275 | } 276 | one = true; 277 | } 278 | } 279 | if (thru == 0) { 280 | return ""; 281 | } 282 | kim = new Kim(bytes, thru); 283 | this.stringkeep.register(kim); 284 | this.substringkeep.registerMany(kim); 285 | return kim.toString(); 286 | } 287 | 288 | private Object readValue() throws JSONException { 289 | switch (read(2)) { 290 | case 0: 291 | return new Integer(read(!bit() ? 4 : !bit() ? 7 : 14)); 292 | case 1: 293 | byte[] bytes = new byte[256]; 294 | int length = 0; 295 | while (true) { 296 | int c = read(4); 297 | if (c == endOfNumber) { 298 | break; 299 | } 300 | bytes[length] = bcd[c]; 301 | length += 1; 302 | } 303 | Object value; 304 | try { 305 | value = JSONObject.stringToValue(new String(bytes, 0, length, 306 | "US-ASCII")); 307 | } catch (UnsupportedEncodingException e) { 308 | throw new JSONException(e); 309 | } 310 | this.values.register(value); 311 | return value; 312 | case 2: 313 | return getAndTick(this.values, this.bitreader); 314 | case 3: 315 | return readJSON(); 316 | default: 317 | throw new JSONException("Impossible."); 318 | } 319 | } 320 | 321 | public Object unzip() throws JSONException { 322 | begin(); 323 | return readJSON(); 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /CCNx/src/org/json/CDL.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * This provides static methods to convert comma delimited text into a 29 | * JSONArray, and to covert a JSONArray into comma delimited text. Comma 30 | * delimited text is a very popular format for data interchange. It is 31 | * understood by most database, spreadsheet, and organizer programs. 32 | *

33 | * Each row of text represents a row in a table or a data record. Each row 34 | * ends with a NEWLINE character. Each row contains one or more values. 35 | * Values are separated by commas. A value can contain any character except 36 | * for comma, unless is is wrapped in single quotes or double quotes. 37 | *

38 | * The first row usually contains the names of the columns. 39 | *

40 | * A comma delimited list can be converted into a JSONArray of JSONObjects. 41 | * The names for the elements in the JSONObjects can be taken from the names 42 | * in the first row. 43 | * @author JSON.org 44 | * @version 2012-11-13 45 | */ 46 | public class CDL { 47 | 48 | /** 49 | * Get the next value. The value can be wrapped in quotes. The value can 50 | * be empty. 51 | * @param x A JSONTokener of the source text. 52 | * @return The value string, or null if empty. 53 | * @throws JSONException if the quoted string is badly formed. 54 | */ 55 | private static String getValue(JSONTokener x) throws JSONException { 56 | char c; 57 | char q; 58 | StringBuffer sb; 59 | do { 60 | c = x.next(); 61 | } while (c == ' ' || c == '\t'); 62 | switch (c) { 63 | case 0: 64 | return null; 65 | case '"': 66 | case '\'': 67 | q = c; 68 | sb = new StringBuffer(); 69 | for (;;) { 70 | c = x.next(); 71 | if (c == q) { 72 | break; 73 | } 74 | if (c == 0 || c == '\n' || c == '\r') { 75 | throw x.syntaxError("Missing close quote '" + q + "'."); 76 | } 77 | sb.append(c); 78 | } 79 | return sb.toString(); 80 | case ',': 81 | x.back(); 82 | return ""; 83 | default: 84 | x.back(); 85 | return x.nextTo(','); 86 | } 87 | } 88 | 89 | /** 90 | * Produce a JSONArray of strings from a row of comma delimited values. 91 | * @param x A JSONTokener of the source text. 92 | * @return A JSONArray of strings. 93 | * @throws JSONException 94 | */ 95 | public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { 96 | JSONArray ja = new JSONArray(); 97 | for (;;) { 98 | String value = getValue(x); 99 | char c = x.next(); 100 | if (value == null || 101 | (ja.length() == 0 && value.length() == 0 && c != ',')) { 102 | return null; 103 | } 104 | ja.put(value); 105 | for (;;) { 106 | if (c == ',') { 107 | break; 108 | } 109 | if (c != ' ') { 110 | if (c == '\n' || c == '\r' || c == 0) { 111 | return ja; 112 | } 113 | throw x.syntaxError("Bad character '" + c + "' (" + 114 | (int)c + ")."); 115 | } 116 | c = x.next(); 117 | } 118 | } 119 | } 120 | 121 | /** 122 | * Produce a JSONObject from a row of comma delimited text, using a 123 | * parallel JSONArray of strings to provides the names of the elements. 124 | * @param names A JSONArray of names. This is commonly obtained from the 125 | * first row of a comma delimited text file using the rowToJSONArray 126 | * method. 127 | * @param x A JSONTokener of the source text. 128 | * @return A JSONObject combining the names and values. 129 | * @throws JSONException 130 | */ 131 | public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) 132 | throws JSONException { 133 | JSONArray ja = rowToJSONArray(x); 134 | return ja != null ? ja.toJSONObject(names) : null; 135 | } 136 | 137 | /** 138 | * Produce a comma delimited text row from a JSONArray. Values containing 139 | * the comma character will be quoted. Troublesome characters may be 140 | * removed. 141 | * @param ja A JSONArray of strings. 142 | * @return A string ending in NEWLINE. 143 | */ 144 | public static String rowToString(JSONArray ja) { 145 | StringBuffer sb = new StringBuffer(); 146 | for (int i = 0; i < ja.length(); i += 1) { 147 | if (i > 0) { 148 | sb.append(','); 149 | } 150 | Object object = ja.opt(i); 151 | if (object != null) { 152 | String string = object.toString(); 153 | if (string.length() > 0 && (string.indexOf(',') >= 0 || 154 | string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || 155 | string.indexOf(0) >= 0 || string.charAt(0) == '"')) { 156 | sb.append('"'); 157 | int length = string.length(); 158 | for (int j = 0; j < length; j += 1) { 159 | char c = string.charAt(j); 160 | if (c >= ' ' && c != '"') { 161 | sb.append(c); 162 | } 163 | } 164 | sb.append('"'); 165 | } else { 166 | sb.append(string); 167 | } 168 | } 169 | } 170 | sb.append('\n'); 171 | return sb.toString(); 172 | } 173 | 174 | /** 175 | * Produce a JSONArray of JSONObjects from a comma delimited text string, 176 | * using the first row as a source of names. 177 | * @param string The comma delimited text. 178 | * @return A JSONArray of JSONObjects. 179 | * @throws JSONException 180 | */ 181 | public static JSONArray toJSONArray(String string) throws JSONException { 182 | return toJSONArray(new JSONTokener(string)); 183 | } 184 | 185 | /** 186 | * Produce a JSONArray of JSONObjects from a comma delimited text string, 187 | * using the first row as a source of names. 188 | * @param x The JSONTokener containing the comma delimited text. 189 | * @return A JSONArray of JSONObjects. 190 | * @throws JSONException 191 | */ 192 | public static JSONArray toJSONArray(JSONTokener x) throws JSONException { 193 | return toJSONArray(rowToJSONArray(x), x); 194 | } 195 | 196 | /** 197 | * Produce a JSONArray of JSONObjects from a comma delimited text string 198 | * using a supplied JSONArray as the source of element names. 199 | * @param names A JSONArray of strings. 200 | * @param string The comma delimited text. 201 | * @return A JSONArray of JSONObjects. 202 | * @throws JSONException 203 | */ 204 | public static JSONArray toJSONArray(JSONArray names, String string) 205 | throws JSONException { 206 | return toJSONArray(names, new JSONTokener(string)); 207 | } 208 | 209 | /** 210 | * Produce a JSONArray of JSONObjects from a comma delimited text string 211 | * using a supplied JSONArray as the source of element names. 212 | * @param names A JSONArray of strings. 213 | * @param x A JSONTokener of the source text. 214 | * @return A JSONArray of JSONObjects. 215 | * @throws JSONException 216 | */ 217 | public static JSONArray toJSONArray(JSONArray names, JSONTokener x) 218 | throws JSONException { 219 | if (names == null || names.length() == 0) { 220 | return null; 221 | } 222 | JSONArray ja = new JSONArray(); 223 | for (;;) { 224 | JSONObject jo = rowToJSONObject(names, x); 225 | if (jo == null) { 226 | break; 227 | } 228 | ja.put(jo); 229 | } 230 | if (ja.length() == 0) { 231 | return null; 232 | } 233 | return ja; 234 | } 235 | 236 | 237 | /** 238 | * Produce a comma delimited text from a JSONArray of JSONObjects. The 239 | * first row will be a list of names obtained by inspecting the first 240 | * JSONObject. 241 | * @param ja A JSONArray of JSONObjects. 242 | * @return A comma delimited text. 243 | * @throws JSONException 244 | */ 245 | public static String toString(JSONArray ja) throws JSONException { 246 | JSONObject jo = ja.optJSONObject(0); 247 | if (jo != null) { 248 | JSONArray names = jo.names(); 249 | if (names != null) { 250 | return rowToString(names) + toString(names, ja); 251 | } 252 | } 253 | return null; 254 | } 255 | 256 | /** 257 | * Produce a comma delimited text from a JSONArray of JSONObjects using 258 | * a provided list of names. The list of names is not included in the 259 | * output. 260 | * @param names A JSONArray of strings. 261 | * @param ja A JSONArray of JSONObjects. 262 | * @return A comma delimited text. 263 | * @throws JSONException 264 | */ 265 | public static String toString(JSONArray names, JSONArray ja) 266 | throws JSONException { 267 | if (names == null || names.length() == 0) { 268 | return null; 269 | } 270 | StringBuffer sb = new StringBuffer(); 271 | for (int i = 0; i < ja.length(); i += 1) { 272 | JSONObject jo = ja.optJSONObject(i); 273 | if (jo != null) { 274 | sb.append(rowToString(jo.toJSONArray(names))); 275 | } 276 | } 277 | return sb.toString(); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /CCNx/src/org/json/JSONWriter.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | import java.io.IOException; 4 | import java.io.Writer; 5 | 6 | /* 7 | Copyright (c) 2006 JSON.org 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | The Software shall be used for Good, not Evil. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | 30 | /** 31 | * JSONWriter provides a quick and convenient way of producing JSON text. 32 | * The texts produced strictly conform to JSON syntax rules. No whitespace is 33 | * added, so the results are ready for transmission or storage. Each instance of 34 | * JSONWriter can produce one JSON text. 35 | *

36 | * A JSONWriter instance provides a value method for appending 37 | * values to the 38 | * text, and a key 39 | * method for adding keys before values in objects. There are array 40 | * and endArray methods that make and bound array values, and 41 | * object and endObject methods which make and bound 42 | * object values. All of these methods return the JSONWriter instance, 43 | * permitting a cascade style. For example,

 44 |  * new JSONWriter(myWriter)
 45 |  *     .object()
 46 |  *         .key("JSON")
 47 |  *         .value("Hello, World!")
 48 |  *     .endObject();
which writes
 49 |  * {"JSON":"Hello, World!"}
50 | *

51 | * The first method called must be array or object. 52 | * There are no methods for adding commas or colons. JSONWriter adds them for 53 | * you. Objects and arrays can be nested up to 20 levels deep. 54 | *

55 | * This can sometimes be easier than using a JSONObject to build a string. 56 | * @author JSON.org 57 | * @version 2011-11-24 58 | */ 59 | public class JSONWriter { 60 | private static final int maxdepth = 200; 61 | 62 | /** 63 | * The comma flag determines if a comma should be output before the next 64 | * value. 65 | */ 66 | private boolean comma; 67 | 68 | /** 69 | * The current mode. Values: 70 | * 'a' (array), 71 | * 'd' (done), 72 | * 'i' (initial), 73 | * 'k' (key), 74 | * 'o' (object). 75 | */ 76 | protected char mode; 77 | 78 | /** 79 | * The object/array stack. 80 | */ 81 | private final JSONObject stack[]; 82 | 83 | /** 84 | * The stack top index. A value of 0 indicates that the stack is empty. 85 | */ 86 | private int top; 87 | 88 | /** 89 | * The writer that will receive the output. 90 | */ 91 | protected Writer writer; 92 | 93 | /** 94 | * Make a fresh JSONWriter. It can be used to build one JSON text. 95 | */ 96 | public JSONWriter(Writer w) { 97 | this.comma = false; 98 | this.mode = 'i'; 99 | this.stack = new JSONObject[maxdepth]; 100 | this.top = 0; 101 | this.writer = w; 102 | } 103 | 104 | /** 105 | * Append a value. 106 | * @param string A string value. 107 | * @return this 108 | * @throws JSONException If the value is out of sequence. 109 | */ 110 | private JSONWriter append(String string) throws JSONException { 111 | if (string == null) { 112 | throw new JSONException("Null pointer"); 113 | } 114 | if (this.mode == 'o' || this.mode == 'a') { 115 | try { 116 | if (this.comma && this.mode == 'a') { 117 | this.writer.write(','); 118 | } 119 | this.writer.write(string); 120 | } catch (IOException e) { 121 | throw new JSONException(e); 122 | } 123 | if (this.mode == 'o') { 124 | this.mode = 'k'; 125 | } 126 | this.comma = true; 127 | return this; 128 | } 129 | throw new JSONException("Value out of sequence."); 130 | } 131 | 132 | /** 133 | * Begin appending a new array. All values until the balancing 134 | * endArray will be appended to this array. The 135 | * endArray method must be called to mark the array's end. 136 | * @return this 137 | * @throws JSONException If the nesting is too deep, or if the object is 138 | * started in the wrong place (for example as a key or after the end of the 139 | * outermost array or object). 140 | */ 141 | public JSONWriter array() throws JSONException { 142 | if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { 143 | this.push(null); 144 | this.append("["); 145 | this.comma = false; 146 | return this; 147 | } 148 | throw new JSONException("Misplaced array."); 149 | } 150 | 151 | /** 152 | * End something. 153 | * @param mode Mode 154 | * @param c Closing character 155 | * @return this 156 | * @throws JSONException If unbalanced. 157 | */ 158 | private JSONWriter end(char mode, char c) throws JSONException { 159 | if (this.mode != mode) { 160 | throw new JSONException(mode == 'a' 161 | ? "Misplaced endArray." 162 | : "Misplaced endObject."); 163 | } 164 | this.pop(mode); 165 | try { 166 | this.writer.write(c); 167 | } catch (IOException e) { 168 | throw new JSONException(e); 169 | } 170 | this.comma = true; 171 | return this; 172 | } 173 | 174 | /** 175 | * End an array. This method most be called to balance calls to 176 | * array. 177 | * @return this 178 | * @throws JSONException If incorrectly nested. 179 | */ 180 | public JSONWriter endArray() throws JSONException { 181 | return this.end('a', ']'); 182 | } 183 | 184 | /** 185 | * End an object. This method most be called to balance calls to 186 | * object. 187 | * @return this 188 | * @throws JSONException If incorrectly nested. 189 | */ 190 | public JSONWriter endObject() throws JSONException { 191 | return this.end('k', '}'); 192 | } 193 | 194 | /** 195 | * Append a key. The key will be associated with the next value. In an 196 | * object, every value must be preceded by a key. 197 | * @param string A key string. 198 | * @return this 199 | * @throws JSONException If the key is out of place. For example, keys 200 | * do not belong in arrays or if the key is null. 201 | */ 202 | public JSONWriter key(String string) throws JSONException { 203 | if (string == null) { 204 | throw new JSONException("Null key."); 205 | } 206 | if (this.mode == 'k') { 207 | try { 208 | this.stack[this.top - 1].putOnce(string, Boolean.TRUE); 209 | if (this.comma) { 210 | this.writer.write(','); 211 | } 212 | this.writer.write(JSONObject.quote(string)); 213 | this.writer.write(':'); 214 | this.comma = false; 215 | this.mode = 'o'; 216 | return this; 217 | } catch (IOException e) { 218 | throw new JSONException(e); 219 | } 220 | } 221 | throw new JSONException("Misplaced key."); 222 | } 223 | 224 | 225 | /** 226 | * Begin appending a new object. All keys and values until the balancing 227 | * endObject will be appended to this object. The 228 | * endObject method must be called to mark the object's end. 229 | * @return this 230 | * @throws JSONException If the nesting is too deep, or if the object is 231 | * started in the wrong place (for example as a key or after the end of the 232 | * outermost array or object). 233 | */ 234 | public JSONWriter object() throws JSONException { 235 | if (this.mode == 'i') { 236 | this.mode = 'o'; 237 | } 238 | if (this.mode == 'o' || this.mode == 'a') { 239 | this.append("{"); 240 | this.push(new JSONObject()); 241 | this.comma = false; 242 | return this; 243 | } 244 | throw new JSONException("Misplaced object."); 245 | 246 | } 247 | 248 | 249 | /** 250 | * Pop an array or object scope. 251 | * @param c The scope to close. 252 | * @throws JSONException If nesting is wrong. 253 | */ 254 | private void pop(char c) throws JSONException { 255 | if (this.top <= 0) { 256 | throw new JSONException("Nesting error."); 257 | } 258 | char m = this.stack[this.top - 1] == null ? 'a' : 'k'; 259 | if (m != c) { 260 | throw new JSONException("Nesting error."); 261 | } 262 | this.top -= 1; 263 | this.mode = this.top == 0 264 | ? 'd' 265 | : this.stack[this.top - 1] == null 266 | ? 'a' 267 | : 'k'; 268 | } 269 | 270 | /** 271 | * Push an array or object scope. 272 | * @param c The scope to open. 273 | * @throws JSONException If nesting is too deep. 274 | */ 275 | private void push(JSONObject jo) throws JSONException { 276 | if (this.top >= maxdepth) { 277 | throw new JSONException("Nesting too deep."); 278 | } 279 | this.stack[this.top] = jo; 280 | this.mode = jo == null ? 'a' : 'k'; 281 | this.top += 1; 282 | } 283 | 284 | 285 | /** 286 | * Append either the value true or the value 287 | * false. 288 | * @param b A boolean. 289 | * @return this 290 | * @throws JSONException 291 | */ 292 | public JSONWriter value(boolean b) throws JSONException { 293 | return this.append(b ? "true" : "false"); 294 | } 295 | 296 | /** 297 | * Append a double value. 298 | * @param d A double. 299 | * @return this 300 | * @throws JSONException If the number is not finite. 301 | */ 302 | public JSONWriter value(double d) throws JSONException { 303 | return this.value(new Double(d)); 304 | } 305 | 306 | /** 307 | * Append a long value. 308 | * @param l A long. 309 | * @return this 310 | * @throws JSONException 311 | */ 312 | public JSONWriter value(long l) throws JSONException { 313 | return this.append(Long.toString(l)); 314 | } 315 | 316 | 317 | /** 318 | * Append an object value. 319 | * @param object The object to append. It can be null, or a Boolean, Number, 320 | * String, JSONObject, or JSONArray, or an object that implements JSONString. 321 | * @return this 322 | * @throws JSONException If the value is out of sequence. 323 | */ 324 | public JSONWriter value(Object object) throws JSONException { 325 | return this.append(JSONObject.valueToString(object)); 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /CCNx/src/org/json/XMLTokener.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * The XMLTokener extends the JSONTokener to provide additional methods 29 | * for the parsing of XML texts. 30 | * @author JSON.org 31 | * @version 2012-11-13 32 | */ 33 | public class XMLTokener extends JSONTokener { 34 | 35 | 36 | /** The table of entity values. It initially contains Character values for 37 | * amp, apos, gt, lt, quot. 38 | */ 39 | public static final java.util.HashMap entity; 40 | 41 | static { 42 | entity = new java.util.HashMap(8); 43 | entity.put("amp", XML.AMP); 44 | entity.put("apos", XML.APOS); 45 | entity.put("gt", XML.GT); 46 | entity.put("lt", XML.LT); 47 | entity.put("quot", XML.QUOT); 48 | } 49 | 50 | /** 51 | * Construct an XMLTokener from a string. 52 | * @param s A source string. 53 | */ 54 | public XMLTokener(String s) { 55 | super(s); 56 | } 57 | 58 | /** 59 | * Get the text in the CDATA block. 60 | * @return The string up to the ]]>. 61 | * @throws JSONException If the ]]> is not found. 62 | */ 63 | public String nextCDATA() throws JSONException { 64 | char c; 65 | int i; 66 | StringBuffer sb = new StringBuffer(); 67 | for (;;) { 68 | c = next(); 69 | if (end()) { 70 | throw syntaxError("Unclosed CDATA"); 71 | } 72 | sb.append(c); 73 | i = sb.length() - 3; 74 | if (i >= 0 && sb.charAt(i) == ']' && 75 | sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { 76 | sb.setLength(i); 77 | return sb.toString(); 78 | } 79 | } 80 | } 81 | 82 | 83 | /** 84 | * Get the next XML outer token, trimming whitespace. There are two kinds 85 | * of tokens: the '<' character which begins a markup tag, and the content 86 | * text between markup tags. 87 | * 88 | * @return A string, or a '<' Character, or null if there is no more 89 | * source text. 90 | * @throws JSONException 91 | */ 92 | public Object nextContent() throws JSONException { 93 | char c; 94 | StringBuffer sb; 95 | do { 96 | c = next(); 97 | } while (Character.isWhitespace(c)); 98 | if (c == 0) { 99 | return null; 100 | } 101 | if (c == '<') { 102 | return XML.LT; 103 | } 104 | sb = new StringBuffer(); 105 | for (;;) { 106 | if (c == '<' || c == 0) { 107 | back(); 108 | return sb.toString().trim(); 109 | } 110 | if (c == '&') { 111 | sb.append(nextEntity(c)); 112 | } else { 113 | sb.append(c); 114 | } 115 | c = next(); 116 | } 117 | } 118 | 119 | 120 | /** 121 | * Return the next entity. These entities are translated to Characters: 122 | * & ' > < ". 123 | * @param ampersand An ampersand character. 124 | * @return A Character or an entity String if the entity is not recognized. 125 | * @throws JSONException If missing ';' in XML entity. 126 | */ 127 | public Object nextEntity(char ampersand) throws JSONException { 128 | StringBuffer sb = new StringBuffer(); 129 | for (;;) { 130 | char c = next(); 131 | if (Character.isLetterOrDigit(c) || c == '#') { 132 | sb.append(Character.toLowerCase(c)); 133 | } else if (c == ';') { 134 | break; 135 | } else { 136 | throw syntaxError("Missing ';' in XML entity: &" + sb); 137 | } 138 | } 139 | String string = sb.toString(); 140 | Object object = entity.get(string); 141 | return object != null ? object : ampersand + string + ";"; 142 | } 143 | 144 | 145 | /** 146 | * Returns the next XML meta token. This is used for skipping over 147 | * and structures. 148 | * @return Syntax characters (< > / = ! ?) are returned as 149 | * Character, and strings and names are returned as Boolean. We don't care 150 | * what the values actually are. 151 | * @throws JSONException If a string is not properly closed or if the XML 152 | * is badly structured. 153 | */ 154 | public Object nextMeta() throws JSONException { 155 | char c; 156 | char q; 157 | do { 158 | c = next(); 159 | } while (Character.isWhitespace(c)); 160 | switch (c) { 161 | case 0: 162 | throw syntaxError("Misshaped meta tag"); 163 | case '<': 164 | return XML.LT; 165 | case '>': 166 | return XML.GT; 167 | case '/': 168 | return XML.SLASH; 169 | case '=': 170 | return XML.EQ; 171 | case '!': 172 | return XML.BANG; 173 | case '?': 174 | return XML.QUEST; 175 | case '"': 176 | case '\'': 177 | q = c; 178 | for (;;) { 179 | c = next(); 180 | if (c == 0) { 181 | throw syntaxError("Unterminated string"); 182 | } 183 | if (c == q) { 184 | return Boolean.TRUE; 185 | } 186 | } 187 | default: 188 | for (;;) { 189 | c = next(); 190 | if (Character.isWhitespace(c)) { 191 | return Boolean.TRUE; 192 | } 193 | switch (c) { 194 | case 0: 195 | case '<': 196 | case '>': 197 | case '/': 198 | case '=': 199 | case '!': 200 | case '?': 201 | case '"': 202 | case '\'': 203 | back(); 204 | return Boolean.TRUE; 205 | } 206 | } 207 | } 208 | } 209 | 210 | 211 | /** 212 | * Get the next XML Token. These tokens are found inside of angle 213 | * brackets. It may be one of these characters: / > = ! ? or it 214 | * may be a string wrapped in single quotes or double quotes, or it may be a 215 | * name. 216 | * @return a String or a Character. 217 | * @throws JSONException If the XML is not well formed. 218 | */ 219 | public Object nextToken() throws JSONException { 220 | char c; 221 | char q; 222 | StringBuffer sb; 223 | do { 224 | c = next(); 225 | } while (Character.isWhitespace(c)); 226 | switch (c) { 227 | case 0: 228 | throw syntaxError("Misshaped element"); 229 | case '<': 230 | throw syntaxError("Misplaced '<'"); 231 | case '>': 232 | return XML.GT; 233 | case '/': 234 | return XML.SLASH; 235 | case '=': 236 | return XML.EQ; 237 | case '!': 238 | return XML.BANG; 239 | case '?': 240 | return XML.QUEST; 241 | 242 | // Quoted string 243 | 244 | case '"': 245 | case '\'': 246 | q = c; 247 | sb = new StringBuffer(); 248 | for (;;) { 249 | c = next(); 250 | if (c == 0) { 251 | throw syntaxError("Unterminated string"); 252 | } 253 | if (c == q) { 254 | return sb.toString(); 255 | } 256 | if (c == '&') { 257 | sb.append(nextEntity(c)); 258 | } else { 259 | sb.append(c); 260 | } 261 | } 262 | default: 263 | 264 | // Name 265 | 266 | sb = new StringBuffer(); 267 | for (;;) { 268 | sb.append(c); 269 | c = next(); 270 | if (Character.isWhitespace(c)) { 271 | return sb.toString(); 272 | } 273 | switch (c) { 274 | case 0: 275 | return sb.toString(); 276 | case '>': 277 | case '/': 278 | case '=': 279 | case '!': 280 | case '?': 281 | case '[': 282 | case ']': 283 | back(); 284 | return sb.toString(); 285 | case '<': 286 | case '"': 287 | case '\'': 288 | throw syntaxError("Bad character in a name"); 289 | } 290 | } 291 | } 292 | } 293 | 294 | 295 | /** 296 | * Skip characters until past the requested string. 297 | * If it is not found, we are left at the end of the source with a result of false. 298 | * @param to A string to skip past. 299 | * @throws JSONException 300 | */ 301 | public boolean skipPast(String to) throws JSONException { 302 | boolean b; 303 | char c; 304 | int i; 305 | int j; 306 | int offset = 0; 307 | int length = to.length(); 308 | char[] circle = new char[length]; 309 | 310 | /* 311 | * First fill the circle buffer with as many characters as are in the 312 | * to string. If we reach an early end, bail. 313 | */ 314 | 315 | for (i = 0; i < length; i += 1) { 316 | c = next(); 317 | if (c == 0) { 318 | return false; 319 | } 320 | circle[i] = c; 321 | } 322 | 323 | /* We will loop, possibly for all of the remaining characters. */ 324 | 325 | for (;;) { 326 | j = offset; 327 | b = true; 328 | 329 | /* Compare the circle buffer with the to string. */ 330 | 331 | for (i = 0; i < length; i += 1) { 332 | if (circle[j] != to.charAt(i)) { 333 | b = false; 334 | break; 335 | } 336 | j += 1; 337 | if (j >= length) { 338 | j -= length; 339 | } 340 | } 341 | 342 | /* If we exit the loop with b intact, then victory is ours. */ 343 | 344 | if (b) { 345 | return true; 346 | } 347 | 348 | /* Get the next character. If there isn't one, then defeat is ours. */ 349 | 350 | c = next(); 351 | if (c == 0) { 352 | return false; 353 | } 354 | /* 355 | * Shove the character in the circle buffer and advance the 356 | * circle offset. The offset is mod n. 357 | */ 358 | circle[offset] = c; 359 | offset += 1; 360 | if (offset >= length) { 361 | offset -= length; 362 | } 363 | } 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/Huff.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import org.json.JSONException; 4 | 5 | /* 6 | Copyright (c) 2013 JSON.org 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | The Software shall be used for Good, not Evil. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | /** 30 | * JSONzip is a compression scheme for JSON text. 31 | * @author JSON.org 32 | * @version 2013-04-18 33 | */ 34 | 35 | /** 36 | * A Huffman encoder/decoder. It operates over a domain of integers, which may 37 | * map to characters or other symbols. Symbols that are used frequently are 38 | * given shorter codes than symbols that are used infrequently. This usually 39 | * produces shorter messages. 40 | * 41 | * Initially, all of the symbols are given the same weight. The weight of a 42 | * symbol is incremented by the tick method. The generate method is used to 43 | * generate the encoding table. The table must be generated before encoding or 44 | * decoding. You may regenerate the table with the latest weights at any time. 45 | */ 46 | public class Huff implements None, PostMortem { 47 | 48 | /** 49 | * The number of symbols known to the encoder. 50 | */ 51 | private final int domain; 52 | 53 | /** 54 | * An array that maps symbol values to symbols. 55 | */ 56 | private final Symbol[] symbols; 57 | 58 | /** 59 | * The root of the decoding table, and the terminal of the encoding table. 60 | */ 61 | private Symbol table; 62 | 63 | /** 64 | * Have any weights changed since the table was last generated? 65 | */ 66 | private boolean upToDate = false; 67 | 68 | /** 69 | * The number of bits in the last symbol. This is used in tracing. 70 | */ 71 | private int width; 72 | 73 | private static class Symbol implements PostMortem { 74 | public Symbol back; 75 | public Symbol next; 76 | public Symbol zero; 77 | public Symbol one; 78 | public final int integer; 79 | public long weight; 80 | 81 | /** 82 | * Make a symbol representing a character or other value. 83 | * 84 | * @param integer 85 | * The symbol's number 86 | */ 87 | public Symbol(int integer) { 88 | this.integer = integer; 89 | this.weight = 0; 90 | this.next = null; 91 | this.back = null; 92 | this.one = null; 93 | this.zero = null; 94 | } 95 | 96 | public boolean postMortem(PostMortem pm) { 97 | boolean result = true; 98 | Symbol that = (Symbol) pm; 99 | 100 | if (this.integer != that.integer || this.weight != that.weight) { 101 | return false; 102 | } 103 | if ((this.back != null) != (that.back != null)) { 104 | return false; 105 | } 106 | Symbol zero = this.zero; 107 | Symbol one = this.one; 108 | if (zero == null) { 109 | if (that.zero != null) { 110 | return false; 111 | } 112 | } else { 113 | result = zero.postMortem(that.zero); 114 | } 115 | if (one == null) { 116 | if (that.one != null) { 117 | return false; 118 | } 119 | } else { 120 | result = one.postMortem(that.one); 121 | } 122 | return result; 123 | } 124 | 125 | } 126 | 127 | /** 128 | * Construct a Huffman encoder/decoder. 129 | * 130 | * @param domain 131 | * The number of values known to the object. 132 | */ 133 | public Huff(int domain) { 134 | this.domain = domain; 135 | int length = domain * 2 - 1; 136 | this.symbols = new Symbol[length]; 137 | 138 | // Make the leaf symbols. 139 | 140 | for (int i = 0; i < domain; i += 1) { 141 | symbols[i] = new Symbol(i); 142 | } 143 | 144 | // SMake the links. 145 | 146 | for (int i = domain; i < length; i += 1) { 147 | symbols[i] = new Symbol(none); 148 | } 149 | } 150 | 151 | /** 152 | * Generate the encoding/decoding table. The table determines the bit 153 | * sequences used by the read and write methods. 154 | * 155 | * @return this 156 | */ 157 | public void generate() { 158 | if (!this.upToDate) { 159 | 160 | // Phase One: Sort the symbols by weight into a linked list. 161 | 162 | Symbol head = this.symbols[0]; 163 | Symbol next; 164 | Symbol previous = head; 165 | Symbol symbol; 166 | 167 | this.table = null; 168 | head.next = null; 169 | for (int i = 1; i < this.domain; i += 1) { 170 | symbol = symbols[i]; 171 | 172 | // If this symbol weights less than the head, then it becomes the new head. 173 | 174 | if (symbol.weight < head.weight) { 175 | symbol.next = head; 176 | head = symbol; 177 | } else { 178 | 179 | // To save time, we will start the search from the previous symbol instead 180 | // of the head unless the current symbol weights less than the previous symbol. 181 | 182 | if (symbol.weight < previous.weight) { 183 | previous = head; 184 | } 185 | 186 | // Find a connected pair (previous and next) where the symbol weighs the same 187 | // or more than previous but less than the next. Link the symbol between them. 188 | 189 | while (true) { 190 | next = previous.next; 191 | if (next == null || symbol.weight < next.weight) { 192 | break; 193 | } 194 | previous = next; 195 | } 196 | symbol.next = next; 197 | previous.next = symbol; 198 | previous = symbol; 199 | } 200 | } 201 | 202 | // Phase Two: Make new symbols from the two lightest symbols until only one 203 | // symbol remains. The final symbol becomes the root of the table binary tree. 204 | 205 | int avail = this.domain; 206 | Symbol first; 207 | Symbol second; 208 | previous = head; 209 | while (true) { 210 | first = head; 211 | second = first.next; 212 | head = second.next; 213 | symbol = this.symbols[avail]; 214 | avail += 1; 215 | symbol.weight = first.weight + second.weight; 216 | symbol.zero = first; 217 | symbol.one = second; 218 | symbol.back = null; 219 | first.back = symbol; 220 | second.back = symbol; 221 | if (head == null) { 222 | break; 223 | } 224 | 225 | // Insert the new symbol back into the sorted list. 226 | 227 | if (symbol.weight < head.weight) { 228 | symbol.next = head; 229 | head = symbol; 230 | previous = head; 231 | } else { 232 | while (true) { 233 | next = previous.next; 234 | if (next == null || symbol.weight < next.weight) { 235 | break; 236 | } 237 | previous = next; 238 | } 239 | symbol.next = next; 240 | previous.next = symbol; 241 | previous = symbol; 242 | } 243 | 244 | } 245 | 246 | // The last remaining symbol is the root of the table. 247 | 248 | this.table = symbol; 249 | this.upToDate = true; 250 | } 251 | } 252 | 253 | private boolean postMortem(int integer) { 254 | int[] bits = new int[this.domain]; 255 | Symbol symbol = this.symbols[integer]; 256 | if (symbol.integer != integer) { 257 | return false; 258 | } 259 | int i = 0; 260 | while (true) { 261 | Symbol back = symbol.back; 262 | if (back == null) { 263 | break; 264 | } 265 | if (back.zero == symbol) { 266 | bits[i] = 0; 267 | } else if (back.one == symbol) { 268 | bits[i] = 1; 269 | } else { 270 | return false; 271 | } 272 | i += 1; 273 | symbol = back; 274 | } 275 | if (symbol != this.table) { 276 | return false; 277 | } 278 | this.width = 0; 279 | symbol = this.table; 280 | while (symbol.integer == none) { 281 | i -= 1; 282 | symbol = bits[i] != 0 ? symbol.one : symbol.zero; 283 | } 284 | return symbol.integer == integer && i == 0; 285 | } 286 | 287 | /** 288 | * Compare two Huffman tables. 289 | */ 290 | public boolean postMortem(PostMortem pm) { 291 | 292 | // Go through every integer in the domain, generating its bit sequence, and 293 | // then proving that that bit sequence produces the same integer. 294 | 295 | for (int integer = 0; integer < this.domain; integer += 1) { 296 | if (!postMortem(integer)) { 297 | JSONzip.log("\nBad huff "); 298 | JSONzip.logchar(integer, integer); 299 | return false; 300 | } 301 | } 302 | return this.table.postMortem(((Huff) pm).table); 303 | } 304 | 305 | /** 306 | * Read bits until a symbol can be identified. The weight of the read 307 | * symbol will be incremented. 308 | * 309 | * @param bitreader 310 | * The source of bits. 311 | * @return The integer value of the symbol. 312 | * @throws JSONException 313 | */ 314 | public int read(BitReader bitreader) throws JSONException { 315 | try { 316 | this.width = 0; 317 | Symbol symbol = this.table; 318 | while (symbol.integer == none) { 319 | this.width += 1; 320 | symbol = bitreader.bit() ? symbol.one : symbol.zero; 321 | } 322 | tick(symbol.integer); 323 | if (JSONzip.probe) { 324 | JSONzip.logchar(symbol.integer, this.width); 325 | } 326 | return symbol.integer; 327 | } catch (Throwable e) { 328 | throw new JSONException(e); 329 | } 330 | } 331 | 332 | /** 333 | * Increase by 1 the weight associated with a value. 334 | * 335 | * @param value 336 | * The number of the symbol to tick 337 | * @return this 338 | */ 339 | public void tick(int value) { 340 | this.symbols[value].weight += 1; 341 | this.upToDate = false; 342 | } 343 | 344 | /** 345 | * Increase by 1 the weight associated with a range of values. 346 | * 347 | * @param from 348 | * The first symbol to tick 349 | * @param to 350 | * The last symbol to tick 351 | * @return this 352 | */ 353 | public void tick(int from, int to) { 354 | for (int value = from; value <= to; value += 1) { 355 | tick(value); 356 | } 357 | } 358 | 359 | /** 360 | * Recur from a symbol back, emitting bits. We recur before emitting to 361 | * make the bits come out in the right order. 362 | * 363 | * @param symbol 364 | * The symbol to write. 365 | * @param bitwriter 366 | * The bitwriter to write it to. 367 | * @throws JSONException 368 | */ 369 | private void write(Symbol symbol, BitWriter bitwriter) 370 | throws JSONException { 371 | try { 372 | Symbol back = symbol.back; 373 | if (back != null) { 374 | this.width += 1; 375 | write(back, bitwriter); 376 | if (back.zero == symbol) { 377 | bitwriter.zero(); 378 | } else { 379 | bitwriter.one(); 380 | } 381 | } 382 | } catch (Throwable e) { 383 | throw new JSONException(e); 384 | } 385 | } 386 | 387 | /** 388 | * Write the bits corresponding to a symbol. The weight of the symbol will 389 | * be incremented. 390 | * 391 | * @param value 392 | * The number of the symbol to write 393 | * @param bitwriter 394 | * The destination of the bits. 395 | * @return this 396 | * @throws JSONException 397 | */ 398 | public void write(int value, BitWriter bitwriter) throws JSONException { 399 | this.width = 0; 400 | write(this.symbols[value], bitwriter); 401 | tick(value); 402 | if (JSONzip.probe) { 403 | JSONzip.logchar(value, this.width); 404 | } 405 | } 406 | } 407 | -------------------------------------------------------------------------------- /CCNx/src/org/json/zip/TrieKeep.java: -------------------------------------------------------------------------------- 1 | package org.json.zip; 2 | 3 | import org.json.Kim; 4 | 5 | /* 6 | Copyright (c) 2013 JSON.org 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | The Software shall be used for Good, not Evil. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | /** 30 | * A TrieKeep is a Keep that implements a Trie. 31 | */ 32 | class TrieKeep extends Keep { 33 | 34 | /** 35 | * The trie is made of nodes. 36 | */ 37 | class Node implements PostMortem { 38 | private int integer; 39 | private Node[] next; 40 | 41 | /** 42 | * Each non-leaf node contains links to up to 256 next nodes. Each node 43 | * has an integer value. 44 | */ 45 | public Node() { 46 | this.integer = none; 47 | this.next = null; 48 | } 49 | 50 | /** 51 | * Get one of a node's 256 links. If it is a leaf node, it returns 52 | * null. 53 | * 54 | * @param cell 55 | * A integer between 0 and 255. 56 | * @return 57 | */ 58 | public Node get(int cell) { 59 | return this.next == null ? null : this.next[cell]; 60 | } 61 | 62 | /** 63 | * Get one of a node's 256 links. If it is a leap node, it returns 64 | * null. The argument is treated as an unsigned integer. 65 | * 66 | * @param cell 67 | * A byte. 68 | * @return 69 | */ 70 | public Node get(byte cell) { 71 | return get(((int) cell) & 0xFF); 72 | } 73 | 74 | /** 75 | * Compare two nodes. Their lengths must be equal. Their links must 76 | * also compare. 77 | */ 78 | public boolean postMortem(PostMortem pm) { 79 | Node that = (Node) pm; 80 | if (that == null) { 81 | JSONzip.log("\nMisalign"); 82 | return false; 83 | } 84 | if (this.integer != that.integer) { 85 | JSONzip.log("\nInteger " + this.integer + " <> " + 86 | that.integer); 87 | return false; 88 | } 89 | if (this.next == null) { 90 | if (that.next == null) { 91 | return true; 92 | } 93 | JSONzip.log("\nNext is null " + this.integer); 94 | return false; 95 | } 96 | for (int i = 0; i < 256; i += 1) { 97 | Node node = this.next[i]; 98 | if (node != null) { 99 | if (!node.postMortem(that.next[i])) { 100 | return false; 101 | } 102 | } else if (that.next[i] != null) { 103 | JSONzip.log("\nMisalign " + i); 104 | return false; 105 | } 106 | } 107 | return true; 108 | } 109 | 110 | /** 111 | * Set a node's link to another node. 112 | * 113 | * @param cell 114 | * An integer between 0 and 255. 115 | * @param node 116 | * The new value for the cell. 117 | */ 118 | public void set(int cell, Node node) { 119 | if (this.next == null) { 120 | this.next = new Node[256]; 121 | } 122 | if (JSONzip.probe) { 123 | if (node == null || this.next[cell] != null) { 124 | JSONzip.log("\nUnexpected set.\n"); 125 | } 126 | } 127 | this.next[cell] = node; 128 | } 129 | 130 | /** 131 | * Set a node's link to another node. 132 | * 133 | * @param cell 134 | * A byte. 135 | * @param node 136 | * The new value for the cell. 137 | */ 138 | public void set(byte cell, Node node) { 139 | set(((int) cell) & 0xFF, node); 140 | } 141 | 142 | /** 143 | * Get one of a node's 256 links. It will not return null. If there is 144 | * no link, then a link is manufactured. 145 | * 146 | * @param cell 147 | * A integer between 0 and 255. 148 | * @return 149 | */ 150 | public Node vet(int cell) { 151 | Node node = get(cell); 152 | if (node == null) { 153 | node = new Node(); 154 | set(cell, node); 155 | } 156 | return node; 157 | } 158 | 159 | /** 160 | * Get one of a node's 256 links. It will not return null. If there is 161 | * no link, then a link is manufactured. 162 | * 163 | * @param cell 164 | * A byte. 165 | * @return 166 | */ 167 | public Node vet(byte cell) { 168 | return vet(((int) cell) & 0xFF); 169 | } 170 | } 171 | 172 | private int[] froms; 173 | private int[] thrus; 174 | private Node root; 175 | private Kim[] kims; 176 | 177 | /** 178 | * Create a new Keep of kims. 179 | * 180 | * @param bits 181 | * The log2 of the capacity of the Keep. For example, if bits is 182 | * 12, then the keep's capacity will be 4096. 183 | */ 184 | public TrieKeep(int bits) { 185 | super(bits); 186 | this.froms = new int[this.capacity]; 187 | this.thrus = new int[this.capacity]; 188 | this.kims = new Kim[this.capacity]; 189 | this.root = new Node(); 190 | } 191 | 192 | /** 193 | * Get the kim associated with an integer. 194 | * 195 | * @param integer 196 | * @return 197 | */ 198 | public Kim kim(int integer) { 199 | Kim kim = this.kims[integer]; 200 | int from = this.froms[integer]; 201 | int thru = this.thrus[integer]; 202 | if (from != 0 || thru != kim.length) { 203 | kim = new Kim(kim, from, thru); 204 | this.froms[integer] = 0; 205 | this.thrus[integer] = kim.length; 206 | this.kims[integer] = kim; 207 | } 208 | return kim; 209 | } 210 | 211 | /** 212 | * Get the length of the Kim associated with an integer. This is sometimes 213 | * much faster than get(integer).length. 214 | * 215 | * @param integer 216 | * @return 217 | */ 218 | public int length(int integer) { 219 | return this.thrus[integer] - this.froms[integer]; 220 | } 221 | 222 | /** 223 | * Find the integer value associated with this key, or nothing if this key 224 | * is not in the keep. 225 | * 226 | * @param key 227 | * An object. 228 | * @return An integer 229 | */ 230 | public int match(Kim kim, int from, int thru) { 231 | Node node = this.root; 232 | int best = none; 233 | for (int at = from; at < thru; at += 1) { 234 | node = node.get(kim.get(at)); 235 | if (node == null) { 236 | break; 237 | } 238 | if (node.integer != none) { 239 | best = node.integer; 240 | } 241 | from += 1; 242 | } 243 | return best; 244 | } 245 | 246 | public boolean postMortem(PostMortem pm) { 247 | boolean result = true; 248 | TrieKeep that = (TrieKeep) pm; 249 | if (this.length != that.length) { 250 | JSONzip.log("\nLength " + this.length + " <> " + that.length); 251 | return false; 252 | } 253 | if (this.capacity != that.capacity) { 254 | JSONzip.log("\nCapacity " + this.capacity + " <> " + 255 | that.capacity); 256 | return false; 257 | } 258 | for (int i = 0; i < this.length; i += 1) { 259 | Kim thiskim = this.kim(i); 260 | Kim thatkim = that.kim(i); 261 | if (!thiskim.equals(thatkim)) { 262 | JSONzip.log("\n[" + i + "] " + thiskim + " <> " + thatkim); 263 | result = false; 264 | } 265 | } 266 | return result && this.root.postMortem(that.root); 267 | } 268 | 269 | public void registerMany(Kim kim) { 270 | int length = kim.length; 271 | int limit = this.capacity - this.length; 272 | if (limit > JSONzip.substringLimit) { 273 | limit = JSONzip.substringLimit; 274 | } 275 | int until = length - (JSONzip.minSubstringLength - 1); 276 | for (int from = 0; from < until; from += 1) { 277 | int len = length - from; 278 | if (len > JSONzip.maxSubstringLength) { 279 | len = JSONzip.maxSubstringLength; 280 | } 281 | len += from; 282 | Node node = this.root; 283 | for (int at = from; at < len; at += 1) { 284 | Node next = node.vet(kim.get(at)); 285 | if (next.integer == none 286 | && at - from >= (JSONzip.minSubstringLength - 1)) { 287 | next.integer = this.length; 288 | this.uses[this.length] = 1; 289 | this.kims[this.length] = kim; 290 | this.froms[this.length] = from; 291 | this.thrus[this.length] = at + 1; 292 | if (JSONzip.probe) { 293 | try { 294 | JSONzip.log("<<" + this.length + " " 295 | + new Kim(kim, from, at + 1) + ">> "); 296 | } catch (Throwable ignore) { 297 | } 298 | } 299 | this.length += 1; 300 | limit -= 1; 301 | if (limit <= 0) { 302 | return; 303 | } 304 | } 305 | node = next; 306 | } 307 | } 308 | } 309 | 310 | public void registerOne(Kim kim) { 311 | int integer = registerOne(kim, 0, kim.length); 312 | if (integer != none) { 313 | this.kims[integer] = kim; 314 | } 315 | } 316 | 317 | public int registerOne(Kim kim, int from, int thru) { 318 | if (this.length < this.capacity) { 319 | Node node = this.root; 320 | for (int at = from; at < thru; at += 1) { 321 | node = node.vet(kim.get(at)); 322 | } 323 | if (node.integer == none) { 324 | int integer = this.length; 325 | node.integer = integer; 326 | this.uses[integer] = 1; 327 | this.kims[integer] = kim; 328 | this.froms[integer] = from; 329 | this.thrus[integer] = thru; 330 | if (JSONzip.probe) { 331 | try { 332 | JSONzip.log("<<" + integer + " " + new Kim(kim, from, thru) + ">> "); 333 | } catch (Throwable ignore) { 334 | } 335 | } 336 | this.length += 1; 337 | return integer; 338 | } 339 | } 340 | return none; 341 | } 342 | 343 | /** 344 | * Reserve space in the keep, compacting if necessary. A keep may contain 345 | * at most -capacity- elements. The keep contents can be reduced by 346 | * deleting all elements with low use counts, rebuilding the trie with the 347 | * survivors. 348 | */ 349 | public void reserve() { 350 | if (this.capacity - this.length < JSONzip.substringLimit) { 351 | int from = 0; 352 | int to = 0; 353 | this.root = new Node(); 354 | while (from < this.capacity) { 355 | if (this.uses[from] > 1) { 356 | Kim kim = this.kims[from]; 357 | int thru = this.thrus[from]; 358 | Node node = this.root; 359 | for (int at = this.froms[from]; at < thru; at += 1) { 360 | Node next = node.vet(kim.get(at)); 361 | node = next; 362 | } 363 | node.integer = to; 364 | this.uses[to] = age(this.uses[from]); 365 | this.froms[to] = this.froms[from]; 366 | this.thrus[to] = thru; 367 | this.kims[to] = kim; 368 | to += 1; 369 | } 370 | from += 1; 371 | } 372 | 373 | // It is possible, but highly unlikely, that too many items survive. 374 | // If that happens, clear the keep. 375 | 376 | if (this.capacity - to < JSONzip.substringLimit) { 377 | this.power = 0; 378 | this.root = new Node(); 379 | to = 0; 380 | } 381 | this.length = to; 382 | while (to < this.capacity) { 383 | this.uses[to] = 0; 384 | this.kims[to] = null; 385 | this.froms[to] = 0; 386 | this.thrus[to] = 0; 387 | to += 1; 388 | 389 | } 390 | } 391 | } 392 | 393 | public Object value(int integer) { 394 | return kim(integer); 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /CCNx/src/org/json/Kim.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | 4 | /* 5 | Copyright (c) 2013 JSON.org 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | The Software shall be used for Good, not Evil. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | /** 29 | * Kim makes immutable eight bit Unicode strings. If the MSB of a byte is set, 30 | * then the next byte is a continuation byte. The last byte of a character 31 | * never has the MSB reset. Every byte that is not the last byte has the MSB 32 | * set. Kim stands for "Keep it minimal". A Unicode character is never longer 33 | * than 3 bytes. Every byte contributes 7 bits to the character. ASCII is 34 | * unmodified. 35 | * 36 | * Kim UTF-8 37 | * one byte U+007F U+007F 38 | * two bytes U+3FFF U+07FF 39 | * three bytes U+10FFF U+FFFF 40 | * four bytes U+10FFFF 41 | * 42 | * Characters in the ranges U+0800..U+3FFF and U+10000..U+10FFFF will be one 43 | * byte smaller when encoded in Kim compared to UTF-8. 44 | * 45 | * Kim is beneficial when using scripts such as Old South Arabian, Aramaic, 46 | * Avestan, Balinese, Batak, Bopomofo, Buginese, Buhid, Carian, Cherokee, 47 | * Coptic, Cyrillic, Deseret, Egyptian Hieroglyphs, Ethiopic, Georgian, 48 | * Glagolitic, Gothic, Hangul Jamo, Hanunoo, Hiragana, Kanbun, Kaithi, 49 | * Kannada, Katakana, Kharoshthi, Khmer, Lao, Lepcha, Limbu, Lycian, Lydian, 50 | * Malayalam, Mandaic, Meroitic, Miao, Mongolian, Myanmar, New Tai Lue, 51 | * Ol Chiki, Old Turkic, Oriya, Osmanya, Pahlavi, Parthian, Phags-Pa, 52 | * Phoenician, Samaritan, Sharada, Sinhala, Sora Sompeng, Tagalog, Tagbanwa, 53 | * Takri, Tai Le, Tai Tham, Tamil, Telugu, Thai, Tibetan, Tifinagh, UCAS. 54 | * 55 | * A kim object can be constructed from an ordinary UTF-16 string, or from a 56 | * byte array. A kim object can produce a UTF-16 string. 57 | * 58 | * As with UTF-8, it is possible to detect character boundaries within a byte 59 | * sequence. UTF-8 is one of the world's great inventions. While Kim is more 60 | * efficient, it is not clear that it is worth the expense of transition. 61 | * 62 | * @version 2013-04-18 63 | */ 64 | public class Kim { 65 | 66 | /** 67 | * The byte array containing the kim's content. 68 | */ 69 | private byte[] bytes = null; 70 | 71 | /** 72 | * The kim's hashcode, conforming to Java's hashcode conventions. 73 | */ 74 | private int hashcode = 0; 75 | 76 | /** 77 | * The number of bytes in the kim. The number of bytes can be as much as 78 | * three times the number of characters. 79 | */ 80 | public int length = 0; 81 | 82 | /** 83 | * The memoization of toString(). 84 | */ 85 | private String string = null; 86 | 87 | /** 88 | * Make a kim from a portion of a byte array. 89 | * 90 | * @param bytes 91 | * A byte array. 92 | * @param from 93 | * The index of the first byte. 94 | * @param thru 95 | * The index of the last byte plus one. 96 | */ 97 | public Kim(byte[] bytes, int from, int thru) { 98 | 99 | // As the bytes are copied into the new kim, a hashcode is computed using a 100 | // modified Fletcher code. 101 | 102 | int sum = 1; 103 | int value; 104 | this.hashcode = 0; 105 | this.length = thru - from; 106 | if (this.length > 0) { 107 | this.bytes = new byte[this.length]; 108 | for (int at = 0; at < this.length; at += 1) { 109 | value = (int) bytes[at + from] & 0xFF; 110 | sum += value; 111 | this.hashcode += sum; 112 | this.bytes[at] = (byte) value; 113 | } 114 | this.hashcode += sum << 16; 115 | } 116 | } 117 | 118 | /** 119 | * Make a kim from a byte array. 120 | * 121 | * @param bytes 122 | * The byte array. 123 | * @param length 124 | * The number of bytes. 125 | */ 126 | public Kim(byte[] bytes, int length) { 127 | this(bytes, 0, length); 128 | } 129 | 130 | /** 131 | * Make a new kim from a substring of an existing kim. The coordinates are 132 | * in byte units, not character units. 133 | * 134 | * @param kim 135 | * The source of bytes. 136 | * @param from 137 | * The point at which to take bytes. 138 | * @param thru 139 | * The point at which to stop taking bytes. 140 | * @return the substring 141 | */ 142 | public Kim(Kim kim, int from, int thru) { 143 | this(kim.bytes, from, thru); 144 | } 145 | 146 | /** 147 | * Make a kim from a string. 148 | * 149 | * @param string 150 | * The string. 151 | * @throws JSONException 152 | * if surrogate pair mismatch. 153 | */ 154 | public Kim(String string) throws JSONException { 155 | int stringLength = string.length(); 156 | this.hashcode = 0; 157 | this.length = 0; 158 | 159 | // First pass: Determine the length of the kim, allowing for the UTF-16 160 | // to UTF-32 conversion, and then the UTF-32 to Kim conversion. 161 | 162 | if (stringLength > 0) { 163 | for (int i = 0; i < stringLength; i += 1) { 164 | int c = string.charAt(i); 165 | if (c <= 0x7F) { 166 | this.length += 1; 167 | } else if (c <= 0x3FFF) { 168 | this.length += 2; 169 | } else { 170 | if (c >= 0xD800 && c <= 0xDFFF) { 171 | i += 1; 172 | int d = string.charAt(i); 173 | if (c > 0xDBFF || d < 0xDC00 || d > 0xDFFF) { 174 | throw new JSONException("Bad UTF16"); 175 | } 176 | } 177 | this.length += 3; 178 | } 179 | } 180 | 181 | // Second pass: Allocate a byte array and fill that array with the conversion 182 | // while computing the hashcode. 183 | 184 | this.bytes = new byte[length]; 185 | int at = 0; 186 | int b; 187 | int sum = 1; 188 | for (int i = 0; i < stringLength; i += 1) { 189 | int character = string.charAt(i); 190 | if (character <= 0x7F) { 191 | bytes[at] = (byte) character; 192 | sum += character; 193 | this.hashcode += sum; 194 | at += 1; 195 | } else if (character <= 0x3FFF) { 196 | b = 0x80 | (character >>> 7); 197 | bytes[at] = (byte) b; 198 | sum += b; 199 | this.hashcode += sum; 200 | at += 1; 201 | b = character & 0x7F; 202 | bytes[at] = (byte) b; 203 | sum += b; 204 | this.hashcode += sum; 205 | at += 1; 206 | } else { 207 | if (character >= 0xD800 && character <= 0xDBFF) { 208 | i += 1; 209 | character = (((character & 0x3FF) << 10) | (string 210 | .charAt(i) & 0x3FF)) + 65536; 211 | } 212 | b = 0x80 | (character >>> 14); 213 | bytes[at] = (byte) b; 214 | sum += b; 215 | this.hashcode += sum; 216 | at += 1; 217 | b = 0x80 | ((character >>> 7) & 0xFF); 218 | bytes[at] = (byte) b; 219 | sum += b; 220 | this.hashcode += sum; 221 | at += 1; 222 | b = character & 0x7F; 223 | bytes[at] = (byte) b; 224 | sum += b; 225 | this.hashcode += sum; 226 | at += 1; 227 | } 228 | } 229 | this.hashcode += sum << 16; 230 | } 231 | } 232 | 233 | /** 234 | * Returns the character at the specified index. The index refers to byte 235 | * values and ranges from 0 to length - 1. The index of the next character 236 | * is at index + Kim.characterSize(kim.characterAt(index)). 237 | * 238 | * @param at 239 | * the index of the char value. The first character is at 0. 240 | * @returns a Unicode character between 0 and 0x10FFFF. 241 | * @throws JSONException 242 | * if at does not point to a valid character. 243 | */ 244 | public int characterAt(int at) throws JSONException { 245 | int c = get(at); 246 | if ((c & 0x80) == 0) { 247 | return c; 248 | } 249 | int character; 250 | int c1 = get(at + 1); 251 | if ((c1 & 0x80) == 0) { 252 | character = ((c & 0x7F) << 7) | c1; 253 | if (character > 0x7F) { 254 | return character; 255 | } 256 | } else { 257 | int c2 = get(at + 2); 258 | character = ((c & 0x7F) << 14) | ((c1 & 0x7F) << 7) | c2; 259 | if ((c2 & 0x80) == 0 && character > 0x3FFF && character <= 0x10FFFF 260 | && (character < 0xD800 || character > 0xDFFF)) { 261 | return character; 262 | } 263 | } 264 | throw new JSONException("Bad character at " + at); 265 | } 266 | 267 | /** 268 | * Returns the number of bytes needed to contain the character in Kim 269 | * format. 270 | * 271 | * @param character 272 | * a Unicode character between 0 and 0x10FFFF. 273 | * @return 1, 2, or 3 274 | * @throws JSONException 275 | * if the character is not representable in a kim. 276 | */ 277 | public static int characterSize(int character) throws JSONException { 278 | if (character < 0 || character > 0x10FFFF) { 279 | throw new JSONException("Bad character " + character); 280 | } 281 | return character <= 0x7F ? 1 : character <= 0x3FFF ? 2 : 3; 282 | } 283 | 284 | /** 285 | * Copy the contents of this kim to a byte array. 286 | * 287 | * @param bytes 288 | * A byte array of sufficient size. 289 | * @param at 290 | * The position within the byte array to take the byes. 291 | * @return The position immediately after the copy. 292 | */ 293 | public int copy(byte[] bytes, int at) { 294 | System.arraycopy(this.bytes, 0, bytes, at, this.length); 295 | return at + this.length; 296 | } 297 | 298 | /** 299 | * Two kim objects containing exactly the same bytes in the same order are 300 | * equal to each other. 301 | * 302 | * @param obj 303 | * the other kim with which to compare. 304 | * @returns true if this and obj are both kim objects containing identical 305 | * byte sequences. 306 | */ 307 | public boolean equals(Object obj) { 308 | if (!(obj instanceof Kim)) { 309 | return false; 310 | } 311 | Kim that = (Kim) obj; 312 | if (this == that) { 313 | return true; 314 | } 315 | if (this.hashcode != that.hashcode) { 316 | return false; 317 | } 318 | return java.util.Arrays.equals(this.bytes, that.bytes); 319 | } 320 | 321 | /** 322 | * Get a byte from a kim. 323 | * @param at 324 | * The position of the byte. The first byte is at 0. 325 | * @return The byte. 326 | * @throws JSONException 327 | * if there is no byte at that position. 328 | */ 329 | public int get(int at) throws JSONException { 330 | if (at < 0 || at > this.length) { 331 | throw new JSONException("Bad character at " + at); 332 | } 333 | return ((int) this.bytes[at]) & 0xFF; 334 | } 335 | 336 | /** 337 | * Returns a hash code value for the kim. 338 | */ 339 | public int hashCode() { 340 | return this.hashcode; 341 | } 342 | 343 | /** 344 | * Produce a UTF-16 String from this kim. The number of codepoints in the 345 | * string will not be greater than the number of bytes in the kim, although 346 | * it could be less. 347 | * 348 | * @return The string. A kim memoizes its string representation. 349 | * @throws JSONException 350 | * if the kim is not valid. 351 | */ 352 | public String toString() throws JSONException { 353 | if (this.string == null) { 354 | int c; 355 | int length = 0; 356 | char chars[] = new char[this.length]; 357 | for (int at = 0; at < this.length; at += characterSize(c)) { 358 | c = this.characterAt(at); 359 | if (c < 0x10000) { 360 | chars[length] = (char) c; 361 | length += 1; 362 | } else { 363 | chars[length] = (char) (0xD800 | ((c - 0x10000) >>> 10)); 364 | length += 1; 365 | chars[length] = (char) (0xDC00 | (c & 0x03FF)); 366 | length += 1; 367 | } 368 | } 369 | this.string = new String(chars, 0, length); 370 | } 371 | return this.string; 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /POX/forwarding.py: -------------------------------------------------------------------------------- 1 | # #Copyright (C) 2015, Delft University of Technology, Faculty of Electrical Engineering, Mathematics and Computer Science, Network Architectures and Services, Niels van Adrichem 2 | # 3 | # This file is part of NDNFlow. 4 | # 5 | # NDNFlow is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # NDNFlow is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with NDNFlow. If not, see . 17 | 18 | """ 19 | OpenNetMon.Forwarding 20 | 21 | Requires openflow.discovery 22 | """ 23 | 24 | from pox.lib.revent.revent import EventMixin, Event 25 | from pox.lib.addresses import IPAddr 26 | from pox.lib.packet.vlan import vlan 27 | from pox.lib.packet.ipv4 import ipv4 28 | 29 | import pox.lib.util as util 30 | from pox.core import core 31 | 32 | import pox.openflow.libopenflow_01 as of 33 | from collections import defaultdict 34 | import pox.lib.packet as pkt 35 | 36 | from collections import namedtuple 37 | 38 | log = core.getLogger() 39 | 40 | switches = {} 41 | switch_ports = {} 42 | adj = defaultdict(lambda:defaultdict(lambda:None)) 43 | 44 | mac_learning = {} 45 | 46 | class ofp_match_withHash(of.ofp_match): 47 | ##Our additions to enable indexing by match specifications 48 | @classmethod 49 | def from_ofp_match_Superclass(cls, other): 50 | match = cls() 51 | 52 | match.wildcards = other.wildcards 53 | match.in_port = other.in_port 54 | match.dl_src = other.dl_src 55 | match.dl_dst = other.dl_dst 56 | match.dl_vlan = other.dl_vlan 57 | match.dl_vlan_pcp = other.dl_vlan_pcp 58 | match.dl_type = other.dl_type 59 | match.nw_tos = other.nw_tos 60 | match.nw_proto = other.nw_proto 61 | match.nw_src = other.nw_src 62 | match.nw_dst = other.nw_dst 63 | match.tp_src = other.tp_src 64 | match.tp_dst = other.tp_dst 65 | return match 66 | 67 | def __hash__(self): 68 | return hash((self.wildcards, self.in_port, self.dl_src, self.dl_dst, self.dl_vlan, self.dl_vlan_pcp, self.dl_type, self.nw_tos, self.nw_proto, self.nw_src, self.nw_dst, self.tp_src, self.tp_dst)) 69 | 70 | class Path(object): 71 | def __init__(self, src, dst, prev, first_port): 72 | self.src = src 73 | self.dst = dst 74 | self.prev = prev 75 | self.first_port = first_port 76 | 77 | def __repr__(self): 78 | ret = util.dpid_to_str(self.dst) 79 | u = self.prev[self.dst] 80 | while(u != None): 81 | ret = util.dpid_to_str(u) + "->" + ret 82 | u = self.prev[u] 83 | 84 | return ret 85 | 86 | def _tuple_me(self): 87 | 88 | list = [self.dst,] 89 | u = self.prev[self.dst] 90 | while u != None: 91 | list.append(u) 92 | u = self.prev[u] 93 | #log.debug("List path: %s", list) 94 | #log.debug("Tuple path: %s", tuple(list)) 95 | return tuple(list) 96 | 97 | def __hash__(self): 98 | return hash(self._tuple_me()) 99 | 100 | def __eq__(self, other): 101 | return self._tuple_me() == other._tuple_me() 102 | 103 | def _get_path(src, dst): 104 | #Bellman-Ford algorithm 105 | keys = switches.keys() 106 | distance = {} 107 | previous = {} 108 | 109 | for dpid in keys: 110 | distance[dpid] = float("+inf") 111 | previous[dpid] = None 112 | 113 | distance[src] = 0 114 | for i in range(len(keys)-1): 115 | for u in adj.keys(): #nested dict 116 | for v in adj[u].keys(): 117 | w = 1 118 | if distance[u] + w < distance[v]: 119 | distance[v] = distance[u] + w 120 | previous[v] = u 121 | 122 | for u in adj.keys(): #nested dict 123 | for v in adj[u].keys(): 124 | w = 1 125 | if distance[u] + w < distance[v]: 126 | log.error("Graph contains a negative-weight cycle") 127 | return None 128 | 129 | first_port = None 130 | v = dst 131 | u = previous[v] 132 | while u is not None: 133 | if u == src: 134 | first_port = adj[u][v] 135 | 136 | v = u 137 | u = previous[v] 138 | 139 | return Path(src, dst, previous, first_port) #path 140 | 141 | def _install_path(prev_path, match): 142 | dst_sw = prev_path.dst 143 | cur_sw = prev_path.dst 144 | dst_pck = match.dl_dst 145 | 146 | msg = of.ofp_flow_mod() 147 | msg.match = match 148 | msg.idle_timeout = 10 149 | msg.flags = of.OFPFF_SEND_FLOW_REM 150 | msg.actions.append(of.ofp_action_output(port = mac_learning[dst_pck].port)) 151 | log.debug("Installing forward from switch %s to output port %s", util.dpid_to_str(cur_sw), mac_learning[dst_pck].port) 152 | switches[dst_sw].connection.send(msg) 153 | 154 | next_sw = cur_sw 155 | cur_sw = prev_path.prev[next_sw] 156 | while cur_sw is not None: #for switch in path.keys(): 157 | msg = of.ofp_flow_mod() 158 | msg.match = match 159 | msg.idle_timeout = 10 160 | msg.flags = of.OFPFF_SEND_FLOW_REM 161 | log.debug("Installing forward from switch %s to switch %s output port %s", util.dpid_to_str(cur_sw), util.dpid_to_str(next_sw), adj[cur_sw][next_sw]) 162 | msg.actions.append(of.ofp_action_output(port = adj[cur_sw][next_sw])) 163 | switches[cur_sw].connection.send(msg) 164 | next_sw = cur_sw 165 | 166 | cur_sw = prev_path.prev[next_sw] 167 | 168 | def _print_rev_path(dst_pck, src, dst, prev_path): 169 | str = "Reverse path from %s to %s over: [%s->dst over port %s]" % (util.dpid_to_str(src), util.dpid_to_str(dst), util.dpid_to_str(dst), mac_learning[dst_pck].port) 170 | next_sw = dst 171 | cur_sw = prev_path[next_sw] 172 | while cur_sw != None: #for switch in path.keys(): 173 | str += "[%s->%s over port %s]" % (util.dpid_to_str(cur_sw), util.dpid_to_str(next_sw), adj[cur_sw][next_sw]) 174 | next_sw = cur_sw 175 | cur_sw = prev_path[next_sw] 176 | 177 | log.debug(str) 178 | 179 | class NewFlow(Event): 180 | def __init__(self, prev_path, match, adj): 181 | Event.__init__(self) 182 | self.match = match 183 | self.prev_path = prev_path 184 | self.adj = adj 185 | 186 | class Switch(EventMixin): 187 | _eventMixin_events = set([ 188 | NewFlow, 189 | ]) 190 | def __init__(self, connection, l3_matching=False): 191 | self.connection = connection 192 | self.l3_matching = l3_matching 193 | connection.addListeners(self) 194 | for p in self.connection.ports.itervalues(): #Enable flooding on all ports until they are classified as links 195 | self.enable_flooding(p.port_no) 196 | 197 | def __repr__(self): 198 | return util.dpid_to_str(self.connection.dpid) 199 | 200 | 201 | def disable_flooding(self, port): 202 | msg = of.ofp_port_mod(port_no = port, 203 | hw_addr = self.connection.ports[port].hw_addr, 204 | config = of.OFPPC_NO_FLOOD, 205 | mask = of.OFPPC_NO_FLOOD) 206 | 207 | self.connection.send(msg) 208 | 209 | 210 | def enable_flooding(self, port): 211 | msg = of.ofp_port_mod(port_no = port, 212 | hw_addr = self.connection.ports[port].hw_addr, 213 | config = 0, # opposite of of.OFPPC_NO_FLOOD, 214 | mask = of.OFPPC_NO_FLOOD) 215 | 216 | self.connection.send(msg) 217 | 218 | def _handle_PacketIn(self, event): 219 | def forward(port): 220 | """Tell the switch to drop the packet""" 221 | msg = of.ofp_packet_out() 222 | msg.actions.append(of.ofp_action_output(port = port)) 223 | if event.ofp.buffer_id is not None: 224 | msg.buffer_id = event.ofp.buffer_id 225 | else: 226 | msg.data = event.ofp.data 227 | msg.in_port = event.port 228 | self.connection.send(msg) 229 | 230 | def flood(): 231 | """Tell all switches to flood the packet, remember that we disable inter-switch flooding at startup""" 232 | #forward(of.OFPP_FLOOD) 233 | for (dpid,switch) in switches.iteritems(): 234 | msg = of.ofp_packet_out() 235 | if switch == self: 236 | if event.ofp.buffer_id is not None: 237 | msg.buffer_id = event.ofp.buffer_id 238 | else: 239 | msg.data = event.ofp.data 240 | msg.in_port = event.port 241 | else: 242 | msg.data = event.ofp.data 243 | ports = [p for p in switch.connection.ports if (dpid,p) not in switch_ports] 244 | if len(ports) > 0: 245 | for p in ports: 246 | msg.actions.append(of.ofp_action_output(port = p)) 247 | switches[dpid].connection.send(msg) 248 | 249 | 250 | def drop(): 251 | """Tell the switch to drop the packet""" 252 | if event.ofp.buffer_id is not None: #nothing to drop because the packet is not in the Switch buffer 253 | msg = of.ofp_packet_out() 254 | msg.buffer_id = event.ofp.buffer_id 255 | event.ofp.buffer_id = None # Mark as dead, copied from James McCauley, not sure what it does but it does not work otherwise 256 | msg.in_port = event.port 257 | self.connection.send(msg) 258 | 259 | log.debug("Received PacketIn") 260 | packet = event.parsed 261 | 262 | SwitchPort = namedtuple('SwitchPoint', 'dpid port') 263 | 264 | if (event.dpid,event.port) not in switch_ports: # only relearn locations if they arrived from non-interswitch links 265 | mac_learning[packet.src] = SwitchPort(event.dpid, event.port) #relearn the location of the mac-address 266 | 267 | if packet.effective_ethertype == packet.LLDP_TYPE: 268 | drop() 269 | log.debug("Switch %s dropped LLDP packet", self) 270 | elif packet.dst.is_multicast: 271 | flood() 272 | log.debug("Switch %s flooded multicast 0x%0.4X type packet", self, packet.effective_ethertype) 273 | elif packet.dst not in mac_learning: 274 | flood() #Let's first learn the location of the recipient before generating and installing any rules for this. We might flood this but that leads to further complications if half way the flood through the network the path has been learned. 275 | log.debug("Switch %s flooded unicast 0x%0.4X type packet, due to unlearned MAC address", self, packet.effective_ethertype) 276 | elif packet.effective_ethertype == packet.ARP_TYPE: 277 | #These packets are sent so not-often that they don't deserve a flow 278 | #Instead of flooding them, we drop it at the current switch and have it resend by the switch to which the recipient is connected. 279 | #flood() 280 | drop() 281 | dst = mac_learning[packet.dst] 282 | msg = of.ofp_packet_out() 283 | msg.data = event.ofp.data 284 | msg.actions.append(of.ofp_action_output(port = dst.port)) 285 | switches[dst.dpid].connection.send(msg) 286 | log.debug("Switch %s processed unicast ARP (0x0806) packet, send to recipient by switch %s", self, util.dpid_to_str(dst.dpid)) 287 | else: 288 | log.debug("Switch %s received PacketIn of type 0x%0.4X, received from %s.%s", self, packet.effective_ethertype, util.dpid_to_str(event.dpid), event.port) 289 | dst = mac_learning[packet.dst] 290 | prev_path = _get_path(self.connection.dpid, dst.dpid) 291 | if prev_path is None: 292 | flood() 293 | return 294 | log.debug("Path from %s to %s over path %s", packet.src, packet.dst, prev_path) 295 | if self.l3_matching == True: #only match on l2-properties, useful when doing experiments with UDP streams as you can insert a flow using ping and then start sending udp. 296 | 297 | match = ofp_match_withHash() 298 | 299 | match.dl_src = packet.src 300 | match.dl_dst = packet.dst 301 | match.dl_type = packet.type 302 | p = packet.next 303 | if isinstance(p, vlan): 304 | match.dl_type = p.eth_type 305 | match.dl_vlan = p.id 306 | match.dl_vlan_pcp = p.pcp 307 | p = p.next 308 | if isinstance(p, ipv4): 309 | match.nw_src = p.srcip 310 | match.nw_dst = p.dstip 311 | match.nw_proto = p.protocol 312 | match.nw_tos = p.tos 313 | p = p.next 314 | else: 315 | match.dl_vlan = of.OFP_VLAN_NONE 316 | match.dl_vlan_pcp = 0 317 | 318 | else: 319 | match = ofp_match_withHash.from_packet(packet) 320 | 321 | _install_path(prev_path, match) 322 | 323 | #forward the packet directly from the last switch, there is no need to have the packet run through the complete network. 324 | drop() 325 | dst = mac_learning[packet.dst] 326 | msg = of.ofp_packet_out() 327 | msg.data = event.ofp.data 328 | msg.actions.append(of.ofp_action_output(port = dst.port)) 329 | switches[dst.dpid].connection.send(msg) 330 | 331 | self.raiseEvent(NewFlow(prev_path, match, adj)) 332 | log.debug("Switch %s processed unicast 0x%0.4x type packet, send to recipient by switch %s", self, packet.effective_ethertype, util.dpid_to_str(dst.dpid)) 333 | 334 | 335 | def _handle_ConnectionDown(self, event): 336 | log.debug("Switch %s going down", util.dpid_to_str(self.connection.dpid)) 337 | del switches[self.connection.dpid] 338 | #pprint(switches) 339 | 340 | 341 | class NewSwitch(Event): 342 | def __init__(self, switch): 343 | Event.__init__(self) 344 | self.switch = switch 345 | 346 | class Forwarding(EventMixin): 347 | _core_name = "opennetmon_forwarding" # we want to be core.opennetmon_forwarding 348 | _eventMixin_events = set([NewSwitch,]) 349 | 350 | def __init__ (self, l3_matching): 351 | log.debug("Forwarding coming up") 352 | 353 | def startup(): 354 | core.openflow.addListeners(self) 355 | core.openflow_discovery.addListeners(self) 356 | log.debug("Forwarding started") 357 | 358 | self.l3_matching = l3_matching 359 | core.call_when_ready(startup, 'openflow', 'openflow_discovery') 360 | 361 | def _handle_LinkEvent(self, event): 362 | link = event.link 363 | if event.added: 364 | log.debug("Received LinkEvent, Link Added from %s to %s over port %d", util.dpid_to_str(link.dpid1), util.dpid_to_str(link.dpid2), link.port1) 365 | adj[link.dpid1][link.dpid2] = link.port1 366 | switch_ports[link.dpid1,link.port1] = link 367 | #switches[link.dpid1].disable_flooding(link.port1) 368 | #pprint(adj) 369 | else: 370 | log.debug("Received LinkEvent, Link Removed from %s to %s over port %d", util.dpid_to_str(link.dpid1), util.dpid_to_str(link.dpid2), link.port1) 371 | ##Disabled those two lines to prevent interference with experiment due to falsely identified disconnected links. 372 | #del adj[link.dpid1][link.dpid2] 373 | #del switch_ports[link.dpid1,link.port1] 374 | 375 | 376 | #switches[link.dpid1].enable_flooding(link.port1) 377 | 378 | 379 | self._calc_ForwardingMatrix() 380 | 381 | def _calc_ForwardingMatrix(self): 382 | log.debug("Calculating forwarding matrix") 383 | 384 | def _handle_ConnectionUp(self, event): 385 | log.debug("New switch connection: %s", event.connection) 386 | sw = Switch(event.connection, l3_matching=self.l3_matching) 387 | switches[event.dpid] = sw; 388 | self.raiseEvent(NewSwitch(sw)) 389 | 390 | 391 | 392 | def launch (l3_matching=False): 393 | 394 | core.registerNew(Forwarding, l3_matching) 395 | 396 | -------------------------------------------------------------------------------- /CCNx/src/org/json/JSONTokener.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.io.StringReader; 9 | 10 | /* 11 | Copyright (c) 2002 JSON.org 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | The Software shall be used for Good, not Evil. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | */ 33 | 34 | /** 35 | * A JSONTokener takes a source string and extracts characters and tokens from 36 | * it. It is used by the JSONObject and JSONArray constructors to parse 37 | * JSON source strings. 38 | * @author JSON.org 39 | * @version 2012-02-16 40 | */ 41 | public class JSONTokener { 42 | 43 | private long character; 44 | private boolean eof; 45 | private long index; 46 | private long line; 47 | private char previous; 48 | private Reader reader; 49 | private boolean usePrevious; 50 | 51 | 52 | /** 53 | * Construct a JSONTokener from a Reader. 54 | * 55 | * @param reader A reader. 56 | */ 57 | public JSONTokener(Reader reader) { 58 | this.reader = reader.markSupported() 59 | ? reader 60 | : new BufferedReader(reader); 61 | this.eof = false; 62 | this.usePrevious = false; 63 | this.previous = 0; 64 | this.index = 0; 65 | this.character = 1; 66 | this.line = 1; 67 | } 68 | 69 | 70 | /** 71 | * Construct a JSONTokener from an InputStream. 72 | */ 73 | public JSONTokener(InputStream inputStream) throws JSONException { 74 | this(new InputStreamReader(inputStream)); 75 | } 76 | 77 | 78 | /** 79 | * Construct a JSONTokener from a string. 80 | * 81 | * @param s A source string. 82 | */ 83 | public JSONTokener(String s) { 84 | this(new StringReader(s)); 85 | } 86 | 87 | 88 | /** 89 | * Back up one character. This provides a sort of lookahead capability, 90 | * so that you can test for a digit or letter before attempting to parse 91 | * the next number or identifier. 92 | */ 93 | public void back() throws JSONException { 94 | if (this.usePrevious || this.index <= 0) { 95 | throw new JSONException("Stepping back two steps is not supported"); 96 | } 97 | this.index -= 1; 98 | this.character -= 1; 99 | this.usePrevious = true; 100 | this.eof = false; 101 | } 102 | 103 | 104 | /** 105 | * Get the hex value of a character (base16). 106 | * @param c A character between '0' and '9' or between 'A' and 'F' or 107 | * between 'a' and 'f'. 108 | * @return An int between 0 and 15, or -1 if c was not a hex digit. 109 | */ 110 | public static int dehexchar(char c) { 111 | if (c >= '0' && c <= '9') { 112 | return c - '0'; 113 | } 114 | if (c >= 'A' && c <= 'F') { 115 | return c - ('A' - 10); 116 | } 117 | if (c >= 'a' && c <= 'f') { 118 | return c - ('a' - 10); 119 | } 120 | return -1; 121 | } 122 | 123 | public boolean end() { 124 | return this.eof && !this.usePrevious; 125 | } 126 | 127 | 128 | /** 129 | * Determine if the source string still contains characters that next() 130 | * can consume. 131 | * @return true if not yet at the end of the source. 132 | */ 133 | public boolean more() throws JSONException { 134 | this.next(); 135 | if (this.end()) { 136 | return false; 137 | } 138 | this.back(); 139 | return true; 140 | } 141 | 142 | 143 | /** 144 | * Get the next character in the source string. 145 | * 146 | * @return The next character, or 0 if past the end of the source string. 147 | */ 148 | public char next() throws JSONException { 149 | int c; 150 | if (this.usePrevious) { 151 | this.usePrevious = false; 152 | c = this.previous; 153 | } else { 154 | try { 155 | c = this.reader.read(); 156 | } catch (IOException exception) { 157 | throw new JSONException(exception); 158 | } 159 | 160 | if (c <= 0) { // End of stream 161 | this.eof = true; 162 | c = 0; 163 | } 164 | } 165 | this.index += 1; 166 | if (this.previous == '\r') { 167 | this.line += 1; 168 | this.character = c == '\n' ? 0 : 1; 169 | } else if (c == '\n') { 170 | this.line += 1; 171 | this.character = 0; 172 | } else { 173 | this.character += 1; 174 | } 175 | this.previous = (char) c; 176 | return this.previous; 177 | } 178 | 179 | 180 | /** 181 | * Consume the next character, and check that it matches a specified 182 | * character. 183 | * @param c The character to match. 184 | * @return The character. 185 | * @throws JSONException if the character does not match. 186 | */ 187 | public char next(char c) throws JSONException { 188 | char n = this.next(); 189 | if (n != c) { 190 | throw this.syntaxError("Expected '" + c + "' and instead saw '" + 191 | n + "'"); 192 | } 193 | return n; 194 | } 195 | 196 | 197 | /** 198 | * Get the next n characters. 199 | * 200 | * @param n The number of characters to take. 201 | * @return A string of n characters. 202 | * @throws JSONException 203 | * Substring bounds error if there are not 204 | * n characters remaining in the source string. 205 | */ 206 | public String next(int n) throws JSONException { 207 | if (n == 0) { 208 | return ""; 209 | } 210 | 211 | char[] chars = new char[n]; 212 | int pos = 0; 213 | 214 | while (pos < n) { 215 | chars[pos] = this.next(); 216 | if (this.end()) { 217 | throw this.syntaxError("Substring bounds error"); 218 | } 219 | pos += 1; 220 | } 221 | return new String(chars); 222 | } 223 | 224 | 225 | /** 226 | * Get the next char in the string, skipping whitespace. 227 | * @throws JSONException 228 | * @return A character, or 0 if there are no more characters. 229 | */ 230 | public char nextClean() throws JSONException { 231 | for (;;) { 232 | char c = this.next(); 233 | if (c == 0 || c > ' ') { 234 | return c; 235 | } 236 | } 237 | } 238 | 239 | 240 | /** 241 | * Return the characters up to the next close quote character. 242 | * Backslash processing is done. The formal JSON format does not 243 | * allow strings in single quotes, but an implementation is allowed to 244 | * accept them. 245 | * @param quote The quoting character, either 246 | * " (double quote) or 247 | * ' (single quote). 248 | * @return A String. 249 | * @throws JSONException Unterminated string. 250 | */ 251 | public String nextString(char quote) throws JSONException { 252 | char c; 253 | StringBuffer sb = new StringBuffer(); 254 | for (;;) { 255 | c = this.next(); 256 | switch (c) { 257 | case 0: 258 | case '\n': 259 | case '\r': 260 | throw this.syntaxError("Unterminated string"); 261 | case '\\': 262 | c = this.next(); 263 | switch (c) { 264 | case 'b': 265 | sb.append('\b'); 266 | break; 267 | case 't': 268 | sb.append('\t'); 269 | break; 270 | case 'n': 271 | sb.append('\n'); 272 | break; 273 | case 'f': 274 | sb.append('\f'); 275 | break; 276 | case 'r': 277 | sb.append('\r'); 278 | break; 279 | case 'u': 280 | sb.append((char)Integer.parseInt(this.next(4), 16)); 281 | break; 282 | case '"': 283 | case '\'': 284 | case '\\': 285 | case '/': 286 | sb.append(c); 287 | break; 288 | default: 289 | throw this.syntaxError("Illegal escape."); 290 | } 291 | break; 292 | default: 293 | if (c == quote) { 294 | return sb.toString(); 295 | } 296 | sb.append(c); 297 | } 298 | } 299 | } 300 | 301 | 302 | /** 303 | * Get the text up but not including the specified character or the 304 | * end of line, whichever comes first. 305 | * @param delimiter A delimiter character. 306 | * @return A string. 307 | */ 308 | public String nextTo(char delimiter) throws JSONException { 309 | StringBuffer sb = new StringBuffer(); 310 | for (;;) { 311 | char c = this.next(); 312 | if (c == delimiter || c == 0 || c == '\n' || c == '\r') { 313 | if (c != 0) { 314 | this.back(); 315 | } 316 | return sb.toString().trim(); 317 | } 318 | sb.append(c); 319 | } 320 | } 321 | 322 | 323 | /** 324 | * Get the text up but not including one of the specified delimiter 325 | * characters or the end of line, whichever comes first. 326 | * @param delimiters A set of delimiter characters. 327 | * @return A string, trimmed. 328 | */ 329 | public String nextTo(String delimiters) throws JSONException { 330 | char c; 331 | StringBuffer sb = new StringBuffer(); 332 | for (;;) { 333 | c = this.next(); 334 | if (delimiters.indexOf(c) >= 0 || c == 0 || 335 | c == '\n' || c == '\r') { 336 | if (c != 0) { 337 | this.back(); 338 | } 339 | return sb.toString().trim(); 340 | } 341 | sb.append(c); 342 | } 343 | } 344 | 345 | 346 | /** 347 | * Get the next value. The value can be a Boolean, Double, Integer, 348 | * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. 349 | * @throws JSONException If syntax error. 350 | * 351 | * @return An object. 352 | */ 353 | public Object nextValue() throws JSONException { 354 | char c = this.nextClean(); 355 | String string; 356 | 357 | switch (c) { 358 | case '"': 359 | case '\'': 360 | return this.nextString(c); 361 | case '{': 362 | this.back(); 363 | return new JSONObject(this); 364 | case '[': 365 | this.back(); 366 | return new JSONArray(this); 367 | } 368 | 369 | /* 370 | * Handle unquoted text. This could be the values true, false, or 371 | * null, or it can be a number. An implementation (such as this one) 372 | * is allowed to also accept non-standard forms. 373 | * 374 | * Accumulate characters until we reach the end of the text or a 375 | * formatting character. 376 | */ 377 | 378 | StringBuffer sb = new StringBuffer(); 379 | while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { 380 | sb.append(c); 381 | c = this.next(); 382 | } 383 | this.back(); 384 | 385 | string = sb.toString().trim(); 386 | if ("".equals(string)) { 387 | throw this.syntaxError("Missing value"); 388 | } 389 | return JSONObject.stringToValue(string); 390 | } 391 | 392 | 393 | /** 394 | * Skip characters until the next character is the requested character. 395 | * If the requested character is not found, no characters are skipped. 396 | * @param to A character to skip to. 397 | * @return The requested character, or zero if the requested character 398 | * is not found. 399 | */ 400 | public char skipTo(char to) throws JSONException { 401 | char c; 402 | try { 403 | long startIndex = this.index; 404 | long startCharacter = this.character; 405 | long startLine = this.line; 406 | this.reader.mark(1000000); 407 | do { 408 | c = this.next(); 409 | if (c == 0) { 410 | this.reader.reset(); 411 | this.index = startIndex; 412 | this.character = startCharacter; 413 | this.line = startLine; 414 | return c; 415 | } 416 | } while (c != to); 417 | } catch (IOException exc) { 418 | throw new JSONException(exc); 419 | } 420 | 421 | this.back(); 422 | return c; 423 | } 424 | 425 | 426 | /** 427 | * Make a JSONException to signal a syntax error. 428 | * 429 | * @param message The error message. 430 | * @return A JSONException object, suitable for throwing 431 | */ 432 | public JSONException syntaxError(String message) { 433 | return new JSONException(message + this.toString()); 434 | } 435 | 436 | 437 | /** 438 | * Make a printable string of this JSONTokener. 439 | * 440 | * @return " at {index} [character {character} line {line}]" 441 | */ 442 | public String toString() { 443 | return " at " + this.index + " [character " + this.character + " line " + 444 | this.line + "]"; 445 | } 446 | } 447 | --------------------------------------------------------------------------------