Added VERY experimental (untested) networking code

This commit is contained in:
nocturn9x 2021-12-27 11:17:24 +01:00
parent fea5e625e2
commit 2f107f7f28
4 changed files with 98 additions and 6 deletions

View File

@ -11,3 +11,26 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import net
import strformat
import shutdown
import ../util/logging
import ../util/misc
proc initControlSocket*(logger: Logger, path: string = "/var/run/nimd.sock"): Socket =
## Initializes NimD's control socket (an unbuffered
## TCP Unix Domain Socket) binding it to the given
## path (defaults to /var/run/nimd.sock)
try:
logger.info(&"Initializing control socket at '{path}'")
if exists(path):
removeFile(path)
result = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP, buffered=false)
bindUnix(result, path)
except OSError:
logger.error(&"Error when binding unix socket at '{path}': {getCurrentExceptionMsg()}")
nimDExit(logger, code=int(osLastError()))

View File

@ -13,10 +13,13 @@
# limitations under the License.
import strformat
import os
import net
import ../util/[logging, misc]
import services
import control
import shutdown
@ -27,10 +30,43 @@ proc mainLoop*(logger: Logger) =
logger.debug(&"Unblocking signals")
unblockSignals(logger)
logger.info("System initialization complete, going idle")
logger.switchToFile()
var opType: string
try:
logger.trace("Calling initControlSocket()")
var serverSocket = initControlSocket(logger)
serverSocket.listen(5)
var clientSocket = newSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
# logger.switchToFile()
while true:
sleepSeconds(30)
serverSocket.accept(clientSocket)
if clientSocket.recv(opType, size=1) == 0:
logger.debug(&"Client has disconnected, waiting for new connection")
continue
logger.debug(&"Received operation type '{opType}' via control socket")
# The operation type is a single byte:
# - 'p' -> poweroff
# - 'r' -> reboot
# - 'h' -> halt
# - 's' -> Services-related operations (start, stop, get status, etc.)
case opType:
of "":
logger.debug(&"Empty read from control socket: did the client disconnect?")
continue
of "p":
logger.info("Received shutdown request")
shutdown(logger)
of "r":
logger.info("Received reboot request")
reboot(logger)
of "h":
logger.info("Received halt request")
halt(logger)
of "s":
discard # TODO
else:
logger.warning(&"Received unknown operation type '{opType}' via control socket, ignoring it")
discard
clientSocket.close()
except:
logger.critical(&"A critical error has occurred while running, restarting the mainloop in 30 seconds! Error -> {getCurrentExceptionMsg()}")
sleepSeconds(30)

View File

@ -327,8 +327,9 @@ proc startService(logger: Logger, service: Service) =
elif pid == 0:
logger.trace(&"New child has been spawned")
supervisorWorker(logger, service, process)
# If the service is unsupervised we just spawn the logger worker
loggerWorker(logger, service, process)
# If the service is unsupervised we just spawn the logger worker (assuming it doesn't use poParentStreams)
if not service.useParentStreams:
loggerWorker(logger, service, process)
except:
logger.error(&"Error while starting service '{service.name}': {getCurrentExceptionMsg()}")

View File

@ -18,6 +18,8 @@ import glob
import strutils
import strformat
import times
import tables
import syscall
import ../util/logging
@ -29,6 +31,9 @@ type ShutdownHandler* = ref object
body*: proc (logger: Logger, code: int)
const reboot_codes = {"poweroff": 0x4321fedc'i64, "restart": 0x01234567'i64, "halt": 0xcdef0123}.toTable()
proc newShutdownHandler*(body: proc (logger: Logger, code: int)): ShutdownHandler =
result = ShutdownHandler(body: body)
@ -80,6 +85,7 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
## NimD's exit point. This function tries to shut down
## as cleanly as possible. When emerg equals true, it will
## try to spawn a root shell and exit
logger.switchToConsole()
if emerg:
# We're in emergency mode: do not crash the kernel, spawn a shell and exit
logger.fatal("NimD has entered emergency mode and cannot continue. You will be now (hopefully) dropped in a root shell: you're on your own. May the force be with you")
@ -89,7 +95,7 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
quit(-1)
logger.warning("The system is shutting down")
logger.info("Processing shutdown runlevel")
startServices(logger, Shutdown)
startServices(logger, RunLevel.Shutdown)
logger.info("Running shutdown handlers")
try:
for handler in shutdownHandlers:
@ -108,4 +114,30 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
logger.info("Terminating child processes with SIGKILL")
discard posix.kill(-1, SIGKILL)
logger.warning("Shutdown procedure complete, sending final termination signal")
quit(code)
proc reboot*(logger: Logger) =
## Reboots the system
logger.debug("Switching logs to console")
logger.switchToConsole()
logger.info("The system is rebooting")
nimDExit(logger, 0, emerg=false)
discard syscall(REBOOT, 0xfee1dead, 537993216, reboot_codes["reboot"])
proc shutdown*(logger: Logger) =
## Shuts the system off
logger.debug("Switching logs to console")
logger.switchToConsole()
logger.info("The system is powering off")
nimDExit(logger, 0, emerg=false)
discard syscall(REBOOT, 0xfee1dead, 537993216, reboot_codes["poweroff"])
proc halt*(logger: Logger) =
## Halts the system
logger.debug("Switching logs to console")
logger.switchToConsole()
logger.info("The system is halting")
nimDExit(logger, 0, emerg=false)
discard syscall(REBOOT, 0xfee1dead, 537993216, reboot_codes["halt"])