-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- use connector for TLS stream - implement HTTP proxy connector
- Loading branch information
Showing
8 changed files
with
486 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,7 @@ set(tlsuv_sources | |
src/p11.c | ||
src/p11.h | ||
src/util.h | ||
src/connector.c | ||
) | ||
|
||
if(USE_OPENSSL) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright (c) NetFoundry Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef TLSUV_CONNECTOR_H | ||
#define TLSUV_CONNECTOR_H | ||
|
||
#include <uv.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
typedef enum tlsuv_proxy_type { | ||
tlsuv_PROXY_HTTP, | ||
// maybe other kinds in the future | ||
} tlsuv_proxy_t; | ||
|
||
// connector creates connected sockets | ||
typedef struct tlsuv_connector_s tlsuv_connector_t; | ||
typedef void (*tlsuv_connect_cb)(uv_os_sock_t sock, int status, void *ctx); | ||
typedef int (*tlsuv_connect)(uv_loop_t *loop, const tlsuv_connector_t *connector, | ||
const char *host, int port, | ||
tlsuv_connect_cb cb, void *ctx); | ||
|
||
extern void tlsuv_set_global_connector(const tlsuv_connector_t* connector); | ||
const tlsuv_connector_t *tlsuv_global_connector(); | ||
|
||
// proxy connector connects to proxy and does proxy negotiation | ||
tlsuv_connector_t *tlsuv_new_proxy_connector(tlsuv_proxy_t type, const char* host, int port); | ||
|
||
struct tlsuv_connector_s { | ||
tlsuv_connect connect; | ||
void (*free)(void *self); | ||
}; | ||
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif //TLSUV_CONNECTOR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
// Copyright (c) NetFoundry Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include <tlsuv/connector.h> | ||
#include <stdlib.h> | ||
|
||
#include "util.h" | ||
|
||
#if _WIN32 | ||
#include "win32_compat.h" | ||
#include <winsock2.h> | ||
#define ioctl ioctlsocket | ||
#define get_error() WSAGetLastError() | ||
#else | ||
#define get_error() errno | ||
#include <sys/ioctl.h> | ||
#include <unistd.h> | ||
#include "um_debug.h" | ||
|
||
#endif | ||
|
||
|
||
struct conn_req_s { | ||
uv_getaddrinfo_t resolve; | ||
void *ctx; | ||
tlsuv_connect_cb cb; | ||
uv_tcp_t sock; | ||
uv_connect_t connect; | ||
|
||
}; | ||
|
||
static uv_os_sock_t new_socket(const struct addrinfo *addr); | ||
static int default_connect(uv_loop_t *l, const tlsuv_connector_t *self, | ||
const char *host, int port, tlsuv_connect_cb cb, void *ctx); | ||
static int proxy_connect(uv_loop_t *l, const tlsuv_connector_t *self, | ||
const char *host, int port, tlsuv_connect_cb cb, void *ctx); | ||
|
||
// prevent freeing default connector | ||
static void default_connector_free(void *self){ | ||
(void)self; | ||
} | ||
|
||
static tlsuv_connector_t default_connector = { | ||
.connect = default_connect, | ||
.free = default_connector_free, | ||
}; | ||
static const tlsuv_connector_t *global_connector = &default_connector; | ||
|
||
struct tlsuv_proxy_connector_s { | ||
tlsuv_connect connect; | ||
void (*free)(tlsuv_connector_t *self); | ||
|
||
tlsuv_proxy_t type; | ||
char *host; | ||
int port; | ||
}; | ||
|
||
void tlsuv_set_global_connector(const tlsuv_connector_t *c) { | ||
global_connector = c ? c : &default_connector; | ||
} | ||
|
||
const tlsuv_connector_t* tlsuv_global_connector() { | ||
return global_connector; | ||
} | ||
|
||
static void on_close(uv_handle_t *h) { | ||
struct conn_req_s *req = h->data; | ||
free(req); | ||
} | ||
|
||
static void on_connect(uv_connect_t *connect, int status) { | ||
struct conn_req_s *req = connect->data; | ||
if (status != 0) { | ||
req->cb(-1, status, req->ctx); | ||
} else { | ||
uv_os_sock_t s; | ||
uv_fileno((const uv_handle_t *) &req->sock, &s); | ||
uv_os_sock_t sock = dup(s); | ||
req->cb(sock, 0, req->ctx); | ||
} | ||
uv_close((uv_handle_t *) &req->sock, on_close); | ||
} | ||
|
||
static void on_resolve(uv_getaddrinfo_t *req, int status, struct addrinfo *addr) { | ||
struct conn_req_s *r = req->data; | ||
if (status != 0) { | ||
r->cb(-1, status, r->ctx); | ||
free(r); | ||
} else { | ||
r->connect.data = r; | ||
r->sock.data = r; | ||
uv_tcp_init(req->loop, &r->sock); | ||
uv_tcp_connect(&r->connect, &r->sock, addr->ai_addr, on_connect); | ||
} | ||
uv_freeaddrinfo(addr); | ||
} | ||
|
||
int default_connect(uv_loop_t *loop, const tlsuv_connector_t *self, | ||
const char *host, int port, | ||
tlsuv_connect_cb cb, void *ctx) { | ||
struct conn_req_s *r = calloc(1, sizeof(*r)); | ||
r->ctx = ctx; | ||
r->resolve.data = r; | ||
r->cb = cb; | ||
|
||
struct addrinfo hints = { | ||
.ai_socktype = SOCK_STREAM, | ||
}; | ||
char portstr[6]; | ||
snprintf(portstr, sizeof portstr, "%d", port); | ||
return uv_getaddrinfo(loop, &r->resolve, on_resolve, host, portstr, &hints); | ||
} | ||
|
||
struct proxy_connect_req { | ||
uv_work_t work; | ||
const struct tlsuv_proxy_connector_s *proxy; | ||
void *data; | ||
const char *host; | ||
int port; | ||
tlsuv_connect_cb cb; | ||
uv_os_sock_t sock; | ||
int err; | ||
|
||
}; | ||
|
||
static void proxy_work(uv_work_t *wr) { | ||
struct proxy_connect_req *r = container_of(wr, struct proxy_connect_req, work); | ||
|
||
int flags = fcntl(r->sock, F_GETFL); | ||
Check failure on line 140 in src/connector.c GitHub Actions / build (windows, openssl)
|
||
fcntl(r->sock, F_SETFL, flags ^ O_NONBLOCK); | ||
Check failure on line 141 in src/connector.c GitHub Actions / build (windows, openssl)
Check failure on line 141 in src/connector.c GitHub Actions / build (windows, openssl)
Check failure on line 141 in src/connector.c GitHub Actions / build (windows, mbedtls)
|
||
|
||
char req[1024]; | ||
size_t reqlen = snprintf(req, sizeof(req), | ||
"CONNECT %s:%d HTTP/1.1\r\n" | ||
"Host: %s:%d\r\n" | ||
"Proxy-Connection: keep-alive\r\n" | ||
"\r\n", | ||
r->host, r->port, r->host, r->port); | ||
ssize_t res = write(r->sock, req, reqlen); | ||
if (res < 0) { | ||
r->err = (int)res; | ||
close(r->sock); | ||
r->sock = -1; | ||
return; | ||
} | ||
|
||
res = read(r->sock, req, sizeof(req)); | ||
if (res < 0) { | ||
r->err = (int)res; | ||
close(r->sock); | ||
r->sock = -1; | ||
return; | ||
} | ||
req[res] = 0; | ||
|
||
int code = 0; | ||
res = sscanf(req, "HTTP/1.%*c %d ", &code); | ||
if (res != 1 || code != 200) { | ||
r->err = ECONNREFUSED; | ||
close(r->sock); | ||
r->sock = -1; | ||
} | ||
} | ||
|
||
static void proxy_work_cb(uv_work_t *wr, int status) { | ||
struct proxy_connect_req *r = container_of(wr, struct proxy_connect_req, work); | ||
r->cb(r->sock, r->err, r->data); | ||
free(r); | ||
} | ||
|
||
static void on_proxy_connect(uv_os_sock_t fd, int status, void *req) { | ||
struct proxy_connect_req *r = req; | ||
if (status != 0) { | ||
r->cb(-1, status, r->data); | ||
free(r); | ||
} else { | ||
r->sock = fd; | ||
uv_queue_work(r->work.loop, &r->work, proxy_work, proxy_work_cb); | ||
} | ||
} | ||
|
||
int proxy_connect(uv_loop_t *loop, const tlsuv_connector_t *self, | ||
const char *host, int port, tlsuv_connect_cb cb, void *ctx) { | ||
const struct tlsuv_proxy_connector_s *proxy = (const struct tlsuv_proxy_connector_s *) self; | ||
struct proxy_connect_req *r = malloc(sizeof(*r)); | ||
r->proxy = proxy; | ||
r->data = ctx; | ||
r->cb = cb; | ||
r->host = host; | ||
r->port = port; | ||
r->work.loop = loop; | ||
return default_connect(loop, &default_connector, proxy->host, proxy->port, on_proxy_connect, r); | ||
} | ||
|
||
void proxy_free(tlsuv_connector_t *self) { | ||
struct tlsuv_proxy_connector_s *c = (struct tlsuv_proxy_connector_s *) self; | ||
free(c->host); | ||
free(c); | ||
} | ||
|
||
tlsuv_connector_t *tlsuv_new_proxy_connector(tlsuv_proxy_t type, const char* host, int port) { | ||
struct tlsuv_proxy_connector_s *c = malloc(sizeof(*c)); | ||
c->type = type; | ||
c->host = strdup(host); | ||
Check warning on line 215 in src/connector.c GitHub Actions / build (ubuntu, openssl)
Check warning on line 215 in src/connector.c GitHub Actions / build (ubuntu, openssl)
Check warning on line 215 in src/connector.c GitHub Actions / build (ubuntu, mbedtls)
|
||
c->port = port; | ||
c->connect = proxy_connect; | ||
c->free = proxy_free; | ||
return (tlsuv_connector_t *)c; | ||
} | ||
|
||
|
Oops, something went wrong.