]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: da: update module to handle schedule mode.
authorDavid Carlier <dcarlier@deviceatlas.com>
Fri, 21 Jan 2022 20:51:20 +0000 (20:51 +0000)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Jan 2022 06:29:01 +0000 (07:29 +0100)
The DeviceAtlas addon can optionally interacts with the new service
 without change of configuration in the HAProxy part.
Note that however it requires the DeviceAtlas Identification C API
2.4.0 minimum from this point.

Signed-off-by: David Carlier <dcarlier@deviceatlas.com>
addons/deviceatlas/da.c

index 4189092264ebfc3e21bf8b403a9674d6d09378c6..969dfaa1ab86cb356381109744d733924cac44aa 100644 (file)
@@ -1,4 +1,7 @@
 #include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <errno.h>
 
 #include <haproxy/api.h>
 #include <haproxy/arg.h>
 #include <haproxy/tools.h>
 #include <dac.h>
 
+#define ATLASTOKSZ PATH_MAX
+#define ATLASMAPNM "/hapdeviceatlas"
+
 static struct {
        void *atlasimgptr;
+       void *atlasmap;
        char *jsonpath;
        char *cookiename;
        size_t cookienamelen;
+       int atlasfd;
        da_atlas_t atlas;
        da_evidence_id_t useragentid;
        da_severity_t loglevel;
@@ -29,11 +37,15 @@ static struct {
        .jsonpath = 0,
        .cookiename = 0,
        .cookienamelen = 0,
+       .atlasmap = NULL,
+       .atlasfd = -1,
        .useragentid = 0,
        .daset = 0,
        .separator = '|',
 };
 
+__decl_thread(HA_SPINLOCK_T dadwsch_lock);
+
 static int da_json_file(char **args, int section_type, struct proxy *curpx,
                         const struct proxy *defpx, const char *file, int line,
                         char **err)
@@ -163,6 +175,16 @@ static int init_deviceatlas(void)
 
                global_deviceatlas.useragentid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
                        "user-agent");
+               if ((global_deviceatlas.atlasfd = shm_open(ATLASMAPNM, O_RDWR, 0660)) != -1) {
+                       global_deviceatlas.atlasmap = mmap(NULL, ATLASTOKSZ, PROT_READ | PROT_WRITE, MAP_SHARED, global_deviceatlas.atlasfd, 0);
+                       if (global_deviceatlas.atlasmap == MAP_FAILED) {
+                               close(global_deviceatlas.atlasfd);
+                               global_deviceatlas.atlasfd = -1;
+                               global_deviceatlas.atlasmap = NULL;
+                       } else {
+                               fprintf(stdout, "Deviceatlas : scheduling support enabled.\n");
+                       }
+               }
                global_deviceatlas.daset = 1;
 
                fprintf(stdout, "Deviceatlas module loaded.\n");
@@ -184,9 +206,58 @@ static void deinit_deviceatlas(void)
                free(global_deviceatlas.atlasimgptr);
        }
 
+       if (global_deviceatlas.atlasfd != -1) {
+               munmap(global_deviceatlas.atlasmap, ATLASTOKSZ);
+               close(global_deviceatlas.atlasfd);
+               shm_unlink(ATLASMAPNM);
+       }
+
        da_fini();
 }
 
+static void da_haproxy_checkinst(void)
+{
+       if (global_deviceatlas.atlasmap != 0) {
+               char *base;
+               base = (char *)global_deviceatlas.atlasmap;
+
+               if (base[0] != 0) {
+                       void *cnew;
+                       size_t atlassz;
+                       char atlasp[ATLASTOKSZ] = {0};
+                       da_atlas_t inst;
+                       da_property_decl_t extraprops[1] = {{NULL, 0}};
+#ifdef USE_THREAD
+                       HA_SPIN_LOCK(OTHER_LOCK, &dadwsch_lock);
+#endif
+                       strlcpy2(atlasp, base, sizeof(atlasp));
+                       if (da_atlas_read_mapped(atlasp, NULL, &cnew, &atlassz) == DA_OK) {
+                               if (da_atlas_open(&inst, extraprops, cnew, atlassz) == DA_OK) {
+                                       char jsonbuf[26];
+                                       time_t jsond;
+
+                                       da_atlas_close(&global_deviceatlas.atlas);
+                                       free(global_deviceatlas.atlasimgptr);
+                                       global_deviceatlas.atlasimgptr = cnew;
+                                       global_deviceatlas.atlas = inst;
+                                       memset(base, 0, ATLASTOKSZ);
+                                       jsond = da_getdatacreation(&global_deviceatlas.atlas);
+                                       ctime_r(&jsond, jsonbuf);
+                                       jsonbuf[24] = 0;
+                                       printf("deviceatlas: new instance, data file date `%s`.\n", jsonbuf);
+                               } else {
+                                       ha_warning("deviceatlas: instance update failed.\n");
+                                       memset(base, 0, ATLASTOKSZ);
+                                       free(cnew);
+                               }
+                       }
+#ifdef USE_THREAD
+                       HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
+#endif
+               }
+       }
+}
+
 static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_t *devinfo)
 {
        struct buffer *tmp;
@@ -272,6 +343,8 @@ static int da_haproxy_conv(const struct arg *args, struct sample *smp, void *pri
                return 1;
        }
 
+       da_haproxy_checkinst();
+
        i = smp->data.u.str.data > sizeof(useragentbuf) ? sizeof(useragentbuf) : smp->data.u.str.data;
        memcpy(useragentbuf, smp->data.u.str.area, i - 1);
        useragentbuf[i - 1] = 0;
@@ -301,6 +374,8 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
                return 0;
        }
 
+       da_haproxy_checkinst();
+
        chn = (smp->strm ? &smp->strm->req : NULL);
        htx = smp_prefetch_htx(smp, chn, NULL, 1);
        if (!htx)