Add evb change callback to SSL Socket
[folly.git] / folly / io / async / AsyncSocket.h
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <folly/Optional.h>
20 #include <folly/SocketAddress.h>
21 #include <folly/detail/SocketFastOpen.h>
22 #include <folly/io/IOBuf.h>
23 #include <folly/io/ShutdownSocketSet.h>
24 #include <folly/io/async/AsyncSocketException.h>
25 #include <folly/io/async/AsyncTimeout.h>
26 #include <folly/io/async/AsyncTransport.h>
27 #include <folly/io/async/DelayedDestruction.h>
28 #include <folly/io/async/EventHandler.h>
29 #include <folly/portability/Sockets.h>
30
31 #include <sys/types.h>
32
33 #include <chrono>
34 #include <memory>
35 #include <map>
36
37 namespace folly {
38
39 /**
40  * A class for performing asynchronous I/O on a socket.
41  *
42  * AsyncSocket allows users to asynchronously wait for data on a socket, and
43  * to asynchronously send data.
44  *
45  * The APIs for reading and writing are intentionally asymmetric.  Waiting for
46  * data to read is a persistent API: a callback is installed, and is notified
47  * whenever new data is available.  It continues to be notified of new events
48  * until it is uninstalled.
49  *
50  * AsyncSocket does not provide read timeout functionality, because it
51  * typically cannot determine when the timeout should be active.  Generally, a
52  * timeout should only be enabled when processing is blocked waiting on data
53  * from the remote endpoint.  For server sockets, the timeout should not be
54  * active if the server is currently processing one or more outstanding
55  * requests for this socket.  For client sockets, the timeout should not be
56  * active if there are no requests pending on the socket.  Additionally, if a
57  * client has multiple pending requests, it will ususally want a separate
58  * timeout for each request, rather than a single read timeout.
59  *
60  * The write API is fairly intuitive: a user can request to send a block of
61  * data, and a callback will be informed once the entire block has been
62  * transferred to the kernel, or on error.  AsyncSocket does provide a send
63  * timeout, since most callers want to give up if the remote end stops
64  * responding and no further progress can be made sending the data.
65  */
66
67 #ifdef _MSC_VER
68 // We do a dynamic_cast on this, in
69 // AsyncTransportWrapper::getUnderlyingTransport so be safe and
70 // force displacements for it. See:
71 // https://msdn.microsoft.com/en-us/library/7sf3txa8.aspx
72 #pragma vtordisp(push, 2)
73 #endif
74 class AsyncSocket : virtual public AsyncTransportWrapper {
75  public:
76   typedef std::unique_ptr<AsyncSocket, Destructor> UniquePtr;
77
78   class ConnectCallback {
79    public:
80     virtual ~ConnectCallback() = default;
81
82     /**
83      * connectSuccess() will be invoked when the connection has been
84      * successfully established.
85      */
86     virtual void connectSuccess() noexcept = 0;
87
88     /**
89      * connectErr() will be invoked if the connection attempt fails.
90      *
91      * @param ex        An exception describing the error that occurred.
92      */
93     virtual void connectErr(const AsyncSocketException& ex)
94       noexcept = 0;
95   };
96
97   class EvbChangeCallback {
98    public:
99     virtual ~EvbChangeCallback() = default;
100
101     // Called when the socket has been attached to a new EVB
102     // and is called from within that EVB thread
103     virtual void evbAttached(AsyncSocket* socket) = 0;
104
105     // Called when the socket is detached from an EVB and
106     // is called from the EVB thread being detached
107     virtual void evbDetached(AsyncSocket* socket) = 0;
108   };
109
110   explicit AsyncSocket();
111   /**
112    * Create a new unconnected AsyncSocket.
113    *
114    * connect() must later be called on this socket to establish a connection.
115    */
116   explicit AsyncSocket(EventBase* evb);
117
118   void setShutdownSocketSet(ShutdownSocketSet* ss);
119
120   /**
121    * Create a new AsyncSocket and begin the connection process.
122    *
123    * @param evb             EventBase that will manage this socket.
124    * @param address         The address to connect to.
125    * @param connectTimeout  Optional timeout in milliseconds for the connection
126    *                        attempt.
127    */
128   AsyncSocket(EventBase* evb,
129                const folly::SocketAddress& address,
130                uint32_t connectTimeout = 0);
131
132   /**
133    * Create a new AsyncSocket and begin the connection process.
134    *
135    * @param evb             EventBase that will manage this socket.
136    * @param ip              IP address to connect to (dotted-quad).
137    * @param port            Destination port in host byte order.
138    * @param connectTimeout  Optional timeout in milliseconds for the connection
139    *                        attempt.
140    */
141   AsyncSocket(EventBase* evb,
142                const std::string& ip,
143                uint16_t port,
144                uint32_t connectTimeout = 0);
145
146   /**
147    * Create a AsyncSocket from an already connected socket file descriptor.
148    *
149    * Note that while AsyncSocket enables TCP_NODELAY for sockets it creates
150    * when connecting, it does not change the socket options when given an
151    * existing file descriptor.  If callers want TCP_NODELAY enabled when using
152    * this version of the constructor, they need to explicitly call
153    * setNoDelay(true) after the constructor returns.
154    *
155    * @param evb EventBase that will manage this socket.
156    * @param fd  File descriptor to take over (should be a connected socket).
157    */
158   AsyncSocket(EventBase* evb, int fd);
159
160   /**
161    * Helper function to create a shared_ptr<AsyncSocket>.
162    *
163    * This passes in the correct destructor object, since AsyncSocket's
164    * destructor is protected and cannot be invoked directly.
165    */
166   static std::shared_ptr<AsyncSocket> newSocket(EventBase* evb) {
167     return std::shared_ptr<AsyncSocket>(new AsyncSocket(evb),
168                                            Destructor());
169   }
170
171   /**
172    * Helper function to create a shared_ptr<AsyncSocket>.
173    */
174   static std::shared_ptr<AsyncSocket> newSocket(
175       EventBase* evb,
176       const folly::SocketAddress& address,
177       uint32_t connectTimeout = 0) {
178     return std::shared_ptr<AsyncSocket>(
179         new AsyncSocket(evb, address, connectTimeout),
180         Destructor());
181   }
182
183   /**
184    * Helper function to create a shared_ptr<AsyncSocket>.
185    */
186   static std::shared_ptr<AsyncSocket> newSocket(
187       EventBase* evb,
188       const std::string& ip,
189       uint16_t port,
190       uint32_t connectTimeout = 0) {
191     return std::shared_ptr<AsyncSocket>(
192         new AsyncSocket(evb, ip, port, connectTimeout),
193         Destructor());
194   }
195
196   /**
197    * Helper function to create a shared_ptr<AsyncSocket>.
198    */
199   static std::shared_ptr<AsyncSocket> newSocket(EventBase* evb, int fd) {
200     return std::shared_ptr<AsyncSocket>(new AsyncSocket(evb, fd),
201                                            Destructor());
202   }
203
204   /**
205    * Destroy the socket.
206    *
207    * AsyncSocket::destroy() must be called to destroy the socket.
208    * The normal destructor is private, and should not be invoked directly.
209    * This prevents callers from deleting a AsyncSocket while it is invoking a
210    * callback.
211    */
212   virtual void destroy() override;
213
214   /**
215    * Get the EventBase used by this socket.
216    */
217   EventBase* getEventBase() const override {
218     return eventBase_;
219   }
220
221   /**
222    * Get the file descriptor used by the AsyncSocket.
223    */
224   virtual int getFd() const {
225     return fd_;
226   }
227
228   /**
229    * Extract the file descriptor from the AsyncSocket.
230    *
231    * This will immediately cause any installed callbacks to be invoked with an
232    * error.  The AsyncSocket may no longer be used after the file descriptor
233    * has been extracted.
234    *
235    * Returns the file descriptor.  The caller assumes ownership of the
236    * descriptor, and it will not be closed when the AsyncSocket is destroyed.
237    */
238   virtual int detachFd();
239
240   /**
241    * Uniquely identifies a handle to a socket option value. Each
242    * combination of level and option name corresponds to one socket
243    * option value.
244    */
245   class OptionKey {
246    public:
247     bool operator<(const OptionKey& other) const {
248       if (level == other.level) {
249         return optname < other.optname;
250       }
251       return level < other.level;
252     }
253     int apply(int fd, int val) const {
254       return setsockopt(fd, level, optname, &val, sizeof(val));
255     }
256     int level;
257     int optname;
258   };
259
260   // Maps from a socket option key to its value
261   typedef std::map<OptionKey, int> OptionMap;
262
263   static const OptionMap emptyOptionMap;
264   static const folly::SocketAddress& anyAddress();
265
266   /**
267    * Initiate a connection.
268    *
269    * @param callback  The callback to inform when the connection attempt
270    *                  completes.
271    * @param address   The address to connect to.
272    * @param timeout   A timeout value, in milliseconds.  If the connection
273    *                  does not succeed within this period,
274    *                  callback->connectError() will be invoked.
275    */
276   virtual void connect(
277       ConnectCallback* callback,
278       const folly::SocketAddress& address,
279       int timeout = 0,
280       const OptionMap& options = emptyOptionMap,
281       const folly::SocketAddress& bindAddr = anyAddress()) noexcept;
282
283   void connect(
284       ConnectCallback* callback,
285       const std::string& ip,
286       uint16_t port,
287       int timeout = 0,
288       const OptionMap& options = emptyOptionMap) noexcept;
289
290   /**
291    * If a connect request is in-flight, cancels it and closes the socket
292    * immediately. Otherwise, this is a no-op.
293    *
294    * This does not invoke any connection related callbacks. Call this to
295    * prevent any connect callback while cleaning up, etc.
296    */
297   void cancelConnect();
298
299   /**
300    * Set the send timeout.
301    *
302    * If write requests do not make any progress for more than the specified
303    * number of milliseconds, fail all pending writes and close the socket.
304    *
305    * If write requests are currently pending when setSendTimeout() is called,
306    * the timeout interval is immediately restarted using the new value.
307    *
308    * (See the comments for AsyncSocket for an explanation of why AsyncSocket
309    * provides setSendTimeout() but not setRecvTimeout().)
310    *
311    * @param milliseconds  The timeout duration, in milliseconds.  If 0, no
312    *                      timeout will be used.
313    */
314   void setSendTimeout(uint32_t milliseconds) override;
315
316   /**
317    * Get the send timeout.
318    *
319    * @return Returns the current send timeout, in milliseconds.  A return value
320    *         of 0 indicates that no timeout is set.
321    */
322   uint32_t getSendTimeout() const override {
323     return sendTimeout_;
324   }
325
326   /**
327    * Set the maximum number of reads to execute from the underlying
328    * socket each time the EventBase detects that new ingress data is
329    * available. The default is unlimited, but callers can use this method
330    * to limit the amount of data read from the socket per event loop
331    * iteration.
332    *
333    * @param maxReads  Maximum number of reads per data-available event;
334    *                  a value of zero means unlimited.
335    */
336   void setMaxReadsPerEvent(uint16_t maxReads) {
337     maxReadsPerEvent_ = maxReads;
338   }
339
340   /**
341    * Get the maximum number of reads this object will execute from
342    * the underlying socket each time the EventBase detects that new
343    * ingress data is available.
344    *
345    * @returns Maximum number of reads per data-available event; a value
346    *          of zero means unlimited.
347    */
348   uint16_t getMaxReadsPerEvent() const {
349     return maxReadsPerEvent_;
350   }
351
352   // Read and write methods
353   void setReadCB(ReadCallback* callback) override;
354   ReadCallback* getReadCallback() const override;
355
356   void write(WriteCallback* callback, const void* buf, size_t bytes,
357              WriteFlags flags = WriteFlags::NONE) override;
358   void writev(WriteCallback* callback, const iovec* vec, size_t count,
359               WriteFlags flags = WriteFlags::NONE) override;
360   void writeChain(WriteCallback* callback,
361                   std::unique_ptr<folly::IOBuf>&& buf,
362                   WriteFlags flags = WriteFlags::NONE) override;
363
364   class WriteRequest;
365   virtual void writeRequest(WriteRequest* req);
366   void writeRequestReady() {
367     handleWrite();
368   }
369
370   // Methods inherited from AsyncTransport
371   void close() override;
372   void closeNow() override;
373   void closeWithReset() override;
374   void shutdownWrite() override;
375   void shutdownWriteNow() override;
376
377   bool readable() const override;
378   bool isPending() const override;
379   virtual bool hangup() const;
380   bool good() const override;
381   bool error() const override;
382   void attachEventBase(EventBase* eventBase) override;
383   void detachEventBase() override;
384   bool isDetachable() const override;
385
386   void getLocalAddress(
387     folly::SocketAddress* address) const override;
388   void getPeerAddress(
389     folly::SocketAddress* address) const override;
390
391   bool isEorTrackingEnabled() const override { return false; }
392
393   void setEorTracking(bool /*track*/) override {}
394
395   bool connecting() const override {
396     return (state_ == StateEnum::CONNECTING);
397   }
398
399   virtual bool isClosedByPeer() const {
400     return (state_ == StateEnum::CLOSED &&
401             (readErr_ == READ_EOF || readErr_ == READ_ERROR));
402   }
403
404   virtual bool isClosedBySelf() const {
405     return (state_ == StateEnum::CLOSED &&
406             (readErr_ != READ_EOF && readErr_ != READ_ERROR));
407   }
408
409   size_t getAppBytesWritten() const override {
410     return appBytesWritten_;
411   }
412
413   size_t getRawBytesWritten() const override {
414     return getAppBytesWritten();
415   }
416
417   size_t getAppBytesReceived() const override {
418     return appBytesReceived_;
419   }
420
421   size_t getRawBytesReceived() const override {
422     return getAppBytesReceived();
423   }
424
425   std::chrono::nanoseconds getConnectTime() const {
426     return connectEndTime_ - connectStartTime_;
427   }
428
429   std::chrono::milliseconds getConnectTimeout() const {
430     return connectTimeout_;
431   }
432
433   bool getTFOAttempted() const {
434     return tfoAttempted_;
435   }
436
437   /**
438    * Returns whether or not the attempt to use TFO
439    * finished successfully. This does not necessarily
440    * mean TFO worked, just that trying to use TFO
441    * succeeded.
442    */
443   bool getTFOFinished() const {
444     return tfoFinished_;
445   }
446
447   /**
448    * Returns whether or not TFO attempt succeded on this
449    * connection.
450    * For servers this is pretty straightforward API and can
451    * be invoked right after the connection is accepted. This API
452    * will perform one syscall.
453    * This API is a bit tricky to use for clients, since clients
454    * only know this for sure after the SYN-ACK is returned. So it's
455    * appropriate to call this only after the first application
456    * data is read from the socket when the caller knows that
457    * the SYN has been ACKed by the server.
458    */
459   bool getTFOSucceded() const;
460
461   // Methods controlling socket options
462
463   /**
464    * Force writes to be transmitted immediately.
465    *
466    * This controls the TCP_NODELAY socket option.  When enabled, TCP segments
467    * are sent as soon as possible, even if it is not a full frame of data.
468    * When disabled, the data may be buffered briefly to try and wait for a full
469    * frame of data.
470    *
471    * By default, TCP_NODELAY is enabled for AsyncSocket objects.
472    *
473    * This method will fail if the socket is not currently open.
474    *
475    * @return Returns 0 if the TCP_NODELAY flag was successfully updated,
476    *         or a non-zero errno value on error.
477    */
478   int setNoDelay(bool noDelay);
479
480
481   /**
482    * Set the FD_CLOEXEC flag so that the socket will be closed if the program
483    * later forks and execs.
484    */
485   void setCloseOnExec();
486
487   /*
488    * Set the Flavor of Congestion Control to be used for this Socket
489    * Please check '/lib/modules/<kernel>/kernel/net/ipv4' for tcp_*.ko
490    * first to make sure the module is available for plugging in
491    * Alternatively you can choose from net.ipv4.tcp_allowed_congestion_control
492    */
493   int setCongestionFlavor(const std::string &cname);
494
495   /*
496    * Forces ACKs to be sent immediately
497    *
498    * @return Returns 0 if the TCP_QUICKACK flag was successfully updated,
499    *         or a non-zero errno value on error.
500    */
501   int setQuickAck(bool quickack);
502
503   /**
504    * Set the send bufsize
505    */
506   int setSendBufSize(size_t bufsize);
507
508   /**
509    * Set the recv bufsize
510    */
511   int setRecvBufSize(size_t bufsize);
512
513   /**
514    * Sets a specific tcp personality
515    * Available only on kernels 3.2 and greater
516    */
517   #define SO_SET_NAMESPACE        41
518   int setTCPProfile(int profd);
519
520   /**
521    * Generic API for reading a socket option.
522    *
523    * @param level     same as the "level" parameter in getsockopt().
524    * @param optname   same as the "optname" parameter in getsockopt().
525    * @param optval    pointer to the variable in which the option value should
526    *                  be returned.
527    * @param optlen    value-result argument, initially containing the size of
528    *                  the buffer pointed to by optval, and modified on return
529    *                  to indicate the actual size of the value returned.
530    * @return          same as the return value of getsockopt().
531    */
532   template <typename T>
533   int getSockOpt(int level, int optname, T* optval, socklen_t* optlen) {
534     return getsockopt(fd_, level, optname, (void*) optval, optlen);
535   }
536
537   /**
538    * Generic API for setting a socket option.
539    *
540    * @param level     same as the "level" parameter in getsockopt().
541    * @param optname   same as the "optname" parameter in getsockopt().
542    * @param optval    the option value to set.
543    * @return          same as the return value of setsockopt().
544    */
545   template <typename T>
546   int setSockOpt(int  level,  int  optname,  const T *optval) {
547     return setsockopt(fd_, level, optname, optval, sizeof(T));
548   }
549
550   virtual void setPeek(bool peek) {
551     peek_ = peek;
552   }
553
554   /**
555    * Enables TFO behavior on the AsyncSocket if FOLLY_ALLOW_TFO
556    * is set.
557    */
558   void enableTFO() {
559     // No-op if folly does not allow tfo
560 #if FOLLY_ALLOW_TFO
561     tfoEnabled_ = true;
562 #endif
563   }
564
565   enum class StateEnum : uint8_t {
566     UNINIT,
567     CONNECTING,
568     ESTABLISHED,
569     CLOSED,
570     ERROR,
571     FAST_OPEN,
572   };
573
574   void setBufferCallback(BufferCallback* cb);
575
576   // Callers should set this prior to connecting the socket for the safest
577   // behavior.
578   void setEvbChangedCallback(std::unique_ptr<EvbChangeCallback> cb) {
579     evbChangeCb_ = std::move(cb);
580   }
581
582   /**
583    * writeReturn is the total number of bytes written, or WRITE_ERROR on error.
584    * If no data has been written, 0 is returned.
585    * exception is a more specific exception that cause a write error.
586    * Not all writes have exceptions associated with them thus writeReturn
587    * should be checked to determine whether the operation resulted in an error.
588    */
589   struct WriteResult {
590     explicit WriteResult(ssize_t ret) : writeReturn(ret) {}
591
592     WriteResult(ssize_t ret, std::unique_ptr<const AsyncSocketException> e)
593         : writeReturn(ret), exception(std::move(e)) {}
594
595     ssize_t writeReturn;
596     std::unique_ptr<const AsyncSocketException> exception;
597   };
598
599   /**
600    * readReturn is the number of bytes read, or READ_EOF on EOF, or
601    * READ_ERROR on error, or READ_BLOCKING if the operation will
602    * block.
603    * exception is a more specific exception that may have caused a read error.
604    * Not all read errors have exceptions associated with them thus readReturn
605    * should be checked to determine whether the operation resulted in an error.
606    */
607   struct ReadResult {
608     explicit ReadResult(ssize_t ret) : readReturn(ret) {}
609
610     ReadResult(ssize_t ret, std::unique_ptr<const AsyncSocketException> e)
611         : readReturn(ret), exception(std::move(e)) {}
612
613     ssize_t readReturn;
614     std::unique_ptr<const AsyncSocketException> exception;
615   };
616
617   /**
618    * A WriteRequest object tracks information about a pending write operation.
619    */
620   class WriteRequest {
621    public:
622     WriteRequest(AsyncSocket* socket, WriteCallback* callback) :
623       socket_(socket), callback_(callback) {}
624
625     virtual void start() {}
626
627     virtual void destroy() = 0;
628
629     virtual WriteResult performWrite() = 0;
630
631     virtual void consume() = 0;
632
633     virtual bool isComplete() = 0;
634
635     WriteRequest* getNext() const {
636       return next_;
637     }
638
639     WriteCallback* getCallback() const {
640       return callback_;
641     }
642
643     uint32_t getTotalBytesWritten() const {
644       return totalBytesWritten_;
645     }
646
647     void append(WriteRequest* next) {
648       assert(next_ == nullptr);
649       next_ = next;
650     }
651
652     void fail(const char* fn, const AsyncSocketException& ex) {
653       socket_->failWrite(fn, ex);
654     }
655
656     void bytesWritten(size_t count) {
657       totalBytesWritten_ += uint32_t(count);
658       socket_->appBytesWritten_ += count;
659     }
660
661    protected:
662     // protected destructor, to ensure callers use destroy()
663     virtual ~WriteRequest() {}
664
665     AsyncSocket* socket_;         ///< parent socket
666     WriteRequest* next_{nullptr};          ///< pointer to next WriteRequest
667     WriteCallback* callback_;     ///< completion callback
668     uint32_t totalBytesWritten_{0};  ///< total bytes written
669   };
670
671  protected:
672   enum ReadResultEnum {
673     READ_EOF = 0,
674     READ_ERROR = -1,
675     READ_BLOCKING = -2,
676     READ_NO_ERROR = -3,
677   };
678
679   enum WriteResultEnum {
680     WRITE_ERROR = -1,
681   };
682
683   /**
684    * Protected destructor.
685    *
686    * Users of AsyncSocket must never delete it directly.  Instead, invoke
687    * destroy() instead.  (See the documentation in DelayedDestruction.h for
688    * more details.)
689    */
690   ~AsyncSocket();
691
692   friend std::ostream& operator << (std::ostream& os, const StateEnum& state);
693
694   enum ShutdownFlags {
695     /// shutdownWrite() called, but we are still waiting on writes to drain
696     SHUT_WRITE_PENDING = 0x01,
697     /// writes have been completely shut down
698     SHUT_WRITE = 0x02,
699     /**
700      * Reads have been shutdown.
701      *
702      * At the moment we don't distinguish between remote read shutdown
703      * (received EOF from the remote end) and local read shutdown.  We can
704      * only receive EOF when a read callback is set, and we immediately inform
705      * it of the EOF.  Therefore there doesn't seem to be any reason to have a
706      * separate state of "received EOF but the local side may still want to
707      * read".
708      *
709      * We also don't currently provide any API for only shutting down the read
710      * side of a socket.  (This is a no-op as far as TCP is concerned, anyway.)
711      */
712     SHUT_READ = 0x04,
713   };
714
715   class BytesWriteRequest;
716
717   class WriteTimeout : public AsyncTimeout {
718    public:
719     WriteTimeout(AsyncSocket* socket, EventBase* eventBase)
720       : AsyncTimeout(eventBase)
721       , socket_(socket) {}
722
723     virtual void timeoutExpired() noexcept {
724       socket_->timeoutExpired();
725     }
726
727    private:
728     AsyncSocket* socket_;
729   };
730
731   class IoHandler : public EventHandler {
732    public:
733     IoHandler(AsyncSocket* socket, EventBase* eventBase)
734       : EventHandler(eventBase, -1)
735       , socket_(socket) {}
736     IoHandler(AsyncSocket* socket, EventBase* eventBase, int fd)
737       : EventHandler(eventBase, fd)
738       , socket_(socket) {}
739
740     virtual void handlerReady(uint16_t events) noexcept {
741       socket_->ioReady(events);
742     }
743
744    private:
745     AsyncSocket* socket_;
746   };
747
748   void init();
749
750   class ImmediateReadCB : public folly::EventBase::LoopCallback {
751    public:
752     explicit ImmediateReadCB(AsyncSocket* socket) : socket_(socket) {}
753     void runLoopCallback() noexcept override {
754       DestructorGuard dg(socket_);
755       socket_->checkForImmediateRead();
756     }
757    private:
758     AsyncSocket* socket_;
759   };
760
761   /**
762    * Schedule checkForImmediateRead to be executed in the next loop
763    * iteration.
764    */
765   void scheduleImmediateRead() noexcept {
766     if (good()) {
767       eventBase_->runInLoop(&immediateReadHandler_);
768     }
769   }
770
771   /**
772    * Schedule handleInitalReadWrite to run in the next iteration.
773    */
774   void scheduleInitialReadWrite() noexcept {
775     if (good()) {
776       DestructorGuard dg(this);
777       eventBase_->runInLoop([this, dg] {
778         if (good()) {
779           handleInitialReadWrite();
780         }
781       });
782     }
783   }
784
785   // event notification methods
786   void ioReady(uint16_t events) noexcept;
787   virtual void checkForImmediateRead() noexcept;
788   virtual void handleInitialReadWrite() noexcept;
789   virtual void prepareReadBuffer(void** buf, size_t* buflen);
790   virtual void handleRead() noexcept;
791   virtual void handleWrite() noexcept;
792   virtual void handleConnect() noexcept;
793   void timeoutExpired() noexcept;
794
795   /**
796    * Attempt to read from the socket.
797    *
798    * @param buf      The buffer to read data into.
799    * @param buflen   The length of the buffer.
800    *
801    * @return Returns a read result. See read result for details.
802    */
803   virtual ReadResult performRead(void** buf, size_t* buflen, size_t* offset);
804
805   /**
806    * Populate an iovec array from an IOBuf and attempt to write it.
807    *
808    * @param callback Write completion/error callback.
809    * @param vec      Target iovec array; caller retains ownership.
810    * @param count    Number of IOBufs to write, beginning at start of buf.
811    * @param buf      Chain of iovecs.
812    * @param flags    set of flags for the underlying write calls, like cork
813    */
814   void writeChainImpl(WriteCallback* callback, iovec* vec,
815                       size_t count, std::unique_ptr<folly::IOBuf>&& buf,
816                       WriteFlags flags);
817
818   /**
819    * Write as much data as possible to the socket without blocking,
820    * and queue up any leftover data to send when the socket can
821    * handle writes again.
822    *
823    * @param callback The callback to invoke when the write is completed.
824    * @param vec      Array of buffers to write; this method will make a
825    *                 copy of the vector (but not the buffers themselves)
826    *                 if the write has to be completed asynchronously.
827    * @param count    Number of elements in vec.
828    * @param buf      The IOBuf that manages the buffers referenced by
829    *                 vec, or a pointer to nullptr if the buffers are not
830    *                 associated with an IOBuf.  Note that ownership of
831    *                 the IOBuf is transferred here; upon completion of
832    *                 the write, the AsyncSocket deletes the IOBuf.
833    * @param flags    Set of write flags.
834    */
835   void writeImpl(WriteCallback* callback, const iovec* vec, size_t count,
836                  std::unique_ptr<folly::IOBuf>&& buf,
837                  WriteFlags flags = WriteFlags::NONE);
838
839   /**
840    * Attempt to write to the socket.
841    *
842    * @param vec             The iovec array pointing to the buffers to write.
843    * @param count           The length of the iovec array.
844    * @param flags           Set of write flags.
845    * @param countWritten    On return, the value pointed to by this parameter
846    *                          will contain the number of iovec entries that were
847    *                          fully written.
848    * @param partialWritten  On return, the value pointed to by this parameter
849    *                          will contain the number of bytes written in the
850    *                          partially written iovec entry.
851    *
852    * @return Returns a WriteResult. See WriteResult for more details.
853    */
854   virtual WriteResult performWrite(
855       const iovec* vec,
856       uint32_t count,
857       WriteFlags flags,
858       uint32_t* countWritten,
859       uint32_t* partialWritten);
860
861   /**
862    * Sends the message over the socket using sendmsg
863    *
864    * @param msg       Message to send
865    * @param msg_flags Flags to pass to sendmsg
866    */
867   AsyncSocket::WriteResult
868   sendSocketMessage(int fd, struct msghdr* msg, int msg_flags);
869
870   virtual ssize_t tfoSendMsg(int fd, struct msghdr* msg, int msg_flags);
871
872   int socketConnect(const struct sockaddr* addr, socklen_t len);
873
874   virtual void scheduleConnectTimeout();
875   void registerForConnectEvents();
876
877   bool updateEventRegistration();
878
879   /**
880    * Update event registration.
881    *
882    * @param enable Flags of events to enable. Set it to 0 if no events
883    * need to be enabled in this call.
884    * @param disable Flags of events
885    * to disable. Set it to 0 if no events need to be disabled in this
886    * call.
887    *
888    * @return true iff the update is successful.
889    */
890   bool updateEventRegistration(uint16_t enable, uint16_t disable);
891
892   // Actually close the file descriptor and set it to -1 so we don't
893   // accidentally close it again.
894   void doClose();
895
896   // error handling methods
897   void startFail();
898   void finishFail();
899   void finishFail(const AsyncSocketException& ex);
900   void invokeAllErrors(const AsyncSocketException& ex);
901   void fail(const char* fn, const AsyncSocketException& ex);
902   void failConnect(const char* fn, const AsyncSocketException& ex);
903   void failRead(const char* fn, const AsyncSocketException& ex);
904   void failWrite(const char* fn, WriteCallback* callback, size_t bytesWritten,
905                  const AsyncSocketException& ex);
906   void failWrite(const char* fn, const AsyncSocketException& ex);
907   void failAllWrites(const AsyncSocketException& ex);
908   virtual void invokeConnectErr(const AsyncSocketException& ex);
909   virtual void invokeConnectSuccess();
910   void invalidState(ConnectCallback* callback);
911   void invalidState(ReadCallback* callback);
912   void invalidState(WriteCallback* callback);
913
914   std::string withAddr(const std::string& s);
915
916   StateEnum state_;                     ///< StateEnum describing current state
917   uint8_t shutdownFlags_;               ///< Shutdown state (ShutdownFlags)
918   uint16_t eventFlags_;                 ///< EventBase::HandlerFlags settings
919   int fd_;                              ///< The socket file descriptor
920   mutable folly::SocketAddress addr_;    ///< The address we tried to connect to
921   mutable folly::SocketAddress localAddr_;
922                                         ///< The address we are connecting from
923   uint32_t sendTimeout_;                ///< The send timeout, in milliseconds
924   uint16_t maxReadsPerEvent_;           ///< Max reads per event loop iteration
925   EventBase* eventBase_;                ///< The EventBase
926   WriteTimeout writeTimeout_;           ///< A timeout for connect and write
927   IoHandler ioHandler_;                 ///< A EventHandler to monitor the fd
928   ImmediateReadCB immediateReadHandler_; ///< LoopCallback for checking read
929
930   ConnectCallback* connectCallback_;    ///< ConnectCallback
931   ReadCallback* readCallback_;          ///< ReadCallback
932   WriteRequest* writeReqHead_;          ///< Chain of WriteRequests
933   WriteRequest* writeReqTail_;          ///< End of WriteRequest chain
934   ShutdownSocketSet* shutdownSocketSet_;
935   size_t appBytesReceived_;             ///< Num of bytes received from socket
936   size_t appBytesWritten_;              ///< Num of bytes written to socket
937   bool isBufferMovable_{false};
938
939   bool peek_{false}; // Peek bytes.
940
941   int8_t readErr_{READ_NO_ERROR};      ///< The read error encountered, if any.
942
943   std::chrono::steady_clock::time_point connectStartTime_;
944   std::chrono::steady_clock::time_point connectEndTime_;
945
946   std::chrono::milliseconds connectTimeout_{0};
947
948   BufferCallback* bufferCallback_{nullptr};
949   bool tfoEnabled_{false};
950   bool tfoAttempted_{false};
951   bool tfoFinished_{false};
952
953   std::unique_ptr<EvbChangeCallback> evbChangeCb_{nullptr};
954 };
955 #ifdef _MSC_VER
956 #pragma vtordisp(pop)
957 #endif
958
959 } // folly