| 2072 | |
| 2073 | |
| 2074 | Encoder* SocketManager::next(int_fd s) |
| 2075 | { |
| 2076 | HttpProxy* proxy = nullptr; // Non-null if needs to be terminated. |
| 2077 | |
| 2078 | synchronized (mutex) { |
| 2079 | // We cannot assume 'sockets.count(s) > 0' here because it's |
| 2080 | // possible that 's' has been removed with a call to |
| 2081 | // SocketManager::close. For example, it could be the case that a |
| 2082 | // socket has gone to CLOSE_WAIT and the call to read in |
| 2083 | // io::read returned 0 causing SocketManager::close to get |
| 2084 | // invoked. Later a call to 'send' or 'sendfile' (e.g., in |
| 2085 | // send_data or send_file) can "succeed" (because the socket is |
| 2086 | // not "closed" yet because there are still some Socket |
| 2087 | // references, namely the reference being used in send_data or |
| 2088 | // send_file!). However, when SocketManager::next is actually |
| 2089 | // invoked we find out there there is no more data and thus stop |
| 2090 | // sending. |
| 2091 | // TODO(benh): Should we actually finish sending the data!? |
| 2092 | if (sockets.count(s) > 0) { |
| 2093 | CHECK(outgoing.count(s) > 0); |
| 2094 | |
| 2095 | if (!outgoing[s].empty()) { |
| 2096 | // More messages! |
| 2097 | Encoder* encoder = outgoing[s].front(); |
| 2098 | outgoing[s].pop(); |
| 2099 | return encoder; |
| 2100 | } else { |
| 2101 | // No more messages ... erase the outgoing queue. |
| 2102 | outgoing.erase(s); |
| 2103 | |
| 2104 | if (dispose.count(s) > 0) { |
| 2105 | // This is either a temporary socket we created or it's a |
| 2106 | // socket that we were receiving data from and possibly |
| 2107 | // sending HTTP responses back on. Clean up either way. |
| 2108 | Option<Address> address = addresses.get(s); |
| 2109 | if (address.isSome()) { |
| 2110 | CHECK(temps.count(address.get()) > 0 && temps[address.get()] == s); |
| 2111 | temps.erase(address.get()); |
| 2112 | addresses.erase(s); |
| 2113 | } |
| 2114 | |
| 2115 | if (proxies.count(s) > 0) { |
| 2116 | proxy = proxies[s]; |
| 2117 | proxies.erase(s); |
| 2118 | } |
| 2119 | |
| 2120 | dispose.erase(s); |
| 2121 | |
| 2122 | auto iterator = sockets.find(s); |
| 2123 | |
| 2124 | // We don't actually close the socket (we wait for the Socket |
| 2125 | // abstraction to close it once there are no more references), |
| 2126 | // but we do shutdown the receiving end so any DataDecoder |
| 2127 | // will get cleaned up (which might have the last reference). |
| 2128 | |
| 2129 | // Hold on to the Socket and remove it from the 'sockets' |
| 2130 | // map so that in the case where 'shutdown()' ends up |
| 2131 | // calling close the termination logic is not run twice. |
no test coverage detected