From ee2667bb1a9c792ae20347ec075afd216b750837 Mon Sep 17 00:00:00 2001 From: flamingcow Date: Sun, 5 May 2019 00:11:57 -0700 Subject: [PATCH] example_clock building and working --- .gitignore | 3 +++ .gitmodules | 3 +++ Makefile | 22 ++++++++++++++++++++++ example_clock.cc | 25 +++++++++++++++++++++++++ firecgi | 1 + firesse.cc | 30 ++++++++++++++++++++++++++++++ firesse.h | 20 ++++++++++++++++++++ stream.cc | 30 ++++++++++++++++++++++++++++++ stream.h | 20 ++++++++++++++++++++ 9 files changed, 154 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 example_clock.cc create mode 160000 firecgi create mode 100644 firesse.cc create mode 100644 firesse.h create mode 100644 stream.cc create mode 100644 stream.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78bbc39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +*.a +example_clock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5c30d06 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "firecgi"] + path = firecgi + url = git@github.com:firestuff/firecgi.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b43042d --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +FIRE_CXX ?= clang++ +FIRE_CXXFLAGS ?= -O3 -std=gnu++2a -Wall -Werror +FIRE_LDLIBS ?= -lgflags -lglog -lpthread + +all: firesse.a example_clock + +objects = firesse.o stream.o + +firesse.a: $(objects) + $(MAKE) --directory=firecgi + ar rcs $@ $^ + +example_clock: example_clock.o $(objects) + $(MAKE) --directory=firecgi + $(FIRE_CXX) $(FIRE_CXXFLAGS) -o $@ $+ firecgi/firecgi.a firecgi/firebuf/firebuf.a $(FIRE_LDLIBS) + +%.o: %.cc *.h Makefile + $(FIRE_CXX) $(FIRE_CXXFLAGS) -c -o $@ $< + +clean: + $(MAKE) --directory=firecgi clean + rm --force example_clock *.o *.a diff --git a/example_clock.cc b/example_clock.cc new file mode 100644 index 0000000..fb63441 --- /dev/null +++ b/example_clock.cc @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "firesse.h" + +DEFINE_int32(port, 9000, "TCP port to bind"); + +int main(int argc, char *argv[]) { + google::InitGoogleLogging(argv[0]); + gflags::ParseCommandLineFlags(&argc, &argv, true); + + firesse::Server server(FLAGS_port, [](std::unique_ptr stream) { + while (true) { + timeval tv; + PCHECK(gettimeofday(&tv, nullptr) == 0); + uint64_t time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (!stream->WriteEvent(std::to_string(time_ms), 0, "time")) { + break; + } + sleep(1); + } + }); + server.Serve(); +} diff --git a/firecgi b/firecgi new file mode 160000 index 0000000..09c4ce2 --- /dev/null +++ b/firecgi @@ -0,0 +1 @@ +Subproject commit 09c4ce2290d909f7d7b103d25942def3617b4fbe diff --git a/firesse.cc b/firesse.cc new file mode 100644 index 0000000..d8192e1 --- /dev/null +++ b/firesse.cc @@ -0,0 +1,30 @@ +#include "firesse.h" + +namespace firesse { + +Server::Server(int port, const std::function)>& callback) + : callback_(callback), + firecgi_server_(port, + [this](std::unique_ptr request) { OnRequest(std::move(request)); }, + 1, + {"HTTP_ACCEPT"}) {} + +void Server::Serve() { + firecgi_server_.Serve(); +} + +void Server::OnRequest(std::unique_ptr request) { + if (request->GetParam("HTTP_ACCEPT") != "text/event-stream") { + LOG(WARNING) << "bad HTTP_ACCEPT: " << request->GetParam("HTTP_ACCEPT"); + request->WriteHeader("Status", "400 Bad Request"); + request->WriteHeader("Content-Type", "text-plain"); + request->WriteBody("No \"Accept: text/event-stream\" header found in request. Please call this endpoint using EventSource."); + request->End(); + return; + } + request->WriteHeader("Content-Type", "text/event-stream"); + request->WriteBody(""); + callback_(std::make_unique(std::move(request))); +} + +} // namespace firesse diff --git a/firesse.h b/firesse.h new file mode 100644 index 0000000..2cb02f4 --- /dev/null +++ b/firesse.h @@ -0,0 +1,20 @@ +#pragma once + +#include "firecgi/firecgi.h" +#include "stream.h" + +namespace firesse { + +class Server { + public: + Server(int port, const std::function)>& callback); + void Serve(); + + private: + void OnRequest(std::unique_ptr request); + + std::function)> callback_; + firecgi::Server firecgi_server_; +}; + +} // namespace firesse diff --git a/stream.cc b/stream.cc new file mode 100644 index 0000000..b6fc372 --- /dev/null +++ b/stream.cc @@ -0,0 +1,30 @@ +#include "stream.h" + +namespace firesse { + +Stream::Stream(std::unique_ptr request) + : request_(std::move(request)) {} + +bool Stream::WriteEvent(const std::string& data, uint64_t id, const std::string& type) { + if (id) { + request_->WriteBody("id: "); + request_->WriteBody(std::to_string(id)); + request_->WriteBody("\n"); + } + if (!type.empty()) { + request_->WriteBody("event: "); + request_->WriteBody(type); + request_->WriteBody("\n"); + } + request_->WriteBody("data: "); + request_->WriteBody(data); + request_->WriteBody("\n\n"); + + return request_->Flush(); +} + +bool Stream::End() { + return request_->End(); +} + +} // namespace firesse diff --git a/stream.h b/stream.h new file mode 100644 index 0000000..534d619 --- /dev/null +++ b/stream.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "firecgi/request.h" + +namespace firesse { + +class Stream { + public: + Stream(std::unique_ptr request); + + [[nodiscard]] bool WriteEvent(const std::string& data, uint64_t id=0, const std::string& type=""); + bool End(); + + private: + std::unique_ptr request_; +}; + +} // namespace firesse