Add a features object to parse RPL_ISUPPORT messages into

Review Request #3267 — Created June 20, 2024 and submitted

Information

ibis/ibis
default

Reviewers

Add a features object to parse RPL_ISUPPORT messages into

Ran the unit tests in valgrind.

Summary ID
Add a features object to parse RPL_ISUPPORT messages into
ce1c7236fc04cff0339803179b40a99456524b9f
Description From Last Updated

there should be a blank line between dependencies and internal headers.

grimgrim

Typically we put the doc comment for the type we're defining here above the G_DECLARE*_TYPE macro. Something like /** * …

grimgrim

Body goes after the parameters, and parameters should be directly under the symbol name without a blank line.

grimgrim

We should probably link to where these properties like AWAYLEN are defined for additional reading. Similar to what we did …

grimgrim

char not gchar

grimgrim

char

grimgrim

this can probably just be a guint I can't imagine anyone supports a nick len of MAX_UINT... After a quick …

grimgrim

if the function is called get_int but returns guint. Since all of the values I looked at (which wasn't all …

grimgrim

char

grimgrim

char

grimgrim

I was imagining that we'd use the hash table to hold all the properties and not just the unknown ones.

grimgrim

You can use ibis_str_equal instead of g_strcmp0

grimgrim

pretty sure we can just use atoi here and then we don't need 64bit values anywhere.

grimgrim

Freezing notification is meant to be used when you're changing multiple properties at once to make sure thay're all set …

grimgrim

as I mentioned earlier, I was imaging this would be something like: gpointer value = NULL; if(ibis_str_equal(feature, IBIS_FEATURE_AWAYLEN)) { ibis_features_set_uint(features, …

grimgrim

Typically our multiline comments have a * at the start of each line and the closing */ on it's own …

grimgrim

AWAYLEN needs to be the exact same as the property name (the first parameter to g_param_spec_*).

grimgrim

Body of the doc comment is missing for all of these. If you have the docs enabled and run the …

grimgrim

Again, these should probably be guint's so g_param_spec_uint instead of g_param_spec_uint64.

grimgrim

This shouldn't be necessary as the unit tests should fail horribly if the regex failed to compile.

grimgrim

char

grimgrim

char

grimgrim

should be < IBIS_VERSION_0_2. The check in the the 0_2 stuff is wrong too and can be fixed here as …

grimgrim

adding a g_assert_true(IBIS_IS_FEATURES(features)); would be nice here.

grimgrim

it might be cleaner to use message = ibis_message_new(IBIS_RPL_ISUPPORT); ibis_message_set_paramsv(message, msg_params);

grimgrim

Should probably add a line break after the first sentenance. The first section is used as a quick summary in …

grimgrim

So as I was trying to fall asleep last night I realized we can just pass the GParamSpec via properties[PROP_FOO] …

grimgrim

Not sure what this check is for? Per https://modern.ircdocs.horse/#rplisupport-005 A single RPL_ISUPPORT reply MUST NOT contain the same parameter multiple …

grimgrim

As mentioned earlier, the TRUE here should instead be the known paramspec. ie properties[PROP_AWAYLEN].

grimgrim

This is a sentenance so it should start with a capital and end in a period.

grimgrim

g_return*_if_fail makes this not nullable as it output a warning or critical at runtime. Something like the following is fine …

grimgrim

I'm not sure the pointers are always going to be the same here. We're probably better off using ibis_str_equal

grimgrim
grim
  1. 
      
  2. So there are a few overall things we need to consider here.

    Someone may want to bind to a property change or use the notify signal, but right now there g_object_notify* isn't being called at all. The use case is a little weird, but someone may want to do the following.

    IbisFeatures *features = NULL;
    
    features = ibis_features_new();
    g_signal_connect(feature, "notify::AWAYLEN", G_CALLBACK(...), NULL);
    

    Right now that signal handler will never be called because, as mentioned above, g_object_notify* isn't being called. This should be done in the parse method, but we should probably use g_object_freeze_notify and g_object_thaw_notify around the bulk of that function.

    Likewise, it might also be nice to have constants for the names in ibisconstants.h. Something like IBIS_FEATURE_NICKLEN and so on.

    That said, right now this doesn't handle unknown features either. That's kind of a tough topic, but it would be nice if we could at least store them.

    My initial thought for this is to add 2 new methods, IbisFeatures.get_string and IbisFeature.get_int. Both whould take a parameter of the feature name and then return it. This would allows users to look up unknown features.

    If the internal representation of the values is a GHashTable that's keyed on the string of the PARAMETER NAME, then the value could be a GValue that's initialized to the either string or int depending on the parameter.

    The methods could look up and return the proper value. Going that route, all of the getters would just call get_string or get_int as necessary.

  3. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    there should be a blank line between dependencies and internal headers.

  4. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    Typically we put the doc comment for the type we're defining here above the G_DECLARE*_TYPE macro.

    Something like

    /**
     * IbisFeatures:
     *
     * An object that keeps try of the features the server supports.
     *
     */
    

    Or something like that.

  5. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    Body goes after the parameters, and parameters should be directly under the symbol name without a blank line.

  6. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    We should probably link to where these properties like AWAYLEN are defined for additional reading. Similar to what we did in ibisconstants.h

  7. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    char not gchar

  8. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    char

  9. ibis/ibisfeatures.h (Diff revision 1)
     
     
    Show all issues

    this can probably just be a guint I can't imagine anyone supports a nick len of MAX_UINT...

    After a quick glance, I'd say the same for the other properties that are marked as guint64.

  10. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    char

  11. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    char

  12. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    You can use ibis_str_equal instead of g_strcmp0

  13. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    pretty sure we can just use atoi here and then we don't need 64bit values anywhere.

  14. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    Typically our multiline comments have a * at the start of each line and the closing */ on it's own line. So something like

    /* Set teh default value specified at
     * https://modern.ircdocs.horse/#rplisupport-parameters
     */
    
  15. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    AWAYLEN needs to be the exact same as the property name (the first parameter to g_param_spec_*).

  16. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    Body of the doc comment is missing for all of these. If you have the docs enabled and run the unit tests, it can alert you to these.

  17. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    Again, these should probably be guint's so g_param_spec_uint instead of g_param_spec_uint64.

  18. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    This shouldn't be necessary as the unit tests should fail horribly if the regex failed to compile.

  19. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    char

  20. ibis/ibisfeatures.c (Diff revision 1)
     
     
    Show all issues

    char

  21. ibis/ibisversion.h (Diff revision 1)
     
     
    Show all issues

    should be < IBIS_VERSION_0_2. The check in the the 0_2 stuff is wrong too and can be fixed here as well.

    1. Whoops, I meant to say that this should be #if IBIS_VERSION_MAX_ALLOWED < IBIS_VERSION_0_3.

      Likewise, line 162 should read #if IBIS_VERSION_MAX_ALLOWED < IBIS_VERSION_0_2 which was the original copy paste error. You don't need to fix it here, but we'll need to fix it eventually.

  22. ibis/tests/test_features.c (Diff revision 1)
     
     
    Show all issues

    adding a g_assert_true(IBIS_IS_FEATURES(features)); would be nice here.

  23. ibis/tests/test_features.c (Diff revision 1)
     
     
    Show all issues

    it might be cleaner to use

    message = ibis_message_new(IBIS_RPL_ISUPPORT);
    ibis_message_set_paramsv(message, msg_params);
    
  24. 
      
ivanhoe
grim
  1. 
      
  2. ibis/ibisfeatures.h (Diff revisions 1 - 2)
     
     
    Show all issues

    if the function is called get_int but returns guint. Since all of the values I looked at (which wasn't all of them) we should probably make this ibis_features_get_uint to avoid confusion and in casewe need to add a signed version in the future.

  3. ibis/ibisfeatures.c (Diff revisions 1 - 2)
     
     
    Show all issues

    I was imagining that we'd use the hash table to hold all the properties and not just the unknown ones.

  4. ibis/ibisfeatures.c (Diff revisions 1 - 2)
     
     
    Show all issues

    Freezing notification is meant to be used when you're changing multiple properties at once to make sure thay're all set before anything acts upons the changes.

    Since this function is only setting a single feature it shouldn't be used here. However it should be used in the caller of this function as that's knows when all of the property changes have been completed.

  5. ibis/ibisfeatures.c (Diff revisions 1 - 2)
     
     
    Show all issues

    as I mentioned earlier, I was imaging this would be something like:

    gpointer value = NULL;
    
    if(ibis_str_equal(feature, IBIS_FEATURE_AWAYLEN)) {
      ibis_features_set_uint(features, IBIS_FEATURE_AWALEN, ibis_str_to_uint(value), TRUE);
    } if(ibis_str_equal(...) {
      ...
    }
    

    Obviously we'd need private helpers like the mentioned ibis_features_set_uint to actually insert everything into the hash table, but then all the values are in a common place.

    I imagine the helpers for them sould be something like the following. The known property names would set the notify parameter to true and then we'd use g_object_notify instead of g_object_notify_by_pspec.

    static void
    ibis_features_set_uint(IbisFeatures *features, const char *name, guint value, gboolean notify)
    {
      GValue *value = NULL;
    
      value = g_new0(GValue, 1);
      g_value_init(value, G_TYPE_UINT);
      g_value_set_uint(value);
    
      g_hash_table_insert(features->features, g_strdup(name), value);
    
      if(notify) {
        g_object_notify(G_OBJECT(features), name);
      }
    }
    

    Likewise, this would mean the getters would need to lookup everything in the hash table too, but since everything is in the hash table, they just call the generic functions. So get_awaylen would become something like

    guint
    ibis_features_get_awaylen(IbisFeatures *features) {
        g_return_val_if_fail(IBIS_IS_FEATURES(features), 0);
    
        return ibis_features_get_uint(features, IBIS_FEATURE_AWAYLEN);
    }
    

    That said, we could argue that we don't need the specific getters either, but they're fine for now as it helps people avoid requesting the wrong type.

  6. ibis/tests/test_features.c (Diff revisions 1 - 2)
     
     

    "moonitor" lul :-D

  7. ibis/ibisstring.h (Diff revision 2)
     
     
    Show all issues

    g_return*_if_fail makes this not nullable as it output a warning or critical at runtime.

    Something like the following is fine to for nullable:

    if(ibis_str_is_empty(str)) {
        return 0;
    }
    
  8. 
      
ivanhoe
grim
  1. 
      
  2. ibis/ibisfeatures.h (Diff revisions 2 - 3)
     
     
    Show all issues

    Should probably add a line break after the first sentenance. The first section is used as a quick summary in the docs.

    See the screen shot below. The first sentenance is fine for the list of all the methods, and the second should probably only be in the specific documentation for the symbol.

    Image

  3. ibis/ibisfeatures.c (Diff revisions 2 - 3)
     
     
    Show all issues

    So as I was trying to fall asleep last night I realized we can just pass the GParamSpec via properties[PROP_FOO] instead of the boolean. If it's that not null, then you just call g_object_notify_by_pspec.

    Doing that you'll avoid the need for the helper function and everything too...

    Sorry again, I meant to get this mentioned in the morning and forgot :-/

  4. ibis/ibisfeatures.c (Diff revisions 2 - 3)
     
     
    Show all issues

    Not sure what this check is for? Per https://modern.ircdocs.horse/#rplisupport-005

    A single RPL_ISUPPORT reply MUST NOT contain the same parameter multiple times nor advertise and negate the same parameter. However, the server is free to advertise or negate the same parameter in separate replies.

    Likewise for the other helpers.

    1. It's so that it does not notify if the value did not change. One way this might happen is when the server advertises a parameter, that has a default value, with the default value.

    2. Got it!

  5. ibis/ibisfeatures.c (Diff revisions 2 - 3)
     
     
    Show all issues

    As mentioned earlier, the TRUE here should instead be the known paramspec. ie properties[PROP_AWAYLEN].

  6. ibis/ibisfeatures.c (Diff revisions 2 - 3)
     
     
    Show all issues

    This is a sentenance so it should start with a capital and end in a period.

  7. 
      
ivanhoe
grim
  1. 
      
  2. ibis/ibisfeatures.c (Diff revisions 3 - 4)
     
     
    Show all issues

    I'm not sure the pointers are always going to be the same here. We're probably better off using ibis_str_equal

    1. Whoops I was meaning to do that, but obviously didn't...

    2. heh, story of my life right here :-D

  3. 
      
grim
grim
  1. Great work! Thank you very much for sticking through the multiple iterations with this and making sure it landed!

  2. 
      
grim
Review request changed
Status:
Completed