Progress.
This commit is contained in:
parent
e781dfa22d
commit
df0c215ff9
8
.gitignore
vendored
8
.gitignore
vendored
@ -3,3 +3,11 @@
|
||||
.backup*
|
||||
a.out
|
||||
__pycache__
|
||||
.venv/
|
||||
gen_pages.py
|
||||
html/
|
||||
latex/
|
||||
mkdocs.yml
|
||||
pgs
|
||||
site/
|
||||
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "doxygen-awesome-css"]
|
||||
path = doxygen-awesome-css
|
||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
21
docs/index.md
Normal file
21
docs/index.md
Normal 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
1
doxygen-awesome-css
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit af1d9030b3ffa7b483fa9997a7272fb12af6af4c
|
1
features.md
Normal file
1
features.md
Normal file
@ -0,0 +1 @@
|
||||
# Features
|
20
pgs.py
Normal file
20
pgs.py
Normal 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
98
pgs_api.h
Normal 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); }
|
Loading…
Reference in New Issue
Block a user