Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# websocket (development version)

* Add support for connecting to websocket through a proxy

# websocket 1.4.1

* Add UCRT toolchain support (@jeroen, #82)
Expand Down
8 changes: 8 additions & 0 deletions R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ wsAddProtocols <- function(wsc_xptr, protocols) {
invisible(.Call(`_websocket_wsAddProtocols`, wsc_xptr, protocols))
}

wsAddProxy <- function(wsc_xptr, proxy_url) {
invisible(.Call(`_websocket_wsAddProxy`, wsc_xptr, proxy_url))
}

wsAddProxyBasicAuth <- function(wsc_xptr, username, password) {
invisible(.Call(`_websocket_wsAddProxyBasicAuth`, wsc_xptr, username, password))
}

wsConnect <- function(wsc_xptr) {
invisible(.Call(`_websocket_wsConnect`, wsc_xptr))
}
Expand Down
19 changes: 18 additions & 1 deletion R/websocket.R
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ null_func <- function(...) { }
#' @param maxMessageSize The maximum size of a message in bytes. If a message
#' larger than this is sent, the connection will fail with the \code{message_too_big}
#' protocol error.
#' @param proxyUrl Optional parameter to connect to websocket through proxy,
#' will usually begin with \code{http://} or \code{https://}.
#' @param proxyUsername Optional parameter to specify proxy username
#' @param proxyPassword Optional parameter to specify proxy password, can not be
#' \code{NULL} if \code{proxyUsername} is given.
#'
#'
#' @name WebSocket
Expand Down Expand Up @@ -151,7 +156,10 @@ WebSocket <- R6Class("WebSocket",
accessLogChannels = c("none"),
errorLogChannels = NULL,
maxMessageSize = 32 * 1024 * 1024,
loop = later::current_loop()
loop = later::current_loop(),
proxyUrl = NULL,
proxyUsername = NULL,
proxyPassword = NULL
) {
private$callbacks <- new.env(parent = emptyenv())
private$callbacks$open <- Callbacks$new()
Expand All @@ -175,6 +183,15 @@ WebSocket <- R6Class("WebSocket",
})
wsAddProtocols(private$wsObj, protocols)

if (!is.null(proxyUrl)) {
wsAddProxy(private$wsObj, proxyUrl)

if (!is.null(proxyUsername)) {
if (is.null(proxyPassword))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing negation?

wsAddProxyBasicAuth(private$wsObj, proxyUsername, proxyPassword);
}
}

private$pendingConnect <- TRUE
if (autoConnect) {
self$connect()
Expand Down
8 changes: 8 additions & 0 deletions man/WebSocket.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Client {
virtual void setup_connection(std::string location, ws_websocketpp::lib::error_code &ec) = 0;
virtual void append_header(std::string key, std::string value) = 0;
virtual void add_subprotocol(std::string const & request) = 0;
virtual void set_proxy(std::string const & proxy_url) = 0;
virtual void set_proxy_basic_auth(std::string const & username, std::string const & password) = 0;
virtual void connect() = 0;

virtual std::string get_subprotocol() const = 0;
Expand Down Expand Up @@ -137,6 +139,12 @@ class ClientImpl : public Client {
void add_subprotocol(std::string const & value) {
con->add_subprotocol(value);
};
void set_proxy(std::string const & proxy_url) {
this->con->set_proxy(proxy_url);
}
void set_proxy_basic_auth(std::string const & username, std::string const & password) {
this->con->set_proxy_basic_auth(username, password);
}
void connect() {
client.connect(this->con);
};
Expand Down
32 changes: 20 additions & 12 deletions src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


#include "cpp11/declarations.hpp"
#include <R_ext/Visibility.h>

// websocket.cpp
SEXP wsCreate(std::string uri, int loop_id, cpp11::environment robjPublic, cpp11::environment robjPrivate, cpp11::strings accessLogChannels, cpp11::strings errorLogChannels, int maxMessageSize);
Expand All @@ -28,6 +29,22 @@ extern "C" SEXP _websocket_wsAddProtocols(SEXP wsc_xptr, SEXP protocols) {
END_CPP11
}
// websocket.cpp
void wsAddProxy(SEXP wsc_xptr, std::string proxy_url);
extern "C" SEXP _websocket_wsAddProxy(SEXP wsc_xptr, SEXP proxy_url) {
BEGIN_CPP11
wsAddProxy(cpp11::as_cpp<cpp11::decay_t<SEXP>>(wsc_xptr), cpp11::as_cpp<cpp11::decay_t<std::string>>(proxy_url));
return R_NilValue;
END_CPP11
}
// websocket.cpp
void wsAddProxyBasicAuth(SEXP wsc_xptr, std::string username, std::string password);
extern "C" SEXP _websocket_wsAddProxyBasicAuth(SEXP wsc_xptr, SEXP username, SEXP password) {
BEGIN_CPP11
wsAddProxyBasicAuth(cpp11::as_cpp<cpp11::decay_t<SEXP>>(wsc_xptr), cpp11::as_cpp<cpp11::decay_t<std::string>>(username), cpp11::as_cpp<cpp11::decay_t<std::string>>(password));
return R_NilValue;
END_CPP11
}
// websocket.cpp
void wsConnect(SEXP wsc_xptr);
extern "C" SEXP _websocket_wsConnect(SEXP wsc_xptr) {
BEGIN_CPP11
Expand Down Expand Up @@ -75,19 +92,10 @@ extern "C" SEXP _websocket_wsUpdateLogChannels(SEXP wsc_xptr, SEXP accessOrError
}

extern "C" {
/* .Call calls */
extern SEXP _websocket_wsAddProtocols(SEXP, SEXP);
extern SEXP _websocket_wsAppendHeader(SEXP, SEXP, SEXP);
extern SEXP _websocket_wsClose(SEXP, SEXP, SEXP);
extern SEXP _websocket_wsConnect(SEXP);
extern SEXP _websocket_wsCreate(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _websocket_wsProtocol(SEXP);
extern SEXP _websocket_wsSend(SEXP, SEXP);
extern SEXP _websocket_wsState(SEXP);
extern SEXP _websocket_wsUpdateLogChannels(SEXP, SEXP, SEXP, SEXP);

static const R_CallMethodDef CallEntries[] = {
{"_websocket_wsAddProtocols", (DL_FUNC) &_websocket_wsAddProtocols, 2},
{"_websocket_wsAddProxy", (DL_FUNC) &_websocket_wsAddProxy, 2},
{"_websocket_wsAddProxyBasicAuth", (DL_FUNC) &_websocket_wsAddProxyBasicAuth, 3},
{"_websocket_wsAppendHeader", (DL_FUNC) &_websocket_wsAppendHeader, 3},
{"_websocket_wsClose", (DL_FUNC) &_websocket_wsClose, 3},
{"_websocket_wsConnect", (DL_FUNC) &_websocket_wsConnect, 1},
Expand All @@ -100,7 +108,7 @@ static const R_CallMethodDef CallEntries[] = {
};
}

extern "C" void R_init_websocket(DllInfo* dll){
extern "C" attribute_visible void R_init_websocket(DllInfo* dll){
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
R_forceSymbols(dll, TRUE);
Expand Down
14 changes: 14 additions & 0 deletions src/websocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ void wsAddProtocols(SEXP wsc_xptr, cpp11::strings protocols) {
}
}

[[cpp11::register]]
void wsAddProxy(SEXP wsc_xptr, std::string proxy_url) {
ASSERT_MAIN_THREAD()
shared_ptr<WebsocketConnection> wsc = xptrGetWsConn(wsc_xptr);
wsc->client->set_proxy(proxy_url);
}

[[cpp11::register]]
void wsAddProxyBasicAuth(SEXP wsc_xptr, std::string username, std::string password) {
ASSERT_MAIN_THREAD()
shared_ptr<WebsocketConnection> wsc = xptrGetWsConn(wsc_xptr);
wsc->client->set_proxy_basic_auth(username, password);
}

[[cpp11::register]]
void wsConnect(SEXP wsc_xptr) {
ASSERT_MAIN_THREAD()
Expand Down