1#' Find an open TCP port 2#' 3#' Finds a random available TCP port for listening on, within a specified range 4#' of ports. The default range of ports to check is 1024 to 49151, which is the 5#' set of TCP User Ports. This function automatically excludes some ports which 6#' are considered unsafe by web browsers. 7#' 8#' @inheritParams runServer 9#' @param min Minimum port number. 10#' @param max Maximum port number. 11#' @param n Number of ports to try before giving up. 12#' 13#' @return A port that is available to listen on. 14#' 15#' @examples 16#' \dontrun{ 17#' s <- startServer("127.0.0.1", randomPort(), list()) 18#' browseURL(paste0("http://127.0.0.1:", s$getPort())) 19#' 20#' s$stop() 21#' } 22#' 23#' @export 24randomPort <- function(min = 1024L, max = 49151L, host = "127.0.0.1", n = 20) { 25 valid_ports <- setdiff(seq.int(min, max), unsafe_ports) 26 27 n <- min(n, length(valid_ports)) 28 # Try up to n ports 29 for (port in sample(valid_ports, n)) { 30 s <- NULL 31 32 # Check if port is open 33 tryCatch( 34 s <- startServer(host, port, list(), quiet = TRUE), 35 error = function(e) { } 36 ) 37 if (!is.null(s)) { 38 s$stop() 39 return(port) 40 } 41 } 42 43 stop("Cannot find an available port.") 44} 45 46# Ports that are considered unsafe by Chrome 47# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome 48# https://github.com/rstudio/shiny/issues/1784 49unsafe_ports <- c( 50 1, 51 7, 52 9, 53 11, 54 13, 55 15, 56 17, 57 19, 58 20, 59 21, 60 22, 61 23, 62 25, 63 37, 64 42, 65 43, 66 53, 67 77, 68 79, 69 87, 70 95, 71 101, 72 102, 73 103, 74 104, 75 109, 76 110, 77 111, 78 113, 79 115, 80 117, 81 119, 82 123, 83 135, 84 139, 85 143, 86 179, 87 389, 88 427, 89 465, 90 512, 91 513, 92 514, 93 515, 94 526, 95 530, 96 531, 97 532, 98 540, 99 548, 100 556, 101 563, 102 587, 103 601, 104 636, 105 993, 106 995, 107 2049, 108 3659, 109 4045, 110 6000, 111 6665, 112 6666, 113 6667, 114 6668, 115 6669, 116 6697 117) 118