wgtpkg-install: choose the port
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 17 Mar 2017 16:03:01 +0000 (17:03 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Fri, 17 Mar 2017 16:49:22 +0000 (17:49 +0100)
The installer now chooses a port for an installed application.

This choose is made by consulting the previously installed
applications and by getting the lowest port available in the
range 1024..32767.

Change-Id: Iab4238b4d52447a2d261d87d45bbb02f0b7a35e5
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
docs/permissions.md
src/wgtpkg-install.c

index 407fdc2..09f68a3 100644 (file)
@@ -14,15 +14,15 @@ framework to keep installed permissions in a database.
 
 The permission names are [URN][URN] of the form:
 
-  urn:AGL:permission:<api>:<level>:<hierarchical-name>
+       urn:AGL:permission:<api>:<level>:<hierarchical-name>
 
 where "AGL" is the NID (the namespace identifier) dedicated to
 AGL (note: a RFC should be produced to standardize this name space).
 
 The permission names are made of NSS (the namespace specific string)
 starting with "permission:" and followed by colon separated
-fields. The 2 first fields are <api> and <level> and the remaining
-fields are grouped to form the <hierarchical-name>.
+fields. The 2 first fields are `<api>` and `<level>` and the remaining
+fields are grouped to form the `<hierarchical-name>`.
 
        <api> ::= [ <pname> ]
 
@@ -32,30 +32,35 @@ fields are grouped to form the <hierarchical-name>.
 
        <extra> ::= "-" | "." | "_" | "@"
 
-The field <api> can be made of any valid character for NSS except
+The field `<api>` can be made of any valid character for NSS except
 the characters colon and star (:*). This field designates the api
 providing the permission. This scheme is used to deduce binding requirements
-from permission requirements. The field <api> can be the empty
+from permission requirements. The field `<api>` can be the empty
 string when the permission is defined by the AGL system itself.
-The field <api> if starting with the character "@" represents
+The field `<api>` if starting with the character "@" represents
 a transversal/cross permission not bound to any binding.
 
        <level> ::= 1*<lower>
 
-The field <level> is made only of letters in lower case.
-The field <level> can only take some predefined values:
-"system", "platform", "partner", "tiers", "owner", "public".
+The field `<level>` is made only of letters in lower case.
+The field `<level>` can only take some predefined values:
+
+ - system
+ - platform
+ - partner
+ - tiers
+ - owner
+ - public
+
+The field `<hierarchical-name>` is made of `<pname>` separated
+by colons.
 
        <hierarchical-name> ::= <pname> 0*(":" <pname>)
 
-The field <hierarchical-name> is made <pname> separated by
-colons. The names at left are hierarchically grouping the
+The names at left are hierarchically grouping the
 names at right. This hierarchical behaviour is intended to
 be used to request permissions using hierarchical grouping.
 
-Permission's level
-------------------
-
 
 [URN]: https://tools.ietf.org/rfc/rfc2141.txt "RFC 2141: URN Syntax"
 
index 836b136..22b8050 100644 (file)
@@ -25,6 +25,8 @@
 #include <assert.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
 #include <sys/stat.h>
 
 #include "verbose.h"
 #include "secmgr-wrap.h"
 #include "utils-dir.h"
 #include "wgtpkg-unit.h"
+#include "utils-systemd.h"
+#include "utils-file.h"
 
 static const char* exec_type_strings[] = {
        "application/x-executable",
        "application/vnd.agl.native"
 };
 
+static const char key_http_port[] = "X-AFM--http-port";
+
+static int get_port_cb(void *closure, const char *name, const char *path, int isuser)
+{
+       char *iter;
+       char *content;
+       size_t length;
+       int rc, p;
+
+       /* reads the file */
+       rc = getfile(path, &content, &length);
+       if (rc < 0)
+               return rc;
+
+       /* process the file */
+       iter = strstr(content, key_http_port);
+       while (iter) {
+               iter += sizeof key_http_port - 1;
+               while(*iter && *iter != '=' && *iter != '\n')
+                       iter++;
+               if (*iter == '=') {
+                       while(*++iter == ' ');
+                       p = atoi(iter);
+                       if (p >= 0 && p < 32768)
+                               ((uint32_t*)closure)[p >> 5] |= (uint32_t)1 << (p & 31);
+               }
+               iter = strstr(iter, key_http_port);
+       }
+       free(content);
+       return 0;
+}
+
+static int get_port()
+{
+       int rc;
+       uint32_t ports[1024]; /* 1024 * 32 = 32768 */
+
+       memset(ports, 0, sizeof ports);
+       rc = systemd_unit_list(0, get_port_cb, &ports);
+       if (rc >= 0) {
+               rc = systemd_unit_list(1, get_port_cb, ports);
+               if (rc >= 0) {
+                       for (rc = 1024 ; rc < 32768 && !~ports[rc >> 5] ; rc += 32);
+                       if (rc == 32768) {
+                               errno = EADDRNOTAVAIL;
+                               rc = -1;
+                       } else {
+                               while (1 & (ports[rc >> 5] >> (rc & 31))) rc++;
+                       }
+               }
+       }
+       return rc;
+}
+
 static int check_defined(const void *data, const char *name)
 {
        if (data)
@@ -294,6 +352,7 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force
        struct wgt_info *ifo;
        const struct wgt_desc *desc;
        char installdir[PATH_MAX];
+       int port;
 
        NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root);
 
@@ -334,7 +393,11 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force
        if (install_exec_flag(desc))
                goto error4;
 
-       if (unit_install(ifo, installdir, FWK_ICON_DIR, 1234/*TODO*/))
+       port = get_port();
+       if (port < 0)
+               goto error4;
+
+       if (unit_install(ifo, installdir, FWK_ICON_DIR, port))
                goto error4;
 
        file_reset();