public PortAddress createPort(
     PortName name, Encoding enc, LengthMultiplier m, Authentication auth, DataEndorser endorser) {
   PortAddress portAddress;
   // get a new random port address that is not in use (that we know of)
   do {
     portAddress = new PortAddress();
   } while (ports.containsKey(portAddress));
   EndorsedPortAdviceFrame portAdviceFrame = new EndorsedPortAdviceFrame();
   portAdviceFrame.encoding = enc;
   portAdviceFrame.lengthMultiplier = m;
   portAdviceFrame.portAddress = portAddress;
   portAdviceFrame.portName = name;
   portAdviceFrame.authentication = auth;
   try {
     byte[] endorsement = endorser.endorse(portAdviceFrame.document());
     portAdviceFrame.endorsement = new ByteArray(endorsement);
     portAdviceFrame.endorsementLength = new EndorsementLength(endorsement.length);
   } catch (IOException e) {
     log("cannot create endorsed port: " + e.toString());
   }
   Connection c =
       new Connection(
           this,
           portAdviceFrame); // port advice frame is public,  our configuration is private (secret
                             // keys, etc)
   //        c.open();  // mus tbe done by caller with Configuration
   ports.put(portAddress, c);
   return portAddress;
 }
 public void run() {
   byte[] last = null;
   while (!Thread.currentThread().isInterrupted()) {
     byte[] data = recv();
     if (!Util.equals(
         data,
         last)) { // prevent re-processing the same received packet again and again... in real
                  // life the transmission doesn't "hang around" but this simulation does not
                  // have a mechanism for "clearing the air" yet.
       last = data;
       // detect frame type
       FrameType frameType = FrameType.nullOrValueOf(Util.first(data, FrameType.LENGTH));
       if (frameType == null) {
         log("Received invalid frame data: " + Hex.encodeHexString(data));
       } else if (frameType.equals(FrameType.BEACON)) { // if( frame instanceof BeaconFrame ) {
         BeaconFrame beaconFrame = new BeaconFrame(data); // (BeaconFrame)frame;
         NodeInfo nodeInfo = nodes.get(beaconFrame.sourceNodeAddress);
         if (nodeInfo == null) {
           nodeInfo = new NodeInfo();
           nodeInfo.address = beaconFrame.sourceNodeAddress;
           nodes.put(beaconFrame.sourceNodeAddress, nodeInfo);
         }
         nodeInfo.lastBeaconAt = System.currentTimeMillis();
         nodes.put(beaconFrame.sourceNodeAddress, nodeInfo);
         beaconReply(beaconFrame);
         for (Connection c : ports.values()) {
           if (c.authentication() == null) {
             portAdviceReply(beaconFrame, c.portAdvice());
           } else {
             portAdviceReply(beaconFrame, c.endorsedPortAdvice());
           }
         }
       } else if (frameType.equals(
           FrameType.PORT_ADVICE)) { // else if( frame instanceof PortAdviceFrame ) {
         PortAdviceFrame portAdviceFrame = new PortAdviceFrame(data); // (PortAdviceFrame)frame;
         // once we have a port advice, we do not let anyone redefine it. node must be reset in
         // order to accept new definitions.
         if (!ports.containsKey(portAdviceFrame.portAddress())) {
           // only add the port advice if we support its protocols
           if (encodings.contains(portAdviceFrame.encoding)) {
             ports.put(portAdviceFrame.portAddress(), new Connection(link, portAdviceFrame));
           }
         }
       } else if (frameType.equals(FrameType.ENDORSED_PORT_ADVICE)) {
         EndorsedPortAdviceFrame endorsedPortAdviceFrame = new EndorsedPortAdviceFrame(data);
         /*
         // if it's authenticated port advice, then we overwrite existing advice for that port;  for example this can be used to change secrets
         Connection c = ports.get(endorsedPortAdviceFrame.portAddress());
         if( c != null ) {
             c.recv(data);
             // XXX TODO hmm, so how do we find out from the connection if the frame was authentic - because we need to know before we do ports.put(...)
         }
         */
         // for now we use the same rule as non-authenticated port advice, which is only to
         // create a new port if we don't already have it
         if (!ports.containsKey(endorsedPortAdviceFrame.portAddress())) {
           // only add the port advice if we support its protocols
           if (encodings.contains(endorsedPortAdviceFrame.encoding)
               && authentications.contains(endorsedPortAdviceFrame.authentication)) {
             ports.put(
                 endorsedPortAdviceFrame.portAddress(),
                 new Connection(link, endorsedPortAdviceFrame));
           }
         }
       } else if (frameType.equals(FrameType.DATA)) {
         Connection c = ports.get(DataFrame.extractPortAddress(data));
         if (c != null) {
           c.recv(
               data); // pass the frame to appropriate connection - it will handle handshakes,
                      // data, etc.
         }
       } else if (frameType.equals(FrameType.ENDORSED_DATA)) {
         Connection c = ports.get(EndorsedDataFrame.extractPortAddress(data));
         if (c != null) {
           c.recv(
               data); // pass the frame to appropriate connection - it will handle handshakes,
                      // data, etc.
         }
       }
     }
     Util.sleep(1, TimeUnit.MILLISECONDS);
   }
 }