mirror of
				https://github.com/ohwgiles/laminar.git
				synced 2025-06-13 12:54:29 +00:00 
			
		
		
		
	server cleanup, fix logic error in early promise resolution
This commit is contained in:
		
							parent
							
								
									cf9bee07db
								
							
						
					
					
						commit
						f923762c7e
					
				@ -69,6 +69,7 @@ struct MonitorScope {
 | 
			
		||||
// registerClient and deregisterClient
 | 
			
		||||
struct LaminarClient {
 | 
			
		||||
    virtual void sendMessage(std::string payload) = 0;
 | 
			
		||||
    virtual void close() = 0;
 | 
			
		||||
    MonitorScope scope;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -174,6 +174,7 @@ public:
 | 
			
		||||
                std::string content;
 | 
			
		||||
                if(laminar.getArtefact(file, content)) {
 | 
			
		||||
                    c->set_status(websocketpp::http::status_code::ok);
 | 
			
		||||
                    c->append_header("Content-Transfer-Encoding", "binary");
 | 
			
		||||
                    c->set_body(content);
 | 
			
		||||
                } else {
 | 
			
		||||
                    c->set_status(websocketpp::http::status_code::not_found);
 | 
			
		||||
@ -181,11 +182,14 @@ public:
 | 
			
		||||
            } else if(resources.handleRequest(resource, &start, &end)) {
 | 
			
		||||
                c->set_status(websocketpp::http::status_code::ok);
 | 
			
		||||
                c->append_header("Content-Encoding", "gzip");
 | 
			
		||||
                c->set_body(std::string(start, end));
 | 
			
		||||
                c->append_header("Content-Transfer-Encoding", "binary");
 | 
			
		||||
                std::string response(start,end);
 | 
			
		||||
                c->set_body(response);
 | 
			
		||||
            } else {
 | 
			
		||||
                // 404
 | 
			
		||||
                c->set_status(websocketpp::http::status_code::not_found);
 | 
			
		||||
            }
 | 
			
		||||
            c->lc->close();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Handle new websocket connection. Parse the URL to determine
 | 
			
		||||
@ -223,7 +227,9 @@ public:
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        wss.set_close_handler([this](websocketpp::connection_hdl hdl){
 | 
			
		||||
            laminar.deregisterClient(wss.get_con_from_hdl(hdl)->lc);
 | 
			
		||||
            websocket::connection_ptr c = wss.get_con_from_hdl(hdl);
 | 
			
		||||
            laminar.deregisterClient(c->lc);
 | 
			
		||||
            c->lc->close();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -266,7 +272,8 @@ struct Server::WebsocketConnection : public LaminarClient, public std::streambuf
 | 
			
		||||
        stream(kj::mv(stream)),
 | 
			
		||||
        out(this),
 | 
			
		||||
        cn(http.newConnection(this)),
 | 
			
		||||
        writePaf(kj::newPromiseAndFulfiller<void>())
 | 
			
		||||
        writePaf(kj::newPromiseAndFulfiller<void>()),
 | 
			
		||||
        closeOnComplete(false)
 | 
			
		||||
    {
 | 
			
		||||
        cn->register_ostream(&out);
 | 
			
		||||
        cn->start();
 | 
			
		||||
@ -278,7 +285,7 @@ struct Server::WebsocketConnection : public LaminarClient, public std::streambuf
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kj::Promise<void> pend() {
 | 
			
		||||
        return stream->tryRead(ibuf, 1, 1024).then([this](size_t sz){
 | 
			
		||||
        return stream->tryRead(ibuf, 1, sizeof(ibuf)).then([this](size_t sz){
 | 
			
		||||
            cn->read_all(ibuf, sz);
 | 
			
		||||
            if(sz == 0 || cn->get_state() == websocketpp::session::state::closed) {
 | 
			
		||||
                cn->eof();
 | 
			
		||||
@ -298,9 +305,9 @@ struct Server::WebsocketConnection : public LaminarClient, public std::streambuf
 | 
			
		||||
            if(payload.empty()) {
 | 
			
		||||
                return kj::Promise<void>(kj::READY_NOW);
 | 
			
		||||
            } else {
 | 
			
		||||
                return stream->write(payload.data(), payload.length()).then([this]{
 | 
			
		||||
                    return writeTask();
 | 
			
		||||
                });
 | 
			
		||||
                return stream->write(payload.data(), payload.size()).then([this](){
 | 
			
		||||
                    return closeOnComplete ? kj::Promise<void>(kj::READY_NOW) : writeTask();
 | 
			
		||||
                }).attach(kj::mv(payload));
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@ -309,6 +316,12 @@ struct Server::WebsocketConnection : public LaminarClient, public std::streambuf
 | 
			
		||||
        cn->send(payload, websocketpp::frame::opcode::text);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void close() override {
 | 
			
		||||
        closeOnComplete = true;
 | 
			
		||||
        outputBuffer.clear();
 | 
			
		||||
        writePaf.fulfiller->fulfill();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::streamsize xsputn(const char* s, std::streamsize sz) override {
 | 
			
		||||
        outputBuffer.append(std::string(s, sz));
 | 
			
		||||
        writePaf.fulfiller->fulfill();
 | 
			
		||||
@ -320,8 +333,8 @@ struct Server::WebsocketConnection : public LaminarClient, public std::streambuf
 | 
			
		||||
    websocket::connection_ptr cn;
 | 
			
		||||
    std::string outputBuffer;
 | 
			
		||||
    kj::PromiseFulfillerPair<void> writePaf;
 | 
			
		||||
    // TODO: think about this size
 | 
			
		||||
    char ibuf[1024];
 | 
			
		||||
    char ibuf[131072];
 | 
			
		||||
    bool closeOnComplete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Server::Server(LaminarInterface& li, kj::StringPtr rpcBindAddress,
 | 
			
		||||
@ -331,30 +344,17 @@ Server::Server(LaminarInterface& li, kj::StringPtr rpcBindAddress,
 | 
			
		||||
    ioContext(kj::setupAsyncIo()),
 | 
			
		||||
    tasks(*this)
 | 
			
		||||
{
 | 
			
		||||
    // RPC task
 | 
			
		||||
    tasks.add(ioContext.provider->getNetwork().parseAddress(rpcBindAddress, 0)
 | 
			
		||||
              .then([this](kj::Own<kj::NetworkAddress>&& addr) {
 | 
			
		||||
        acceptRpcClient(addr->listen());
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    { // RPC task
 | 
			
		||||
        auto paf = kj::newPromiseAndFulfiller<uint>();
 | 
			
		||||
        tasks.add(ioContext.provider->getNetwork().parseAddress(rpcBindAddress, 0)
 | 
			
		||||
                  .then(kj::mvCapture(paf.fulfiller,
 | 
			
		||||
                                      [this](kj::Own<kj::PromiseFulfiller<uint>>&& portFulfiller,
 | 
			
		||||
                                      kj::Own<kj::NetworkAddress>&& addr) {
 | 
			
		||||
            auto listener = addr->listen();
 | 
			
		||||
            portFulfiller->fulfill(listener->getPort());
 | 
			
		||||
            acceptRpcClient(kj::mv(listener));
 | 
			
		||||
        })));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { // HTTP task
 | 
			
		||||
        auto paf = kj::newPromiseAndFulfiller<uint>();
 | 
			
		||||
        tasks.add(ioContext.provider->getNetwork().parseAddress(httpBindAddress, 0)
 | 
			
		||||
                  .then(kj::mvCapture(paf.fulfiller,
 | 
			
		||||
                                      [this](kj::Own<kj::PromiseFulfiller<uint>>&& portFulfiller,
 | 
			
		||||
                                      kj::Own<kj::NetworkAddress>&& addr) {
 | 
			
		||||
            auto listener = addr->listen();
 | 
			
		||||
            portFulfiller->fulfill(listener->getPort());
 | 
			
		||||
            acceptHttpClient(kj::mv(listener));
 | 
			
		||||
        })));
 | 
			
		||||
    }
 | 
			
		||||
    // HTTP task
 | 
			
		||||
    tasks.add(ioContext.provider->getNetwork().parseAddress(httpBindAddress, 0)
 | 
			
		||||
              .then([this](kj::Own<kj::NetworkAddress>&& addr) {
 | 
			
		||||
        acceptHttpClient(addr->listen());
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Server::~Server() {
 | 
			
		||||
@ -392,7 +392,10 @@ void Server::acceptHttpClient(kj::Own<kj::ConnectionReceiver>&& listener) {
 | 
			
		||||
                            kj::Own<kj::AsyncIoStream>&& connection) {
 | 
			
		||||
            acceptHttpClient(kj::mv(listener));
 | 
			
		||||
            auto conn = kj::heap<WebsocketConnection>(kj::mv(connection), *httpInterface);
 | 
			
		||||
            return conn->pend().exclusiveJoin(conn->writeTask()).attach(std::move(conn));
 | 
			
		||||
            auto promises = kj::heapArrayBuilder<kj::Promise<void>>(2);
 | 
			
		||||
            promises.add(std::move(conn->pend()));
 | 
			
		||||
            promises.add(std::move(conn->writeTask()));
 | 
			
		||||
            return kj::joinPromises(promises.finish()).attach(std::move(conn));
 | 
			
		||||
        }))
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
@ -412,9 +415,8 @@ void Server::acceptRpcClient(kj::Own<kj::ConnectionReceiver>&& listener) {
 | 
			
		||||
// handles stdout/stderr from a child process by sending it to the provided
 | 
			
		||||
// callback function
 | 
			
		||||
kj::Promise<void> Server::handleProcessOutput(kj::AsyncInputStream* stream, std::function<void(char*,size_t)> readCb) {
 | 
			
		||||
    // TODO think about this size
 | 
			
		||||
    static char* buffer = new char[1024];
 | 
			
		||||
    return stream->tryRead(buffer, 1, 1024).then([this,stream,readCb](size_t sz) {
 | 
			
		||||
    static char* buffer = new char[131072];
 | 
			
		||||
    return stream->tryRead(buffer, 1, sizeof(buffer)).then([this,stream,readCb](size_t sz) {
 | 
			
		||||
        readCb(buffer, sz);
 | 
			
		||||
        if(sz > 0) {
 | 
			
		||||
            return handleProcessOutput(stream, readCb);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user