123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- #
- # Simple CMS
- #
- # Copyright (C) 2011-2024 Michael Büsch <m@bues.ch>
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- import sys
- sys.path.insert(0, "/opt/cms/lib/python3/site-packages/")
- import os, fcntl, socket, atexit, time
- try:
- from cms_cython.socket import *
- from cms_cython import CMS, CMSException
- except ImportError as e:
- print("cms-backd: Failed to import cms_cython:", e, file=sys.stderr)
- from cms.socket import *
- from cms import CMS, CMSException
- def init_systemd():
- notify_socket = os.getenv("NOTIFY_SOCKET")
- if not notify_socket:
- raise ValueError("env: NOTIFY_SOCKET not set.")
- listen_fds = os.getenv("LISTEN_FDS")
- if not listen_fds:
- raise ValueError("env: LISTEN_FDS not set.")
- listen_fds = int(listen_fds, 10)
- if listen_fds <= 0 or listen_fds > 1:
- raise ValueError("env: Invalid LISTEN_FDS.")
- with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) as sdsock:
- sdsock.connect(notify_socket)
- fd = 3
- for i in range(fd, fd + listen_fds):
- fcntl.fcntl(i, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- backsock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
- sdsock.sendall(b"READY=1")
- return backsock
- def run_backd(backsock):
- cms = CMS(domain="", debug=True)
- atexit.register(cms.shutdown)
- while True:
- try:
- conn, addr = backsock.accept()
- msg = recv_message(conn, MAGIC_BACK)
- except Exception as e:
- print(f"cms-backd: Receive failed: {e}", file=sys.stderr)
- continue
- if cms.debug:
- startStamp = time.monotonic()
- status = 200 # Ok
- reply_body = b""
- reply_mime = ""
- extra_headers = []
- try:
- if isinstance(msg, MsgGet):
- cms.domain = msg.host
- protocol = "https" if msg.https else "http"
- reply_body, reply_mime = cms.get(msg.path, msg.query, protocol)
- elif isinstance(msg, MsgPost):
- cms.domain = msg.host
- protocol = "https" if msg.https else "http"
- reply_body, reply_mime = cms.post(msg.path, msg.query, msg.body, msg.body_mime, protocol)
- else:
- raise RuntimeError("Received invalid message.")
- except CMSException as e:
- status = e.httpStatusCode
- reply_body, reply_mime, extra_headers = cms.getErrorPage(e, protocol)
- if cms.debug and "html" in reply_mime:
- delta = time.monotonic() - startStamp
- ms = delta * 1e3
- reply_body += ("\n<!-- generated in %.3f ms -->" % ms).encode("UTF-8", "ignore")
- reply = MsgReply(
- status=status,
- body=reply_body,
- mime=reply_mime,
- extra_headers=extra_headers,
- )
- reply_data = reply.pack()
- try:
- conn.sendall(reply_data)
- except Exception as e:
- print(f"cms-backd: Failed to send reply: {e}", file=sys.stderr)
- continue
- if __name__ == "__main__":
- run_backd(init_systemd())
- # vim: ts=4 sw=4 expandtab
|