Im working with embedded Linux for a router. There is a web GUI for the user to configure router options. When user fill a web form this is submitted to a web server function that is responsible of validating the user input, save the configuration and restart some service. For instance, the function to change DNS settings do something like this:
#include <cms_dal.h>
#include <runservices.h>
void dnsform (form *input)
{
DNS_T dns;
char *dnsenable;
char *dns1;
char *dns2;
dnsenable = GetFormVar(input, "dnsenable", ""); // Get value in the POST request for the form field named dnsenable
dns1 = GetFormVar(input, "dns1", "");
if (!isValidIPAddress(dns1)) // Validate User Input
goto DNS_error;
dns2 = GetFormVar(input, "dns1", "");
if (!isValidIPAddress(dns1))
goto DNS_error;
/* Fill DNS_T dns before saving to the configuration */
if (atoi(dnsenable))
dns.enable=1;
else
dns.enable=0;
inet_aton(dns1, &dns.dns1);
inet_aton(dns1, &dns.dns2);
/* Save new conf */
cm_dal_set(DNS_ID, (void*)&dns);
/* Restart DNS Server */
dns_server_restart();
DNS_error:
ERR_400(); // Return 400 error to the browser
}
cms_dal.h
is the library with the methods to save/retrieve configuration parameters from persistent memory. This library implements cms_dal_set()
function and defines DNS_ID
and the DNS_T
type too. runservices.h
contain the dns_server_start()
method.
Router has a command line interface too, and the function to apply DNS settings using the command line interface looks like above web server function.
I think we should better to abstract some slightly cohesive layers. This is, web server or the command line interface should know nothing about DNS_T type as it is a cms_dal
library implementation issue about how it stores and retrieve data from the flash memory.
I would like to separate validation and saving and setting up DNS service (as a domain object) from the router user interfaces. Maybe i can create some ADT that encapsulates DNS Server object, then it can exposes some interfaces to validate, save and set DNS object configuration. So the web server function may look like this:
#include <dns_server_tad.h>
void dnsform (form *input)
{
char *dnsenable;
char *dns1;
char *dns2;
dnsenable = GetFormVar(input, "dnsenable", ""); // Get value in the POST request for the form field named dnsenable
dns1 = GetFormVar(input, "dns1", "");
dns2 = GetFormVar(input, "dns1", "");
if (!isValidDNS (dnsenable, dns1, dns2))
ERR_400(); // Return 400 error to the browser
if (!saveDns(dnsenable, dns1, dns2))
ERR_500(); // Return 500 error to the browser
/* Restart DNS Server */
restartdns();
}
I am thinking about pros and cons doing above or about better ways to do the same. I think some pros are:
- User interfaces dont implement domain object validation twice.
- We can implement unit testing for the new abstract layers.
- We improve cohesion and abstraction of the code.
About the new ADT encapsulating DNS object, should this ADT be part of the cms_dal.h
library? Should this TAD only expose int restartDNS(char *dnsenable, char *dns1...)
function and do the validation and saving of the parameters internally? If i want to do the same for the Firewall (set of filter rules) object, should the new ADT expose a new public data type that represent a collection of filter rules for the user interfaces to be displayed/set? I am willing to listen to ideas that improve the design and code cleanup of this project.