mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
raw: tls conns
Raw + tls needs a little extra handling during connect.
This commit is contained in:
parent
02f7e06776
commit
3d98e29518
3 changed files with 306 additions and 5 deletions
|
@ -24,6 +24,57 @@
|
|||
|
||||
#include <private-lib-core.h>
|
||||
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
static int
|
||||
lws_raw_skt_connect(struct lws *wsi)
|
||||
{
|
||||
int n;
|
||||
#if defined(LWS_WITH_TLS)
|
||||
const char *cce = NULL;
|
||||
char ccebuf[128];
|
||||
|
||||
#if !defined(LWS_WITH_SYS_ASYNC_DNS)
|
||||
switch (lws_client_create_tls(wsi, &cce, 1)) {
|
||||
#else
|
||||
switch (lws_client_create_tls(wsi, &cce, 0)) {
|
||||
#endif
|
||||
case CCTLS_RETURN_ERROR:
|
||||
lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
|
||||
return -1;
|
||||
case CCTLS_RETURN_RETRY:
|
||||
return 0;
|
||||
case CCTLS_RETURN_DONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
|
||||
n = lws_ssl_client_connect2(wsi, ccebuf, sizeof(ccebuf));
|
||||
if (n < 0) {
|
||||
lws_inform_client_conn_fail(wsi, (void *)ccebuf,
|
||||
strlen(ccebuf));
|
||||
|
||||
return -1;
|
||||
}
|
||||
if (n != 1)
|
||||
return 0; /* wait */
|
||||
}
|
||||
#endif
|
||||
|
||||
n = user_callback_handle_rxflow(wsi->a.protocol->callback,
|
||||
wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
|
||||
wsi->user_space, NULL, 0);
|
||||
if (n) {
|
||||
lws_inform_client_conn_fail(wsi, (void *)"user", 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
lwsi_set_state(wsi, LRS_ESTABLISHED);
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
struct lws_pollfd *pollfd)
|
||||
|
@ -82,6 +133,14 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
|
|||
case LRS_WAITING_CONNECT:
|
||||
goto nope;
|
||||
|
||||
case LRS_WAITING_SSL:
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
n = lws_raw_skt_connect(wsi);
|
||||
if (n < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
|
||||
/* SOCKS Greeting Reply */
|
||||
|
@ -177,16 +236,21 @@ try_pollout:
|
|||
return LWS_HPI_RET_HANDLED;
|
||||
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
|
||||
!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL))
|
||||
if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
|
||||
if (!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL))
|
||||
return LWS_HPI_RET_WSI_ALREADY_DIED;
|
||||
|
||||
if (lws_raw_skt_connect(wsi) < 0)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lwsi_state(wsi) == LRS_WAITING_SSL)
|
||||
return LWS_HPI_RET_HANDLED;
|
||||
|
||||
/* one shot */
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
|
||||
lwsl_notice("%s a\n", __func__);
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* clear back-to-back write detection */
|
||||
wsi->could_have_pending = 0;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
project(lws-minimal-raw-client C)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
find_package(libwebsockets CONFIG REQUIRED)
|
||||
list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR})
|
||||
include(CheckCSourceCompiles)
|
||||
include(LwsCheckRequirements)
|
||||
|
||||
set(SAMP lws-minimal-raw-client)
|
||||
set(SRCS main.c)
|
||||
|
||||
set(requirements 1)
|
||||
require_lws_config(LWS_WITH_CLIENT 1 requirements)
|
||||
|
||||
if (requirements)
|
||||
add_executable(${SAMP} ${SRCS})
|
||||
|
||||
if (websockets_shared)
|
||||
target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS})
|
||||
add_dependencies(${SAMP} websockets_shared)
|
||||
else()
|
||||
target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS})
|
||||
endif()
|
||||
endif()
|
214
minimal-examples-lowlevel/raw/minimal-raw-client/main.c
Normal file
214
minimal-examples-lowlevel/raw/minimal-raw-client/main.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* lws-minimal-raw-client
|
||||
*
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates connecting a "raw" client connection
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#if !defined(WIN32)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static struct lws *raw_wsi, *stdin_wsi;
|
||||
static uint8_t buf[LWS_PRE + 4096];
|
||||
static int waiting, interrupted;
|
||||
static struct lws_context *context;
|
||||
static int us_wait_after_input_close = LWS_USEC_PER_SEC / 10;
|
||||
|
||||
static const char *server = "libwebsockets.org", *port = "443";
|
||||
|
||||
static int
|
||||
callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
const char *cp = (const char *)in;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
/* callbacks related to file descriptor */
|
||||
|
||||
case LWS_CALLBACK_RAW_ADOPT_FILE:
|
||||
lwsl_user("LWS_CALLBACK_RAW_ADOPT_FILE\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_CLOSE_FILE:
|
||||
lwsl_user("LWS_CALLBACK_RAW_CLOSE_FILE\n");
|
||||
/* stdin close, wait 1s then close the raw skt */
|
||||
stdin_wsi = NULL; /* invalid now we close */
|
||||
if (raw_wsi)
|
||||
lws_set_timer_usecs(raw_wsi, us_wait_after_input_close);
|
||||
else {
|
||||
interrupted = 1;
|
||||
lws_cancel_service(context);
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_RX_FILE:
|
||||
lwsl_user("LWS_CALLBACK_RAW_RX_FILE\n");
|
||||
waiting = (int)read(0, buf, sizeof(buf));
|
||||
lwsl_notice("raw file read %d\n", waiting);
|
||||
if (waiting < 0)
|
||||
return -1;
|
||||
|
||||
if (raw_wsi)
|
||||
lws_callback_on_writable(raw_wsi);
|
||||
lws_rx_flow_control(wsi, 0);
|
||||
break;
|
||||
|
||||
|
||||
/* callbacks related to raw socket descriptor */
|
||||
|
||||
case LWS_CALLBACK_RAW_ADOPT:
|
||||
lwsl_user("LWS_CALLBACK_RAW_ADOPT\n");
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_CONNECTED:
|
||||
lwsl_user("LWS_CALLBACK_RAW_CONNECTED\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_CLOSE:
|
||||
lwsl_user("LWS_CALLBACK_RAW_CLOSE\n");
|
||||
/*
|
||||
* If the socket to the remote server closed, we must close
|
||||
* and drop any remaining stdin
|
||||
*/
|
||||
interrupted = 1;
|
||||
lws_cancel_service(context);
|
||||
/* our pointer to this wsi is invalid now we close */
|
||||
raw_wsi = NULL;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_RX:
|
||||
lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
|
||||
while (len--)
|
||||
putchar(*cp++);
|
||||
fflush(stdout);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_WRITEABLE:
|
||||
lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n");
|
||||
// lwsl_hexdump_info(buf, waiting);
|
||||
if (!waiting)
|
||||
break;
|
||||
if (stdin_wsi)
|
||||
lws_rx_flow_control(stdin_wsi, 1);
|
||||
if (lws_write(wsi, buf, (unsigned int)waiting, LWS_WRITE_RAW) != waiting) {
|
||||
lwsl_notice("%s: raw skt write failed\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_TIMER:
|
||||
lwsl_user("LWS_CALLBACK_TIMER\n");
|
||||
interrupted = 1;
|
||||
lws_cancel_service(context);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{ "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 },
|
||||
LWS_PROTOCOL_LIST_TERM
|
||||
};
|
||||
|
||||
static int
|
||||
system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link,
|
||||
int current, int target)
|
||||
{
|
||||
struct lws_client_connect_info i;
|
||||
|
||||
if (current != LWS_SYSTATE_OPERATIONAL ||
|
||||
target != LWS_SYSTATE_OPERATIONAL)
|
||||
return 0;
|
||||
|
||||
memset(&i, 0, sizeof i);
|
||||
i.context = context;
|
||||
i.method = "RAW";
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
i.alpn = "http/1.1";
|
||||
i.address = server;
|
||||
i.host = server;
|
||||
i.port = atoi(port);
|
||||
i.local_protocol_name = "raw-test";
|
||||
|
||||
waiting = lws_snprintf((char *)buf, sizeof(buf), "GET / HTTP/1.1\xaHost: libwebsockets.org\xa\xa");
|
||||
|
||||
if (!lws_client_connect_via_info(&i)) {
|
||||
lwsl_err("Client creation failed\n");
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
const char *p;
|
||||
int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
|
||||
lws_state_notify_link_t notifier = { { NULL, NULL, NULL },
|
||||
system_notify_cb, "app" };
|
||||
lws_state_notify_link_t *na[] = { ¬ifier, NULL };
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
||||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal raw client\n");
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN_SERVER;
|
||||
info.protocols = protocols;
|
||||
info.register_notifier_list = na;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 0);
|
||||
|
||||
lwsl_user("%s: destroying context\n", __func__);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue