aboutsummaryrefslogtreecommitdiff
path: root/daemon/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/server.c')
-rw-r--r--daemon/server.c871
1 files changed, 572 insertions, 299 deletions
diff --git a/daemon/server.c b/daemon/server.c
index 9ad048d..f551265 100644
--- a/daemon/server.c
+++ b/daemon/server.c
@@ -36,7 +36,22 @@
#include <weshd.h> /* définitions du protocole depuis `weshd.x` */
-#define REQADDR inet_ntoa(svc_getcaller(req->rq_xprt)->sin_addr)
+/* ---
+ * Get the string for an address, for logging.
+ * --- */
+
+static const char *addrstr(struct in6_addr *src)
+{
+ static char str[INET6_ADDRSTRLEN + 1] = {0};
+
+ return (inet_ntop(AF_INET6, src, str, sizeof(str)));
+}
+
+#define REQADDR addrstr(&svc_getcaller(req->rq_xprt)->sin6_addr)
+
+/* ---
+ * Macro to get the WES resource from the ID.
+ * --- */
#define GETWES(ID, RET, RESP) { \
int getwes_err; \
@@ -65,87 +80,105 @@ static weslist_t *list;
static jmp_buf endjmp;
/* ---
+ * Requêtes de base.
+ * --- */
+
+/* `weshd_null_1_svc()`: Ne rien faire (sert à pinger le service). */
+
+void *weshd_null_1_svc(void *argp, struct svc_req *req)
+{
+ static char val[4] = "ok!";
+
+ (void)argp;
+ (void)req;
+ return ((void*)&val);
+}
+
+/* ---
* Gestion des ressources existentes.
* --- */
/* `gather_1_svc()`: Création de ressource, ou récupération de ressource
* existante. */
-wespret_with_id_t *gather_1_svc(wespregopts_t *args,
+wespret_with_id_t *gather_1_svc(wespoptions_t *args,
struct svc_req *req)
{
static wespret_with_id_t resp;
- wescreatedata_t data;
- int (*addfunc)(weslist_t *, wes_t **, wescreatedata_t *);
const unsigned char *ip;
- wesaddr_t *addr; int err;
+ wesaddr_t addr; int err;
+ wespoptions_ip_t *ipopts;
wes_t *wes;
resp.ret = WESPRET_INT;
msg((wlnotice, "(%s) register server", REQADDR));
- /* On vérifie le type de ressource WES à créer. */
-
switch (args->type) {
- case WESPREGTYPE_DUMMY:
- addfunc = &add_dummy_wes;
- break;
- case WESPREGTYPE_IP:
- addfunc = &add_ip_wes;
+ case WESPTYPE_DUMMY:
+ /* On crée et ajoute directement la ressource de type dummy,
+ * sans faire de chichis. */
+
+ err = add_dummy_wes(list, &wes);
break;
- default:
- resp.ret = WESPRET_VAL;
- return (&resp);
- }
- /* On prépare les données de création en fonction de ce qui est envoyé. */
+ case WESPTYPE_IP:
+ /* On prépare l'adresse IP. */
- addr = &data.addr;
- switch (args->ip.type) {
- case WESPIPTYPE_4:
- ip = args->ip.ipv4;
+ ipopts = &args->wespoptions_t_u.ip;
- msg((wlnotice, "(%s) using IPv4 address %hhu.%hhu.%hhu.%hhu", \
- REQADDR, ip[0], ip[1], ip[2], ip[3]));
+ switch (ipopts->addr.type) {
+ case WESPIPTYPE_4:
+ ip = ipopts->addr.wespip_t_u.addr4;
- addr->type = WINET;
- addr->data.inet.has = HASIPv4;
- memcpy(addr->data.inet.ipv4, ip, 4);
+ msg((wlnotice, "(%s) using IPv4 address %hhu.%hhu.%hhu.%hhu",
+ REQADDR, ip[0], ip[1], ip[2], ip[3]));
- break;
+ addr.type = WINET;
+ addr.data.inet.has = HASIPv4;
+ memcpy(addr.data.inet.ipv4, ip, 4);
- case WESPIPTYPE_6:
- ip = args->ip.ipv6;
+ break;
- msg((wlnotice, "(%s) using IPv6 address "
- "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:"
- "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX",
- REQADDR, ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7],
- ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]));
+ case WESPIPTYPE_6:
+ ip = ipopts->addr.wespip_t_u.addr6;
- addr->type = WINET;
- addr->data.inet.has = HASIPv6;
- memcpy(addr->data.inet.ipv6, ip, 16);
+ msg((wlnotice, "(%s) using IPv6 address "
+ "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:"
+ "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX",
+ REQADDR, ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
+ ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
+ ip[14], ip[15]));
- break;
+ addr.type = WINET;
+ addr.data.inet.has = HASIPv6;
+ memcpy(addr.data.inet.ipv6, ip, 16);
- default:
- addr->type = WNONET;
+ break;
+
+ default:
+ addr.type = WNONET;
+ break;
+ }
+
+ /* On définit les identifiants. */
+
+ err = add_ip_wes(list, &wes, &addr,
+ ipopts->http_username, ipopts->http_password,
+ ipopts->ftp_username, ipopts->ftp_password);
break;
- }
- /* On définit les identifiants. */
+ default:
+ /* Je ne connais pas ce type de WES. */
- data.http_username = args->http_username;
- data.http_password = args->http_password;
- data.ftp_username = args->ftp_username;
- data.ftp_password = args->ftp_password;
+ resp.ret = WESPRET_VAL;
+ return (&resp);
+ }
- /* On ajoute la ressource en utilisant la fonction dédiée de l'interface
- * choisie par le client. */
+ /* On regarde l'erreur retournée par la fonction dédiée de création et
+ * d'ajout à la liste. */
- switch ((err = (*addfunc)(list, &wes, &data))) {
+ switch (err) {
case WROK:
msg((wlinfo, "success in creating the resource!"));
break;
@@ -199,366 +232,603 @@ wespret_t *unregister_1_svc(wespid_t *id, struct svc_req *req)
}
/* ---
- * Gestion du nom d'hôte du serveur WES.
+ * Récupération de la configuration du serveur WES.
* --- */
-/* `get_host_name_1_svc()`: Récupération du nom d'hôte. */
-
-wespret_with_hostname_t *get_host_name_1_svc(wespid_t *id, struct svc_req *req)
-{
- static wespret_with_hostname_t resp;
- wes_t *wes;
-
- msg((wlnotice, "(%s) get hostname on server %d", REQADDR, *id));
-
- GETWES(*id, resp.ret, &resp)
-
- resp.ret = WESPRET_OK;
- resp.hostname = wes->name;
- return (&resp);
-}
-
-/* `set_host_name_1_svc()`: Définition du nom d'hôte. */
+/* `get_1_svc()`: Récupération de la configuration d'un serveur WES. */
-wespret_t *set_host_name_1_svc(wespid_with_hostname_t *args,
+wespret_with_wes_t *get_1_svc(wespid_with_wes_flags_t *args,
struct svc_req *req)
{
- static wespret_t ret;
- int err; wes_t *wes;
- char *name;
-
- msg((wlnotice, "(%s) set hostname on server %d", REQADDR, args->id));
- ret = WESPRET_INT;
+ static wespret_with_wes_t resp;
+ wescfg_t cfg, *cfgobj;
+ wes_t *wes; int err;
+ wescfgflags_t flags;
+ wespdt_t *pdt;
+ wespipmore_t *ipmoar;
- GETWES(args->id, ret, &ret)
+ msg((wlnotice, "(%s) get server %d config", REQADDR, args->id));
- /* Validation du hostname à définir. */
+ /* Récupération du WES. */
- if ((err = prep_valid_name(&name, args->hostname))) switch (err) {
- case WRVAL:
- ret = WESPRET_VAL;
- return (&ret);
+ GETWES(args->id, resp.ret, &resp)
+ /* On convertit les flags du protocole au format interne (au cas où
+ * les deux diffèrent, ce qui n'est pas le cas au moment où j'écris
+ * ce bout de code). */
+
+ flags = 0;
+ if (args->to_get & WESP_NAME)
+ flags |= WESCFG_NAME;
+ if (args->to_get & WESP_TIME)
+ flags |= WESCFG_TIME;
+
+ switch (wes->iface->type) {
+ case WESTYPE_IP:
+ if (args->to_get & WESP_DHCP)
+ flags |= WESCFG_DHCP;
+ if (args->to_get & WESP_IP)
+ flags |= WESCFG_IP;
+ if (args->to_get & WESP_MASK)
+ flags |= WESCFG_MASK;
+ if (args->to_get & WESP_GW)
+ flags |= WESCFG_GW;
+ if (args->to_get & WESP_DNS1)
+ flags |= WESCFG_DNS1;
+ if (args->to_get & WESP_DNS2)
+ flags |= WESCFG_DNS2;
+ if (args->to_get & WESP_MAC)
+ flags |= WESCFG_MAC;
+ break;
default:
- return (&ret);
+ break;
}
- msg((wlinfo, "hostname is '%s'", name));
+ /* Appel de la procédure correspondant à l'interface. */
- /* Mettre à jour via l'interface. */
+ switch ((err = (*wes->iface->getcfg)(wes, flags, &cfgobj))) {
+ case WROK:
+ break;
- if (!wes->iface->setname) {
- ret = WESPRET_IMP;
- free_name(name);
- return (&ret);
+ default:
+ msg((wlerror, "getcfg error: %s", error_string(err)));
+ resp.ret = WESPRET_INT;
+ return (&resp);
}
- if ((err = (*wes->iface->setname)(wes, name))) {
- free_name(name);
- ret = WESPRET_INT;
- return (&ret);
+ /* Décodage. */
+
+ memcpy(&cfg, cfgobj, sizeof(cfg));
+ correct_cfg(wes, &cfg, flags);
+
+ resp.wes.name = wes->name;
+ pdt = &resp.wes.current_time;
+ pdt->year = cfg.current_time.year;
+ pdt->mon = cfg.current_time.mon;
+ pdt->dom = cfg.current_time.dom;
+ pdt->hour = cfg.current_time.hour;
+ pdt->min = cfg.current_time.min;
+ pdt->sec = cfg.current_time.sec;
+ pdt->dow = cfg.current_time.dow;
+ pdt->tzhour = cfg.current_time.tzhour;
+ pdt->tzmin = cfg.current_time.tzmin;
+ pdt->dst = cfg.current_time.sum;
+
+ switch (wes->iface->type) {
+ case WESTYPE_DUMMY:
+ resp.wes.more.type = WESPTYPE_DUMMY;
+ break;
+ case WESTYPE_IP:
+ resp.wes.more.type = WESPTYPE_IP;
+ ipmoar = &resp.wes.more.wespmore_t_u.ip;
+ ipmoar->dhcp_enabled = cfg.more.ip.dhcp_enabled;
+ memcpy(ipmoar->ip, cfg.more.ip.ip, 4);
+ memcpy(ipmoar->mask, cfg.more.ip.mask, 4);
+ memcpy(ipmoar->gw, cfg.more.ip.gw, 4);
+ memcpy(ipmoar->dns1, cfg.more.ip.dns1, 4);
+ memcpy(ipmoar->dns2, cfg.more.ip.dns2, 4);
+ memcpy(ipmoar->mac, cfg.more.ip.mac, 6);
+ break;
+ default:
+ msg((wlerror, "invalid iftype: %d", wes->iface->type));
+ resp.ret = WESPRET_INT;
+ set_obj_to_free(wes, cfgobj);
+ return (&resp);
}
- /* Tout a réussi, on définit le nom de la ressource. */
-
- assign_name(wes, name);
+ /* Tout est bien qui finit bien ! */
- ret = WESPRET_OK;
- return (&ret);
+ resp.ret = WESPRET_OK;
+ set_obj_to_free(wes, cfgobj);
+ return (&resp);
}
-/* ---
- * Gestion des identifiants du serveur WES.
- * --- */
-
-/* `set_http_ids_1_svc()`: Définition des identifiants HTTP. */
+/* `set_1_svc()`: Définition de la configuration d'un serveur WES. */
-wespret_t *set_http_ids_1_svc(wespid_with_ids_t *args, struct svc_req *req)
+wespret_t *set_1_svc(wespid_with_wes_t *args, struct svc_req *req)
{
static wespret_t ret;
+ wes_t *wes; wescfg_t cfg;
+ wescfgflags_t setflags;
+ wespipmore_t *ipmoar;
+ int err;
- msg((wlnotice, "(%s) set http ids on server %d", REQADDR, args->id));
-
- ret = WESPRET_IMP;
- return (&ret);
-}
-
-/* `set_ftp_ids_1_svc()`: Définition des identifiants FTP. */
-
-wespret_t *set_ftp_ids_1_svc(wespid_with_ids_t *args, struct svc_req *req)
-{
- static wespret_t ret;
+ msg((wlnotice, "(%s) set server %d config", REQADDR, args->id));
- msg((wlnotice, "(%s) set ftp ids on server %d", REQADDR, args->id));
+ /* Récupération du WES. */
- ret = WESPRET_IMP;
- return (&ret);
-}
+ GETWES(args->id, ret, &ret)
-/* ---
- * Gestion de l'heure du serveur WES.
- * --- */
+ /* Préparation des arguments,
+ * avec gestion des drapeaux. */
-/* `get_date_time_1_svc()`: Récupération de l'horodate. */
+ ret = WESPRET_VAL;
-wespret_with_datetime_t *get_date_time_1_svc(wespid_t *id, struct svc_req *req)
-{
- static wespret_with_datetime_t resp;
- wes_t *wes; westime_object_t *dt;
+ cfg.free = NULL;
+ setflags = 0;
- msg((wlnotice, "(%s) get datetime from server %d", REQADDR, *id));
+ if (args->wes.to_set & WESP_NAME)
+ setflags |= WESCFG_NAME;
+ if (args->wes.to_set & WESP_TIME)
+ setflags |= WESCFG_TIME;
- resp.ret = WESPRET_INT;
+ switch (wes->iface->type) {
+ case WESTYPE_DUMMY:
+ case WESTYPE_NONE:
+ if (args->wes.more.type != WESPTYPE_DUMMY)
+ return (&ret);
+ break;
- GETWES(*id, resp.ret, &resp)
+ case WESTYPE_IP:
+ if (args->wes.more.type != WESPTYPE_IP)
+ return (&ret);
+
+ if (args->wes.to_set & WESP_DHCP)
+ setflags |= WESCFG_DHCP;
+ if (args->wes.to_set & WESP_MASK)
+ setflags |= WESCFG_MASK;
+ if (args->wes.to_set & WESP_IP)
+ setflags |= WESCFG_IP;
+ if (args->wes.to_set & WESP_GW)
+ setflags |= WESCFG_GW;
+ if (args->wes.to_set & WESP_DNS1)
+ setflags |= WESCFG_DNS1;
+ if (args->wes.to_set & WESP_DNS2)
+ setflags |= WESCFG_DNS2;
+
+ ipmoar = &args->wes.more.wespmore_t_u.ip;
+ cfg.more.ip.dhcp_enabled = ipmoar->dhcp_enabled;
+ memcpy(cfg.more.ip.ip, ipmoar->ip, 4);
+ memcpy(cfg.more.ip.mask, ipmoar->mask, 4);
+ memcpy(cfg.more.ip.gw, ipmoar->gw, 4);
+ memcpy(cfg.more.ip.dns1, ipmoar->dns1, 4);
+ memcpy(cfg.more.ip.dns2, ipmoar->dns2, 4);
+ break;
+ }
- /* Extraction via l'interface. */
+ /* Appel à la fonction associée de l'interface. */
- if (!wes->iface->gettime) {
- resp.ret = WESPRET_IMP;
- return (&resp);
+ if (!wes->iface->setcfg) {
+ ret = WESPRET_IMP;
+ return (&ret);
}
- switch ((*wes->iface->gettime)(wes, &dt)) {
+ switch ((err = (*wes->iface->setcfg)(wes, setflags, &cfg))) {
case WROK:
break;
-
- case WRNOHOST:
- resp.ret = WESPRET_CON;
- return (&resp);
-
default:
- resp.ret = WESPRET_INT;
- return (&resp);
+ msg((wlerror, "error while setting config: %s", error_string(err)));
+ break;
}
- /* Conversion en les données du protocole. */
-
- resp.dt.year = dt->cfg.dt.year;
- resp.dt.mon = dt->cfg.dt.mon;
- resp.dt.dom = dt->cfg.dt.dom;
- resp.dt.hour = dt->cfg.dt.hour;
- resp.dt.min = dt->cfg.dt.min;
- resp.dt.sec = dt->cfg.dt.sec;
- resp.dt.dow = dt->cfg.dt.dow;
- resp.dt.sum = dt->cfg.dt.sum;
- resp.dt.tz = dt->cfg.dt.tzhour * 60 + dt->cfg.dt.tzmin;
-
- /* Tout est bien qui finit bien ! */
+ /* On est bons ! */
- msg((wlinfo, "datetime gathered successfully"));
-
- set_obj_to_free(wes, dt);
- resp.ret = WESPRET_OK;
- return (&resp);
+ ret = WESPRET_OK;
+ return (&ret);
}
-/* `set_date_time_1_svc()`: Définition de l'horodate. */
+/* `query_wes_1_svc()`: recherche et listage de serveurs WES. */
-wespret_t *set_date_time_1_svc(wespid_with_datetime_t *args,
+wespret_with_wes_list_t *query_wes_1_svc(wespquery_t *args,
struct svc_req *req)
{
- static wespret_t ret;
+ static wespret_with_wes_list_t resp;
- msg((wlnotice, "(%s) set datetime on server %d", REQADDR, args->id));
+ msg((wlnotice, "(%s) query servers", REQADDR));
- ret = WESPRET_IMP;
- return (&ret);
+ /* TODO */
+ (void)args;
+
+ resp.ret = WESPRET_IMP;
+ return (&resp);
}
/* ---
- * Gestion de l'aspect réseau du serveur WES.
+ * Gestion des compteurs.
* --- */
-/* `get_network_1_svc()`: Récupération des paramètres réseau. */
+/* `get_meter_1_svc()`: Récupération de la configuration d'un compteur. */
-wespret_with_net_t *get_network_1_svc(wespid_t *id, struct svc_req *req)
+wespret_with_meter_t *get_meter_1_svc(wespid_with_meter_id_t *args,
+ struct svc_req *req)
{
- static wespret_with_net_t resp; wesnet_object_t *net;
- wes_t *wes; int err;
+ static wespret_with_meter_t resp;
+ wes_t *wes;
+ wesmetertype_t expected_type;
+ wesmeterflags_t flags;
+ wesmetercfg_t *cfg;
+ wesif_getmeter_t *getmeter;
+ int ret;
+
+ msg((wlnotice, "(%s) get meter %d config from server %d",
+ REQADDR, args->meter_id, args->id));
+
+ switch (args->expected_type) {
+ case WESPMETERTYPE_NONE:
+ expected_type = WESMETERTYPE_NONE;
+ break;
+ case WESPMETERTYPE_AMPER:
+ expected_type = WESMETERTYPE_AMPER;
+ break;
+ case WESPMETERTYPE_PULSE:
+ expected_type = WESMETERTYPE_PULSE;
+ break;
+ case WESPMETERTYPE_TELEINFO:
+ expected_type = WESMETERTYPE_TELEINFO;
+ break;
+ default:
+ resp.ret = WESPRET_IMP;
+ return (&resp);
+ }
- msg((wlnotice, "(%s) get network info from server %d", REQADDR, *id));
- resp.ret = WESPRET_INT;
+ /* Récupération du WES. */
+
+ GETWES(args->id, resp.ret, &resp)
+
+ /* Préparation des arguments. */
+
+ flags = 0;
+ if (args->to_get & WESPMETER_NAME)
+ flags |= WESMETER_NAME;
+ if (args->to_get & WESPMETER_READ)
+ flags |= WESMETER_READ;
+ if (args->to_get & WESPMETER_MODE)
+ flags |= WESMETER_MODE;
+ if (args->to_get & WESPMETER_WHAT)
+ flags |= WESMETER_WHAT;
+ if (args->to_get & WESPMETER_TYPE)
+ flags |= WESMETER_TYPE;
+ if (args->to_get & WESPMETER_FIXED_COSTS)
+ flags |= WESMETER_FIXED_COSTS;
+ if (args->to_get & WESPMETER_PRORATA)
+ flags |= WESMETER_PRORATA;
+
+ switch (expected_type) {
+ case WESMETERTYPE_NONE:
+ break;
- GETWES(*id, resp.ret, &resp)
+ case WESMETERTYPE_AMPER:
+ if (args->to_get & WESPMETER_COST)
+ flags |= WESMETER_COST;
+ if (args->to_get & WESPMETER_VOLTAGE)
+ flags |= WESMETER_VOLTAGE;
+ break;
+
+ case WESMETERTYPE_PULSE:
+ if (args->to_get & WESPMETER_COST)
+ flags |= WESMETER_COST;
+ if (args->to_get & WESPMETER_METHOD)
+ flags |= WESMETER_METHOD;
+ if (args->to_get & WESPMETER_GROUP)
+ flags |= WESMETER_GROUP;
+ break;
- /* Extraction depuis l'interface. */
+ case WESMETERTYPE_TELEINFO:
+ if (args->to_get & WESPMETER_COSTS_BASE)
+ flags |= WESMETER_COSTS_BASE;
+ if (args->to_get & WESPMETER_COSTS_HCHP)
+ flags |= WESMETER_COSTS_HCHP;
+ if (args->to_get & WESPMETER_COSTS_TEMPO)
+ flags |= WESMETER_COSTS_TEMPO;
+ if (args->to_get & WESPMETER_COSTS_EJP)
+ flags |= WESMETER_COSTS_EJP;
+ if (args->to_get & WESPMETER_BDPV_ENABLED)
+ flags |= WESMETER_BDPV_ENABLED;
+ if (args->to_get & WESPMETER_BDPV_IDS)
+ flags |= WESMETER_BDPV_IDS;
+ if (args->to_get & WESPMETER_BDPV_TIME)
+ flags |= WESMETER_BDPV_TIME;
+ break;
+ }
- if (!wes->iface->getnet) {
+ getmeter = wes->iface->getmeter;
+ if (!getmeter) {
resp.ret = WESPRET_IMP;
return (&resp);
}
- switch ((err = (*wes->iface->getnet)(wes, &net))) {
+ ret = (*getmeter)(wes, args->meter_id, expected_type, flags, &cfg);
+ switch (ret) {
case WROK:
break;
-
- case WRNOHOST:
- resp.ret = WESPRET_CON;
- return (&resp);
-
default:
- msg((wlerror, "if error occurred: %s", error_string(err)));
+ msg((wlerror, "could not get meter cfg: %s", error_string(ret)));
resp.ret = WESPRET_INT;
return (&resp);
}
- /* On convertit ça dans la structure de données du protocole. */
-
- resp.cfg.enable_dhcp = net->cfg.dhcp_enabled;
- memcpy(resp.cfg.ip, net->cfg.ip, 4);
- memcpy(resp.cfg.mask, net->cfg.mask, 4);
- memcpy(resp.cfg.gw, net->cfg.gw, 4);
- memcpy(resp.cfg.dns1, net->cfg.ns[0], 4);
- memcpy(resp.cfg.dns2, net->cfg.ns[1], 4);
- memcpy(resp.data.mac, net->data.mac, 6);
+ correct_meter(wes, cfg, expected_type, flags);
+
+ /* Traduction en le format du protocole. */
+
+ {
+ wespmeter_t *r;
+ wespmetermore_amper_t *amp;
+ wespmetermore_pulse_t *pul;
+ wespmetermore_teleinfo_t *tic;
+
+ r = &resp.meter;
+ r->name = cfg->name;
+ r->rd = cfg->is_read;
+ r->fixed_cost = cfg->fixed_cost;
+ r->prorata = cfg->prorata;
+
+ switch (cfg->mode) {
+ case WESMETERMODE_CONSO:
+ r->mode = WESPMETERMODE_CONSO;
+ break;
+ case WESMETERMODE_PROD:
+ r->mode = WESPMETERMODE_PROD;
+ break;
+ }
+
+ switch (cfg->what) {
+ case WESMETERWHAT_UNKNOWN:
+ r->what = WESPMETERWHAT_UNKNOWN;
+ break;
+ case WESMETERWHAT_WATER:
+ r->what = WESPMETERWHAT_WATER;
+ break;
+ case WESMETERWHAT_GAS:
+ r->what = WESPMETERWHAT_GAS;
+ break;
+ case WESMETERWHAT_ELEC:
+ r->what = WESPMETERWHAT_ELEC;
+ break;
+ case WESMETERWHAT_FUEL:
+ r->what = WESPMETERWHAT_FUEL;
+ break;
+ }
+
+ switch (cfg->type) {
+ case WESMETERTYPE_NONE:
+ r->more.type = WESPMETERTYPE_NONE;
+ break;
+ case WESMETERTYPE_AMPER:
+ r->more.type = WESPMETERTYPE_AMPER;
+ amp = &r->more.wespmetermore_t_u.amper;
+
+ amp->voltage = cfg->more.amper.voltage;
+ amp->cost = cfg->more.amper.cost;
+ break;
+ case WESMETERTYPE_PULSE:
+ r->more.type = WESPMETERTYPE_PULSE;
+ pul = &r->more.wespmetermore_t_u.pulse;
+
+ pul->group_size = cfg->more.pulse.group_size;
+ pul->cost = cfg->more.pulse.cost;
+
+ switch (cfg->more.pulse.method) {
+ case WESPLSMETHOD_ILS:
+ pul->method = WESPPLSMETHOD_ILS;
+ break;
+ case WESPLSMETHOD_ELEC:
+ pul->method = WESPPLSMETHOD_ELEC;
+ break;
+ }
+
+ break;
+ case WESMETERTYPE_TELEINFO:
+ r->more.type = WESPMETERTYPE_TELEINFO;
+ tic = &r->more.wespmetermore_t_u.teleinfo;
+
+ tic->cost_base_th = cfg->more.teleinfo.cost_base_th;
+ tic->cost_hchp_hc = cfg->more.teleinfo.cost_hchp_hc;
+ tic->cost_hchp_hp = cfg->more.teleinfo.cost_hchp_hp;
+ tic->cost_tempo_hcjb = cfg->more.teleinfo.cost_tempo_hcjb;
+ tic->cost_tempo_hpjb = cfg->more.teleinfo.cost_tempo_hpjb;
+ tic->cost_tempo_hcjw = cfg->more.teleinfo.cost_tempo_hcjw;
+ tic->cost_tempo_hpjw = cfg->more.teleinfo.cost_tempo_hpjw;
+ tic->cost_tempo_hcjr = cfg->more.teleinfo.cost_tempo_hcjr;
+ tic->cost_tempo_hpjr = cfg->more.teleinfo.cost_tempo_hpjr;
+ tic->cost_ejp_hn = cfg->more.teleinfo.cost_ejp_hn;
+ tic->cost_ejp_pm = cfg->more.teleinfo.cost_ejp_pm;
+
+ tic->bdpv_enabled = cfg->more.teleinfo.bdpv_enabled;
+ tic->bdpv_hour = cfg->more.teleinfo.bdpv_hour;
+ tic->bdpv_min = cfg->more.teleinfo.bdpv_min;
+ tic->bdpv_username = cfg->more.teleinfo.bdpv_username;
+ tic->bdpv_password = cfg->more.teleinfo.bdpv_password;
+ break;
+ }
+ }
- /* La réponse est bonne. */
+ /* Tout va bien ! */
resp.ret = WESPRET_OK;
- set_obj_to_free(wes, net);
+ set_obj_to_free(wes, cfg);
return (&resp);
}
-/* `set_network_1_svc()`: Définition des paramètres réseau. */
+/* `set_meter_1_svc()`: Définition de la configuration d'un compteur. */
-wespret_t *set_network_1_svc(wespid_with_net_t *args, struct svc_req *req)
+wespret_t *set_meter_1_svc(wespid_with_meter_t *args, struct svc_req *req)
{
static wespret_t ret;
- msg((wlnotice, "(%s) set network config on server %d", REQADDR, args->id));
+ msg((wlnotice, "(%s) set meter %d config on server %d",
+ REQADDR, args->meter_id, args->id));
+
+ /* TODO */
ret = WESPRET_IMP;
return (&ret);
}
-/* ---
- * Gestion du TÉLÉINFO.
- * --- */
+/* `get_meter_data_1_svc()`: Récupération des valeurs d'un compteur. */
+
+wespret_with_meter_data_t *get_meter_data_1_svc(
+ wespid_with_meter_id_and_span_t *args, struct svc_req *req)
+{
+ static wespret_with_meter_data_t resp;
+
+ msg((wlnotice, "(%s) get meter %d values from server %d",
+ REQADDR, args->meter_id, args->id));
-/* `get_tic_1_svc()`: Récupération de la configuration et des données
- * immédiates d'un compteur branché via TÉLÉINFO. */
+ /* TODO */
-wespret_with_tic_t *get_tic_1_svc(wespid_with_tic_id_t *args,
+ resp.ret = WESPRET_IMP;
+ return (&resp);
+}
+
+/* `query_meters_1_svc()`: Recherche de compteurs. */
+
+wespret_with_meter_list_t *query_meters_1_svc(wespid_with_meter_query_t *args,
struct svc_req *req)
{
- static wespret_with_tic_t resp;
- westic_object_t *tic; wes_t *wes;
- int err;
+ static wespret_with_meter_list_t resp;
+ wespmeter_list_element_t results[10];
+ int ret, meter_id;
+ wesmetertype_t meter_type;
+ wespmetertype_t meter_ptype;
+ wes_t *wes;
+ void *iter;
- msg((wlnotice, "(%s) get teleinfo %d info from server %d", REQADDR,
- args->tic_id, args->id));
- resp.ret = WESPRET_INT;
+ msg((wlnotice, "(%s) query meters on server %d",
+ REQADDR, args->id));
+
+ /* Vérification des paramètres */
- /* On vérifie si le numéro du compteur est bon. */
+ resp.ret = WESPRET_VAL;
+ resp.meters.meters_val = results;
+ resp.meters.meters_len = 0;
+
+ if (args->offset < 0 || args->offset > 32766
+ || args->count < 1 || args->count > 10)
+ return (&resp);
+ switch (args->of_type) {
+ case WESPMETERTYPE_NONE:
+ meter_type = WESMETERTYPE_NONE;
+ break;
+ case WESPMETERTYPE_AMPER:
+ meter_type = WESMETERTYPE_AMPER;
+ break;
+ case WESPMETERTYPE_PULSE:
+ meter_type = WESMETERTYPE_PULSE;
+ break;
+ case WESPMETERTYPE_TELEINFO:
+ meter_type = WESMETERTYPE_TELEINFO;
+ break;
+ default:
+ return (&resp);
+ }
+
+ /* Récupération du WES. */
GETWES(args->id, resp.ret, &resp)
- /* On récupère les données. */
+ /* Création de l'itérateur. */
- if (!wes->iface->gettic) {
+ if (!wes->iface->getmeteriter || !wes->iface->getmeternext
+ || !wes->iface->skipmeters) {
resp.ret = WESPRET_IMP;
return (&resp);
}
- switch ((err = (*wes->iface->gettic)(wes, args->tic_id, &tic))) {
- case WROK:
+ switch ((ret = (*wes->iface->getmeteriter)(wes, meter_type, &iter))) {
+ case 0:
break;
- case WRNOHOST:
- resp.ret = WESPRET_CON;
- return (&resp);
-
default:
- msg((wlerror, "tic error: %s", error_string(err)));
+ msg((wlerror, "could not get meter iterator: %s", error_string(ret)));
+ resp.ret = WESPRET_INT;
return (&resp);
}
- /* Conversion. */
-
- resp.cfg.read = tic->cfg.is_read;
- resp.cfg.name = tic->cfg.name;
- resp.cfg.mode = tic->cfg.mode;
- resp.cfg.abo = tic->cfg.abo;
- resp.cfg.prorata = tic->cfg.prorata;
- resp.cfg.tarif_base = tic->cfg.tarif_base;
- resp.cfg.tarif_hchp_hc = tic->cfg.tarif_hchp_hc;
- resp.cfg.tarif_hchp_hp = tic->cfg.tarif_hchp_hp;
- resp.cfg.tarif_tempo_hcjb = tic->cfg.tarif_tempo_hcjb;
- resp.cfg.tarif_tempo_hpjb = tic->cfg.tarif_tempo_hpjb;
- resp.cfg.tarif_tempo_hcjw = tic->cfg.tarif_tempo_hcjw;
- resp.cfg.tarif_tempo_hpjw = tic->cfg.tarif_tempo_hpjw;
- resp.cfg.tarif_tempo_hcjr = tic->cfg.tarif_tempo_hcjr;
- resp.cfg.tarif_tempo_hpjr = tic->cfg.tarif_tempo_hpjr;
- resp.cfg.tarif_ejp_hn = tic->cfg.tarif_ejp_hn;
- resp.cfg.tarif_ejp_pm = tic->cfg.tarif_ejp_pm;
- resp.cfg.bdpv_enabled = tic->cfg.bdpv_enabled;
- resp.cfg.bdpv_hour = tic->cfg.bdpv_hour;
- resp.cfg.bdpv_min = tic->cfg.bdpv_min;
-
- resp.data.plugged_in = tic->data.is_plugged_in;
- resp.data.standing_by = tic->data.is_standing_by;
- memcpy(resp.data.adco, tic->data.adco, 12);
- resp.data.tarif = tic->data.tarif;
- resp.data.phmode = tic->data.phases;
- resp.data.period = tic->data.period;
- resp.data.isousc = tic->data.isousc;
- resp.data.pa = tic->data.pa;
- resp.data.iinst[0] = tic->data.iinst[0];
- resp.data.iinst[1] = tic->data.iinst[1];
- resp.data.iinst[2] = tic->data.iinst[2];
- resp.data.imax[0] = tic->data.imax[0];
- resp.data.imax[1] = tic->data.imax[1];
- resp.data.imax[2] = tic->data.imax[2];
- resp.data.index_base = tic->data.index_base;
- resp.data.index_hchp_hc = tic->data.index_hchp_hc;
- resp.data.index_hchp_hp = tic->data.index_hchp_hp;
- resp.data.index_tempo_hcjb = tic->data.index_tempo_hcjb;
- resp.data.index_tempo_hpjb = tic->data.index_tempo_hpjb;
- resp.data.index_tempo_hcjw = tic->data.index_tempo_hcjw;
- resp.data.index_tempo_hpjw = tic->data.index_tempo_hpjw;
- resp.data.index_tempo_hcjr = tic->data.index_tempo_hcjr;
- resp.data.index_tempo_hpjr = tic->data.index_tempo_hpjr;
- resp.data.index_ejp_hn = tic->data.index_ejp_hn;
- resp.data.index_ejp_pm = tic->data.index_ejp_pm;
-
- /* Tout va bien, on peut retourner comme quoi on a bien rempli la
- * structure. */
-
- resp.ret = WESPRET_OK;
- set_obj_to_free(wes, tic);
- return (&resp);
-}
+ /* Passer les premiers compteurs. */
+
+ if (args->offset
+ && (ret = (*wes->iface->skipmeters)(iter, args->offset))) {
+ if (wes->iface->delmeteriter)
+ (*wes->iface->delmeteriter)(iter);
+ switch (ret) {
+ default:
+ msg((wlerror, "could not skip meters: %s", error_string(ret)));
+ resp.ret = WESPRET_INT;
+ return (&resp);
+ }
+ }
-/* `get_tic_values_1_svc()`: récupérer des valeurs du compteur via TÉLÉINFO
- * pour une date donnée. */
+ /* Lire les compteurs. */
+
+ while (resp.meters.meters_len < (u_int)args->count) {
+ ret = (*wes->iface->getmeternext)(iter, &meter_id, &meter_type);
+ if (ret == WRITER)
+ break;
+ else if (ret) {
+ if (wes->iface->delmeteriter)
+ (*wes->iface->delmeteriter)(iter);
+
+ resp.meters.meters_len = 0;
+ switch (ret) {
+ default:
+ msg((wlerror, "could not get next meter: %s",
+ error_string(ret)));
+ resp.ret = WESPRET_INT;
+ return (&resp);
+ }
+ }
+
+ /* Traitement dans le tableau. */
+
+ switch (meter_type) {
+ case WESMETERTYPE_NONE:
+ meter_ptype = WESPMETERTYPE_NONE;
+ break;
+ case WESMETERTYPE_AMPER:
+ meter_ptype = WESPMETERTYPE_AMPER;
+ break;
+ case WESMETERTYPE_PULSE:
+ meter_ptype = WESPMETERTYPE_PULSE;
+ break;
+ case WESMETERTYPE_TELEINFO:
+ meter_ptype = WESPMETERTYPE_TELEINFO;
+ break;
+ default:
+ msg((wlerror, "unknown meter type: %d", meter_type));
+
+ if (wes->iface->delmeteriter)
+ (*wes->iface->delmeteriter)(iter);
+
+ resp.ret = WESPRET_INT;
+ resp.meters.meters_len = 0;
+ return (&resp);
+ }
+
+ resp.meters.meters_val[resp.meters.meters_len].id = meter_id;
+ resp.meters.meters_val[resp.meters.meters_len].type = meter_ptype;
+ ++resp.meters.meters_len;
+ }
-wespret_with_ticdata_t *get_tic_values_1_svc(
- wespid_with_tic_id_and_time_t *args, struct svc_req *req)
-{
- static wespret_with_ticdata_t resp;
+ /* Destruction planifiée de l'itérateur. */
- msg((wlnotice, "(%s) get teleinfo %d values on server %d",
- REQADDR, args->tic_id, args->id));
+ if (wes->iface->delmeteriter)
+ (*wes->iface->delmeteriter)(iter);
- resp.ret = WESPRET_IMP;
+ resp.ret = WESPRET_OK;
return (&resp);
}
-/* `set_tic_1_svc()`: Définition de la configuration d'un compteur branché
- * via TÉLÉINFO. */
-
-wespret_t *set_tic_1_svc(wespid_with_tic_t *args, struct svc_req *req)
-{
- static wespret_t ret;
-
- msg((wlnotice, "(%s) set teleinfo %d config on server %d", REQADDR,
- args->tic_id, args->id));
-
- ret = WESPRET_IMP;
- return (&ret);
-}
-
/* ---
* Fonction de lancement du serveur, avec gestions de signaux.
* --- */
@@ -568,7 +838,6 @@ wespret_t *set_tic_1_svc(wespid_with_tic_t *args, struct svc_req *req)
static __attribute__((noreturn)) void its_the_signal(int sig)
{
(void)sig;
-
longjmp(endjmp, 1);
}
@@ -579,7 +848,8 @@ int run_server(weslist_t *llist)
SVCXPRT *tcp = NULL;
/* On stocke les données des appels de service (svc) pour que
- * ceux-ci puissent les utiliser. */
+ * ceux-ci puissent les utiliser. C'est du global parce que l'interface
+ * legacy de SunRPC ne permet pas de transmettre des cookies. */
list = llist;
@@ -607,14 +877,17 @@ int run_server(weslist_t *llist)
/* Lancement de l'application.
* Remarquez la subtilité : on annonce que le serveur tourne alors qu'en
* réalité, pas encore. Mais chut, il ne faut surtout pas que
- * l'administrateur apprenne ça ;) */
+ * l'administrateur apprenne ça, il dirait encore que les développeurs
+ * c'est vraiment que des bidouilleurs ;) */
if (setjmp(endjmp) == 0) {
msg((wlnotice, "The server is now running."));
svc_run();
}
- /* Libération de mémoire. */
+ /* Libération de mémoire.
+ * Malheureusement, il n'y a pas vraiment de moyen de libérer les
+ * ressources allouées en interne par `svc_run()` à ce stade… :/ */
msg((wlnotice, "Stopping the server."));
svc_destroy(tcp);