mirror of https://github.com/nocturn9x/nimd.git
Added VERY experimental (untested) networking code
This commit is contained in:
parent
fea5e625e2
commit
2f107f7f28
|
@ -11,3 +11,26 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# 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()))
|
|
@ -13,10 +13,13 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import strformat
|
import strformat
|
||||||
import os
|
import os
|
||||||
|
import net
|
||||||
|
|
||||||
|
|
||||||
import ../util/[logging, misc]
|
import ../util/[logging, misc]
|
||||||
import services
|
import services
|
||||||
|
import control
|
||||||
|
import shutdown
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,10 +30,43 @@ proc mainLoop*(logger: Logger) =
|
||||||
logger.debug(&"Unblocking signals")
|
logger.debug(&"Unblocking signals")
|
||||||
unblockSignals(logger)
|
unblockSignals(logger)
|
||||||
logger.info("System initialization complete, going idle")
|
logger.info("System initialization complete, going idle")
|
||||||
logger.switchToFile()
|
var opType: string
|
||||||
try:
|
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:
|
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:
|
except:
|
||||||
logger.critical(&"A critical error has occurred while running, restarting the mainloop in 30 seconds! Error -> {getCurrentExceptionMsg()}")
|
logger.critical(&"A critical error has occurred while running, restarting the mainloop in 30 seconds! Error -> {getCurrentExceptionMsg()}")
|
||||||
sleepSeconds(30)
|
sleepSeconds(30)
|
||||||
|
|
|
@ -327,7 +327,8 @@ proc startService(logger: Logger, service: Service) =
|
||||||
elif pid == 0:
|
elif pid == 0:
|
||||||
logger.trace(&"New child has been spawned")
|
logger.trace(&"New child has been spawned")
|
||||||
supervisorWorker(logger, service, process)
|
supervisorWorker(logger, service, process)
|
||||||
# If the service is unsupervised we just spawn the logger worker
|
# 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)
|
loggerWorker(logger, service, process)
|
||||||
except:
|
except:
|
||||||
logger.error(&"Error while starting service '{service.name}': {getCurrentExceptionMsg()}")
|
logger.error(&"Error while starting service '{service.name}': {getCurrentExceptionMsg()}")
|
||||||
|
|
|
@ -18,6 +18,8 @@ import glob
|
||||||
import strutils
|
import strutils
|
||||||
import strformat
|
import strformat
|
||||||
import times
|
import times
|
||||||
|
import tables
|
||||||
|
import syscall
|
||||||
|
|
||||||
|
|
||||||
import ../util/logging
|
import ../util/logging
|
||||||
|
@ -29,6 +31,9 @@ type ShutdownHandler* = ref object
|
||||||
body*: proc (logger: Logger, code: int)
|
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 =
|
proc newShutdownHandler*(body: proc (logger: Logger, code: int)): ShutdownHandler =
|
||||||
result = ShutdownHandler(body: body)
|
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
|
## NimD's exit point. This function tries to shut down
|
||||||
## as cleanly as possible. When emerg equals true, it will
|
## as cleanly as possible. When emerg equals true, it will
|
||||||
## try to spawn a root shell and exit
|
## try to spawn a root shell and exit
|
||||||
|
logger.switchToConsole()
|
||||||
if emerg:
|
if emerg:
|
||||||
# We're in emergency mode: do not crash the kernel, spawn a shell and exit
|
# 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")
|
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)
|
quit(-1)
|
||||||
logger.warning("The system is shutting down")
|
logger.warning("The system is shutting down")
|
||||||
logger.info("Processing shutdown runlevel")
|
logger.info("Processing shutdown runlevel")
|
||||||
startServices(logger, Shutdown)
|
startServices(logger, RunLevel.Shutdown)
|
||||||
logger.info("Running shutdown handlers")
|
logger.info("Running shutdown handlers")
|
||||||
try:
|
try:
|
||||||
for handler in shutdownHandlers:
|
for handler in shutdownHandlers:
|
||||||
|
@ -108,4 +114,30 @@ proc nimDExit*(logger: Logger, code: int, emerg: bool = true) =
|
||||||
logger.info("Terminating child processes with SIGKILL")
|
logger.info("Terminating child processes with SIGKILL")
|
||||||
discard posix.kill(-1, SIGKILL)
|
discard posix.kill(-1, SIGKILL)
|
||||||
logger.warning("Shutdown procedure complete, sending final termination signal")
|
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"])
|
||||||
|
|
Loading…
Reference in New Issue