libfilezilla
Loading...
Searching...
No Matches
socket.hpp
Go to the documentation of this file.
1#ifndef LIBFILEZILLA_SOCKET_HEADER
2#define LIBFILEZILLA_SOCKET_HEADER
3
10
11#include "libfilezilla.hpp"
12
13#include "event_handler.hpp"
14#include "iputils.hpp"
15
16#include <memory>
17
18#include <errno.h>
19
21struct sockaddr;
22
23namespace fz {
24class buffer;
25class thread_pool;
26
35{
42
48
53 read = 0x4,
54
59 write = 0x8,
60};
61
62inline bool operator&(socket_event_flag lhs, socket_event_flag rhs) {
63 return (static_cast<std::underlying_type_t<socket_event_flag>>(lhs) & static_cast<std::underlying_type_t<socket_event_flag>>(rhs)) != 0;
64}
66{
67 return static_cast<socket_event_flag>(static_cast<std::underlying_type_t<socket_event_flag>>(lhs) | static_cast<std::underlying_type_t<socket_event_flag>>(rhs));
68}
69inline socket_event_flag& operator|=(socket_event_flag& lhs, socket_event_flag rhs)
70{
71 lhs = lhs | rhs;
72 return lhs;
73}
74
75
84class FZ_PUBLIC_SYMBOL socket_event_source
85{
86public:
87 virtual ~socket_event_source() = default;
88
93 socket_event_source* root() const {
94 return root_;
95 }
96
97protected:
98 socket_event_source() = delete;
100 : root_(root)
101 {}
102
103 socket_event_source* const root_{};
104};
105
107struct socket_event_type;
108
132
134struct hostaddress_event_type{};
135
140
147void FZ_PUBLIC_SYMBOL remove_socket_events(event_handler * handler, socket_event_source const* const source);
148
160fz::socket_event_flag FZ_PUBLIC_SYMBOL change_socket_event_handler(event_handler * old_handler, event_handler * new_handler, socket_event_source const* const source, fz::socket_event_flag remove);
161
163class socket_thread;
164
166class FZ_PUBLIC_SYMBOL socket_base
167{
168public:
176 int set_buffer_sizes(int size_receive, int size_send);
177
179 address_type address_family() const;
180
186 std::string local_ip(bool strip_zone_index = false) const;
187
193 int local_port(int& error) const;
194
195 static std::string address_to_string(sockaddr const* addr, int addr_len, bool with_port = true, bool strip_zone_index = false);
196 static std::string address_to_string(char const* buf, int buf_len);
197
203 bool bind(std::string const& address);
204
205#if FZ_WINDOWS
206 typedef intptr_t socket_t;
207#else
208 typedef int socket_t;
209#endif
210
211 int close();
212
213protected:
214 friend class socket_thread;
215
216 socket_base(thread_pool& pool, event_handler* evt_handler, socket_event_source* ev_source);
217 virtual ~socket_base() = default;
218
219 // Note: Unlocks the lock.
220 void detach_thread(scoped_lock & l);
221
222 thread_pool & thread_pool_;
223 event_handler* evt_handler_;
224
225 socket_thread* socket_thread_{};
226
227 socket_event_source * const ev_source_{};
228
229 socket_t fd_{-1};
230
231 unsigned int port_{};
232
233 int family_;
234
235 int buffer_sizes_[2];
236};
237
238class socket;
239
241{
243 none,
244
247};
248
250class FZ_PUBLIC_SYMBOL socket_descriptor final
251{
252public:
253 socket_descriptor() = default;
254 ~socket_descriptor();
255 explicit socket_descriptor(socket_base::socket_t fd) noexcept : fd_(fd) {}
256
257 socket_descriptor(socket_descriptor const&) = delete;
258 socket_descriptor& operator=(socket_descriptor const&) = delete;
259
260 socket_descriptor(socket_descriptor && rhs) noexcept { std::swap(fd_, rhs.fd_); }
261 socket_descriptor& operator=(socket_descriptor && rhs) noexcept {
262 std::swap(fd_, rhs.fd_);
263 return *this;
264 }
265
266 socket_base::socket_t detach() {
267 socket_base::socket_t ret = fd_;
268 fd_ = -1;
269 return ret;
270 }
271
272 explicit operator bool() const { return fd_ != -1; }
273
279 std::string peer_ip(bool strip_zone_index = false) const;
280
286 int peer_port(int& error) const;
287
288private:
289 socket_base::socket_t fd_{-1};
290};
291
299class FZ_PUBLIC_SYMBOL listen_socket final : public socket_base, public socket_event_source
300{
301 friend class socket_base;
302 friend class socket_thread;
303public:
304 listen_socket(thread_pool& pool, event_handler* evt_handler);
305 virtual ~listen_socket();
306
307 listen_socket(listen_socket const&) = delete;
308 listen_socket& operator=(listen_socket const&) = delete;
309
310 static std::unique_ptr<listen_socket> from_descriptor(socket_descriptor && desc, thread_pool & pool, int & error, fz::event_handler * handler = nullptr);
311
319 int listen(address_type family, int port = 0);
320
322 std::unique_ptr<socket> accept(int& error, fz::event_handler * handler = nullptr);
323
331
332 listen_socket_state get_state() const;
333
334 void set_event_handler(event_handler* pEvtHandler);
335
336private:
337 listen_socket_state state_{};
338};
339
340
342enum class socket_state : unsigned char
343{
345 none,
346
351
354
358
361
364
367};
368
374class FZ_PUBLIC_SYMBOL socket_interface : public socket_event_source
375{
376public:
377 socket_interface(socket_interface const&) = delete;
378 socket_interface& operator=(socket_interface const&) = delete;
379
380 virtual int read(void* buffer, unsigned int size, int& error) = 0;
381 virtual int write(void const* buffer, unsigned int size, int& error) = 0;
382
383 template<typename T, std::enable_if_t<std::is_signed_v<T>, int> = 0>
384 int read(void* buffer, T size, int& error)
385 {
386 if (size < 0) {
387 error = EINVAL;
388 return -1;
389 }
390
391 return read(buffer, static_cast<unsigned int>(size), error);
392 }
393 template<typename T, std::enable_if_t<std::is_unsigned_v<T> && (sizeof(T) > sizeof(unsigned int)), int> = 0>
394 int read(void* buffer, T size, int& error)
395 {
396 if (size > std::numeric_limits<unsigned int>::max()) {
397 size = std::numeric_limits<unsigned int>::max();
398 }
399 return read(buffer, static_cast<unsigned int>(size), error);
400 }
401
402 template<typename T, std::enable_if_t<std::is_signed_v<T>, int> = 0>
403 int write(void const* buffer, T size, int& error)
404 {
405 if (size < 0) {
406 error = EINVAL;
407 return -1;
408 }
409
410 return write(buffer, static_cast<std::make_unsigned_t<T>>(size), error);
411 }
412 template<typename T, std::enable_if_t<std::is_unsigned_v<T> && (sizeof(T) > sizeof(unsigned int)), int> = 0>
413 int write(void const* buffer, T size, int& error)
414 {
415 if (size > std::numeric_limits<unsigned int>::max()) {
416 size = std::numeric_limits<unsigned int>::max();
417 }
418 return write(buffer, static_cast<unsigned int>(size), error);
419 }
420
421 virtual void set_event_handler(event_handler* pEvtHandler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) = 0;
422
423 virtual native_string peer_host() const = 0;
424 virtual int peer_port(int& error) const = 0;
425
426 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) = 0;
427
428 virtual fz::socket_state get_state() const = 0;
429
440 virtual int shutdown() = 0;
441
443 virtual int shutdown_read() = 0;
444
445protected:
446 socket_interface() = delete;
447
448 explicit socket_interface(socket_event_source * root)
449 : socket_event_source(root)
450 {}
451};
452
461class FZ_PUBLIC_SYMBOL socket final : public socket_base, public socket_interface
462{
463 friend class socket_thread;
464public:
465 socket(thread_pool& pool, event_handler* evt_handler);
466 virtual ~socket();
467
468 socket(socket const&) = delete;
469 socket& operator=(socket const&) = delete;
470
471 static std::unique_ptr<socket> from_descriptor(socket_descriptor && desc, thread_pool & pool, int & error, fz::event_handler * handler = nullptr);
472
473 socket_state get_state() const override;
474 bool is_connected() const {
475 socket_state s = get_state();
477 };
478
492 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) override;
493
509 virtual int read(void *buffer, unsigned int size, int& error) override;
510
526 virtual int write(void const* buffer, unsigned int size, int& error) override;
527
533 std::string peer_ip(bool strip_zone_index = false) const;
534
536 virtual native_string peer_host() const override;
537
543 virtual int peer_port(int& error) const override;
544
552
553 virtual int shutdown() override;
554
567 virtual void set_event_handler(event_handler* pEvtHandler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) override;
568
569 enum
570 {
573
576
579 };
580
581 int flags() const { return flags_; }
582
584 void set_flags(int flags, bool enable);
585
587 void set_flags(int flags);
588
595
596 virtual int shutdown_read() override { return 0; }
597
598 socket_t get_descriptor();
599
600 std::optional<duration> srtt();
601
602#ifndef FZ_WINDOWS
618 int send_fd(fz::buffer & buf, int fd, int & error);
619
629 int read_fd(fz::buffer & buf, int &fd, int & error);
630#endif
631
632private:
633 friend class socket_base;
634 friend class listen_socket;
635 native_string host_;
636
637 duration keepalive_interval_;
638
639 int flags_{};
640 socket_state state_{};
641};
642
658class FZ_PUBLIC_SYMBOL socket_layer : public socket_interface
659{
660public:
661 explicit socket_layer(event_handler* handler, socket_interface& next_layer, bool event_passthrough);
662 virtual ~socket_layer();
663
664 socket_layer(socket_layer const&) = delete;
665 socket_layer& operator=(socket_layer const&) = delete;
666
668 virtual void set_event_handler(event_handler* handler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) override;
669
675 virtual native_string peer_host() const override { return next_layer_.peer_host(); }
676
682 virtual int peer_port(int& error) const override { return next_layer_.peer_port(error); }
683
685 socket_interface& next() { return next_layer_; }
686
708 virtual int shutdown_read() override;
709
710 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) override {
711 return next_layer_.connect(host, port, family);
712 }
713
714 virtual int shutdown() override {
715 return next_layer_.shutdown();
716 }
717
718 virtual socket_state get_state() const override {
719 return next_layer_.get_state();
720 }
721
722protected:
729
735 void forward_hostaddress_event(socket_event_source* source, std::string const& address);
736
742
743 event_handler* event_handler_{};
744 socket_interface& next_layer_;
745 bool event_passthrough_{};
746};
747
756std::string FZ_PUBLIC_SYMBOL socket_error_string(int error);
757
761native_string FZ_PUBLIC_SYMBOL socket_error_description(int error);
762
774std::optional<std::pair<std::unique_ptr<fz::socket>, std::unique_ptr<fz::socket>>> FZ_PUBLIC_SYMBOL create_tcp_socketpair(fz::thread_pool & pool);
775
776
777#ifdef FZ_WINDOWS
778
780class FZ_PRIVATE_SYMBOL winsock_initializer final
781{
782public:
783 winsock_initializer();
784 ~winsock_initializer();
785
786private:
787 bool initialized_{};
788};
789
790#ifndef EISCONN
791#define EISCONN WSAEISCONN
792#endif
793#ifndef EINPROGRESS
794#define EINPROGRESS WSAEINPROGRESS
795#endif
796#ifndef EAFNOSUPPORT
797#define EAFNOSUPPORT WSAEAFNOSUPPORT
798#endif
799#ifndef EADDRINUSE
800#define EADDRINUSE WSAEADDRINUSE
801#endif
802#ifndef ENOBUFS
803#define ENOBUFS WSAENOBUFS
804#endif
805#ifndef EPROTONOSUPPORT
806#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
807#endif
808#ifndef EALREADY
809#define EALREADY WSAEALREADY
810#endif
811#ifndef ECONNREFUSED
812#define ECONNREFUSED WSAECONNREFUSED
813#endif
814#ifndef ENOTSOCK
815#define ENOTSOCK WSAENOTSOCK
816#endif
817#ifndef ETIMEDOUT
818#define ETIMEDOUT WSAETIMEDOUT
819#endif
820#ifndef ENETUNREACH
821#define ENETUNREACH WSAENETUNREACH
822#endif
823#ifndef EHOSTUNREACH
824#define EHOSTUNREACH WSAEHOSTUNREACH
825#endif
826#ifndef ENOTCONN
827#define ENOTCONN WSAENOTCONN
828#endif
829#ifndef ENETRESET
830#define ENETRESET WSAENETRESET
831#endif
832#ifndef EOPNOTSUPP
833#define EOPNOTSUPP WSAEOPNOTSUPP
834#endif
835#ifndef ESHUTDOWN
836#define ESHUTDOWN WSAESHUTDOWN
837#endif
838#ifndef EMSGSIZE
839#define EMSGSIZE WSAEMSGSIZE
840#endif
841#ifndef ECONNABORTED
842#define ECONNABORTED WSAECONNABORTED
843#endif
844#ifndef ECONNRESET
845#define ECONNRESET WSAECONNRESET
846#endif
847#ifndef EHOSTDOWN
848#define EHOSTDOWN WSAEHOSTDOWN
849#endif
850#ifndef ESOCKTNOSUPPORT
851#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
852#endif
853#ifndef EADDRNOTAVAIL
854#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
855#endif
856
857// For the future:
858// Handle ERROR_NETNAME_DELETED=64
859#endif //FZ_WINDOWS
860
861}
862
863#endif
Definition buffer.hpp:360
The duration class represents a time interval in milliseconds.
Definition time.hpp:298
Definition event_handler.hpp:63
Simple Listen socket.
Definition socket.hpp:300
socket_descriptor fast_accept(int &error)
Like accept, but only returns a socket descriptor.
int listen(address_type family, int port=0)
Starts listening.
std::unique_ptr< socket > accept(int &error, fz::event_handler *handler=nullptr)
Accepts incoming connection. If no socket is returned, error contains the reason.
A simple scoped lock.
Definition mutex.hpp:117
This is the recommended event class.
Definition event.hpp:68
Common base clase for fz::socket and fz::listen_socket.
Definition socket.hpp:167
std::string local_ip(bool strip_zone_index=false) const
Returns local address of a connected socket.
int set_buffer_sizes(int size_receive, int size_send)
Sets socket buffer sizes.
address_type address_family() const
If connected, either ipv4, ipv6 or unix, unknown otherwise.
bool bind(std::string const &address)
Bind socket to the specific local IP.
int local_port(int &error) const
Returns local port of a connected socket.
Lightweight holder for socket descriptors.
Definition socket.hpp:251
std::string peer_ip(bool strip_zone_index=false) const
Returns remote address of a connected socket.
int peer_port(int &error) const
Returns remote port of a connected socket.
All classes sending socket events should derive from this.
Definition socket.hpp:85
socket_event_source * root() const
Gets the root source.
Definition socket.hpp:93
virtual int shutdown()=0
Signals peers that we want to close the connections.
virtual int shutdown_read()=0
void set_event_passthrough(socket_event_flag retrigger_block=socket_event_flag{})
virtual native_string peer_host() const override
Definition socket.hpp:675
void forward_hostaddress_event(socket_event_source *source, std::string const &address)
virtual int shutdown() override
Signals peers that we want to close the connections.
Definition socket.hpp:714
void forward_socket_event(socket_event_source *source, socket_event_flag t, int error)
virtual void set_event_handler(event_handler *handler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{}) override
The handler for any events generated (or forwarded) by this layer.
virtual int peer_port(int &error) const override
Definition socket.hpp:682
virtual int shutdown_read() override
Check that all layers further down also have reached EOF.
socket_interface & next()
The next layer further down. Usually another layer or the actual socket.
Definition socket.hpp:685
IPv6 capable, non-blocking socket class.
Definition socket.hpp:462
virtual native_string peer_host() const override
Returns the hostname passed to connect().
void set_flags(int flags, bool enable)
Enables or disabled the passed flags.
virtual int shutdown() override
Signals peers that we want to close the connections.
virtual int connect(native_string const &host, unsigned int port, address_type family=address_type::unknown) override
Starts connecting to the given host, given as name, IPv4 or IPv6 address.
virtual void set_event_handler(event_handler *pEvtHandler, fz::socket_event_flag retrigger_block=fz::socket_event_flag{}) override
Changes the associated event handler.
std::string peer_ip(bool strip_zone_index=false) const
Returns remote address of a connected socket.
void set_flags(int flags)
Sets the entire mask of enabled flag, disabling all others.
virtual int write(void const *buffer, unsigned int size, int &error) override
Write data to socket.
@ flag_keepalive
flag_keepalive enables TCP keepalive.
Definition socket.hpp:575
@ flag_nodelay
flag_nodelay disables Nagle's algorithm
Definition socket.hpp:572
@ flag_oobinline
Inline delivery of OOB data.
Definition socket.hpp:578
virtual int peer_port(int &error) const override
Returns remote port of a connected socket.
virtual int read(void *buffer, unsigned int size, int &error) override
Read data from socket.
int ideal_send_buffer_size()
void set_keepalive_interval(duration const &d)
virtual int shutdown_read() override
Definition socket.hpp:596
A dumb thread-pool for asynchronous tasks.
Definition thread_pool.hpp:64
Declares the event_handler class.
Various functions to deal with IP address strings.
Sets some global macros and further includes string.hpp.
The namespace used by libfilezilla.
Definition apply.hpp:17
fz::socket_event_flag change_socket_event_handler(event_handler *old_handler, event_handler *new_handler, socket_event_source const *const source, fz::socket_event_flag remove)
Changes all pending socket events from source.
listen_socket_state
Definition socket.hpp:241
@ listening
Only in listening state you can get a connection event.
Definition socket.hpp:246
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition string.hpp:69
simple_event< hostaddress_event_type, socket_event_source *, std::string > hostaddress_event
Definition socket.hpp:139
socket_state
State transitions are monotonically increasing.
Definition socket.hpp:343
@ connected
Socket is in its normal working state. You can get send and receive events.
Definition socket.hpp:353
@ shut_down
Write side has finished shutting down. Receive still working normally.
Definition socket.hpp:360
@ failed
Socket has failed. Further events disabled.
Definition socket.hpp:366
@ closed
Socket has been closed. Further events disabled.
Definition socket.hpp:363
@ shutting_down
Definition socket.hpp:357
@ connecting
Definition socket.hpp:350
std::string socket_error_string(int error)
Gets a symbolic name for socket errors.
simple_event< socket_event_type, socket_event_source *, socket_event_flag, int > socket_event
Definition socket.hpp:131
void remove_socket_events(event_handler *handler, socket_event_source const *const source)
Remove all pending socket events from source sent to handler.
native_string socket_error_description(int error)
Gets a human-readable, translated description of the error.
@ read
Data has become available.
Definition process.hpp:29
@ write
data can be written.
Definition process.hpp:32
socket_event_flag
The type of a socket event.
Definition socket.hpp:35
@ connection
Definition socket.hpp:47
@ connection_next
Definition socket.hpp:41
std::optional< std::pair< std::unique_ptr< fz::socket >, std::unique_ptr< fz::socket > > > create_tcp_socketpair(fz::thread_pool &pool)
Creates a pair of connected TCP sockets.