diff options
Diffstat (limited to 'daemon/server.c')
-rw-r--r-- | daemon/server.c | 871 |
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); |