Dns manager daemon and clients can be built, once again.
This commit is contained in:
parent
ee7d20cc21
commit
a78eb8c889
@ -22,9 +22,9 @@ dependencies:
|
|||||||
|
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
dnsmanager:
|
dnsmanagerd:
|
||||||
main: src/main.cr
|
main: src/main.cr
|
||||||
dnsmanager-client:
|
dnsmanager-client:
|
||||||
main: src/client/main.cr
|
main: src/client/main.cr
|
||||||
|
|
||||||
license: MIT
|
license: ISC
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
require "../../requests/*"
|
require "../../requests/*"
|
||||||
|
|
||||||
class DNSManager::Client < IPC::Client
|
class DNSManager::Client < IPC
|
||||||
|
property server_fd : Int32 = -1
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
initialize "dnsmanager"
|
super()
|
||||||
|
fd = self.connect "dnsmanager"
|
||||||
|
if fd.nil?
|
||||||
|
raise "couldn't connect to 'auth' IPC service"
|
||||||
|
end
|
||||||
|
@server_fd = fd
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: parse_message should raise exception if response not anticipated
|
# TODO: parse_message should raise exception if response not anticipated
|
||||||
@ -14,33 +21,50 @@ class DNSManager::Client < IPC::Client
|
|||||||
em << DNSManager::Response::Error
|
em << DNSManager::Response::Error
|
||||||
em.parse_ipc_json message
|
em.parse_ipc_json message
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
# Simple users.
|
# Simple users.
|
||||||
class DNSManager::Client < IPC::Client
|
#
|
||||||
|
|
||||||
def login(token : String)
|
def login(token : String)
|
||||||
request = DNSManager::Request::Login.new token
|
request = DNSManager::Request::Login.new token
|
||||||
send_now @server_fd.not_nil!, request
|
send_now request
|
||||||
parse_message [ DNSManager::Response::Success ], read
|
parse_message [ DNSManager::Response::Success ], read
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adding a full zone.
|
# Adding a full zone.
|
||||||
def user_zone_add(zone : DNSManager::Storage::Zone)
|
def user_zone_add(zone : DNSManager::Storage::Zone)
|
||||||
request = DNSManager::Request::AddOrUpdateZone.new zone
|
request = DNSManager::Request::AddOrUpdateZone.new zone
|
||||||
send_now @server_fd.not_nil!, request
|
send_now request
|
||||||
parse_message [ DNSManager::Response::Success, DNSManager::Response::InvalidZone ], read
|
parse_message [ DNSManager::Response::Success, DNSManager::Response::InvalidZone ], read
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
#
|
||||||
# Admin stuff.
|
# Admin stuff.
|
||||||
class DNSManager::Client < IPC::Client
|
#
|
||||||
|
|
||||||
def admin_maintainance(key : String, subject : DNSManager::Request::Maintainance::Subject, value : Int32? = nil)
|
def admin_maintainance(key : String, subject : DNSManager::Request::Maintainance::Subject, value : Int32? = nil)
|
||||||
request = DNSManager::Request::Maintainance.new(key,subject)
|
request = DNSManager::Request::Maintainance.new(key,subject)
|
||||||
if value
|
if value
|
||||||
request.value = value
|
request.value = value
|
||||||
end
|
end
|
||||||
send_now @server_fd.not_nil!, request
|
send_now request
|
||||||
parse_message [ DNSManager::Response::Success ], read
|
parse_message [ DNSManager::Response::Success ], read
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_now(msg : IPC::JSON)
|
||||||
|
m = IPCMessage::TypedMessage.new msg.type.to_u8, msg.to_json
|
||||||
|
write @server_fd, m
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_now(type : Request::Type, payload)
|
||||||
|
m = IPCMessage::TypedMessage.new type.value.to_u8, payload
|
||||||
|
write @server_fd, m
|
||||||
|
end
|
||||||
|
|
||||||
|
def read
|
||||||
|
slice = self.read @server_fd
|
||||||
|
m = IPCMessage::TypedMessage.deserialize slice
|
||||||
|
m.not_nil!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
54
src/main.cr
54
src/main.cr
@ -24,22 +24,29 @@ require "./storage.cr"
|
|||||||
require "./network.cr"
|
require "./network.cr"
|
||||||
|
|
||||||
|
|
||||||
class DNSManager::Service < IPC::Server
|
class DNSManager::Service < IPC
|
||||||
property configuration : Baguette::Configuration::DNSManager
|
property configuration : Baguette::Configuration::DNSManager
|
||||||
getter storage : DNSManager::Storage
|
getter storage : DNSManager::Storage
|
||||||
getter logged_users : Hash(Int32, AuthD::User::Public)
|
getter logged_users : Hash(Int32, AuthD::User::Public)
|
||||||
|
|
||||||
property authd : AuthD::Client
|
property authd : AuthD::Client
|
||||||
|
|
||||||
def initialize(@configuration, @authd : AuthD::Client)
|
def initialize(@configuration, @authd_key : String)
|
||||||
@storage = DNSManager::Storage.new @configuration.storage_directory
|
super()
|
||||||
|
@storage = DNSManager::Storage.new @configuration.storage_directory, @configuration.recreate_indexes
|
||||||
|
|
||||||
@logged_users = Hash(Int32, AuthD::User::Public).new
|
@logged_users = Hash(Int32, AuthD::User::Public).new
|
||||||
|
|
||||||
super @configuration.service_name
|
# TODO: auth service isn't in the FDs pool.
|
||||||
|
# If the service crashes, dnsmanagerd won't know it.
|
||||||
|
@authd = AuthD::Client.new
|
||||||
|
authd.key = @authd_key
|
||||||
|
|
||||||
|
self.timer @configuration.ipc_timer
|
||||||
|
self.service_init @configuration.service_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_logged_user(event : IPC::Event::Events)
|
def get_logged_user(event : IPC::Event)
|
||||||
@logged_users[event.fd]?
|
@logged_users[event.fd]?
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -47,10 +54,13 @@ class DNSManager::Service < IPC::Server
|
|||||||
@authd.decode_token token
|
@authd.decode_token token
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_request(event : IPC::Event::MessageReceived)
|
def handle_request(event : IPC::Event)
|
||||||
request_start = Time.utc
|
request_start = Time.utc
|
||||||
|
|
||||||
request = DNSManager.requests.parse_ipc_json event.message
|
array = event.message.not_nil!
|
||||||
|
slice = Slice.new array.to_unsafe, array.size
|
||||||
|
message = IPCMessage::TypedMessage.deserialize slice
|
||||||
|
request = DNSManager.requests.parse_ipc_json message.not_nil!
|
||||||
|
|
||||||
if request.nil?
|
if request.nil?
|
||||||
raise "unknown request type"
|
raise "unknown request type"
|
||||||
@ -81,42 +91,39 @@ class DNSManager::Service < IPC::Server
|
|||||||
# in the responses. Allows identifying responses easily.
|
# in the responses. Allows identifying responses easily.
|
||||||
response.id = request.id
|
response.id = request.id
|
||||||
|
|
||||||
send event.fd, response
|
schedule event.fd, response
|
||||||
|
|
||||||
duration = Time.utc - request_start
|
duration = Time.utc - request_start
|
||||||
|
|
||||||
response_str = response.class.name.sub /^DNSManager::Response::/, ""
|
response_name = response.class.name.sub /^DNSManager::Response::/, ""
|
||||||
|
|
||||||
if response.is_a? DNSManager::Response::Error
|
if response.is_a? DNSManager::Response::Error
|
||||||
Baguette::Log.warning ">> #{response_str} (#{response.reason})"
|
Baguette::Log.warning ">> #{response_name} (#{response.reason})"
|
||||||
else
|
else
|
||||||
Baguette::Log.debug ">> #{response_str} (Total duration: #{duration})"
|
Baguette::Log.debug ">> #{response_name} (Total duration: #{duration})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
Baguette::Log.title "Starting #{@configuration.service_name}"
|
Baguette::Log.title "Starting #{@configuration.service_name}"
|
||||||
|
|
||||||
@base_timer = configuration.ipc_timer
|
|
||||||
@timer = configuration.ipc_timer
|
|
||||||
|
|
||||||
self.loop do |event|
|
self.loop do |event|
|
||||||
begin
|
begin
|
||||||
case event
|
case event.type
|
||||||
when IPC::Event::Timer
|
when LibIPC::EventType::Timer
|
||||||
Baguette::Log.debug "Timer" if @configuration.print_ipc_timer
|
Baguette::Log.debug "Timer" if @configuration.print_ipc_timer
|
||||||
|
|
||||||
when IPC::Event::Connection
|
when LibIPC::EventType::Connection
|
||||||
Baguette::Log.debug "connection from #{event.fd}"
|
Baguette::Log.debug "connection from #{event.fd}"
|
||||||
|
|
||||||
when IPC::Event::Disconnection
|
when LibIPC::EventType::Disconnection
|
||||||
Baguette::Log.debug "disconnection from #{event.fd}"
|
Baguette::Log.debug "disconnection from #{event.fd}"
|
||||||
@logged_users.delete event.fd
|
@logged_users.delete event.fd
|
||||||
|
|
||||||
when IPC::Event::MessageSent
|
when LibIPC::EventType::MessageTx
|
||||||
Baguette::Log.debug "message sent to #{event.fd}"
|
Baguette::Log.debug "message sent to #{event.fd}"
|
||||||
|
|
||||||
when IPC::Event::MessageReceived
|
when LibIPC::EventType::MessageRx
|
||||||
Baguette::Log.debug "message received from #{event.fd}"
|
Baguette::Log.debug "message received from #{event.fd}"
|
||||||
handle_request event
|
handle_request event
|
||||||
|
|
||||||
@ -125,7 +132,7 @@ class DNSManager::Service < IPC::Server
|
|||||||
if event.responds_to?(:fd)
|
if event.responds_to?(:fd)
|
||||||
fd = event.fd
|
fd = event.fd
|
||||||
Baguette::Log.warning "closing #{fd}"
|
Baguette::Log.warning "closing #{fd}"
|
||||||
remove_fd fd
|
close fd
|
||||||
@logged_users.delete fd
|
@logged_users.delete fd
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -206,10 +213,9 @@ def main
|
|||||||
exit 0
|
exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
authd = AuthD::Client.new
|
authd_key = authd_configuration.shared_key.not_nil!
|
||||||
authd.key = authd_configuration.shared_key.not_nil!
|
|
||||||
|
|
||||||
service = DNSManager::Service.new configuration, authd
|
service = DNSManager::Service.new configuration, authd_key
|
||||||
service.run
|
service.run
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ require "ipc"
|
|||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
class IPC::JSON
|
class IPC::JSON
|
||||||
def handle(service : IPC::Server, event : IPC::Event::Events)
|
def handle(service : IPC, event : IPC::Event)
|
||||||
raise "unimplemented"
|
raise "unimplemented"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ class DNSManager::Request
|
|||||||
def initialize(@key, @subject)
|
def initialize(@key, @subject)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event::Events)
|
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event)
|
||||||
# This request means serious business.
|
# This request means serious business.
|
||||||
raise AdminAuthorizationException.new if key != dnsmanagerd.authd.key
|
raise AdminAuthorizationException.new if key != dnsmanagerd.authd.key
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ class DNSManager::Request
|
|||||||
def initialize(@token)
|
def initialize(@token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event::Events)
|
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event)
|
||||||
user, _ = dnsmanagerd.decode_token token
|
user, _ = dnsmanagerd.decode_token token
|
||||||
dnsmanagerd.logged_users[event.fd] = user
|
dnsmanagerd.logged_users[event.fd] = user
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ class DNSManager::Request
|
|||||||
def initialize(@zone)
|
def initialize(@zone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event::Events)
|
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event)
|
||||||
user = dnsmanagerd.get_logged_user event
|
user = dnsmanagerd.get_logged_user event
|
||||||
raise NotLoggedException.new if user.nil?
|
raise NotLoggedException.new if user.nil?
|
||||||
|
|
||||||
|
@ -12,13 +12,21 @@ class DNSManager::Storage
|
|||||||
getter zones : DODB::CachedDataBase(Zone)
|
getter zones : DODB::CachedDataBase(Zone)
|
||||||
getter zones_by_domain : DODB::Index(Zone)
|
getter zones_by_domain : DODB::Index(Zone)
|
||||||
|
|
||||||
def initialize(@root : String)
|
def initialize(@root : String, reindex : Bool = false)
|
||||||
@user_data = DODB::CachedDataBase(UserData).new "#{@root}/user-data"
|
@user_data = DODB::CachedDataBase(UserData).new "#{@root}/user-data"
|
||||||
@user_data_by_uid = @user_data.new_index "uid", &.uid.to_s
|
@user_data_by_uid = @user_data.new_index "uid", &.uid.to_s
|
||||||
@zones = DODB::CachedDataBase(Zone).new "#{@root}/zones"
|
@zones = DODB::CachedDataBase(Zone).new "#{@root}/zones"
|
||||||
@zones_by_domain = @zones.new_index "domain", &.domain
|
@zones_by_domain = @zones.new_index "domain", &.domain
|
||||||
|
|
||||||
Baguette::Log.info "storage initialized"
|
Baguette::Log.info "storage initialized"
|
||||||
|
|
||||||
|
if reindex
|
||||||
|
Baguette::Log.debug "Reindexing user data..."
|
||||||
|
@user_data.reindex_everything!
|
||||||
|
Baguette::Log.debug "Reindexing zones..."
|
||||||
|
@zones.reindex_everything!
|
||||||
|
Baguette::Log.debug "Reindexed!"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_user_data(uid : Int32)
|
def get_user_data(uid : Int32)
|
||||||
|
Loading…
Reference in New Issue
Block a user