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