private void releaseAllocation() {
   if (refreshTask != null && !refreshTask.isCancelled()) {
     logger.debug("Releasing previous allocation");
     sendBlockingStunRequest(MessageFactory.createRefreshRequest(0));
     refreshTask.cancel(true);
   }
 }
示例#2
0
 /**
  * Creates a new <tt>Request</tt> instance which is to be sent by this
  * <tt>StunCandidateHarvest</tt> in order to retry a specific <tt>Request</tt>. For example, the
  * long-term credential mechanism dictates that a <tt>Request</tt> is first sent by the client
  * without any credential-related attributes, then it gets challenged by the server and the client
  * retries the original <tt>Request</tt> with the appropriate credential-related attributes in
  * response.
  *
  * @param request the <tt>Request</tt> which is to be retried by this
  *     <tt>StunCandidateHarvest</tt>
  * @return the new <tt>Request</tt> instance which is to be sent by this
  *     <tt>StunCandidateHarvest</tt> in order to retry the specified <tt>request</tt>
  */
 protected Request createRequestToRetry(Request request) {
   switch (request.getMessageType()) {
     case Message.BINDING_REQUEST:
       return MessageFactory.createBindingRequest();
     default:
       throw new IllegalArgumentException("request.messageType");
   }
 }
 private void permit(InetSocketAddress address) {
   logger.info("Permitting sends from {}", address);
   Request createPermissionRequest =
       MessageFactory.createCreatePermissionRequest(
           new TransportAddress(address, Transport.UDP),
           TransactionID.createNewTransactionID().getBytes());
   sendBlockingStunRequest(createPermissionRequest);
   logger.debug("Permitted sends from {}", address);
 }
  private void handleChannelBindRequest() throws InterruptedException, IOException, StunException {
    StunMessageEvent event = eventsReceivedByTurnServer.poll(5, TimeUnit.SECONDS);
    TransportAddress remoteAddress = event.getRemoteAddress();

    Request request = (Request) event.getMessage();
    assertThat(request.getMessageType(), is(Message.CHANNELBIND_REQUEST));
    Response channelBindResponse = MessageFactory.createChannelBindResponse();

    sendResponse(remoteAddress, request, channelBindResponse);
  }
  private void handleCreatePermissionRequest()
      throws StunException, IOException, InterruptedException {
    StunMessageEvent event = eventsReceivedByTurnServer.poll(5, TimeUnit.SECONDS);
    TransportAddress remoteAddress = event.getRemoteAddress();

    Request request = (Request) event.getMessage();
    assertThat(request.getMessageType(), is(Message.CREATEPERMISSION_REQUEST));
    Response createPermissionResponse = MessageFactory.createCreatePermissionResponse();

    sendResponse(remoteAddress, request, createPermissionResponse);
  }
  @NotNull
  private ScheduledFuture<?> scheduleRefresh(int interval) {
    return scheduledExecutorService.scheduleWithFixedDelay(
        (Runnable)
            () -> {
              logger.debug("Refreshing TURN allocation");
              sendBlockingStunRequest(MessageFactory.createRefreshRequest(interval));

              for (Map.Entry<TransportAddress, Character> entry : peerAddressToChannel.entrySet()) {
                bind(entry.getKey(), entry.getValue());
              }
            },
        interval,
        interval,
        TimeUnit.SECONDS);
  }
  private void handleAllocationRequest() throws StunException, IOException, InterruptedException {
    StunMessageEvent event = eventsReceivedByTurnServer.poll(5, TimeUnit.SECONDS);
    TransportAddress localAddress = event.getLocalAddress();
    TransportAddress remoteAddress = event.getRemoteAddress();

    Request request = (Request) event.getMessage();
    assertThat(request.getMessageType(), is(Message.ALLOCATE_REQUEST));
    Response allocationResponse =
        MessageFactory.createAllocationResponse(
            request,
            remoteAddress,
            new TransportAddress(localAddress.getHostAddress(), 2222, UDP),
            100);

    sendResponse(remoteAddress, request, allocationResponse);
  }
  private void allocateAddress(TransportAddress turnServerAddress)
      throws StunException, IOException {
    logger.info("Requesting address allocation at {}", serverAddress);
    Response response = sendBlockingStunRequest(MessageFactory.createAllocateRequest(UDP, false));

    byte[] transactionID = response.getTransactionID();
    relayedAddress =
        ((XorRelayedAddressAttribute) response.getAttribute(XOR_RELAYED_ADDRESS))
            .getAddress(transactionID);
    mappedAddress =
        ((XorMappedAddressAttribute) response.getAttribute(XOR_MAPPED_ADDRESS))
            .getAddress(transactionID);

    logger.info("Relayed address: {}, mapped address: {}", relayedAddress, mappedAddress);

    refreshTask = scheduleRefresh(refreshInterval);
  }
  private void bind(TransportAddress address, int channelNumber) {
    if (peerAddressToChannel.containsKey(address)) {
      return;
    }

    logger.info("Binding '{}' to channel '{}'", address, channelNumber);
    Response response =
        sendBlockingStunRequest(
            MessageFactory.createChannelBindRequest(
                (char) channelNumber, address, TransactionID.createNewTransactionID().getBytes()));
    if (response.isSuccessResponse()) {
      logger.debug("Bound '{}' to channel '{}'", address, channelNumber);

      peerAddressToChannel.put(address, (char) channelNumber);
      channelToPeerAddress.put((char) channelNumber, address);
    } else {
      logger.warn("Binding for '{}' to channel '{}' failed", address, channelNumber);
    }
  }
示例#10
0
 /**
  * Creates a new <tt>Request</tt> which is to be sent to {@link StunCandidateHarvester#stunServer}
  * in order to start resolving {@link #hostCandidate}.
  *
  * @return a new <tt>Request</tt> which is to be sent to {@link StunCandidateHarvester#stunServer}
  *     in order to start resolving {@link #hostCandidate}
  */
 protected Request createRequestToStartResolvingCandidate() {
   return MessageFactory.createBindingRequest();
 }
  @Override
  public void processRequest(StunMessageEvent evt) throws IllegalArgumentException {
    if (logger.isLoggable(Level.FINER)) {
      logger.setLevel(Level.FINEST);
    }
    Message message = evt.getMessage();
    if (message.getMessageType() == Message.CONNECT_REQUEST) {
      logger.finer("Received Connect request " + evt);

      Character errorCode = null;
      XorPeerAddressAttribute peerAddress = null;
      FiveTuple fiveTuple = null;
      Response response = null;
      ConnectionIdAttribute connectionId = null;
      if (!message.containsAttribute(Attribute.XOR_PEER_ADDRESS)) {
        errorCode = ErrorCodeAttribute.BAD_REQUEST;
      } else {
        peerAddress = (XorPeerAddressAttribute) message.getAttribute(Attribute.XOR_PEER_ADDRESS);
        peerAddress.setAddress(peerAddress.getAddress(), evt.getTransactionID().getBytes());
        logger.finest("Peer Address requested : " + peerAddress.getAddress());
        TransportAddress clientAddress = evt.getRemoteAddress();
        TransportAddress serverAddress = evt.getLocalAddress();
        Transport transport = evt.getLocalAddress().getTransport();
        fiveTuple = new FiveTuple(clientAddress, serverAddress, transport);
        Allocation allocation = this.turnStack.getServerAllocation(fiveTuple);
        if (allocation == null) {
          errorCode = ErrorCodeAttribute.ALLOCATION_MISMATCH;
        } else if (!allocation.isPermitted(peerAddress.getAddress())) {
          errorCode = ErrorCodeAttribute.FORBIDDEN;
        } else {
          // code for processing the connect request.
          connectionId = AttributeFactory.createConnectionIdAttribute();
          logger.finest("Created ConnectionID : " + connectionId.getConnectionIdValue());
          try {
            Socket socket =
                new Socket(
                    peerAddress.getAddress().getAddress(), peerAddress.getAddress().getPort());
            socket.setSoTimeout(30 * 1000);
            IceTcpSocketWrapper iceSocket = new IceTcpSocketWrapper(socket);
            this.turnStack.addSocket(iceSocket);
          } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          /**
           * TODO Create a new TCP connection to the peer from relay address. wait for at-least 30
           * seconds. If it fails then send 447 error code.
           */
          this.turnStack.addUnAcknowlededConnectionId(
              connectionId.getConnectionIdValue(), peerAddress.getAddress(), allocation);
          logger.finest("Creating Connect Success Response.");
          response = MessageFactory.createConnectResponse(connectionId.getConnectionIdValue());
        }
      }
      if (errorCode != null) {
        response = MessageFactory.createConnectErrorResponse(errorCode);
        logger.finest("error Code : " + (int) errorCode + " on ConnectRequest");
      }
      try {
        logger.finest("Sending Connect Response");
        turnStack.sendResponse(
            evt.getTransactionID().getBytes(),
            response,
            evt.getLocalAddress(),
            evt.getRemoteAddress());
      } catch (Exception e) {
        System.err.println("Failed to send response");
        logger.log(
            Level.INFO, "Failed to send " + response + " through " + evt.getLocalAddress(), e);
        // try to trigger a 500 response although if this one failed,
        throw new RuntimeException("Failed to send a response", e);
      }
    } else {
      return;
    }
  }