1 #ifndef LIBFILEZILLA_SOCKET_HEADER
2 #define LIBFILEZILLA_SOCKET_HEADER
3
4 /** \file
5 * \brief Socket classes for networking
6 *
7 * Declares the \ref fz::socket and \ref fz::listen_socket classes,
8 * alongside supporting classes to handle socket events.
9 */
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
20 /// \private
21 struct sockaddr;
22
23 namespace fz {
24 class thread_pool;
25
26 /** \brief The type of a socket event
27 *
28 * In received events, exactly a single bit is always set.
29 *
30 * Flag combinations are used when changing event handlers,
31 * \sa f::socket::set_event_handler
32 */
33 enum class socket_event_flag
34 {
35 /**
36 * Sent if connection attempt has failed, but there are still
37 * additional addresses to try.
38 * Errors can be ignored for this type.
39 */
40 connection_next = 0x1,
41
42 /**
43 * If no error is set, the connection has been established.
44 * If an error is set, the connection could not be established.
45 */
46 connection = 0x2,
47
48 /**
49 * If no error is set, data has become available.
50 * If an error is set, the connection has failed.
51 */
52 read = 0x4,
53
54 /**
55 * If no error is set, data can be written.
56 * If an error is set, the connection has failed.
57 */
58 write = 0x8,
59 };
60
operator &(socket_event_flag lhs,socket_event_flag rhs)61 inline bool operator&(socket_event_flag lhs, socket_event_flag rhs) {
62 return (static_cast<std::underlying_type_t<socket_event_flag>>(lhs) & static_cast<std::underlying_type_t<socket_event_flag>>(rhs)) != 0;
63 }
operator |(socket_event_flag lhs,socket_event_flag rhs)64 inline socket_event_flag operator|(socket_event_flag lhs, socket_event_flag rhs)
65 {
66 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));
67 }
operator |=(socket_event_flag & lhs,socket_event_flag rhs)68 inline socket_event_flag& operator|=(socket_event_flag& lhs, socket_event_flag rhs)
69 {
70 lhs = lhs | rhs;
71 return lhs;
72 }
73
74
75 /**
76 * \brief All classes sending socket events should derive from this.
77 *
78 * Allows implementing socket layers, e.g. for TLS.
79 *
80 * \sa fz::RemoveSocketEvents
81 * \sa fz::ChangeSocketEventHandler
82 */
83 class FZ_PUBLIC_SYMBOL socket_event_source
84 {
85 public:
86 virtual ~socket_event_source() = default;
87
88 /** \brief Gets the root source
89 *
90 * In a layered stack of sources this would be the socket itself.
91 */
root() const92 socket_event_source* root() const {
93 return root_;
94 }
95
96 protected:
97 socket_event_source() = delete;
socket_event_source(socket_event_source * root)98 explicit socket_event_source(socket_event_source* root)
99 : root_(root)
100 {}
101
102 socket_event_source* const root_{};
103 };
104
105 /// \private
106 struct socket_event_type;
107
108 /**
109 * All socket events are sent through this.
110 *
111 * \sa \ref fz::socket_event_flag
112 *
113 * If the error value is non-zero for the connection, read and write events,
114 * the socket has failed and needs to be closed. Doing anything else with
115 * failed sockets is undefined behavior.
116 * Failure events can be received at any time.
117 *
118 * Read and write events are edge-triggered:
119 * - After receiving a read event for a socket, it will not be sent again
120 * unless a subsequent call to socket_interface::read or
121 * socket_interface::shutdown_read has returned EAGAIN.
122 * - The same holds for the write event and socket_interface::write and
123 * socket_interface::shutdown
124 * - A successful connection events doubles as write event, it does not
125 * act as read event
126 *
127 * It is a grave violation to call the read/write/shutdown functions
128 * again after they returned EAGAIN without first waiting for the event.
129 */
130 typedef simple_event<socket_event_type, socket_event_source*, socket_event_flag, int> socket_event;
131
132 /// \private
133 struct hostaddress_event_type{};
134
135 /**
136 * Whenever a hostname has been resolved to an IP address, this event is sent with the resolved IP address literal.
137 */
138 typedef simple_event<hostaddress_event_type, socket_event_source*, std::string> hostaddress_event;
139
140 /**
141 * \brief Remove all pending socket events from source sent to handler.
142 *
143 * Useful e.g. if you want to destroy the handler but keep the source.
144 * This function is called, through change_socket_event_handler, by socket::set_event_handler(0)
145 */
146 void FZ_PUBLIC_SYMBOL remove_socket_events(event_handler * handler, socket_event_source const* const source);
147
148 /**
149 * \brief Changes all pending socket events from source
150 *
151 * If newHandler is null, remove_socket_events is called.
152 *
153 * This function is called by socket::set_event_handler().
154 *
155 * Example use-cases: Handoff after proxy handshakes, or handoff to TLS classes in case of STARTTLS mechanism
156 *
157 * Returns which events are still pending.
158 */
159 fz::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);
160
161 /// \private
162 class socket_thread;
163
164 /// Common base clase for fz::socket and fz::listen_socket
165 class FZ_PUBLIC_SYMBOL socket_base
166 {
167 public:
168 /**
169 * \brief Sets socket buffer sizes.
170 *
171 * Internally this sets SO_RCVBUF and SO_SNDBUF on the socket.
172 *
173 * If called on listen socket, sizes will be inherited by accepted sockets.
174 */
175 int set_buffer_sizes(int size_receive, int size_send);
176
177 /// If connected, either ipv4 or ipv6, unknown otherwise
178 address_type address_family() const;
179
180 /**
181 * \brief Returns local address of a connected socket
182 *
183 * \return empty string on error
184 */
185 std::string local_ip(bool strip_zone_index = false) const;
186
187 /**
188 * \brief Returns local port of a connected socket
189 *
190 * \return -1 on error
191 */
192 int local_port(int& error) const;
193
194 static std::string address_to_string(sockaddr const* addr, int addr_len, bool with_port = true, bool strip_zone_index = false);
195 static std::string address_to_string(char const* buf, int buf_len);
196
197 /**
198 * \brief Bind socket to the specific local IP
199 *
200 * Undefined after having called connect/listen
201 */
202 bool bind(std::string const& address);
203
204 #if FZ_WINDOWS
205 typedef intptr_t socket_t;
206 #else
207 typedef int socket_t;
208 #endif
209
210 protected:
211 friend class socket_thread;
212
213 socket_base(thread_pool& pool, event_handler* evt_handler, socket_event_source* ev_source);
214 virtual ~socket_base() = default;
215
216 int close();
217
218 // Note: Unlocks the lock.
219 void detach_thread(scoped_lock & l);
220
221 thread_pool & thread_pool_;
222 event_handler* evt_handler_;
223
224 socket_thread* socket_thread_{};
225
226 socket_event_source * const ev_source_{};
227
228 socket_t fd_{-1};
229
230 unsigned int port_{};
231
232 int family_;
233
234 int buffer_sizes_[2];
235 };
236
237 class socket;
238
239 enum class listen_socket_state
240 {
241 /// How the socket is initially
242 none,
243
244 /// Only in listening state you can get a connection event.
245 listening,
246 };
247
248 /// Lightweight holder for socket descriptors
249 class FZ_PUBLIC_SYMBOL socket_descriptor final
250 {
251 public:
252 socket_descriptor() = default;
253 ~socket_descriptor();
socket_descriptor(socket_base::socket_t fd)254 explicit socket_descriptor(socket_base::socket_t fd) noexcept : fd_(fd) {}
255
256 socket_descriptor(socket_descriptor const&) = delete;
257 socket_descriptor& operator=(socket_descriptor const&) = delete;
258
socket_descriptor(socket_descriptor && rhs)259 socket_descriptor(socket_descriptor && rhs) noexcept { std::swap(fd_, rhs.fd_); }
operator =(socket_descriptor && rhs)260 socket_descriptor& operator=(socket_descriptor && rhs) noexcept {
261 std::swap(fd_, rhs.fd_);
262 return *this;
263 }
264
detach()265 socket_base::socket_t detach() {
266 socket_base::socket_t ret = fd_;
267 fd_ = -1;
268 return ret;
269 }
270
operator bool() const271 explicit operator bool() const { return fd_ != -1; }
272
273 private:
274 socket_base::socket_t fd_{-1};
275 };
276
277 /**
278 * \brief Simple Listen socket
279 *
280 * When a client connects, a socket event with the connection flag is send.
281 *
282 * Call accept to accept.
283 */
284 class FZ_PUBLIC_SYMBOL listen_socket final : public socket_base, public socket_event_source
285 {
286 friend class socket_base;
287 friend class socket_thread;
288 public:
289 listen_socket(thread_pool& pool, event_handler* evt_handler);
290 virtual ~listen_socket();
291
292 listen_socket(listen_socket const&) = delete;
293 listen_socket& operator=(listen_socket const&) = delete;
294
295 /**
296 * \brief Starts listening
297 *
298 * If no port is given, let the operating system decide on a port. Can use local_port to query it afterwards.
299 *
300 * The address type, if not fz::address_type::unknown, must may the type of the address passed to bind()
301 */
302
303 int listen(address_type family, int port = 0);
304
305 /// Accepts incoming connection. If no socket is returned, error contains the reason
306 std::unique_ptr<socket> accept(int& error, fz::event_handler * handler = nullptr);
307
308 /**
309 * \brief Like accept, but only returns a socket descriptor.
310 *
311 * Best suited for tight accept loops where the descriptor is handed
312 * off to other threads.
313 */
314 socket_descriptor fast_accept(int& error);
315
316 listen_socket_state get_state() const;
317
318 void set_event_handler(event_handler* pEvtHandler);
319
320 private:
321 listen_socket_state state_{};
322 };
323
324
325 /// State transitions are monotonically increasing
326 enum class socket_state : unsigned char
327 {
328 /// How the socket is initially
329 none,
330
331 /// Only in connecting state you can get a connection event.
332 /// After sending the event, socket is in connected or failed state
333 /// depending whether error value is set in the event.
334 connecting,
335
336 /// Socket is in its normal working state. You can get send and receive events
337 connected,
338
339 /// Shutting down of the write side. Transitions to
340 /// shutdown with a single write event.
341 shutting_down,
342
343 /// Write side has finished shutting down. Receive still working normally.
344 shut_down,
345
346 /// Socket has been closed. Further events disabled.
347 closed,
348
349 /// Socket has failed. Further events disabled.
350 failed
351 };
352
353 /**
354 * \brief Interface for sockets
355 *
356 * Can be used for layers, see fz::socket for the expected semantics.
357 */
358 class FZ_PUBLIC_SYMBOL socket_interface : public socket_event_source
359 {
360 public:
361 socket_interface(socket_interface const&) = delete;
362 socket_interface& operator=(socket_interface const&) = delete;
363
364 virtual int read(void* buffer, unsigned int size, int& error) = 0;
365 virtual int write(void const* buffer, unsigned int size, int& error) = 0;
366
367 template<typename T, std::enable_if_t<std::is_signed_v<T>, int> = 0>
read(void * buffer,T size,int & error)368 int read(void* buffer, T size, int& error)
369 {
370 if (size < 0) {
371 error = EINVAL;
372 return -1;
373 }
374
375 return read(buffer, static_cast<unsigned int>(size), error);
376 }
377 template<typename T, std::enable_if_t<std::is_unsigned_v<T> && (sizeof(T) > sizeof(unsigned int)), int> = 0>
read(void * buffer,T size,int & error)378 int read(void* buffer, T size, int& error)
379 {
380 if (size > std::numeric_limits<unsigned int>::max()) {
381 size = std::numeric_limits<unsigned int>::max();
382 }
383 return read(buffer, static_cast<unsigned int>(size), error);
384 }
385
386 template<typename T, std::enable_if_t<std::is_signed_v<T>, int> = 0>
write(void const * buffer,T size,int & error)387 int write(void const* buffer, T size, int& error)
388 {
389 if (size < 0) {
390 error = EINVAL;
391 return -1;
392 }
393
394 return write(buffer, static_cast<std::make_unsigned_t<T>>(size), error);
395 }
396 template<typename T, std::enable_if_t<std::is_unsigned_v<T> && (sizeof(T) > sizeof(unsigned int)), int> = 0>
write(void const * buffer,T size,int & error)397 int write(void const* buffer, T size, int& error)
398 {
399 if (size > std::numeric_limits<unsigned int>::max()) {
400 size = std::numeric_limits<unsigned int>::max();
401 }
402 return write(buffer, static_cast<unsigned int>(size), error);
403 }
404
405 virtual void set_event_handler(event_handler* pEvtHandler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) = 0;
406
407 virtual native_string peer_host() const = 0;
408 virtual int peer_port(int& error) const = 0;
409
410 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) = 0;
411
412 virtual fz::socket_state get_state() const = 0;
413
414 /**
415 * \brief Signals peers that we want to close the connections.
416 *
417 * Only disallows further sends, does not affect reading from the
418 * socket.
419 *
420 * Returns 0 on success, an error code otherwise.
421 * If it returns EGAIN, shutdown is not yet complete. Call shutdown
422 * again after the next write event.
423 */
424 virtual int shutdown() = 0;
425
426 /// \see socket_layer::shutdown_read
427 virtual int shutdown_read() = 0;
428
429 protected:
430 socket_interface() = delete;
431
socket_interface(socket_event_source * root)432 explicit socket_interface(socket_event_source * root)
433 : socket_event_source(root)
434 {}
435 };
436
437 /**
438 * \brief IPv6 capable, non-blocking socket class
439 *
440 * Uses and edge-triggered socket events.
441 *
442 * Error codes are the same as used by the POSIX socket functions,
443 * see 'man 2 socket', 'man 2 connect', ...
444 */
445 class FZ_PUBLIC_SYMBOL socket final : public socket_base, public socket_interface
446 {
447 friend class socket_thread;
448 public:
449 socket(thread_pool& pool, event_handler* evt_handler);
450 virtual ~socket();
451
452 socket(socket const&) = delete;
453 socket& operator=(socket const&) = delete;
454
455 static std::unique_ptr<socket> from_descriptor(socket_descriptor && desc, thread_pool & pool, int & error, fz::event_handler * handler = nullptr);
456
457 socket_state get_state() const override;
is_connected() const458 bool is_connected() const {
459 socket_state s = get_state();
460 return s == socket_state::connected || s == socket_state::shutting_down || s == socket_state::shut_down;
461 };
462
463 /**
464 * \brief Starts connecting to the given host, given as name, IPv4 or IPv6 address.
465 *
466 * Returns 0 on success, else an error code.
467 *
468 * Success only means that the establishing of the connection
469 * has started. Once the connection gets fully established or
470 * establishment fails, a connection event gets sent, with the error
471 * parameter indicating success or failure.
472 *
473 * If host is a name that can be resolved, a hostaddress socket event gets
474 * sent during establishment.
475 */
476 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) override;
477
478 /**
479 * \brief Read data from socket
480 *
481 * Reads data from socket, returns the number of octets read or -1 on error.
482 *
483 * May return fewer octets than requested. Return of 0 bytes read indicates EOF.
484 *
485 * Can be called after having receiving a socket event with the read
486 * flag and can thenceforth be called until until it returns an error.
487 *
488 * If the error is EAGAIN, wait for the next read event. On other errors
489 * the socket has failed and should be closed.
490 *
491 * Takes care of EINTR internally.
492 */
493 virtual int read(void *buffer, unsigned int size, int& error) override;
494
495 /**
496 * \brief Write data to socket
497 *
498 * Writes data to the socket, returns the number of octets written or -1 on error.
499 *
500 * May return fewer octets than requested.
501 *
502 * Can be called after having receiving a socket event with the write
503 * flag and can thenceforth be called until until it returns an error.
504 *
505 * If the error is EAGAIN, wait for the next write event. On other errors
506 * the socket has failed and should be closed.
507 *
508 * Takes care of EINTR internally.
509 */
510 virtual int write(void const* buffer, unsigned int size, int& error) override;
511
512 /**
513 * \brief Returns remote address of a connected socket
514 *
515 * \return empty string on error
516 */
517 std::string peer_ip(bool strip_zone_index = false) const;
518
519 /// Returns the hostname passed to connect()
520 virtual native_string peer_host() const override;
521
522 /**
523 * \brief Returns remote port of a connected socket
524 *
525 * \return -1 on error
526 */
527 virtual int peer_port(int& error) const override;
528
529 /**
530 * On a connected socket, gets the ideal send buffer size or
531 * -1 if it cannot be determined.
532 *
533 * Currently only implemented for Windows.
534 */
535 int ideal_send_buffer_size();
536
537 virtual int shutdown() override;
538
539 /**
540 * \brief Changes the associated event handler.
541 *
542 * Pending events are rewritten to the new handler, or deleted if there is no new handler.
543 *
544 * Initially, the new handler is assumed to be waiting on read and write events and if the
545 * socket is in a readable/writable state, the corresponding events are sent if not already
546 * pending.
547 *
548 * As exception, events passed in retrigger_block are always removed and not resent if the socket
549 * is in the readable/writable state.
550 */
551 virtual void set_event_handler(event_handler* pEvtHandler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) override;
552
553 enum
554 {
555 /// flag_nodelay disables Nagle's algorithm
556 flag_nodelay = 0x01,
557
558 /// flag_keepalive enables TCP keepalive.
559 flag_keepalive = 0x02
560 };
561
flags() const562 int flags() const { return flags_; }
563
564 /// Enables or disabled the passed flags
565 void set_flags(int flags, bool enable);
566
567 /// Sets the entire mask of enabled flag, disabling all others
568 void set_flags(int flags);
569
570 /**
571 * Sets the interval between TCP keepalive packets.
572 *
573 * Duration must not be smaller than 5 minutes. The default interval is 2 hours.
574 */
575 void set_keepalive_interval(duration const& d);
576
shutdown_read()577 virtual int shutdown_read() override { return 0; }
578
579 private:
580 friend class socket_base;
581 friend class listen_socket;
582 native_string host_;
583
584 duration keepalive_interval_;
585
586 int flags_{};
587 socket_state state_{};
588 };
589
590 /**
591 * \brief A base class for socket layers.
592 *
593 * Can be used to implement layers, e.g. for TLS or rate-limiting.
594 *
595 * Layers can in general be added on top of the next layer in any state,
596 * though individual layers may post restrictions on this.
597 *
598 * Note instance lifetime, layers must be destroyed in reverse order.
599 *
600 * For safe closing of a layer hierarchy, both the write and read side
601 * should be shut down first, otherwise pending data might get discarded.
602 * The shutdown and shutdown_read functions may return EAGAIN, in which
603 * case they must be called again after the next write/read event.
604 */
605 class FZ_PUBLIC_SYMBOL socket_layer : public socket_interface
606 {
607 public:
608 explicit socket_layer(event_handler* handler, socket_interface& next_layer, bool event_passthrough);
609 virtual ~socket_layer();
610
611 socket_layer(socket_layer const&) = delete;
612 socket_layer& operator=(socket_layer const&) = delete;
613
614 /// The handler for any events generated (or forwarded) by this layer.
615 virtual void set_event_handler(event_handler* handler, fz::socket_event_flag retrigger_block = fz::socket_event_flag{}) override;
616
617 /**
618 * Can be overridden to return something different, e.g. a proxy layer
619 * would return the hostname of the peer connected to through the proxy,
620 * whereas the next layer would return the address of the proxy itself.
621 */
peer_host() const622 virtual native_string peer_host() const override { return next_layer_.peer_host(); }
623
624 /**
625 * Can be overridden to return something different, e.g. a proxy layer
626 * would return the post of the peer connected to through the proxy,
627 * whereas the next layer would return the port of the proxy itself.
628 */
peer_port(int & error) const629 virtual int peer_port(int& error) const override { return next_layer_.peer_port(error); }
630
631 /// The next layer further down. Usually another layer or the actual socket.
next()632 socket_interface& next() { return next_layer_; }
633
634 /**
635 * \brief Check that all layers further down also have reached EOF.
636 *
637 * Can only be called after read has returned 0, calling it earlier is undefined.
638 * shutdown_read should be called after eof to ensure all layers have reached EOF.
639 *
640 * \return 0 on success
641 * \return EAGAIN if the shutdown cannot be completed, wait for a read event and try again.
642 * \return otherwise an error has occurred.
643 *
644 * On an ordinary socket, this is a no-op. Some layers however may return an EOF before the
645 * next lower layer has reached its own EOF, such as the EOF of the secure channel from
646 * \ref fz::tls_layer.
647 *
648 * Closing the layer stack without all layers having reached EOF can lead to truncation on
649 * the write side: With a lower layer's EOF waiting in TCP's receive buffer and data pending
650 * in the send buffer, closing the socket is not graceful, it discards all pending data.
651 * Through shutdown_read you can assure that no pending data is left to receive, on this or
652 * any lower layer, so that closing the socket is done graceful ensuring delivery of all
653 * data in the send buffer (assuming there are no network errors).
654 */
655 virtual int shutdown_read() override;
656
connect(native_string const & host,unsigned int port,address_type family=address_type::unknown)657 virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) override {
658 return next_layer_.connect(host, port, family);
659 }
660
shutdown()661 virtual int shutdown() override {
662 return next_layer_.shutdown();
663 }
664
get_state() const665 virtual socket_state get_state() const override {
666 return next_layer_.get_state();
667 }
668
669 protected:
670 /**
671 * Call in a derived classes handler for fz::socket_event. Results in
672 * a call to operator()(fz::event_base const&) on the event handler passed
673 * to socket_layer.
674 */
675 void forward_socket_event(socket_event_source* source, socket_event_flag t, int error);
676
677 /**
678 * Call in a derived classes handler for fz::hostaddress_event. Results in
679 * a call to operator()(fz::event_base const&) on the event handler passed
680 * to socket_layer.
681 */
682 void forward_hostaddress_event(socket_event_source* source, std::string const& address);
683
684 /**
685 * A pass-through layer does not handle events itself. Instead any events sent by the next layer get
686 * sent to the event handler passed to the layer.
687 */
688 void set_event_passthrough(socket_event_flag retrigger_block = socket_event_flag{});
689
690 event_handler* event_handler_{};
691 socket_interface& next_layer_;
692 bool event_passthrough_{};
693 };
694
695 /**
696 * \brief Gets a symbolic name for socket errors.
697 *
698 * For example, <tt>error_string(EAGAIN) == "EAGAIN"</tt>
699 *
700 * \return name if the error code is known
701 * \return number as string if the error code is not known
702 */
703 std::string FZ_PUBLIC_SYMBOL socket_error_string(int error);
704
705 /**
706 * \brief Gets a human-readable, translated description of the error
707 */
708 native_string FZ_PUBLIC_SYMBOL socket_error_description(int error);
709
710
711 #ifdef FZ_WINDOWS
712
713 #ifndef EISCONN
714 #define EISCONN WSAEISCONN
715 #endif
716 #ifndef EINPROGRESS
717 #define EINPROGRESS WSAEINPROGRESS
718 #endif
719 #ifndef EAFNOSUPPORT
720 #define EAFNOSUPPORT WSAEAFNOSUPPORT
721 #endif
722 #ifndef EADDRINUSE
723 #define EADDRINUSE WSAEADDRINUSE
724 #endif
725 #ifndef ENOBUFS
726 #define ENOBUFS WSAENOBUFS
727 #endif
728 #ifndef EPROTONOSUPPORT
729 #define EPROTONOSUPPORT WSAEPROTONOSUPPORT
730 #endif
731 #ifndef EALREADY
732 #define EALREADY WSAEALREADY
733 #endif
734 #ifndef ECONNREFUSED
735 #define ECONNREFUSED WSAECONNREFUSED
736 #endif
737 #ifndef ENOTSOCK
738 #define ENOTSOCK WSAENOTSOCK
739 #endif
740 #ifndef ETIMEDOUT
741 #define ETIMEDOUT WSAETIMEDOUT
742 #endif
743 #ifndef ENETUNREACH
744 #define ENETUNREACH WSAENETUNREACH
745 #endif
746 #ifndef EHOSTUNREACH
747 #define EHOSTUNREACH WSAEHOSTUNREACH
748 #endif
749 #ifndef ENOTCONN
750 #define ENOTCONN WSAENOTCONN
751 #endif
752 #ifndef ENETRESET
753 #define ENETRESET WSAENETRESET
754 #endif
755 #ifndef EOPNOTSUPP
756 #define EOPNOTSUPP WSAEOPNOTSUPP
757 #endif
758 #ifndef ESHUTDOWN
759 #define ESHUTDOWN WSAESHUTDOWN
760 #endif
761 #ifndef EMSGSIZE
762 #define EMSGSIZE WSAEMSGSIZE
763 #endif
764 #ifndef ECONNABORTED
765 #define ECONNABORTED WSAECONNABORTED
766 #endif
767 #ifndef ECONNRESET
768 #define ECONNRESET WSAECONNRESET
769 #endif
770 #ifndef EHOSTDOWN
771 #define EHOSTDOWN WSAEHOSTDOWN
772 #endif
773
774 // For the future:
775 // Handle ERROR_NETNAME_DELETED=64
776 #endif //FZ_WINDOWS
777
778 }
779
780 #endif
781