Dns manager daemon and clients can be built, once again.
This commit is contained in:
		
							parent
							
								
									ee7d20cc21
								
							
						
					
					
						commit
						a78eb8c889
					
				
					 8 changed files with 80 additions and 42 deletions
				
			
		| 
						 | 
					@ -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.
 | 
						#
 | 
				
			||||||
class DNSManager::Client < IPC::Client
 | 
						# Admin stuff.
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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…
	
	Add table
		
		Reference in a new issue