`Server` implementation.
| 2118 | |
| 2119 | // `Server` implementation. |
| 2120 | Future<Nothing> run() |
| 2121 | { |
| 2122 | return state.transition<State::INITIALIZED, State::RUNNING>([=]() { |
| 2123 | // Start the accept loop and store the future so we can later |
| 2124 | // discard it when we need to stop the server. |
| 2125 | accepting = loop( |
| 2126 | self(), |
| 2127 | [=]() { |
| 2128 | return socket.accept(); |
| 2129 | }, |
| 2130 | [=](const network::Socket& socket) -> ControlFlow<Nothing> { |
| 2131 | // If we've transitioned to STOPPING we should break. It |
| 2132 | // may seem like we should never get here because we |
| 2133 | // discard the accept loop before we transition to |
| 2134 | // STOPPING but it's possible that we've already |
| 2135 | // dispatched this lambda and it is only now getting |
| 2136 | // invoked. It's critical that we break because after we |
| 2137 | // transition to STOPPING we assume that `clients` will |
| 2138 | // not be modified by the accept loop. |
| 2139 | if (state.is<State::STOPPING>()) { |
| 2140 | return Break(); |
| 2141 | } |
| 2142 | |
| 2143 | Client client = { |
| 2144 | /* .socket = */ socket, |
| 2145 | /* .serving = */ http::serve( |
| 2146 | socket, |
| 2147 | [=](const Request& request) { |
| 2148 | return f(socket, request); |
| 2149 | }) |
| 2150 | }; |
| 2151 | |
| 2152 | clients.put(socket, client); |
| 2153 | |
| 2154 | client.serving |
| 2155 | .onAny(defer(self(), [=](const Future<Nothing>&) { |
| 2156 | clients.erase(socket); |
| 2157 | })); |
| 2158 | |
| 2159 | return Continue(); |
| 2160 | }); |
| 2161 | |
| 2162 | // We return a _discardable_ `accepting` so the caller can stop |
| 2163 | // running a server by "discarding the run", for example: |
| 2164 | // |
| 2165 | // Future<Nothing> run = server.run(); |
| 2166 | // run.discard(); |
| 2167 | // |
| 2168 | // Even if we returned an _undiscardable_ `accepting` we still |
| 2169 | // need to do a `recover()` on it in the event that the accept |
| 2170 | // loop fails (or is abandoned) so we can stop the server (if it |
| 2171 | // isn't already being stopped). If `accepting` completes |
| 2172 | // successfully then we must be stopping so just wait until |
| 2173 | // we've stopped! |
| 2174 | return accepting |
| 2175 | .then(defer(self(), [=]() { |
| 2176 | return state.when<State::STOPPED>(); |
| 2177 | })) |
nothing calls this directly
no test coverage detected