OpenVPN 3 Core Library
Loading...
Searching...
No Matches
httpserv.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14#include <string>
15#include <vector>
16#include <sstream>
17#include <ostream>
18#include <cstdint>
19#include <utility>
20#include <memory>
21#include <unordered_map>
22#include <deque>
23
24#include <openvpn/io/io.hpp>
25
38#include <openvpn/addr/ip.hpp>
49
50#ifdef VPN_BINDING_PROFILES
52#endif
53
54#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
55#include <openvpn/kovpn/sock_mark.hpp>
56#endif
57
58// include acceptors for different protocols
62#if defined(OPENVPN_PLATFORM_WIN)
64#endif
65#ifdef ASIO_HAS_LOCAL_SOCKETS
67#endif
68
69#ifndef OPENVPN_HTTP_SERV_RC
70#define OPENVPN_HTTP_SERV_RC RC<thread_unsafe_refcount>
71#endif
72
74
75OPENVPN_EXCEPTION(http_server_exception);
76
77typedef unsigned int client_t;
78typedef std::int64_t content_len_t;
79
80struct Status
81{
82 // Error codes
83 enum
84 {
98
100 };
101
102 static std::string error_str(const size_t status)
103 {
104 static const char *error_names[] = {
105 "E_SUCCESS",
106 "E_TCP",
107 "E_HTTP",
108 "E_EXCEPTION",
109 "E_HEADER_SIZE",
110 "E_CONTENT_SIZE",
111 "E_EOF_SSL",
112 "E_EOF_TCP",
113 "E_GENERAL_TIMEOUT",
114 "E_EXTERNAL_STOP",
115 "E_PIPELINE_OVERFLOW",
116 "E_SHUTDOWN",
117 "E_ABORTED",
118 };
119
120 static_assert(N_ERRORS == array_size(error_names), "HTTP error names array inconsistency");
121 if (status < N_ERRORS)
122 return error_names[status];
123 else
124 return "E_???";
125 }
126};
127
128struct Config : public RC<thread_unsafe_refcount>
129{
131
133#if defined(OPENVPN_PLATFORM_WIN)
134 std::string sddl_string; // Windows named-pipe security descriptor as string
135#endif
136#ifdef ASIO_HAS_LOCAL_SOCKETS
137 mode_t unix_mode = 0;
138#endif
139 unsigned int tcp_backlog = 16;
140 unsigned int tcp_throttle_max_connections_per_period = 0; // set > 0 to enable throttling
141 Time::Duration tcp_throttle_period;
142 unsigned int tcp_max = 0;
143 unsigned int general_timeout = 60;
144 unsigned int max_headers = 0;
145 unsigned int max_header_bytes = 0;
147 unsigned int msg_overhead_bytes = 0;
148 unsigned int send_queue_max_size = 0;
149 unsigned int free_list_max_size = 8;
150 unsigned int pipeline_max_size = 64;
151 unsigned int sockopt_flags = 0;
152 std::string http_server_id;
155};
156
158{
159 // content length if Transfer-Encoding: chunked
160 static constexpr content_len_t CHUNKED = -1;
161
162 int http_status = 0;
163 std::string http_status_str; // optional
164 std::string type;
165 std::string content_encoding;
166 std::string basic_realm;
168 bool no_cache = false;
169 bool keepalive = false;
170 bool lean_headers = false;
171 std::vector<std::string> extra_headers;
173};
174
176{
177 public:
178 class Client;
179
180 private:
182
183 public:
184 class Client : public Base
185 {
186 friend Base;
187 friend Listener;
188
189 public:
191 {
193 };
194
196
198 {
199 friend Listener;
200 friend Client;
201
202 Initializer(openvpn_io::io_context &io_context_arg,
203 Listener *parent_arg,
204 AsioPolySock::Base::Ptr &&socket_arg,
205 const client_t client_id_arg)
206 : io_context(io_context_arg),
207 parent(parent_arg),
208 socket(std::move(socket_arg)),
209 client_id(client_id_arg)
210 {
211 }
212
213 openvpn_io::io_context &io_context;
217 };
218
220 {
222
224 virtual void stop()
225 {
226 }
227 };
228
229 virtual ~Client()
230 {
231 stop(false, false);
232 }
233
234 bool remote_ip_port(IP::Addr &addr, unsigned int &port) const
235 {
236 if (sock)
237 return sock->remote_ip_port(addr, port);
238 else
239 return false;
240 }
241
243 {
244 IP::Addr addr;
245 unsigned int port;
246 if (remote_ip_port(addr, port))
247 return addr;
248 else
249 return IP::Addr();
250 }
251
253 {
254 if (ssl_sess)
255 return ssl_sess->auth_cert();
256 else
257 return AuthCert::Ptr();
258 }
259
260 bool is_ssl() const
261 {
262 return bool(ssl_sess);
263 }
264
265 bool is_local() const
266 {
267 if (sock)
268 return sock->is_local();
269 else
270 return false;
271 }
272
273 bool is_alt_routing() const
274 {
275#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
276 return is_alt_routing_;
277#else
278 return false;
279#endif
280 }
281
282 protected:
284 : Base(ci.parent->config),
286 sock(std::move(ci.socket)),
287 parent(ci.parent),
290 {
291 }
292
294 {
296
297 content_info = std::move(ci);
298
301
302 // websocket?
303 const bool ws = (content_info.websocket && content_info.http_status == HTTP::Status::SwitchingProtocols);
304
305 if (ws)
307 else
309
311 http_out();
312
313 if (ws)
315 }
316
318 {
320 outbuf = std::move(buf);
322 http_out();
323 }
324
325 // return true if client asked for keepalive
327 {
328 return headers().get_value_trim("connection") == "keep-alive";
329 }
330
331 const HTTP::Request &request() const
332 {
333 return request_reply();
334 }
335
337 {
338 activity();
339 }
340
341 void external_stop(const std::string &description)
342 {
344 }
345
346 void abort(const std::string &description, const int status = Status::E_ABORTED)
347 {
348 if (!halt)
349 error_handler(status, description);
350 }
351
352 std::string remote_endpoint_str() const
353 {
354 try
355 {
356 if (sock)
357 return sock->remote_endpoint_str();
358 }
359 catch (const std::exception &)
360 {
361 }
362 return "[unknown endpoint]";
363 }
364
366 {
367 return client_id;
368 }
369
371 {
372 return parent;
373 }
374
375#ifdef ASIO_HAS_LOCAL_SOCKETS
376 int unix_fd()
377 {
378 AsioPolySock::Unix *uds = dynamic_cast<AsioPolySock::Unix *>(sock.get());
379 if (uds)
380 return uds->socket.native_handle();
381 else
382 return -1;
383 }
384#endif
385
386 openvpn_io::io_context &io_context;
388 std::deque<BufferAllocated> pipeline;
389 Time::Duration timeout_duration;
390
391 private:
393 friend LinkImpl::Base; // calls tcp_* handlers
394
395 void generate_reply_headers_http(std::ostream &os)
396 {
397 os << "HTTP/1.1 " << content_info.http_status << ' ';
398 if (content_info.http_status_str.empty())
399 os << HTTP::Status::to_string(content_info.http_status);
400 else
401 os << content_info.http_status_str;
402 os << "\r\n";
403 if (!content_info.lean_headers)
404 {
405 if (!parent->config->http_server_id.empty())
406 os << "Server: " << parent->config->http_server_id << "\r\n";
407 os << "Date: " << date_time_rfc822() << "\r\n";
408 }
409 if (!content_info.basic_realm.empty())
410 os << "WWW-Authenticate: Basic realm=\"" << content_info.basic_realm << "\"\r\n";
411 if (content_info.length)
412 os << "Content-Type: " << content_info.type << "\r\n";
413 if (content_info.length > 0)
414 os << "Content-Length: " << content_info.length << "\r\n";
415 else if (content_info.length == ContentInfo::CHUNKED)
416 os << "Transfer-Encoding: chunked\r\n";
417 for (auto &h : content_info.extra_headers)
418 os << h << "\r\n";
419 if (!content_info.content_encoding.empty())
420 os << "Content-Encoding: " << content_info.content_encoding << "\r\n";
421 if (content_info.no_cache && !content_info.lean_headers)
422 os << "Cache-Control: no-cache, no-store, must-revalidate\r\n";
423 if ((keepalive = content_info.keepalive))
424 os << "Connection: keep-alive\r\n";
425 else
426 os << "Connection: close\r\n";
427 os << "\r\n";
428 }
429
430 void generate_reply_headers_websocket(std::ostream &os)
431 {
432 os << "HTTP/1.1 101 Switching Protocols\r\n";
433 if (content_info.websocket)
434 content_info.websocket->server_headers(os);
435 for (auto &h : content_info.extra_headers)
436 os << h << "\r\n";
437 os << "\r\n";
438 }
439
440 // transition to websocket i/o after we push HTTP
441 // headers to client
443 {
444 cancel_general_timeout(); // timeouts could be harmful for long-running websockets
445 set_async_out(true); // websockets require async output
446 websocket = true; // enable websocket in httpcommon
447 ready = false; // enable tcp_in
448 consume_pipeline(); // process data received while tcp_in was disabled
449 }
450
452 {
453 timeout_duration.set_zero();
455 }
456
457 void start(const Acceptor::Item::SSLMode ssl_mode)
458 {
459 timeout_coarse.init(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024));
460 link.reset(new LinkImpl(this,
461 *sock,
462 parent->config->send_queue_max_size,
463 parent->config->free_list_max_size,
464 (*parent->config->frame)[Frame::READ_HTTP],
465 stats));
466 link->set_raw_mode(true);
467 switch (ssl_mode)
468 {
470 break;
472 ssl_sess = parent->config->ssl_factory->ssl();
473 break;
474#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
475 case Acceptor::Item::AltRouting:
476 is_alt_routing_ = true;
477 break;
478#endif
479 }
480 restart(true);
481 }
482
483 void restart(const bool initial)
484 {
485 timeout_duration = Time::Duration::seconds(parent->config->general_timeout);
487 activity();
488 rr_reset();
489 ready = false;
491 if (initial || handoff)
492 link->start();
493 handoff = false;
494 }
495
496 void stop(const bool remove_self_from_map, const bool shutdown)
497 {
498 if (halt)
499 return;
500 halt = true;
501 if (!http_stop_called)
503 http_destroy();
505 if (link)
506 link->stop();
507 if (sock)
508 {
509 if (shutdown)
511 sock->close();
512 }
513 if (remove_self_from_map)
514 openvpn_io::post(io_context, [self = Ptr(this), parent = Listener::Ptr(parent)]() mutable
515 { parent->remove_client(std::move(self)); });
516 }
517
518 void activity()
519 {
520 if (timeout_duration.defined())
521 {
522 const Time now = Time::now();
523 const Time next = now + timeout_duration;
524 if (!timeout_coarse.similar(next))
525 {
526 timeout_coarse.reset(next);
528 timeout_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
529 {
530 if (!error)
531 self->timeout_callback(error); });
532 }
533 }
534 }
535
536 void timeout_callback(const openvpn_io::error_code &e)
537 {
538 if (halt || e)
539 return;
540 error_handler(Status::E_GENERAL_TIMEOUT, "General timeout");
541 }
542
544 {
545 if (!buf.empty())
547 if (halt)
548 return;
549 if (buf.empty())
550 return;
551 if (pipeline.size() >= parent->config->pipeline_max_size)
552 error_handler(Status::E_PIPELINE_OVERFLOW, "Pipeline overflow");
553 pipeline.push_back(std::move(buf));
554 }
555
557 {
558 while (!pipeline.empty() && !ready)
559 {
560 BufferAllocated buf(std::move(pipeline.front()));
561 pipeline.pop_front();
562 tcp_in(buf);
563 }
564 }
565
566 // Implemented by child class for any kind of intercept processing
567 // (i.e. parsing and stripping the Proxy Protocol v1 header)
569 {
570 }
571
572 // methods called by LinkImpl
573
575 {
576 if (halt)
577 return false;
578
579 tcp_intercept(b);
580
581 try
582 {
583 activity();
584 if (ready)
586 else
587 tcp_in(b); // call Base
588 }
589 catch (const std::exception &e)
590 {
591 handle_exception("tcp_read_handler", e);
592 }
593 return !handoff; // don't requeue read if handoff, i.e. parent wants to take control of session socket
594 }
595
597 {
598 if (halt)
599 return;
600
601 try
602 {
603 http_out();
604 }
605 catch (const std::exception &e)
606 {
607 handle_exception("tcp_write_queue_needs_send", e);
608 }
609 }
610
612 {
613 if (halt)
614 return;
615
616 try
617 {
619 return;
620 }
621 catch (const std::exception &e)
622 {
623 handle_exception("tcp_eof_handler", e);
624 }
625 }
626
627 void tcp_error_handler(const char *error)
628 {
629 if (halt)
630 return;
631 error_handler(Status::E_TCP, std::string("HTTPCore TCP: ") + error);
632 }
633
634 // methods called by Base
635
640
645
647 {
648 if (http_out_eof())
649 {
650 if (keepalive && !websocket)
651 restart(false);
652 else
653 error_handler(Status::E_SUCCESS, "Succeeded");
654 }
655 }
656
658 {
659 return http_headers_received();
660 }
661
663 {
664 http_content_in(buf);
665 }
666
668 {
669 activity();
670 return link->send(buf);
671 }
672
674 {
675 return link->send_queue_empty();
676 }
677
679 const bool parent_handoff)
680 {
681 if (halt)
682 return;
683 ready = true;
684 handoff = parent_handoff;
685 add_to_pipeline(residual);
687 }
688
689 void base_error_handler(const int errcode, const std::string &err)
690 {
691 error_handler(errcode, err);
692 }
693
694 // error handlers
695
696 void asio_error_handler(int errcode, const char *func_name, const openvpn_io::error_code &error)
697 {
698 error_handler(errcode, std::string("HTTPCore Asio ") + func_name + ": " + error.message());
699 }
700
701 void handle_exception(const char *func_name, const std::exception &e)
702 {
703 error_handler(Status::E_EXCEPTION, std::string("HTTPCore Exception ") + func_name + ": " + e.what());
704 }
705
706 void error_handler(const int errcode, const std::string &err)
707 {
708 const bool shutdown = http_stop(errcode, err);
709 http_stop_called = true;
710 stop(true, shutdown);
711 }
712
713 // virtual methods
714
716 {
717 return BufferPtr();
718 }
719
721 {
722 }
723
725 {
726 return true;
727 }
728
730 {
731 }
732
734 {
735 }
736
738 {
739 }
740
741 virtual void http_headers_sent(const Buffer &buf)
742 {
743 }
744
745 virtual bool http_out_eof()
746 {
747 return true;
748 }
749
750 virtual bool http_stop(const int status, const std::string &description)
751 {
752 return false;
753 }
754
755 virtual void http_destroy()
756 {
757 }
758
764 bool keepalive = false;
765 bool handoff = false;
766 bool http_stop_called = false;
767
768#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
769 bool is_alt_routing_ = false;
770#endif
771 };
772
773 public:
775
776 template <typename L> // L is a Listen::Item or Listen::List
777 Listener(openvpn_io::io_context &io_context_arg,
778 const Config::Ptr &config_arg,
779 const L &listen_item_or_list,
780 const Client::Factory::Ptr &client_factory_arg)
781 : io_context(io_context_arg),
782 listen_list(listen_item_or_list),
783 config(config_arg),
784 client_factory(client_factory_arg),
786 {
787 }
788
789 void start() override
790 {
791 if (halt)
792 return;
793
794 acceptors.reserve(listen_list.size());
795 for (const auto &listen_item : listen_list)
796 {
797 switch (listen_item.proto())
798 {
799 case Protocol::TCP:
800 case Protocol::TCPv4:
801 case Protocol::TCPv6:
802 {
803 // ssl enabled?
805 switch (listen_item.ssl)
806 {
808 ssl_mode = bool(config->ssl_factory) ? Acceptor::Item::SSLOn : Acceptor::Item::SSLOff;
809 break;
811 if (listen_item.ssl == Listen::Item::SSLOn && !config->ssl_factory)
812 throw http_server_exception("listen item has 'ssl' qualifier, but no SSL configuration");
813 ssl_mode = Acceptor::Item::SSLOn;
814 break;
816 break;
817#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
818 case Listen::Item::AltRouting:
819 ssl_mode = Acceptor::Item::AltRouting;
820 break;
821#endif
822 }
823
824 OPENVPN_LOG("HTTP" << ((ssl_mode == Acceptor::Item::SSLOn) ? "S" : "") << " Listen: " << listen_item.to_string());
825
826 // init TCP acceptor
828
829 // parse address/port of local endpoint
830#ifdef VPN_BINDING_PROFILES
831 const IP::Addr ip_addr = ViaVPN::server_local_addr(listen_item, via_vpn_gw(listen_item.proto));
832#else
833 const IP::Addr ip_addr(listen_item.addr, listen_item.directive);
834#endif
835 a->local_endpoint.address(ip_addr.to_asio());
836 a->local_endpoint.port(HostPort::parse_port(listen_item.port, "http listen"));
837
838 // open socket
839 a->acceptor.open(a->local_endpoint.protocol());
840
841 // set options
842 a->set_socket_options(config->sockopt_flags);
843
844 // bind to local address
845#ifdef OPENVPN_DEBUG_ACCEPT
846 OPENVPN_LOG("ACCEPTOR BIND " << a->local_endpoint);
847#endif
848 a->acceptor.bind(a->local_endpoint);
849
850 // listen for incoming client connections
851 a->acceptor.listen(config->tcp_backlog);
852
853 // save acceptor
854 acceptors.emplace_back(std::move(a), ssl_mode);
855
856 // queue accept on listen socket
857 queue_accept_throttled(acceptors.size() - 1, false);
858 }
859 break;
860#if defined(OPENVPN_PLATFORM_WIN)
862 {
863 OPENVPN_LOG("HTTP Listen: " << listen_item.to_string());
864
865 // create named pipe
866 Acceptor::NamedPipe::Ptr a(new Acceptor::NamedPipe(io_context, listen_item.addr, config->sddl_string));
867
868 // save acceptor
869 acceptors.emplace_back(std::move(a), Acceptor::Item::SSLOff);
870
871 // queue accept on listen socket
872 queue_accept_throttled(acceptors.size() - 1, false);
873 }
874 break;
875#endif
876#ifdef ASIO_HAS_LOCAL_SOCKETS
878 {
879 OPENVPN_LOG("HTTP Listen: " << listen_item.to_string());
880
882
883 // set endpoint
884 a->pre_listen(listen_item.addr);
885 a->local_endpoint.path(listen_item.addr);
886
887 // open socket
888 a->acceptor.open(a->local_endpoint.protocol());
889
890 // bind to local address
891 a->acceptor.bind(a->local_endpoint);
892
893 // set socket permissions in filesystem
894 a->set_socket_permissions(listen_item.addr, config->unix_mode);
895
896 // listen for incoming client connections
897 a->acceptor.listen();
898
899 // save acceptor
900 acceptors.emplace_back(std::move(a), Acceptor::Item::SSLOff);
901
902 // queue accept on listen socket
903 queue_accept_throttled(acceptors.size() - 1, false);
904 }
905 break;
906#endif
907 default:
908 throw http_server_exception("listen on unknown protocol");
909 }
910 }
911 }
912
913 void stop() override
914 {
915 if (halt)
916 return;
917 halt = true;
918
919 // close acceptors
921
923
924 // stop clients
925 for (auto &c : clients)
926 c.second->stop(false, false);
927 clients.clear();
928
929 // stop client factory
930 if (client_factory)
931 client_factory->stop();
932 }
933
934 template <typename CLIENT_INSTANCE, typename FUNC>
935 void walk(FUNC func) const
936 {
937 for (auto &c : clients)
938 func(*static_cast<CLIENT_INSTANCE *>(c.second.get()));
939 }
940
941 private:
942 typedef std::unordered_map<client_t, Client::Ptr> ClientMap;
943
944 void queue_accept(const size_t acceptor_index)
945 {
946 acceptors[acceptor_index].acceptor->async_accept(this, acceptor_index, io_context);
947 }
948
949 void queue_accept_throttled(const size_t acceptor_index, const bool debit_one)
950 {
951 if (config->tcp_throttle_max_connections_per_period)
952 {
953 if (throttle_acceptor_indices.empty())
954 {
955 const Time now = Time::now();
956 if (now >= throttle_expire)
957 throttle_reset(now, debit_one);
958 if (throttle_connections > 0)
959 {
961 queue_accept(acceptor_index);
962 }
963 else
964 {
965 // throttle it
966 throttle_acceptor_indices.push_back(acceptor_index);
968 }
969 }
970 else
971 throttle_acceptor_indices.push_back(acceptor_index);
972 }
973 else
974 queue_accept(acceptor_index);
975 }
976
977 void throttle_reset(const Time &now, const bool debit_one)
978 {
979 throttle_connections = config->tcp_throttle_max_connections_per_period;
980 if (debit_one)
982 throttle_expire = now + config->tcp_throttle_period;
983 }
984
986 {
988 throttle_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
989 {
990 if (self->halt || error)
991 return;
992 self->throttle_timer_callback(); });
993 }
994
996 {
997 throttle_reset(Time::now(), false);
998 while (!throttle_acceptor_indices.empty() && throttle_connections > 0)
999 {
1000 const size_t acceptor_index = throttle_acceptor_indices.front();
1001 queue_accept(acceptor_index);
1002 throttle_acceptor_indices.pop_front();
1004 }
1005 if (!throttle_acceptor_indices.empty())
1007 }
1008
1009 void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) override
1010 {
1011 if (halt)
1012 return;
1013
1014 const size_t acceptor_index = sock->index();
1015
1016 try
1017 {
1018 if (!error)
1019 {
1020 const Acceptor::Item::SSLMode ssl_mode = acceptors[acceptor_index].ssl_mode;
1021
1022#ifdef OPENVPN_DEBUG_ACCEPT
1023 OPENVPN_LOG("ACCEPT from " << sock->remote_endpoint_str());
1024#endif
1025
1026 sock->non_blocking(true);
1027 sock->set_cloexec();
1028 sock->tcp_nodelay();
1029
1030 if (config->tcp_max && clients.size() >= config->tcp_max)
1031 throw http_server_exception("max clients exceeded");
1032 if (!allow_client(*sock))
1033 throw http_server_exception("client socket rejected");
1034
1035#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING
1036 if (ssl_mode == Acceptor::Item::AltRouting)
1037 {
1038 const KovpnSockMark ksm(sock->native_handle());
1039 if (!ksm.is_internal()) // error if !OVPN_SHIM_INTERNAL in shim flags
1040 throw http_server_exception("non alt-routing socket: " + ksm.to_string());
1041 }
1042#endif
1043
1044 const client_t client_id = new_client_id();
1045 Client::Initializer ci(io_context, this, std::move(sock), client_id);
1046 Client::Ptr cli = client_factory->new_client(ci);
1047 clients[client_id] = cli;
1048
1049 cli->start(ssl_mode);
1050 }
1051 else
1052 throw http_server_exception("accept failed: " + error.message());
1053 }
1054 catch (const std::exception &e)
1055 {
1056 OPENVPN_LOG("exception in handle_accept: " << e.what());
1057 }
1058
1059 queue_accept_throttled(acceptor_index, true);
1060 }
1061
1063 {
1064 while (true)
1065 {
1066 // find an ID that's not already in use
1067 const client_t id = next_id++;
1068 if (clients.find(id) == clients.end())
1069 return id;
1070 }
1071 }
1072
1074 {
1075 remove_client_id(cli->get_client_id());
1076 }
1077
1078 void remove_client_id(const client_t client_id)
1079 {
1080 ClientMap::const_iterator e = clients.find(client_id);
1081 if (e != clients.end())
1082 clients.erase(e);
1083 }
1084
1086 {
1087 return true;
1088 }
1089
1090#ifdef VPN_BINDING_PROFILES
1091 static ViaVPN::GatewayType via_vpn_gw(const Protocol &proto)
1092 {
1093 switch (proto())
1094 {
1095 case Protocol::TCPv4:
1096 return ViaVPN::GW4;
1097 case Protocol::TCPv6:
1098 return ViaVPN::GW6;
1099 default:
1100 return ViaVPN::GW;
1101 }
1102 }
1103#endif
1104
1105 openvpn_io::io_context &io_context;
1109 bool halt = false;
1110
1112
1116 std::deque<size_t> throttle_acceptor_indices;
1117
1120};
1121
1122} // namespace openvpn::WS::Server
std::size_t expires_at(const Time &t)
void async_wait(F &&func)
RCPtr< AuthCert > Ptr
Definition authcert.hpp:46
bool similar(const Time &t) const
void init(const Time::Duration &pre, const Time::Duration &post)
void reset(const Time &t)
bool empty() const
Returns true if the buffer is empty.
Definition buffer.hpp:1219
openvpn_io::ip::address to_asio() const
Definition ip.hpp:594
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
static Ptr Create(ArgsT &&...args)
Creates a new instance of RcEnable with the given arguments.
Definition make_rc.hpp:43
virtual const AuthCert::Ptr & auth_cert() const =0
static TimeType now()
Definition time.hpp:305
const HTTP::HeaderList & headers() const
void tcp_in(BufferAllocated &b)
void set_async_out(const bool async_out_arg)
CONTENT_INFO content_info
const REQUEST_REPLY::State & request_reply() const
SessionStats::Ptr stats
Initializer(openvpn_io::io_context &io_context_arg, Listener *parent_arg, AsioPolySock::Base::Ptr &&socket_arg, const client_t client_id_arg)
Definition httpserv.hpp:202
std::string remote_endpoint_str() const
Definition httpserv.hpp:352
std::deque< BufferAllocated > pipeline
Definition httpserv.hpp:388
virtual void http_content_in(BufferAllocated &buf)
Definition httpserv.hpp:737
virtual bool http_stop(const int status, const std::string &description)
Definition httpserv.hpp:750
void base_http_done_handler(BufferAllocated &residual, const bool parent_handoff)
Definition httpserv.hpp:678
void generate_reply_headers_http(std::ostream &os)
Definition httpserv.hpp:395
virtual void tcp_intercept(BufferAllocated &b)
Definition httpserv.hpp:568
void asio_error_handler(int errcode, const char *func_name, const openvpn_io::error_code &error)
Definition httpserv.hpp:696
void generate_reply_headers(ContentInfo ci)
Definition httpserv.hpp:293
TCPTransport::TCPLink< AsioProtocol, Client *, false > LinkImpl
Definition httpserv.hpp:392
void start(const Acceptor::Item::SSLMode ssl_mode)
Definition httpserv.hpp:457
bool base_link_send(BufferAllocated &buf)
Definition httpserv.hpp:667
bool tcp_read_handler(BufferAllocated &b)
Definition httpserv.hpp:574
void timeout_callback(const openvpn_io::error_code &e)
Definition httpserv.hpp:536
bool remote_ip_port(IP::Addr &addr, unsigned int &port) const
Definition httpserv.hpp:234
void handle_exception(const char *func_name, const std::exception &e)
Definition httpserv.hpp:701
void external_stop(const std::string &description)
Definition httpserv.hpp:341
void stop(const bool remove_self_from_map, const bool shutdown)
Definition httpserv.hpp:496
void base_http_content_in(BufferAllocated &buf)
Definition httpserv.hpp:662
void abort(const std::string &description, const int status=Status::E_ABORTED)
Definition httpserv.hpp:346
void error_handler(const int errcode, const std::string &err)
Definition httpserv.hpp:706
void tcp_error_handler(const char *error)
Definition httpserv.hpp:627
virtual void http_pipeline_peek(BufferAllocated &buf)
Definition httpserv.hpp:733
const HTTP::Request & request() const
Definition httpserv.hpp:331
void generate_reply_headers_websocket(std::ostream &os)
Definition httpserv.hpp:430
void base_error_handler(const int errcode, const std::string &err)
Definition httpserv.hpp:689
openvpn_io::io_context & io_context
Definition httpserv.hpp:386
virtual void http_headers_sent(const Buffer &buf)
Definition httpserv.hpp:741
void restart(const bool initial)
Definition httpserv.hpp:483
void generate_custom_reply_headers(BufferPtr &&buf)
Definition httpserv.hpp:317
void add_to_pipeline(BufferAllocated &buf)
Definition httpserv.hpp:543
void remove_client(Client::Ptr cli)
virtual bool allow_client(AsioPolySock::Base &sock)
void walk(FUNC func) const
Definition httpserv.hpp:935
std::deque< size_t > throttle_acceptor_indices
void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) override
void throttle_reset(const Time &now, const bool debit_one)
Definition httpserv.hpp:977
std::unordered_map< client_t, Client::Ptr > ClientMap
Definition httpserv.hpp:942
void remove_client_id(const client_t client_id)
openvpn_io::io_context & io_context
Listener(openvpn_io::io_context &io_context_arg, const Config::Ptr &config_arg, const L &listen_item_or_list, const Client::Factory::Ptr &client_factory_arg)
Definition httpserv.hpp:777
WS::HTTPBase< Client, Config, Status, HTTP::RequestType, ContentInfo, content_len_t, OPENVPN_HTTP_SERV_RC > Base
Definition httpserv.hpp:181
void queue_accept(const size_t acceptor_index)
Definition httpserv.hpp:944
Client::Factory::Ptr client_factory
void queue_accept_throttled(const size_t acceptor_index, const bool debit_one)
Definition httpserv.hpp:949
static IP::Addr server_local_addr(const LISTEN_ITEM &listen_item, const GatewayType gw_type)
Definition httpvpn.hpp:81
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_HTTP_SERV_RC
Definition httpserv.hpp:70
#define OPENVPN_LOG(args)
const char * to_string(const int status)
Definition status.hpp:34
unsigned short parse_port(const std::string &port, const std::string &title)
Definition hostport.hpp:46
unsigned int client_t
Definition httpserv.hpp:77
std::int64_t content_len_t
Definition httpserv.hpp:78
constexpr std::size_t array_size(T(&)[N])
Definition arraysize.hpp:19
std::string date_time_rfc822()
Definition timestr.hpp:185
RCPtr< BufferAllocatedRc > BufferPtr
Definition buffer.hpp:1859
@ GROW
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
Definition buffer.hpp:872
std::string get_value_trim(const std::string &key) const
Definition header.hpp:84
unsigned int tcp_throttle_max_connections_per_period
Definition httpserv.hpp:140
SSLFactoryAPI::Ptr ssl_factory
Definition httpserv.hpp:132
content_len_t max_content_bytes
Definition httpserv.hpp:146
unsigned int send_queue_max_size
Definition httpserv.hpp:148
unsigned int free_list_max_size
Definition httpserv.hpp:149
Time::Duration tcp_throttle_period
Definition httpserv.hpp:141
SessionStats::Ptr stats
Definition httpserv.hpp:154
unsigned int msg_overhead_bytes
Definition httpserv.hpp:147
std::vector< std::string > extra_headers
Definition httpserv.hpp:171
WebSocket::Server::PerRequest::Ptr websocket
Definition httpserv.hpp:172
static constexpr content_len_t CHUNKED
Definition httpserv.hpp:160
virtual Client::Ptr new_client(Initializer &ci)=0
static std::string error_str(const size_t status)
Definition httpserv.hpp:102
proxy_host_port port