| 1153 | } |
| 1154 | |
| 1155 | static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const std::string& endpoint, const std::string& username) |
| 1156 | { |
| 1157 | std::string host; |
| 1158 | // In preference order, we choose the following for the port: |
| 1159 | // 1. -rpcport |
| 1160 | // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) |
| 1161 | // 3. default port for chain |
| 1162 | uint16_t port{BaseParams().RPCPort()}; |
| 1163 | { |
| 1164 | uint16_t rpcconnect_port{0}; |
| 1165 | const std::string rpcconnect_str = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT); |
| 1166 | if (!SplitHostPort(rpcconnect_str, rpcconnect_port, host)) { |
| 1167 | // Uses argument provided as-is |
| 1168 | // (rather than value parsed) |
| 1169 | // to aid the user in troubleshooting |
| 1170 | throw std::runtime_error(strprintf("Invalid port provided in -rpcconnect: %s", rpcconnect_str)); |
| 1171 | } else { |
| 1172 | if (rpcconnect_port != 0) { |
| 1173 | // Use the valid port provided in rpcconnect |
| 1174 | port = rpcconnect_port; |
| 1175 | } // else, no port was provided in rpcconnect (continue using default one) |
| 1176 | } |
| 1177 | |
| 1178 | if (std::optional<std::string> rpcport_arg = gArgs.GetArg("-rpcport")) { |
| 1179 | // -rpcport was specified |
| 1180 | const uint16_t rpcport_int{ToIntegral<uint16_t>(rpcport_arg.value()).value_or(0)}; |
| 1181 | if (rpcport_int == 0) { |
| 1182 | // Uses argument provided as-is |
| 1183 | // (rather than value parsed) |
| 1184 | // to aid the user in troubleshooting |
| 1185 | throw std::runtime_error(strprintf("Invalid port provided in -rpcport: %s", rpcport_arg.value())); |
| 1186 | } |
| 1187 | |
| 1188 | // Use the valid port provided |
| 1189 | port = rpcport_int; |
| 1190 | |
| 1191 | // If there was a valid port provided in rpcconnect, |
| 1192 | // rpcconnect_port is non-zero. |
| 1193 | if (rpcconnect_port != 0) { |
| 1194 | tfm::format(std::cerr, "Warning: Port specified in both -rpcconnect and -rpcport. Using -rpcport %u\n", port); |
| 1195 | } |
| 1196 | } |
| 1197 | } |
| 1198 | |
| 1199 | // Set connection timeout |
| 1200 | const int timeout = gArgs.GetIntArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT); |
| 1201 | std::chrono::seconds timeout_duration; |
| 1202 | if (timeout > 0) { |
| 1203 | timeout_duration = std::chrono::seconds(timeout); |
| 1204 | } else { |
| 1205 | // Use 5 year timeout for "indefinite" |
| 1206 | timeout_duration = std::chrono::years(5); |
| 1207 | } |
| 1208 | |
| 1209 | // Get credentials |
| 1210 | std::string rpc_credentials; |
| 1211 | std::optional<AuthCookieResult> auth_cookie_result; |
| 1212 | if (gArgs.GetArg("-rpcpassword", "") == "") { |