use of org.eclipse.jetty.websocket.api.extensions.ExtensionConfig in project jetty.project by eclipse.
the class ExtensionStack method negotiate.
/**
* Perform the extension negotiation.
* <p>
* For the list of negotiated extensions, use {@link #getNegotiatedExtensions()}
*
* @param configs
* the configurations being requested
*/
public void negotiate(List<ExtensionConfig> configs) {
if (LOG.isDebugEnabled())
LOG.debug("Extension Configs={}", configs);
this.extensions = new ArrayList<>();
String[] rsvClaims = new String[3];
for (ExtensionConfig config : configs) {
Extension ext = factory.newInstance(config);
if (ext == null) {
// Extension not present on this side
continue;
}
// Check RSV
if (ext.isRsv1User() && (rsvClaims[0] != null)) {
LOG.debug("Not adding extension {}. Extension {} already claimed RSV1", config, rsvClaims[0]);
continue;
}
if (ext.isRsv2User() && (rsvClaims[1] != null)) {
LOG.debug("Not adding extension {}. Extension {} already claimed RSV2", config, rsvClaims[1]);
continue;
}
if (ext.isRsv3User() && (rsvClaims[2] != null)) {
LOG.debug("Not adding extension {}. Extension {} already claimed RSV3", config, rsvClaims[2]);
continue;
}
// Add Extension
extensions.add(ext);
addBean(ext);
if (LOG.isDebugEnabled())
LOG.debug("Adding Extension: {}", config);
// Record RSV Claims
if (ext.isRsv1User()) {
rsvClaims[0] = ext.getName();
}
if (ext.isRsv2User()) {
rsvClaims[1] = ext.getName();
}
if (ext.isRsv3User()) {
rsvClaims[2] = ext.getName();
}
}
}
use of org.eclipse.jetty.websocket.api.extensions.ExtensionConfig in project jetty.project by eclipse.
the class WebSocketClient method connect.
/**
* Connect to remote websocket endpoint
*
* @param websocket
* the websocket object
* @param toUri
* the websocket uri to connect to
* @param request
* the upgrade request information
* @param upgradeListener
* the upgrade listener
* @return the future for the session, available on success of connect
* @throws IOException
* if unable to connect
*/
public Future<Session> connect(Object websocket, URI toUri, ClientUpgradeRequest request, UpgradeListener upgradeListener) throws IOException {
/* Note: UpgradeListener is used by javax.websocket.ClientEndpointConfig.Configurator
* See: org.eclipse.jetty.websocket.jsr356.JsrUpgradeListener
*/
if (!isStarted()) {
throw new IllegalStateException(WebSocketClient.class.getSimpleName() + "@" + this.hashCode() + " is not started");
}
// Validate websocket URI
if (!toUri.isAbsolute()) {
throw new IllegalArgumentException("WebSocket URI must be absolute");
}
if (StringUtil.isBlank(toUri.getScheme())) {
throw new IllegalArgumentException("WebSocket URI must include a scheme");
}
String scheme = toUri.getScheme().toLowerCase(Locale.ENGLISH);
if (("ws".equals(scheme) == false) && ("wss".equals(scheme) == false)) {
throw new IllegalArgumentException("WebSocket URI scheme only supports [ws] and [wss], not [" + scheme + "]");
}
request.setRequestURI(toUri);
request.setLocalEndpoint(websocket);
// Validate Requested Extensions
for (ExtensionConfig reqExt : request.getExtensions()) {
if (!extensionRegistry.isAvailable(reqExt.getName())) {
throw new IllegalArgumentException("Requested extension [" + reqExt.getName() + "] is not installed");
}
}
if (LOG.isDebugEnabled())
LOG.debug("connect websocket {} to {}", websocket, toUri);
init();
WebSocketUpgradeRequest wsReq = new WebSocketUpgradeRequest(this, httpClient, request);
wsReq.setUpgradeListener(upgradeListener);
return wsReq.sendAsync();
}
use of org.eclipse.jetty.websocket.api.extensions.ExtensionConfig in project jetty.project by eclipse.
the class WebSocketUpgradeRequest method initWebSocketHeaders.
private void initWebSocketHeaders() {
method(HttpMethod.GET);
version(HttpVersion.HTTP_1_1);
// The Upgrade Headers
header(HttpHeader.UPGRADE, "websocket");
header(HttpHeader.CONNECTION, "Upgrade");
// The WebSocket Headers
header(HttpHeader.SEC_WEBSOCKET_KEY, genRandomKey());
header(HttpHeader.SEC_WEBSOCKET_VERSION, "13");
// (Per the hybi list): Add no-cache headers to avoid compatibility issue.
// There are some proxies that rewrite "Connection: upgrade"
// to "Connection: close" in the response if a request doesn't contain
// these headers.
header(HttpHeader.PRAGMA, "no-cache");
header(HttpHeader.CACHE_CONTROL, "no-cache");
// handle "Sec-WebSocket-Extensions"
if (!apiRequestFacade.getExtensions().isEmpty()) {
for (ExtensionConfig ext : apiRequestFacade.getExtensions()) {
header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, ext.getParameterizedName());
}
}
// handle "Sec-WebSocket-Protocol"
if (!apiRequestFacade.getSubProtocols().isEmpty()) {
for (String protocol : apiRequestFacade.getSubProtocols()) {
header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, protocol);
}
}
if (upgradeListener != null) {
upgradeListener.onHandshakeRequest(apiRequestFacade);
}
}
use of org.eclipse.jetty.websocket.api.extensions.ExtensionConfig in project jetty.project by eclipse.
the class WebSocketUpgradeRequest method upgrade.
@Override
public void upgrade(HttpResponse response, HttpConnectionOverHTTP oldConn) {
if (!this.getHeaders().get(HttpHeader.UPGRADE).equalsIgnoreCase("websocket")) {
// Not my upgrade
throw new HttpResponseException("Not WebSocket Upgrade", response);
}
// Check the Accept hash
String reqKey = this.getHeaders().get(HttpHeader.SEC_WEBSOCKET_KEY);
String expectedHash = AcceptHash.hashKey(reqKey);
String respHash = response.getHeaders().get(HttpHeader.SEC_WEBSOCKET_ACCEPT);
if (expectedHash.equalsIgnoreCase(respHash) == false) {
throw new HttpResponseException("Invalid Sec-WebSocket-Accept hash", response);
}
// We can upgrade
EndPoint endp = oldConn.getEndPoint();
WebSocketClientConnection connection = new WebSocketClientConnection(endp, wsClient.getExecutor(), wsClient.getScheduler(), localEndpoint.getPolicy(), wsClient.getBufferPool());
URI requestURI = this.getURI();
WebSocketSession session = getSessionFactory().createSession(requestURI, localEndpoint, connection);
session.setUpgradeRequest(new ClientUpgradeRequest(this));
session.setUpgradeResponse(new ClientUpgradeResponse(response));
connection.addListener(session);
ExtensionStack extensionStack = new ExtensionStack(getExtensionFactory());
List<ExtensionConfig> extensions = new ArrayList<>();
HttpField extField = response.getHeaders().getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS);
if (extField != null) {
String[] extValues = extField.getValues();
if (extValues != null) {
for (String extVal : extValues) {
QuotedStringTokenizer tok = new QuotedStringTokenizer(extVal, ",");
while (tok.hasMoreTokens()) {
extensions.add(ExtensionConfig.parse(tok.nextToken()));
}
}
}
}
extensionStack.negotiate(extensions);
extensionStack.configure(connection.getParser());
extensionStack.configure(connection.getGenerator());
// Setup Incoming Routing
connection.setNextIncomingFrames(extensionStack);
extensionStack.setNextIncoming(session);
// Setup Outgoing Routing
session.setOutgoingHandler(extensionStack);
extensionStack.setNextOutgoing(connection);
session.addManaged(extensionStack);
session.setFuture(fut);
wsClient.addManaged(session);
if (upgradeListener != null) {
upgradeListener.onHandshakeResponse(new ClientUpgradeResponse(response));
}
// Now swap out the connection
endp.upgrade(connection);
}
use of org.eclipse.jetty.websocket.api.extensions.ExtensionConfig in project jetty.project by eclipse.
the class BrowserDebugTool method createWebSocket.
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) {
LOG.debug("Creating BrowserSocket");
if (req.getSubProtocols() != null) {
if (!req.getSubProtocols().isEmpty()) {
String subProtocol = req.getSubProtocols().get(0);
resp.setAcceptedSubProtocol(subProtocol);
}
}
String ua = req.getHeader("User-Agent");
String rexts = req.getHeader("Sec-WebSocket-Extensions");
// manually negotiate extensions
List<ExtensionConfig> negotiated = new ArrayList<>();
// adding frame debug
negotiated.add(new ExtensionConfig("@frame-capture; output-dir=target"));
for (ExtensionConfig config : req.getExtensions()) {
if (config.getName().equals("permessage-deflate")) {
// what we are interested in here
negotiated.add(config);
continue;
}
// skip all others
}
resp.setExtensions(negotiated);
LOG.debug("User-Agent: {}", ua);
LOG.debug("Sec-WebSocket-Extensions (Request) : {}", rexts);
LOG.debug("Sec-WebSocket-Protocol (Request): {}", req.getHeader("Sec-WebSocket-Protocol"));
LOG.debug("Sec-WebSocket-Protocol (Response): {}", resp.getAcceptedSubProtocol());
req.getExtensions();
return new BrowserSocket(ua, rexts);
}
Aggregations