ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
stdio.c
Go to the documentation of this file.
1#include "mcp.h"
2#include <stdio.h>
3#include <string.h>
4#include <stdlib.h>
5
6static int protocol_fd = -1;
8 protocol_fd = platform_dup(STDOUT_FILENO);
9 if (protocol_fd < 0)
10 return SET_ERRNO(ERROR_FILE_OPERATION, "Cannot reserve MCP stdout");
11 return platform_dup2(STDERR_FILENO, STDOUT_FILENO);
12}
14 if (protocol_fd >= 0) {
15 platform_close(protocol_fd);
16 protocol_fd = -1;
17 }
18}
19void mcp_stdio_send(mcp_server_t *s, yyjson_mut_doc *response) {
20 size_t size;
21 char *json = yyjson_mut_write(response, 0, &size);
22 if (!json)
23 return;
24 mutex_lock(&s->output_mutex);
25 bool ok = platform_write_all(protocol_fd, json, size) == size && platform_write_all(protocol_fd, "\n", 1) == 1;
26 mutex_unlock(&s->output_mutex);
27 free(json); // yyjson owns allocations made by its default allocator.
28 if (!ok)
29 atomic_store_bool(&s->stopping, true);
30}
32 char *line = SAFE_MALLOC(MCP_MAX_INPUT + 1, char *);
33 size_t n = 0;
34 bool overflow = false;
35 while (!atomic_load_bool(&s->stopping)) {
36 int c = fgetc(stdin);
37 if (c == EOF)
38 break;
39 if (c != '\n') {
40 if (n < MCP_MAX_INPUT)
41 line[n++] = (char)c;
42 else
43 overflow = true;
44 continue;
45 }
46 if (n && line[n - 1] == '\r')
47 --n;
48 if (!n && !overflow)
49 continue;
50 yyjson_doc *doc = overflow ? NULL : yyjson_read(line, n, YYJSON_READ_NOFLAG);
51 bool pending = false;
52 yyjson_mut_doc *response =
53 doc ? mcp_dispatch(s, doc, NULL, NULL, &pending)
54 : mcp_error(NULL, overflow ? -32600 : -32700, overflow ? "Request exceeds 24 MiB" : "Parse error");
55 if (response) {
56 mcp_stdio_send(s, response);
57 yyjson_mut_doc_free(response);
58 }
59 if (doc)
60 yyjson_doc_free(doc);
61 n = 0;
62 overflow = false;
63 mcp_jobs_reap(s, false);
64 }
65 SAFE_FREE(line);
66 for (unsigned i = 0; i < s->policy.max_jobs; ++i)
67 if (s->jobs[i].renderer_job.started)
69 mcp_jobs_reap(s, true);
70 return ASCIICHAT_OK;
71}
#define SET_ERRNO(code,...)
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_MALLOC(size, cast)
Definition common.h:265
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_FILE_OPERATION
asciichat_error_t platform_dup2(int source_fd, int target_fd)
size_t platform_write_all(int fd, const void *buf, size_t count)
Write all bytes to a file descriptor, handling partial writes.
int platform_dup(int fd)
void http_renderer_job_cancel(http_renderer_job_t *job)
#define MCP_MAX_INPUT
Definition mcp.h:29
yyjson_mut_doc * mcp_error(yyjson_val *id, int code, const char *message)
yyjson_mut_doc * mcp_dispatch(mcp_server_t *server, yyjson_doc *message, void *connection, const char *session_id, bool *pending)
struct mcp_server mcp_server_t
The useful part of mcp job is in server, message, response, request: together they describe what is p...
void mcp_jobs_reap(mcp_server_t *server, bool all)
asciichat_error_t mcp_stdio_reserve(void)
Definition stdio.c:7
asciichat_error_t mcp_stdio_run(mcp_server_t *s)
Definition stdio.c:31
void mcp_stdio_send(mcp_server_t *s, yyjson_mut_doc *response)
Definition stdio.c:19
void mcp_stdio_release(void)
Definition stdio.c:13
🔤 String Manipulation and Shell Escaping Utilities
http_renderer_job_t renderer_job
Definition mcp.h:67
unsigned max_jobs
Definition mcp.h:41
mutex_t output_mutex
Definition mcp.h:83
atomic_t stopping
Definition mcp.h:85
mcp_job_t * jobs
Definition mcp.h:82
mcp_policy_t policy
Definition mcp.h:81