1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00
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:
Andy Green 2016-01-14 11:37:56 +08:00
parent 7a0fcf2fc5
commit 809d69aa85
6 changed files with 102 additions and 11 deletions

View file

@ -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
----------------

View file

@ -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

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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;
/*