LCOV - code coverage report
Current view: top level - libmalcontent - session-limits.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 170 171 99.4 %
Date: 2022-05-30 19:36:54 Functions: 19 19 100.0 %
Branches: 42 49 85.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
       2                 :            :  *
       3                 :            :  * Copyright © 2019 Endless Mobile, Inc.
       4                 :            :  *
       5                 :            :  * This library is free software; you can redistribute it and/or
       6                 :            :  * modify it under the terms of the GNU Lesser General Public
       7                 :            :  * License as published by the Free Software Foundation; either
       8                 :            :  * version 2.1 of the License, or (at your option) any later version.
       9                 :            :  *
      10                 :            :  * This library is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :            :  * Lesser General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU Lesser General Public
      16                 :            :  * License along with this library; if not, write to the Free Software
      17                 :            :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
      18                 :            :  *
      19                 :            :  * Authors:
      20                 :            :  *  - Philip Withnall <withnall@endlessm.com>
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "config.h"
      24                 :            : 
      25                 :            : #include <glib.h>
      26                 :            : #include <glib-object.h>
      27                 :            : #include <glib/gi18n-lib.h>
      28                 :            : #include <gio/gio.h>
      29                 :            : #include <libmalcontent/manager.h>
      30                 :            : #include <libmalcontent/session-limits.h>
      31                 :            : 
      32                 :            : #include "libmalcontent/session-limits-private.h"
      33                 :            : 
      34                 :            : 
      35                 :            : /* struct _MctSessionLimits is defined in session-limits-private.h */
      36                 :            : 
      37   [ +  -  +  -  :          6 : G_DEFINE_BOXED_TYPE (MctSessionLimits, mct_session_limits,
                   +  - ]
      38                 :            :                      mct_session_limits_ref, mct_session_limits_unref)
      39                 :            : 
      40                 :            : /**
      41                 :            :  * mct_session_limits_ref:
      42                 :            :  * @limits: (transfer none): an #MctSessionLimits
      43                 :            :  *
      44                 :            :  * Increment the reference count of @limits, and return the same pointer to it.
      45                 :            :  *
      46                 :            :  * Returns: (transfer full): the same pointer as @limits
      47                 :            :  * Since: 0.5.0
      48                 :            :  */
      49                 :            : MctSessionLimits *
      50                 :          4 : mct_session_limits_ref (MctSessionLimits *limits)
      51                 :            : {
      52                 :          4 :   g_return_val_if_fail (limits != NULL, NULL);
      53                 :          4 :   g_return_val_if_fail (limits->ref_count >= 1, NULL);
      54                 :          4 :   g_return_val_if_fail (limits->ref_count <= G_MAXINT - 1, NULL);
      55                 :            : 
      56                 :          4 :   limits->ref_count++;
      57                 :          4 :   return limits;
      58                 :            : }
      59                 :            : 
      60                 :            : /**
      61                 :            :  * mct_session_limits_unref:
      62                 :            :  * @limits: (transfer full): an #MctSessionLimits
      63                 :            :  *
      64                 :            :  * Decrement the reference count of @limits. If the reference count reaches
      65                 :            :  * zero, free the @limits and all its resources.
      66                 :            :  *
      67                 :            :  * Since: 0.5.0
      68                 :            :  */
      69                 :            : void
      70                 :         48 : mct_session_limits_unref (MctSessionLimits *limits)
      71                 :            : {
      72                 :         48 :   g_return_if_fail (limits != NULL);
      73                 :         48 :   g_return_if_fail (limits->ref_count >= 1);
      74                 :            : 
      75                 :         48 :   limits->ref_count--;
      76                 :            : 
      77         [ +  + ]:         48 :   if (limits->ref_count <= 0)
      78                 :            :     {
      79                 :         44 :       g_free (limits);
      80                 :            :     }
      81                 :            : }
      82                 :            : 
      83                 :            : /**
      84                 :            :  * mct_session_limits_get_user_id:
      85                 :            :  * @limits: an #MctSessionLimits
      86                 :            :  *
      87                 :            :  * Get the user ID of the user this #MctSessionLimits is for.
      88                 :            :  *
      89                 :            :  * Returns: user ID of the relevant user, or `(uid_t) -1` if unknown
      90                 :            :  * Since: 0.5.0
      91                 :            :  */
      92                 :            : uid_t
      93                 :          3 : mct_session_limits_get_user_id (MctSessionLimits *limits)
      94                 :            : {
      95                 :          3 :   g_return_val_if_fail (limits != NULL, (uid_t) -1);
      96                 :          3 :   g_return_val_if_fail (limits->ref_count >= 1, (uid_t) -1);
      97                 :            : 
      98                 :          3 :   return limits->user_id;
      99                 :            : }
     100                 :            : 
     101                 :            : /**
     102                 :            :  * mct_session_limits_is_enabled:
     103                 :            :  * @limits: an #MctSessionLimits
     104                 :            :  *
     105                 :            :  * Check whether any session limits are enabled and are going to impose at least
     106                 :            :  * one restriction on the user. This gives a high level view of whether session
     107                 :            :  * limit parental controls are ‘enabled’ for the given user.
     108                 :            :  *
     109                 :            :  * This function is equivalent to the value returned by the
     110                 :            :  * `time_limit_enabled_out` argument of
     111                 :            :  * mct_session_limits_check_time_remaining().
     112                 :            :  *
     113                 :            :  * Returns: %TRUE if the session limits object contains at least one restrictive
     114                 :            :  *    session limit, %FALSE if there are no limits in place
     115                 :            :  * Since: 0.7.0
     116                 :            :  */
     117                 :            : gboolean
     118                 :          3 : mct_session_limits_is_enabled (MctSessionLimits *limits)
     119                 :            : {
     120                 :          3 :   g_return_val_if_fail (limits != NULL, FALSE);
     121                 :          3 :   g_return_val_if_fail (limits->ref_count >= 1, FALSE);
     122                 :            : 
     123                 :          3 :   return (limits->limit_type != MCT_SESSION_LIMITS_TYPE_NONE);
     124                 :            : }
     125                 :            : 
     126                 :            : /**
     127                 :            :  * mct_session_limits_check_time_remaining:
     128                 :            :  * @limits: an #MctSessionLimits
     129                 :            :  * @now_usecs: current time as microseconds since the Unix epoch (UTC),
     130                 :            :  *     typically queried using g_get_real_time()
     131                 :            :  * @time_remaining_secs_out: (out) (optional): return location for the number
     132                 :            :  *     of seconds remaining before the user’s session has to end, if limits are
     133                 :            :  *     in force
     134                 :            :  * @time_limit_enabled_out: (out) (optional): return location for whether time
     135                 :            :  *     limits are enabled for this user
     136                 :            :  *
     137                 :            :  * Check whether the user has time remaining in which they are allowed to use
     138                 :            :  * the computer, assuming that @now_usecs is the current time, and applying the
     139                 :            :  * session limit policy from @limits to it.
     140                 :            :  *
     141                 :            :  * This will return whether the user is allowed to use the computer now; further
     142                 :            :  * information about the policy and remaining time is provided in
     143                 :            :  * @time_remaining_secs_out and @time_limit_enabled_out.
     144                 :            :  *
     145                 :            :  * Returns: %TRUE if the user this @limits corresponds to is allowed to be in
     146                 :            :  *     an active session at the given time; %FALSE otherwise
     147                 :            :  * Since: 0.5.0
     148                 :            :  */
     149                 :            : gboolean
     150                 :        102 : mct_session_limits_check_time_remaining (MctSessionLimits *limits,
     151                 :            :                                          guint64           now_usecs,
     152                 :            :                                          guint64          *time_remaining_secs_out,
     153                 :            :                                          gboolean         *time_limit_enabled_out)
     154                 :            : {
     155                 :            :   guint64 time_remaining_secs;
     156                 :            :   gboolean time_limit_enabled;
     157                 :            :   gboolean user_allowed_now;
     158                 :        102 :   g_autoptr(GDateTime) now_dt = NULL;
     159                 :            :   guint64 now_time_of_day_secs;
     160                 :            : 
     161                 :        102 :   g_return_val_if_fail (limits != NULL, FALSE);
     162                 :        102 :   g_return_val_if_fail (limits->ref_count >= 1, FALSE);
     163                 :            : 
     164                 :            :   /* Helper calculations. */
     165                 :        102 :   now_dt = g_date_time_new_from_unix_utc (now_usecs / G_USEC_PER_SEC);
     166         [ +  + ]:        102 :   if (now_dt == NULL)
     167                 :            :     {
     168                 :          2 :       time_remaining_secs = 0;
     169                 :          2 :       time_limit_enabled = TRUE;
     170                 :          2 :       user_allowed_now = FALSE;
     171                 :          2 :       goto out;
     172                 :            :     }
     173                 :            : 
     174                 :        100 :   now_time_of_day_secs = ((g_date_time_get_hour (now_dt) * 60 +
     175                 :        100 :                            g_date_time_get_minute (now_dt)) * 60 +
     176                 :        100 :                           g_date_time_get_second (now_dt));
     177                 :            : 
     178                 :            :   /* Work out the limits. */
     179         [ +  + ]:        100 :   switch (limits->limit_type)
     180                 :            :     {
     181                 :         60 :     case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE:
     182         [ +  + ]:         96 :       user_allowed_now = (now_time_of_day_secs >= limits->daily_start_time &&
     183         [ +  + ]:         36 :                           now_time_of_day_secs < limits->daily_end_time);
     184         [ +  + ]:         60 :       time_remaining_secs = user_allowed_now ? (limits->daily_end_time - now_time_of_day_secs) : 0;
     185                 :         60 :       time_limit_enabled = TRUE;
     186                 :            : 
     187                 :         60 :       g_debug ("%s: Daily schedule limit allowed in %u–%u (now is %"
     188                 :            :                G_GUINT64_FORMAT "); %" G_GUINT64_FORMAT " seconds remaining",
     189                 :            :                G_STRFUNC, limits->daily_start_time, limits->daily_end_time,
     190                 :            :                now_time_of_day_secs, time_remaining_secs);
     191                 :            : 
     192                 :         60 :       break;
     193                 :         40 :     case MCT_SESSION_LIMITS_TYPE_NONE:
     194                 :            :     default:
     195                 :         40 :       user_allowed_now = TRUE;
     196                 :         40 :       time_remaining_secs = G_MAXUINT64;
     197                 :         40 :       time_limit_enabled = FALSE;
     198                 :            : 
     199                 :         40 :       g_debug ("%s: No limit enabled", G_STRFUNC);
     200                 :            : 
     201                 :         40 :       break;
     202                 :            :     }
     203                 :            : 
     204                 :        102 : out:
     205                 :            :   /* Postconditions. */
     206                 :        102 :   g_assert (!user_allowed_now || time_remaining_secs > 0);
     207                 :        102 :   g_assert (user_allowed_now || time_remaining_secs == 0);
     208                 :        102 :   g_assert (time_limit_enabled || time_remaining_secs == G_MAXUINT64);
     209                 :            : 
     210                 :            :   /* Output. */
     211         [ +  + ]:        102 :   if (time_remaining_secs_out != NULL)
     212                 :          8 :     *time_remaining_secs_out = time_remaining_secs;
     213         [ +  + ]:        102 :   if (time_limit_enabled_out != NULL)
     214                 :          8 :     *time_limit_enabled_out = time_limit_enabled;
     215                 :            : 
     216                 :        102 :   return user_allowed_now;
     217                 :            : }
     218                 :            : 
     219                 :            : /**
     220                 :            :  * mct_session_limits_serialize:
     221                 :            :  * @limits: an #MctSessionLimits
     222                 :            :  *
     223                 :            :  * Build a #GVariant which contains the session limits from @limits, in an
     224                 :            :  * opaque variant format. This format may change in future, but
     225                 :            :  * mct_session_limits_deserialize() is guaranteed to always be able to load any
     226                 :            :  * variant produced by the current or any previous version of
     227                 :            :  * mct_session_limits_serialize().
     228                 :            :  *
     229                 :            :  * Returns: (transfer floating): a new, floating #GVariant containing the
     230                 :            :  *    session limits
     231                 :            :  * Since: 0.7.0
     232                 :            :  */
     233                 :            : GVariant *
     234                 :          8 : mct_session_limits_serialize (MctSessionLimits *limits)
     235                 :            : {
     236                 :         16 :   g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{sv}"));
     237                 :          8 :   g_autoptr(GVariant) limit_variant = NULL;
     238                 :            :   const gchar *limit_property_name;
     239                 :            : 
     240                 :          8 :   g_return_val_if_fail (limits != NULL, NULL);
     241                 :          8 :   g_return_val_if_fail (limits->ref_count >= 1, NULL);
     242                 :            : 
     243                 :            :   /* The serialisation format is exactly the
     244                 :            :    * `com.endlessm.ParentalControls.SessionLimits` D-Bus interface. */
     245      [ +  +  - ]:          8 :   switch (limits->limit_type)
     246                 :            :     {
     247                 :          4 :     case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE:
     248                 :          4 :       limit_variant = g_variant_new ("(uu)",
     249                 :            :                                      limits->daily_start_time,
     250                 :            :                                      limits->daily_end_time);
     251                 :          4 :       limit_property_name = "DailySchedule";
     252                 :          4 :       break;
     253                 :          4 :     case MCT_SESSION_LIMITS_TYPE_NONE:
     254                 :          4 :       limit_variant = NULL;
     255                 :          4 :       limit_property_name = NULL;
     256                 :          4 :       break;
     257                 :          0 :     default:
     258                 :            :       g_assert_not_reached ();
     259                 :            :     }
     260                 :            : 
     261         [ +  + ]:          8 :   if (limit_property_name != NULL)
     262                 :            :     {
     263                 :          4 :       g_variant_builder_add (&builder, "{sv}", limit_property_name,
     264                 :          4 :                              g_steal_pointer (&limit_variant));
     265                 :            :     }
     266                 :            : 
     267                 :          8 :   g_variant_builder_add (&builder, "{sv}", "LimitType",
     268                 :          8 :                          g_variant_new_uint32 (limits->limit_type));
     269                 :            : 
     270                 :          8 :   return g_variant_builder_end (&builder);
     271                 :            : }
     272                 :            : 
     273                 :            : /**
     274                 :            :  * mct_session_limits_deserialize:
     275                 :            :  * @variant: a serialized session limits variant
     276                 :            :  * @user_id: the ID of the user the session limits relate to
     277                 :            :  * @error: return location for a #GError, or %NULL
     278                 :            :  *
     279                 :            :  * Deserialize a set of session limits previously serialized with
     280                 :            :  * mct_session_limits_serialize(). This function guarantees to be able to
     281                 :            :  * deserialize any serialized form from this version or older versions of
     282                 :            :  * libmalcontent.
     283                 :            :  *
     284                 :            :  * If deserialization fails, %MCT_MANAGER_ERROR_INVALID_DATA will be returned.
     285                 :            :  *
     286                 :            :  * Returns: (transfer full): deserialized session limits
     287                 :            :  * Since: 0.7.0
     288                 :            :  */
     289                 :            : MctSessionLimits *
     290                 :         21 : mct_session_limits_deserialize (GVariant  *variant,
     291                 :            :                                 uid_t      user_id,
     292                 :            :                                 GError   **error)
     293                 :            : {
     294                 :         21 :   g_autoptr(MctSessionLimits) session_limits = NULL;
     295                 :            :   guint32 limit_type;
     296                 :            :   guint32 daily_start_time, daily_end_time;
     297                 :            : 
     298                 :         21 :   g_return_val_if_fail (variant != NULL, NULL);
     299                 :         21 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     300                 :            : 
     301                 :            :   /* Check the overall type. */
     302         [ +  + ]:         21 :   if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}")))
     303                 :            :     {
     304                 :          4 :       g_set_error (error, MCT_MANAGER_ERROR,
     305                 :            :                    MCT_MANAGER_ERROR_INVALID_DATA,
     306                 :            :                    _("Session limit for user %u was in an unrecognized format"),
     307                 :            :                    (guint) user_id);
     308                 :          4 :       return NULL;
     309                 :            :     }
     310                 :            : 
     311                 :            :   /* Extract the properties we care about. The default values here should be
     312                 :            :    * kept in sync with those in the `com.endlessm.ParentalControls.SessionLimits`
     313                 :            :    * D-Bus interface. */
     314         [ +  + ]:         17 :   if (!g_variant_lookup (variant, "LimitType", "u",
     315                 :            :                          &limit_type))
     316                 :            :     {
     317                 :            :       /* Default value. */
     318                 :          8 :       limit_type = MCT_SESSION_LIMITS_TYPE_NONE;
     319                 :            :     }
     320                 :            : 
     321                 :            :   /* Check that the limit type is something we support. */
     322                 :            :   G_STATIC_ASSERT (sizeof (limit_type) >= sizeof (MctSessionLimitsType));
     323                 :            : 
     324         [ +  + ]:         17 :   if ((guint) limit_type > MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE)
     325                 :            :     {
     326                 :          2 :       g_set_error (error, MCT_MANAGER_ERROR,
     327                 :            :                    MCT_MANAGER_ERROR_INVALID_DATA,
     328                 :            :                    _("Session limit for user %u has an unrecognized type ‘%u’"),
     329                 :            :                    (guint) user_id, limit_type);
     330                 :          2 :       return NULL;
     331                 :            :     }
     332                 :            : 
     333         [ +  + ]:         15 :   if (!g_variant_lookup (variant, "DailySchedule", "(uu)",
     334                 :            :                          &daily_start_time, &daily_end_time))
     335                 :            :     {
     336                 :            :       /* Default value. */
     337                 :          4 :       daily_start_time = 0;
     338                 :          4 :       daily_end_time = 24 * 60 * 60;
     339                 :            :     }
     340                 :            : 
     341         [ +  + ]:         15 :   if (daily_start_time >= daily_end_time ||
     342         [ +  + ]:         13 :       daily_end_time > 24 * 60 * 60)
     343                 :            :     {
     344                 :          4 :       g_set_error (error, MCT_MANAGER_ERROR,
     345                 :            :                    MCT_MANAGER_ERROR_INVALID_DATA,
     346                 :            :                    _("Session limit for user %u has invalid daily schedule %u–%u"),
     347                 :            :                    (guint) user_id, daily_start_time, daily_end_time);
     348                 :          4 :       return NULL;
     349                 :            :     }
     350                 :            : 
     351                 :            :   /* Success. Create an #MctSessionLimits object to contain the results. */
     352                 :         11 :   session_limits = g_new0 (MctSessionLimits, 1);
     353                 :         11 :   session_limits->ref_count = 1;
     354                 :         11 :   session_limits->user_id = user_id;
     355                 :         11 :   session_limits->limit_type = limit_type;
     356                 :         11 :   session_limits->daily_start_time = daily_start_time;
     357                 :         11 :   session_limits->daily_end_time = daily_end_time;
     358                 :            : 
     359                 :         11 :   return g_steal_pointer (&session_limits);
     360                 :            : }
     361                 :            : 
     362                 :            : /*
     363                 :            :  * Actual implementation of #MctSessionLimitsBuilder.
     364                 :            :  *
     365                 :            :  * All members are %NULL if un-initialised, cleared, or ended.
     366                 :            :  */
     367                 :            : typedef struct
     368                 :            : {
     369                 :            :   MctSessionLimitsType limit_type;
     370                 :            : 
     371                 :            :   /* Which member is used is determined by @limit_type: */
     372                 :            :   union
     373                 :            :     {
     374                 :            :       struct
     375                 :            :         {
     376                 :            :           guint start_time;  /* seconds since midnight */
     377                 :            :           guint end_time;  /* seconds since midnight */
     378                 :            :         } daily_schedule;
     379                 :            :     };
     380                 :            : 
     381                 :            :   /*< private >*/
     382                 :            :   gpointer padding[10];
     383                 :            : } MctSessionLimitsBuilderReal;
     384                 :            : 
     385                 :            : G_STATIC_ASSERT (sizeof (MctSessionLimitsBuilderReal) ==
     386                 :            :                  sizeof (MctSessionLimitsBuilder));
     387                 :            : G_STATIC_ASSERT (__alignof__ (MctSessionLimitsBuilderReal) ==
     388                 :            :                  __alignof__ (MctSessionLimitsBuilder));
     389                 :            : 
     390   [ +  -  +  -  :          6 : G_DEFINE_BOXED_TYPE (MctSessionLimitsBuilder, mct_session_limits_builder,
                   +  - ]
     391                 :            :                      mct_session_limits_builder_copy, mct_session_limits_builder_free)
     392                 :            : 
     393                 :            : /**
     394                 :            :  * mct_session_limits_builder_init:
     395                 :            :  * @builder: an uninitialised #MctSessionLimitsBuilder
     396                 :            :  *
     397                 :            :  * Initialise the given @builder so it can be used to construct a new
     398                 :            :  * #MctSessionLimits. @builder must have been allocated on the stack, and must
     399                 :            :  * not already be initialised.
     400                 :            :  *
     401                 :            :  * Construct the #MctSessionLimits by calling methods on @builder, followed by
     402                 :            :  * mct_session_limits_builder_end(). To abort construction, use
     403                 :            :  * mct_session_limits_builder_clear().
     404                 :            :  *
     405                 :            :  * Since: 0.5.0
     406                 :            :  */
     407                 :            : void
     408                 :         22 : mct_session_limits_builder_init (MctSessionLimitsBuilder *builder)
     409                 :            : {
     410                 :         22 :   MctSessionLimitsBuilder local_builder = MCT_SESSION_LIMITS_BUILDER_INIT ();
     411                 :         22 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     412                 :            : 
     413                 :         22 :   g_return_if_fail (_builder != NULL);
     414                 :         22 :   g_return_if_fail (_builder->limit_type == MCT_SESSION_LIMITS_TYPE_NONE);
     415                 :            : 
     416                 :         22 :   memcpy (builder, &local_builder, sizeof (local_builder));
     417                 :            : }
     418                 :            : 
     419                 :            : /**
     420                 :            :  * mct_session_limits_builder_clear:
     421                 :            :  * @builder: an #MctSessionLimitsBuilder
     422                 :            :  *
     423                 :            :  * Clear @builder, freeing any internal state in it. This will not free the
     424                 :            :  * top-level storage for @builder itself, which is assumed to be allocated on
     425                 :            :  * the stack.
     426                 :            :  *
     427                 :            :  * If called on an already-cleared #MctSessionLimitsBuilder, this function is
     428                 :            :  * idempotent.
     429                 :            :  *
     430                 :            :  * Since: 0.5.0
     431                 :            :  */
     432                 :            : void
     433                 :         76 : mct_session_limits_builder_clear (MctSessionLimitsBuilder *builder)
     434                 :            : {
     435                 :         76 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     436                 :            : 
     437                 :         76 :   g_return_if_fail (_builder != NULL);
     438                 :            : 
     439                 :            :   /* Nothing to free here for now. */
     440                 :         76 :   _builder->limit_type = MCT_SESSION_LIMITS_TYPE_NONE;
     441                 :            : }
     442                 :            : 
     443                 :            : /**
     444                 :            :  * mct_session_limits_builder_new:
     445                 :            :  *
     446                 :            :  * Construct a new #MctSessionLimitsBuilder on the heap. This is intended for
     447                 :            :  * language bindings. The returned builder must eventually be freed with
     448                 :            :  * mct_session_limits_builder_free(), but can be cleared zero or more times with
     449                 :            :  * mct_session_limits_builder_clear() first.
     450                 :            :  *
     451                 :            :  * Returns: (transfer full): a new heap-allocated #MctSessionLimitsBuilder
     452                 :            :  * Since: 0.5.0
     453                 :            :  */
     454                 :            : MctSessionLimitsBuilder *
     455                 :         16 : mct_session_limits_builder_new (void)
     456                 :            : {
     457                 :         16 :   g_autoptr(MctSessionLimitsBuilder) builder = NULL;
     458                 :            : 
     459                 :         16 :   builder = g_new0 (MctSessionLimitsBuilder, 1);
     460                 :         16 :   mct_session_limits_builder_init (builder);
     461                 :            : 
     462                 :         16 :   return g_steal_pointer (&builder);
     463                 :            : }
     464                 :            : 
     465                 :            : /**
     466                 :            :  * mct_session_limits_builder_copy:
     467                 :            :  * @builder: an #MctSessionLimitsBuilder
     468                 :            :  *
     469                 :            :  * Copy the given @builder to a newly-allocated #MctSessionLimitsBuilder on the
     470                 :            :  * heap. This is safe to use with cleared, stack-allocated
     471                 :            :  * #MctSessionLimitsBuilders.
     472                 :            :  *
     473                 :            :  * Returns: (transfer full): a copy of @builder
     474                 :            :  * Since: 0.5.0
     475                 :            :  */
     476                 :            : MctSessionLimitsBuilder *
     477                 :          4 : mct_session_limits_builder_copy (MctSessionLimitsBuilder *builder)
     478                 :            : {
     479                 :          4 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     480                 :          4 :   g_autoptr(MctSessionLimitsBuilder) copy = NULL;
     481                 :            :   MctSessionLimitsBuilderReal *_copy;
     482                 :            : 
     483                 :          4 :   g_return_val_if_fail (builder != NULL, NULL);
     484                 :            : 
     485                 :          4 :   copy = mct_session_limits_builder_new ();
     486                 :          4 :   _copy = (MctSessionLimitsBuilderReal *) copy;
     487                 :            : 
     488                 :          4 :   mct_session_limits_builder_clear (copy);
     489                 :          4 :   _copy->limit_type = _builder->limit_type;
     490                 :            : 
     491         [ +  + ]:          4 :   switch (_builder->limit_type)
     492                 :            :     {
     493                 :          2 :     case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE:
     494                 :          2 :       _copy->daily_schedule.start_time = _builder->daily_schedule.start_time;
     495                 :          2 :       _copy->daily_schedule.end_time = _builder->daily_schedule.end_time;
     496                 :          2 :       break;
     497                 :          2 :     case MCT_SESSION_LIMITS_TYPE_NONE:
     498                 :            :     default:
     499                 :          2 :       break;
     500                 :            :     }
     501                 :            : 
     502                 :          4 :   return g_steal_pointer (&copy);
     503                 :            : }
     504                 :            : 
     505                 :            : /**
     506                 :            :  * mct_session_limits_builder_free:
     507                 :            :  * @builder: a heap-allocated #MctSessionLimitsBuilder
     508                 :            :  *
     509                 :            :  * Free an #MctSessionLimitsBuilder originally allocated using
     510                 :            :  * mct_session_limits_builder_new(). This must not be called on stack-allocated
     511                 :            :  * builders initialised using mct_session_limits_builder_init().
     512                 :            :  *
     513                 :            :  * Since: 0.5.0
     514                 :            :  */
     515                 :            : void
     516                 :         16 : mct_session_limits_builder_free (MctSessionLimitsBuilder *builder)
     517                 :            : {
     518                 :         16 :   g_return_if_fail (builder != NULL);
     519                 :            : 
     520                 :         16 :   mct_session_limits_builder_clear (builder);
     521                 :         16 :   g_free (builder);
     522                 :            : }
     523                 :            : 
     524                 :            : /**
     525                 :            :  * mct_session_limits_builder_end:
     526                 :            :  * @builder: an initialised #MctSessionLimitsBuilder
     527                 :            :  *
     528                 :            :  * Finish constructing an #MctSessionLimits with the given @builder, and return
     529                 :            :  * it. The #MctSessionLimitsBuilder will be cleared as if
     530                 :            :  * mct_session_limits_builder_clear() had been called.
     531                 :            :  *
     532                 :            :  * Returns: (transfer full): a newly constructed #MctSessionLimits
     533                 :            :  * Since: 0.5.0
     534                 :            :  */
     535                 :            : MctSessionLimits *
     536                 :         33 : mct_session_limits_builder_end (MctSessionLimitsBuilder *builder)
     537                 :            : {
     538                 :         33 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     539                 :         33 :   g_autoptr(MctSessionLimits) session_limits = NULL;
     540                 :            : 
     541                 :         33 :   g_return_val_if_fail (_builder != NULL, NULL);
     542                 :            : 
     543                 :            :   /* Build the #MctSessionLimits. */
     544                 :         33 :   session_limits = g_new0 (MctSessionLimits, 1);
     545                 :         33 :   session_limits->ref_count = 1;
     546                 :         33 :   session_limits->user_id = -1;
     547                 :         33 :   session_limits->limit_type = _builder->limit_type;
     548                 :            : 
     549         [ +  + ]:         33 :   switch (_builder->limit_type)
     550                 :            :     {
     551                 :         16 :     case MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE:
     552                 :         16 :       session_limits->daily_start_time = _builder->daily_schedule.start_time;
     553                 :         16 :       session_limits->daily_end_time = _builder->daily_schedule.end_time;
     554                 :         16 :       break;
     555                 :         17 :     case MCT_SESSION_LIMITS_TYPE_NONE:
     556                 :            :     default:
     557                 :            :       /* Defaults: */
     558                 :         17 :       session_limits->daily_start_time = 0;
     559                 :         17 :       session_limits->daily_end_time = 24 * 60 * 60;
     560                 :         17 :       break;
     561                 :            :     }
     562                 :            : 
     563                 :         33 :   mct_session_limits_builder_clear (builder);
     564                 :            : 
     565                 :         33 :   return g_steal_pointer (&session_limits);
     566                 :            : }
     567                 :            : 
     568                 :            : /**
     569                 :            :  * mct_session_limits_builder_set_none:
     570                 :            :  * @builder: an initialised #MctSessionLimitsBuilder
     571                 :            :  *
     572                 :            :  * Unset any session limits currently set in the @builder.
     573                 :            :  *
     574                 :            :  * Since: 0.5.0
     575                 :            :  */
     576                 :            : void
     577                 :          2 : mct_session_limits_builder_set_none (MctSessionLimitsBuilder *builder)
     578                 :            : {
     579                 :          2 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     580                 :            : 
     581                 :          2 :   g_return_if_fail (_builder != NULL);
     582                 :            : 
     583                 :            :   /* This will need to free other limit types’ data first in future. */
     584                 :          2 :   _builder->limit_type = MCT_SESSION_LIMITS_TYPE_NONE;
     585                 :            : }
     586                 :            : 
     587                 :            : /**
     588                 :            :  * mct_session_limits_builder_set_daily_schedule:
     589                 :            :  * @builder: an initialised #MctSessionLimitsBuilder
     590                 :            :  * @start_time_secs: number of seconds since midnight when the user’s session
     591                 :            :  *     can first start
     592                 :            :  * @end_time_secs: number of seconds since midnight when the user’s session can
     593                 :            :  *     last end
     594                 :            :  *
     595                 :            :  * Set the session limits in @builder to be a daily schedule, where sessions are
     596                 :            :  * allowed between @start_time_secs and @end_time_secs every day.
     597                 :            :  * @start_time_secs and @end_time_secs are given as offsets from the start of
     598                 :            :  * the day, in seconds. @end_time_secs must be greater than @start_time_secs.
     599                 :            :  * @end_time_secs must be at most `24 * 60 * 60`.
     600                 :            :  *
     601                 :            :  * This will overwrite any other session limits.
     602                 :            :  *
     603                 :            :  * Since: 0.5.0
     604                 :            :  */
     605                 :            : void
     606                 :         20 : mct_session_limits_builder_set_daily_schedule (MctSessionLimitsBuilder *builder,
     607                 :            :                                                guint                    start_time_secs,
     608                 :            :                                                guint                    end_time_secs)
     609                 :            : {
     610                 :         20 :   MctSessionLimitsBuilderReal *_builder = (MctSessionLimitsBuilderReal *) builder;
     611                 :            : 
     612                 :         20 :   g_return_if_fail (_builder != NULL);
     613                 :         20 :   g_return_if_fail (start_time_secs < end_time_secs);
     614                 :         20 :   g_return_if_fail (end_time_secs <= 24 * 60 * 60);
     615                 :            : 
     616                 :            :   /* This will need to free other limit types’ data first in future. */
     617                 :         20 :   _builder->limit_type = MCT_SESSION_LIMITS_TYPE_DAILY_SCHEDULE;
     618                 :         20 :   _builder->daily_schedule.start_time = start_time_secs;
     619                 :         20 :   _builder->daily_schedule.end_time = end_time_secs;
     620                 :            : }

Generated by: LCOV version 1.14