Progress.

This commit is contained in:
retoor 2024-12-31 15:26:13 +01:00
parent e781dfa22d
commit df0c215ff9
8 changed files with 3021 additions and 0 deletions

8
.gitignore vendored
View File

@ -3,3 +3,11 @@
.backup*
a.out
__pycache__
.venv/
gen_pages.py
html/
latex/
mkdocs.yml
pgs
site/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "doxygen-awesome-css"]
path = doxygen-awesome-css
url = https://github.com/jothepro/doxygen-awesome-css.git

2869
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

21
docs/index.md Normal file
View File

@ -0,0 +1,21 @@
# Pretty Good Server API
# Reference
::: pgscript
::: pgs
For project page visit [molodetz.nl](https://molodetz.nl).
## Commands
* `build build` - Builds application and formats source.
* `build run` - Builds application and runs it.
## Project layout
pgs.c # Main application.
py.h # Python plugin handler.
pgscript.py # Script to be defined by user.
pgs.py # Dummy file representing the pgs api.
pgs_api.h # Actual C application.

1
doxygen-awesome-css Submodule

@ -0,0 +1 @@
Subproject commit af1d9030b3ffa7b483fa9997a7272fb12af6af4c

1
features.md Normal file
View File

@ -0,0 +1 @@
# Features

20
pgs.py Normal file
View File

@ -0,0 +1,20 @@
def is_http(header_bytes: bytes) -> bool:
"""
Returns True if the header is an HTTP request.
"""
def is_ssh(header_bytes: bytes) -> bool:
"""
Returns True if the header is an SSH request.
"""
def write(fd: int, header_bytes: bytes) -> int:
"""
Sends data chunked to the client.
"""
def read(fd: int, length: int) -> bytes:
"""
Read n bytes from the client. Will not block.
"""

98
pgs_api.h Normal file
View File

@ -0,0 +1,98 @@
#define PY_SSIZE_T_CLEAN 1
#include <Python.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
static PyObject *pgs_api_is_http(PyObject *self, PyObject *args) {
const char *py_bytes;
if (!PyArg_ParseTuple(args, "y", &py_bytes)) {
return NULL;
}
bool is_http = strstr(py_bytes, "HTTP/") != NULL;
return is_http ? Py_True : Py_False;
}
static PyObject *pgs_api_is_ssh(PyObject *self, PyObject *args) {
const char *py_bytes;
if (!PyArg_ParseTuple(args, "y", &py_bytes)) {
return NULL;
}
bool is_ssh = strstr(py_bytes, "SSH") != NULL;
return is_ssh ? Py_True : Py_False;
}
static PyObject *pgs_api_read(PyObject *self, PyObject *args) {
int fd, length;
if (!PyArg_ParseTuple(args, "ii", &fd, &length)) {
return NULL;
}
char buffer[length + 1];
ssize_t bytes_read = read(fd, buffer, length);
buffer[bytes_read] = 0;
Py_buffer *pybuffer = (Py_buffer *)malloc(bytes_read);
PyBuffer_FillInfo(pybuffer, 0, &buffer, bytes_read, false, PyBUF_CONTIG);
return PyMemoryView_FromBuffer(pybuffer);
}
static PyObject *pgs_api_write(PyObject *self, PyObject *args) {
int fd, length;
const char *input_data;
Py_ssize_t input_length;
if (!PyArg_ParseTuple(args, "is", &fd, &input_data, &input_length)) {
return NULL;
}
ssize_t bytes_sent_total = 0;
input_length = strlen(input_data);
while (true) {
ssize_t bytes_sent =
send(fd, input_data + bytes_sent_total, input_length, 0);
if (bytes_sent < 1) {
return PyLong_FromSsize_t(bytes_sent);
}
bytes_sent_total += bytes_sent;
if (bytes_sent_total == input_length) {
break;
}
}
return PyLong_FromSsize_t(input_length);
}
// A simple function: add two numbers
static PyObject *mymodule_add(PyObject *self, PyObject *args) {
double a, b, result;
if (!PyArg_ParseTuple(args, "dd", &a, &b)) {
return NULL;
}
result = a + b;
return PyFloat_FromDouble(result);
}
// Method table for the module
static PyMethodDef MyModuleMethods[] = {
{"add", mymodule_add, METH_VARARGS, "Add two numbers"},
{"read", pgs_api_read, METH_VARARGS, "Read fd"},
{"write", pgs_api_write, METH_VARARGS, "Write fd"},
{"is_ssh", pgs_api_is_ssh, METH_VARARGS,
"Check if header contains SSH data."},
{"is_http", pgs_api_is_http, METH_VARARGS,
"Check if header contains HTTP data."},
{NULL, NULL, 0, NULL} // Sentinel
};
// Module definition structure
static struct PyModuleDef mymodule = {
PyModuleDef_HEAD_INIT,
"pgs", // Module name
"Pretty Good Server API.", // Module docstring
-1, // Size of per-interpreter state of the module
MyModuleMethods // Methods
};
// Module initialization function
PyMODINIT_FUNC PyInit_mymodule(void) { return PyModule_Create(&mymodule); }