diff options
author | jbauch <jbauch@webrtc.org> | 2016-01-06 22:20:28 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-07 06:20:31 +0000 |
commit | 4331fcd51736b030f30c31a35c732f119b31b6fc (patch) | |
tree | b91da15ee6a72267a8add45cb436c7618bdaf161 /webrtc | |
parent | 44cc7950160aee01889a6b5a21a384b20cfb5532 (diff) | |
download | webrtc-4331fcd51736b030f30c31a35c732f119b31b6fc.tar.gz |
Remove duplicate code in SocketDispatcher
This CL is a follow-up on https://codereview.webrtc.org/1452903006/ which
moved the definition of SocketDispatcher to physicalsocketserver.h.
Here the duplicate implementations are merged with only some #ifdef parts.
BUG=
Review URL: https://codereview.webrtc.org/1537273002
Cr-Commit-Position: refs/heads/master@{#11160}
Diffstat (limited to 'webrtc')
-rw-r--r-- | webrtc/base/physicalsocketserver.cc | 446 |
1 files changed, 214 insertions, 232 deletions
diff --git a/webrtc/base/physicalsocketserver.cc b/webrtc/base/physicalsocketserver.cc index 524617221c..3e454527ca 100644 --- a/webrtc/base/physicalsocketserver.cc +++ b/webrtc/base/physicalsocketserver.cc @@ -546,6 +546,220 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) { return 0; } +SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss) +#if defined(WEBRTC_WIN) + : PhysicalSocket(ss), id_(0), signal_close_(false) +#else + : PhysicalSocket(ss) +#endif +{ +} + +SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) +#if defined(WEBRTC_WIN) + : PhysicalSocket(ss, s), id_(0), signal_close_(false) +#else + : PhysicalSocket(ss, s) +#endif +{ +} + +SocketDispatcher::~SocketDispatcher() { + Close(); +} + +bool SocketDispatcher::Initialize() { + ASSERT(s_ != INVALID_SOCKET); + // Must be a non-blocking +#if defined(WEBRTC_WIN) + u_long argp = 1; + ioctlsocket(s_, FIONBIO, &argp); +#elif defined(WEBRTC_POSIX) + fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); +#endif + ss_->Add(this); + return true; +} + +bool SocketDispatcher::Create(int type) { + return Create(AF_INET, type); +} + +bool SocketDispatcher::Create(int family, int type) { + // Change the socket to be non-blocking. + if (!PhysicalSocket::Create(family, type)) + return false; + + if (!Initialize()) + return false; + +#if defined(WEBRTC_WIN) + do { id_ = ++next_id_; } while (id_ == 0); +#endif + return true; +} + +#if defined(WEBRTC_WIN) + +WSAEVENT SocketDispatcher::GetWSAEvent() { + return WSA_INVALID_EVENT; +} + +SOCKET SocketDispatcher::GetSocket() { + return s_; +} + +bool SocketDispatcher::CheckSignalClose() { + if (!signal_close_) + return false; + + char ch; + if (recv(s_, &ch, 1, MSG_PEEK) > 0) + return false; + + state_ = CS_CLOSED; + signal_close_ = false; + SignalCloseEvent(this, signal_err_); + return true; +} + +int SocketDispatcher::next_id_ = 0; + +#elif defined(WEBRTC_POSIX) + +int SocketDispatcher::GetDescriptor() { + return s_; +} + +bool SocketDispatcher::IsDescriptorClosed() { + // We don't have a reliable way of distinguishing end-of-stream + // from readability. So test on each readable call. Is this + // inefficient? Probably. + char ch; + ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK); + if (res > 0) { + // Data available, so not closed. + return false; + } else if (res == 0) { + // EOF, so closed. + return true; + } else { // error + switch (errno) { + // Returned if we've already closed s_. + case EBADF: + // Returned during ungraceful peer shutdown. + case ECONNRESET: + return true; + default: + // Assume that all other errors are just blocking errors, meaning the + // connection is still good but we just can't read from it right now. + // This should only happen when connecting (and at most once), because + // in all other cases this function is only called if the file + // descriptor is already known to be in the readable state. However, + // it's not necessary a problem if we spuriously interpret a + // "connection lost"-type error as a blocking error, because typically + // the next recv() will get EOF, so we'll still eventually notice that + // the socket is closed. + LOG_ERR(LS_WARNING) << "Assuming benign blocking error"; + return false; + } + } +} + +#endif // WEBRTC_POSIX + +uint32_t SocketDispatcher::GetRequestedEvents() { + return enabled_events_; +} + +void SocketDispatcher::OnPreEvent(uint32_t ff) { + if ((ff & DE_CONNECT) != 0) + state_ = CS_CONNECTED; + +#if defined(WEBRTC_WIN) + // We set CS_CLOSED from CheckSignalClose. +#elif defined(WEBRTC_POSIX) + if ((ff & DE_CLOSE) != 0) + state_ = CS_CLOSED; +#endif +} + +#if defined(WEBRTC_WIN) + +void SocketDispatcher::OnEvent(uint32_t ff, int err) { + int cache_id = id_; + // Make sure we deliver connect/accept first. Otherwise, consumers may see + // something like a READ followed by a CONNECT, which would be odd. + if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) { + if (ff != DE_CONNECT) + LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff; + enabled_events_ &= ~DE_CONNECT; +#if !defined(NDEBUG) + dbg_addr_ = "Connected @ "; + dbg_addr_.append(GetRemoteAddress().ToString()); +#endif + SignalConnectEvent(this); + } + if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) { + enabled_events_ &= ~DE_ACCEPT; + SignalReadEvent(this); + } + if ((ff & DE_READ) != 0) { + enabled_events_ &= ~DE_READ; + SignalReadEvent(this); + } + if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) { + enabled_events_ &= ~DE_WRITE; + SignalWriteEvent(this); + } + if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) { + signal_close_ = true; + signal_err_ = err; + } +} + +#elif defined(WEBRTC_POSIX) + +void SocketDispatcher::OnEvent(uint32_t ff, int err) { + // Make sure we deliver connect/accept first. Otherwise, consumers may see + // something like a READ followed by a CONNECT, which would be odd. + if ((ff & DE_CONNECT) != 0) { + enabled_events_ &= ~DE_CONNECT; + SignalConnectEvent(this); + } + if ((ff & DE_ACCEPT) != 0) { + enabled_events_ &= ~DE_ACCEPT; + SignalReadEvent(this); + } + if ((ff & DE_READ) != 0) { + enabled_events_ &= ~DE_READ; + SignalReadEvent(this); + } + if ((ff & DE_WRITE) != 0) { + enabled_events_ &= ~DE_WRITE; + SignalWriteEvent(this); + } + if ((ff & DE_CLOSE) != 0) { + // The socket is now dead to us, so stop checking it. + enabled_events_ = 0; + SignalCloseEvent(this, err); + } +} + +#endif // WEBRTC_POSIX + +int SocketDispatcher::Close() { + if (s_ == INVALID_SOCKET) + return 0; + +#if defined(WEBRTC_WIN) + id_ = 0; + signal_close_ = false; +#endif + ss_->Remove(this); + return PhysicalSocket::Close(); +} + #if defined(WEBRTC_POSIX) class EventDispatcher : public Dispatcher { public: @@ -782,120 +996,6 @@ class PosixSignalDispatcher : public Dispatcher { PhysicalSocketServer *owner_; }; -SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss) - : PhysicalSocket(ss) { -} - -SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) - : PhysicalSocket(ss, s) { -} - -SocketDispatcher::~SocketDispatcher() { - Close(); -} - -bool SocketDispatcher::Initialize() { - ss_->Add(this); - fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); - return true; -} - -bool SocketDispatcher::Create(int type) { - return Create(AF_INET, type); -} - -bool SocketDispatcher::Create(int family, int type) { - // Change the socket to be non-blocking. - if (!PhysicalSocket::Create(family, type)) - return false; - - return Initialize(); -} - -int SocketDispatcher::GetDescriptor() { - return s_; -} - -bool SocketDispatcher::IsDescriptorClosed() { - // We don't have a reliable way of distinguishing end-of-stream - // from readability. So test on each readable call. Is this - // inefficient? Probably. - char ch; - ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK); - if (res > 0) { - // Data available, so not closed. - return false; - } else if (res == 0) { - // EOF, so closed. - return true; - } else { // error - switch (errno) { - // Returned if we've already closed s_. - case EBADF: - // Returned during ungraceful peer shutdown. - case ECONNRESET: - return true; - default: - // Assume that all other errors are just blocking errors, meaning the - // connection is still good but we just can't read from it right now. - // This should only happen when connecting (and at most once), because - // in all other cases this function is only called if the file - // descriptor is already known to be in the readable state. However, - // it's not necessary a problem if we spuriously interpret a - // "connection lost"-type error as a blocking error, because typically - // the next recv() will get EOF, so we'll still eventually notice that - // the socket is closed. - LOG_ERR(LS_WARNING) << "Assuming benign blocking error"; - return false; - } - } -} - -uint32_t SocketDispatcher::GetRequestedEvents() { - return enabled_events_; -} - -void SocketDispatcher::OnPreEvent(uint32_t ff) { - if ((ff & DE_CONNECT) != 0) - state_ = CS_CONNECTED; - if ((ff & DE_CLOSE) != 0) - state_ = CS_CLOSED; -} - -void SocketDispatcher::OnEvent(uint32_t ff, int err) { - // Make sure we deliver connect/accept first. Otherwise, consumers may see - // something like a READ followed by a CONNECT, which would be odd. - if ((ff & DE_CONNECT) != 0) { - enabled_events_ &= ~DE_CONNECT; - SignalConnectEvent(this); - } - if ((ff & DE_ACCEPT) != 0) { - enabled_events_ &= ~DE_ACCEPT; - SignalReadEvent(this); - } - if ((ff & DE_READ) != 0) { - enabled_events_ &= ~DE_READ; - SignalReadEvent(this); - } - if ((ff & DE_WRITE) != 0) { - enabled_events_ &= ~DE_WRITE; - SignalWriteEvent(this); - } - if ((ff & DE_CLOSE) != 0) { - // The socket is now dead to us, so stop checking it. - enabled_events_ = 0; - SignalCloseEvent(this, err); - } -} - -int SocketDispatcher::Close() { - if (s_ == INVALID_SOCKET) - return 0; - - ss_->Remove(this); - return PhysicalSocket::Close(); -} - class FileDispatcher: public Dispatcher, public AsyncFile { public: FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) { @@ -1009,124 +1109,6 @@ private: PhysicalSocketServer* ss_; WSAEVENT hev_; }; - -SocketDispatcher::SocketDispatcher(PhysicalSocketServer* ss) - : PhysicalSocket(ss), - id_(0), - signal_close_(false) { -} - -SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer* ss) - : PhysicalSocket(ss, s), - id_(0), - signal_close_(false) { -} - -SocketDispatcher::~SocketDispatcher() { - Close(); -} - -bool SocketDispatcher::Initialize() { - ASSERT(s_ != INVALID_SOCKET); - // Must be a non-blocking - u_long argp = 1; - ioctlsocket(s_, FIONBIO, &argp); - ss_->Add(this); - return true; -} - -bool SocketDispatcher::Create(int type) { - return Create(AF_INET, type); -} - -bool SocketDispatcher::Create(int family, int type) { - // Create socket - if (!PhysicalSocket::Create(family, type)) - return false; - - if (!Initialize()) - return false; - - do { id_ = ++next_id_; } while (id_ == 0); - return true; -} - -int SocketDispatcher::Close() { - if (s_ == INVALID_SOCKET) - return 0; - - id_ = 0; - signal_close_ = false; - ss_->Remove(this); - return PhysicalSocket::Close(); -} - -uint32_t SocketDispatcher::GetRequestedEvents() { - return enabled_events_; -} - -void SocketDispatcher::OnPreEvent(uint32_t ff) { - if ((ff & DE_CONNECT) != 0) - state_ = CS_CONNECTED; - // We set CS_CLOSED from CheckSignalClose. -} - -void SocketDispatcher::OnEvent(uint32_t ff, int err) { - int cache_id = id_; - // Make sure we deliver connect/accept first. Otherwise, consumers may see - // something like a READ followed by a CONNECT, which would be odd. - if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) { - if (ff != DE_CONNECT) - LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff; - enabled_events_ &= ~DE_CONNECT; -#if !defined(NDEBUG) - dbg_addr_ = "Connected @ "; - dbg_addr_.append(GetRemoteAddress().ToString()); -#endif - SignalConnectEvent(this); - } - if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) { - enabled_events_ &= ~DE_ACCEPT; - SignalReadEvent(this); - } - if ((ff & DE_READ) != 0) { - enabled_events_ &= ~DE_READ; - SignalReadEvent(this); - } - if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) { - enabled_events_ &= ~DE_WRITE; - SignalWriteEvent(this); - } - if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) { - signal_close_ = true; - signal_err_ = err; - } -} - -WSAEVENT SocketDispatcher::GetWSAEvent() { - return WSA_INVALID_EVENT; -} - -SOCKET SocketDispatcher::GetSocket() { - return s_; -} - -bool SocketDispatcher::CheckSignalClose() { - if (!signal_close_) - return false; - - char ch; - if (recv(s_, &ch, 1, MSG_PEEK) > 0) - return false; - - state_ = CS_CLOSED; - signal_close_ = false; - SignalCloseEvent(this, signal_err_); - return true; -} - -int SocketDispatcher::next_id_ = 0; - #endif // WEBRTC_WIN // Sets the value of a boolean value to false when signaled. |