OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/TcpServerSocket.h" |
| 6 |
| 7 #include <assert.h> |
| 8 #include <string.h> |
| 9 |
| 10 #include "include/ppapi/cpp/private/net_address_private.h" |
| 11 #include "net/SocketSubSystem.h" |
| 12 #include "ppapi/c/pp_errors.h" |
| 13 #include "ppapi/cpp/module.h" |
| 14 #include "util/DebugPrint.h" |
| 15 |
| 16 TCPServerSocket::TCPServerSocket(int oflag, |
| 17 const char* host, uint16_t port) |
| 18 : ref_(1), oflag_(oflag), factory_(this), socket_(NULL), |
| 19 host_(host), port_(port), resource_(0) { |
| 20 } |
| 21 |
| 22 TCPServerSocket::~TCPServerSocket() { |
| 23 assert(!socket_); |
| 24 assert(!ref_); |
| 25 } |
| 26 |
| 27 void TCPServerSocket::addref() { |
| 28 ++ref_; |
| 29 } |
| 30 |
| 31 void TCPServerSocket::release() { |
| 32 if (!--ref_) |
| 33 delete this; |
| 34 } |
| 35 |
| 36 FileStream* TCPServerSocket::dup(int fd) { |
| 37 return NULL; |
| 38 } |
| 39 |
| 40 int TCPServerSocket::read(char* buf, size_t count, size_t* nread) { |
| 41 return -1; |
| 42 } |
| 43 |
| 44 int TCPServerSocket::write(const char* buf, size_t count, size_t* nwrote) { |
| 45 return -1; |
| 46 } |
| 47 |
| 48 void TCPServerSocket::close() { |
| 49 if (socket_) { |
| 50 int32_t result = PP_OK_COMPLETIONPENDING; |
| 51 pp::Module::Get()->core()->CallOnMainThread(0, |
| 52 factory_.NewCallback(&TCPServerSocket::Close, &result)); |
| 53 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 54 while (result == PP_OK_COMPLETIONPENDING) |
| 55 sys->cond().wait(sys->mutex()); |
| 56 } |
| 57 } |
| 58 |
| 59 int TCPServerSocket::fcntl(int cmd, va_list ap) { |
| 60 if (cmd == F_GETFL) { |
| 61 return oflag_; |
| 62 } else if (cmd == F_SETFL) { |
| 63 oflag_ = va_arg(ap, long); |
| 64 return 0; |
| 65 } else { |
| 66 return -1; |
| 67 } |
| 68 } |
| 69 |
| 70 bool TCPServerSocket::is_read_ready() { |
| 71 return !is_open() || resource_; |
| 72 } |
| 73 |
| 74 bool TCPServerSocket::is_write_ready() { |
| 75 return !is_open(); |
| 76 } |
| 77 |
| 78 bool TCPServerSocket::is_exception() { |
| 79 return !is_open(); |
| 80 } |
| 81 |
| 82 bool TCPServerSocket::listen(int backlog) { |
| 83 int32_t result = PP_OK_COMPLETIONPENDING; |
| 84 pp::Module::Get()->core()->CallOnMainThread(0, |
| 85 factory_.NewCallback(&TCPServerSocket::Listen, backlog, &result)); |
| 86 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 87 while (result == PP_OK_COMPLETIONPENDING) |
| 88 sys->cond().wait(sys->mutex()); |
| 89 return result == PP_OK; |
| 90 } |
| 91 |
| 92 PP_Resource TCPServerSocket::accept() { |
| 93 if (!resource_) |
| 94 return 0; |
| 95 |
| 96 PP_Resource ret = resource_; |
| 97 resource_ = 0; |
| 98 pp::Module::Get()->core()->CallOnMainThread(0, |
| 99 factory_.NewCallback(&TCPServerSocket::Accept, |
| 100 static_cast<int32_t*>(NULL))); |
| 101 |
| 102 return ret; |
| 103 } |
| 104 |
| 105 void TCPServerSocket::Listen(int32_t result, int backlog, int32_t* pres) { |
| 106 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 107 Mutex::Lock lock(sys->mutex()); |
| 108 assert(!socket_); |
| 109 socket_ = new pp::TCPServerSocketPrivate(sys->instance()); |
| 110 |
| 111 // Ignore bind address and always bind to localhost. |
| 112 uint8_t localhost_ip[4] = { 127, 0, 0, 1 }; |
| 113 PP_NetAddress_Private localhost = {}; |
| 114 if (pp::NetAddressPrivate::CreateFromIPv4Address( |
| 115 localhost_ip, port_, &localhost)) { |
| 116 LOG("TCPServerSocket::Listen: %s\n", |
| 117 pp::NetAddressPrivate::Describe(localhost, true).c_str()); |
| 118 *pres = socket_->Listen(&localhost, backlog, |
| 119 factory_.NewCallback(&TCPServerSocket::Accept, pres)); |
| 120 } else { |
| 121 *pres = PP_ERROR_FAILED; |
| 122 } |
| 123 |
| 124 if (*pres != PP_OK_COMPLETIONPENDING) { |
| 125 sys->cond().broadcast(); |
| 126 } |
| 127 } |
| 128 |
| 129 void TCPServerSocket::Accept(int32_t result, int32_t* pres) { |
| 130 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 131 Mutex::Lock lock(sys->mutex()); |
| 132 assert(socket_); |
| 133 if (result == PP_OK) { |
| 134 result = socket_->Accept(&resource_, |
| 135 factory_.NewCallback(&TCPServerSocket::OnAccept)); |
| 136 if (result == PP_OK_COMPLETIONPENDING) |
| 137 result = PP_OK; |
| 138 } |
| 139 if (pres) |
| 140 *pres = result; |
| 141 sys->cond().broadcast(); |
| 142 } |
| 143 |
| 144 void TCPServerSocket::OnAccept(int32_t result) { |
| 145 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 146 Mutex::Lock lock(sys->mutex()); |
| 147 assert(socket_); |
| 148 sys->cond().broadcast(); |
| 149 } |
| 150 |
| 151 void TCPServerSocket::Close(int32_t result, int32_t* pres) { |
| 152 SocketSubSystem* sys = SocketSubSystem::GetSocketSubSystem(); |
| 153 Mutex::Lock lock(sys->mutex()); |
| 154 delete socket_; |
| 155 socket_ = NULL; |
| 156 *pres = PP_OK; |
| 157 sys->cond().broadcast(); |
| 158 } |
| 159 |
OLD | NEW |