view seobeo/examples/sse_server_example.c @ 272:41a49c29a28f

polish JRPG conversation experience Integrate desktop conversations into the utility panel, simplify the mobile frame, add modal destinations and a reusable Zenbu composer lab, and preserve explicit conversation resume behavior. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 16:05:29 -0700
parents 1f9877b637e9
children
line wrap: on
line source

#include "seobeo/seobeo.h"

#include <stdio.h>
#include <unistd.h>

static void Send_Later(void *p_context)
{
  Seobeo_SSE_Stream *p_stream = p_context;
  usleep(100000);
  if (Seobeo_SSE_Is_Open(p_stream))
    Seobeo_SSE_Send_Data(p_stream, "later");
}

static void Release_Stream(void *p_context)
{
  Seobeo_SSE_Release(p_context);
}

static void Events(
    Seobeo_SSE_Stream *p_stream,
    Seobeo_Request_Entry *p_request,
    Dowa_Arena *p_arena)
{
  (void)p_request;
  (void)p_arena;
  Seobeo_SSE_Send_Data(p_stream, "connected");
  if (Seobeo_SSE_Retain(p_stream))
  {
    Seobeo_Worker_Result result = Seobeo_Thread_Start_Detached(
        Send_Later,
        p_stream,
        Release_Stream);
    if (result != SEOBEO_WORKER_OK)
      Seobeo_SSE_Release(p_stream);
  }
}

static void Post_Events(
    Seobeo_SSE_Stream *p_stream,
    Seobeo_Request_Entry *p_request,
    Dowa_Arena *p_arena)
{
  (void)p_arena;
  Seobeo_Request_Entry *p_topic =
      Dowa_HashMap_Get_Ptr(p_request, ":topic");
  Seobeo_Request_Entry *p_body =
      Dowa_HashMap_Get_Ptr(p_request, "Body");
  char event[256];
  int length = snprintf(
      event,
      sizeof(event),
      "topic=%s body=%s",
      p_topic ? p_topic->value : "",
      p_body ? p_body->value : "");
  if (length > 0 && (size_t)length < sizeof(event))
    Seobeo_SSE_Send_Data(p_stream, event);
}

static Seobeo_Request_Entry *Health(
    Seobeo_Request_Entry *p_request,
    Dowa_Arena *p_arena)
{
  (void)p_request;
  Seobeo_Request_Entry *p_response = NULL;
  Dowa_HashMap_Push_Arena(p_response, "status", "200", p_arena);
  Dowa_HashMap_Push_Arena(
      p_response,
      "content-type",
      "text/plain",
      p_arena);
  Dowa_HashMap_Push_Arena(p_response, "body", "ok", p_arena);
  return p_response;
}

int main(int argc, char **argv)
{
  const char *port = argc > 1 ? argv[1] : "18081";
  Seobeo_Router_Init();
  Seobeo_Router_Register_SSE("/events", Events);
  Seobeo_Router_Register_SSE_Method(
      "POST",
      "/events/:topic",
      Post_Events);
  Seobeo_Router_Register("GET", "/health", Health);
  int result = Seobeo_Web_Server_Start_On(
      "127.0.0.1",
      "seobeo/examples",
      port,
      SEOBEO_MODE_EDGE,
      1);
  Seobeo_Router_Destroy();
  return result;
}