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:
 
 
 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
 
 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> ]
 
 
        <api> ::= [ <pname> ]
 
@@ -32,30 +32,35 @@ fields are grouped to form the <hierarchical-name>.
 
        <extra> ::= "-" | "." | "_" | "@"
 
 
        <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
 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.
 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>
 
 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>)
 
 
        <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.
 
 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"
 
 
 [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 <assert.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
 #include <sys/stat.h>
 
 #include "verbose.h"
 #include <sys/stat.h>
 
 #include "verbose.h"
 #include "secmgr-wrap.h"
 #include "utils-dir.h"
 #include "wgtpkg-unit.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* 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)
 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];
        struct wgt_info *ifo;
        const struct wgt_desc *desc;
        char installdir[PATH_MAX];
+       int port;
 
        NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root);
 
 
        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 (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();
                goto error4;
 
        file_reset();