redirect
This adds redirect support to the client side. Lws will follow server redirects (301) up to three deep. Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
7a0fcf2fc5
commit
809d69aa85
6 changed files with 102 additions and 11 deletions
|
@ -162,6 +162,10 @@ LWS_SERVER_OPTION_SSL_ECD
|
|||
|
||||
to build in support and select it at runtime.
|
||||
|
||||
6) There's a new api lws_parse_uri() that simplies chopping up
|
||||
https://xxx:yyy/zzz uris into parts nicely. The test client now uses this
|
||||
to allow proper uris.
|
||||
|
||||
|
||||
User api changes
|
||||
----------------
|
||||
|
|
|
@ -313,6 +313,56 @@ failed:
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
|
||||
* this only works if still in HTTP, ie, not upgraded yet
|
||||
* wsi: connection to reset
|
||||
* address: network address of the new server
|
||||
* port: port to connect to
|
||||
* path: uri path to connect to on the new server
|
||||
* host: host header to send to the new server
|
||||
*/
|
||||
LWS_VISIBLE struct lws *
|
||||
lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host)
|
||||
{
|
||||
if (wsi->u.hdr.redirects == 3) {
|
||||
lwsl_err("%s: Too many redirects\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
wsi->u.hdr.redirects++;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
wsi->use_ssl = ssl;
|
||||
#else
|
||||
if (ssl) {
|
||||
lwsl_err("%s: not configured for ssl\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path);
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
|
||||
return NULL;
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
|
||||
return NULL;
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
|
||||
return NULL;
|
||||
|
||||
close(wsi->sock);
|
||||
remove_wsi_socket_from_fds(wsi);
|
||||
wsi->sock = LWS_SOCK_INVALID;
|
||||
wsi->state = LWSS_CLIENT_UNCONNECTED;
|
||||
wsi->protocol = NULL;
|
||||
wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
wsi->u.hdr.ah->c_port = port;
|
||||
|
||||
return lws_client_connect_2(wsi);
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_client_connect_via_info() - Connect to another websocket server
|
||||
* @i:pointer to lws_client_connect_info struct
|
||||
|
|
21
lib/client.c
21
lib/client.c
|
@ -509,8 +509,8 @@ lws_client_interpret_server_handshake(struct lws *wsi)
|
|||
{
|
||||
struct lws_context *context = wsi->context;
|
||||
int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
|
||||
int n, len, okay = 0, isErrorCodeReceived = 0;
|
||||
const char *pc;
|
||||
int n, len, okay = 0, isErrorCodeReceived = 0, port = 0, ssl = 0;
|
||||
const char *pc, *prot, *ads = NULL, *path;
|
||||
char *p;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
const struct lws_extension *ext;
|
||||
|
@ -532,7 +532,24 @@ lws_client_interpret_server_handshake(struct lws *wsi)
|
|||
lwsl_info("no URI\n");
|
||||
goto bail3;
|
||||
}
|
||||
n = atoi(p);
|
||||
if (n == 301 || n == 302 || n == 303 || n == 307 || n == 308) {
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
|
||||
if (!p)
|
||||
goto bail3;
|
||||
|
||||
if (lws_parse_uri(p, &prot, &ads, &port, &path))
|
||||
goto bail3;
|
||||
|
||||
if (!strcmp(prot, "wss://") || !strcmp(prot, "https://"))
|
||||
ssl = 1;
|
||||
|
||||
if (lws_client_reset(wsi, ssl, ads, port, path, ads)) {
|
||||
lwsl_err("Redirect failed\n");
|
||||
goto bail3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
|
||||
lwsl_info("no ACCEPT\n");
|
||||
isErrorCodeReceived = 1;
|
||||
|
|
|
@ -1096,6 +1096,17 @@ lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_parse_uri: cut up https:/xxx:yyy/zzz into pieces
|
||||
* Notice it does so by dropping '\0' into input string
|
||||
*
|
||||
* @p: incoming uri string.. will get written to
|
||||
* @prot: result pointer for protocol part (https://)
|
||||
* @ads: result pointer for address part
|
||||
* @port: result pointer for port part
|
||||
* @path: result pointer for path part
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_parse_uri(char *p, const char **prot, const char **ads, int *port, const char **path)
|
||||
{
|
||||
|
|
|
@ -836,6 +836,7 @@ struct _lws_header_related {
|
|||
char esc_stash;
|
||||
char post_literal_equal;
|
||||
unsigned char parser_state; /* enum lws_token_indexes */
|
||||
char redirects;
|
||||
};
|
||||
|
||||
struct _lws_websocket_related {
|
||||
|
@ -1034,6 +1035,10 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec);
|
|||
LWS_EXTERN struct lws *
|
||||
lws_client_connect_2(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE struct lws *
|
||||
lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host);
|
||||
|
||||
|
||||
LWS_EXTERN struct lws *
|
||||
lws_create_new_server_wsi(struct lws_context *context);
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ int main(int argc, char **argv)
|
|||
struct lws_context_creation_info info;
|
||||
struct lws_client_connect_info i;
|
||||
struct lws_context *context;
|
||||
const char *address;
|
||||
const char *prot;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
|
@ -321,7 +321,16 @@ int main(int argc, char **argv)
|
|||
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
address = argv[optind];
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
i.port = port;
|
||||
if (lws_parse_uri(argv[optind], &prot, &i.address, &i.port, &i.path))
|
||||
goto usage;
|
||||
|
||||
if (!strcmp(prot, "http://") || !strcmp(prot, "ws://"))
|
||||
use_ssl = 0;
|
||||
if (!strcmp(prot, "https://") || !strcmp(prot, "wss://"))
|
||||
use_ssl = 1;
|
||||
|
||||
/*
|
||||
* create the websockets context. This tracks open connections and
|
||||
|
@ -342,15 +351,10 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
i.context = context;
|
||||
i.address = address;
|
||||
i.port = port;
|
||||
i.ssl_connection = use_ssl;
|
||||
i.path = "/";
|
||||
i.host = argv[optind];
|
||||
i.origin = argv[optind];
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.ietf_version_or_minus_one = ietf_version;
|
||||
i.client_exts = exts;
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue