[sr-dev] [kamailio/kamailio] export functions of ims_charging and ims_diameter_server to kemi (#2704)

Daniel-Constantin Mierla notifications at github.com
Thu Apr 8 18:58:02 CEST 2021


Thanks for working on exporting to kemi from various ims related module!

However, the functions exported to the native kamailio.cfg cannot be directly exported to kemi. It has to be split in one where the parameters must be converted to `str*` and `int`, which then calls the function that can be exported to kemi. For example, next is the current `w_ro_ccr_stop()`:

```
static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) {
    struct ro_session* ro_session;
    struct ro_session_entry *ro_session_entry;
    unsigned int h_entry;
    str s_code, s_reason;
    unsigned int code;
    int dir = 0; /*any side*/

    LM_DBG("Inside Ro_CCR_Stop with direction [%s]\n", c_direction);
    if (strlen(c_direction) == 4) {
        if (c_direction[0] == 'O' || c_direction[0] == 'o') {
            dir = RO_ORIG_DIRECTION;
        } else {
            dir = RO_TERM_DIRECTION;
        }
    } else {
        LM_ERR("Unknown direction [%s] to terminate\n", c_direction);
        return RO_RETURN_FALSE;
    }
    struct dlg_cell* dlg = dlgb.get_dlg(msg);
    if (!dlg) {
        LM_ERR("Unable to find dialog to send CCR STOP record\n");
        return RO_RETURN_ERROR;
    }

    if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) {
        LM_ERR("failed to get code\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_ERROR;
    }
    LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s);
    if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) {
        LM_ERR("failed to get reason\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_ERROR;
    }

    if (str2int(&s_code, &code) != 0) {
        LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s);
        dlgb.release_dlg(dlg);
        return RO_RETURN_FALSE;
    }

//    switch (code) {
//        case 486:
//            termcode = VS_TERMCODE_BUSYHERE;
//            break;
//        case 487:
//            termcode = VS_TERMCODE_CANCELLED;
//            break;
//        case 480:
//        case 408:
//            /* subscriber not available */
//            termcode = VS_TERMCODE_NOTFOUND;
//            break;
//    }

    LM_DBG("Sending Stop record with code [%d] and reason [%.*s]\n", code, s_reason.len, s_reason.s);

    LM_DBG("Found DLG [%d : %d]\n", dlg->h_id, dlg->h_entry);

    ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, dir, 0);
    if (ro_session == NULL) {
        LM_DBG("no ro_session - ignoring\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_TRUE;
    }
    h_entry = ro_session->h_entry;
    ro_session_entry = &(ro_session_table->entries[h_entry]);

    ro_session_lock(ro_session_table, ro_session_entry);
    
    if (ro_session->ccr_sent == 1) {
        LM_DBG("Ro CCR already sent for session [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
        goto done;
    }
    send_ccr_stop_with_param(ro_session, code, &s_reason);
    //TODO = check the CCR was sent successfully.
    LM_DBG("Setting Ro session [%.*s] ccr_sent to 1\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
    ro_session->ccr_sent = 1;
    ro_session->active = -1;
//    counter_add(ims_charging_cnts_h.active_ro_sessions, -1);
done:
    unref_ro_session(ro_session, 1, 0);
    ro_session_unlock(ro_session_table, ro_session_entry);
    dlgb.release_dlg(dlg);
    return RO_RETURN_TRUE;
}
```

It has to be split to:

```
static int ki_ro_ccr_stop(sip_msg_t *msg, str* p_direction, int p_code, str* p_reason) {
    struct ro_session* ro_session;
    struct ro_session_entry *ro_session_entry;
    unsigned int h_entry;
    str s_reason;
    unsigned int code;
    int dir = 0; /*any side*/
    char *c_direction;

   c_direction = p_direction->s;
   s_reason = *p_reason;
   code = (unsigned int)p_code;

    LM_DBG("Inside Ro_CCR_Stop with direction [%s]\n", c_direction);
    if (strlen(c_direction) == 4) {
        if (c_direction[0] == 'O' || c_direction[0] == 'o') {
            dir = RO_ORIG_DIRECTION;
        } else {
            dir = RO_TERM_DIRECTION;
        }
    } else {
        LM_ERR("Unknown direction [%s] to terminate\n", c_direction);
        return RO_RETURN_FALSE;
    }
    struct dlg_cell* dlg = dlgb.get_dlg(msg);
    if (!dlg) {
        LM_ERR("Unable to find dialog to send CCR STOP record\n");
        return RO_RETURN_ERROR;
    }

//    switch (code) {
//        case 486:
//            termcode = VS_TERMCODE_BUSYHERE;
//            break;
//        case 487:
//            termcode = VS_TERMCODE_CANCELLED;
//            break;
//        case 480:
//        case 408:
//            /* subscriber not available */
//            termcode = VS_TERMCODE_NOTFOUND;
//            break;
//    }

    LM_DBG("Sending Stop record with code [%d] and reason [%.*s]\n", code, s_reason.len, s_reason.s);

    LM_DBG("Found DLG [%d : %d]\n", dlg->h_id, dlg->h_entry);

    ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, dir, 0);
    if (ro_session == NULL) {
        LM_DBG("no ro_session - ignoring\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_TRUE;
    }
    h_entry = ro_session->h_entry;
    ro_session_entry = &(ro_session_table->entries[h_entry]);

    ro_session_lock(ro_session_table, ro_session_entry);
    
    if (ro_session->ccr_sent == 1) {
        LM_DBG("Ro CCR already sent for session [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
        goto done;
    }
    send_ccr_stop_with_param(ro_session, code, &s_reason);
    //TODO = check the CCR was sent successfully.
    LM_DBG("Setting Ro session [%.*s] ccr_sent to 1\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
    ro_session->ccr_sent = 1;
    ro_session->active = -1;
//    counter_add(ims_charging_cnts_h.active_ro_sessions, -1);
done:
    unref_ro_session(ro_session, 1, 0);
    ro_session_unlock(ro_session_table, ro_session_entry);
    dlgb.release_dlg(dlg);
    return RO_RETURN_TRUE;
}
```

And:

```
static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) {
    str s_direction, s_code, s_reason;
    int code;

   s_direction.s = c_direction;
   s_direction.len = strlen(c_direction);

    if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) {
        LM_ERR("failed to get code\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_ERROR;
    }
    LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s);
    if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) {
        LM_ERR("failed to get reason\n");
        dlgb.release_dlg(dlg);
        return RO_RETURN_ERROR;
    }

    if (str2int(&s_code, &code) != 0) {
        LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s);
        dlgb.release_dlg(dlg);
        return RO_RETURN_FALSE;
    }

    return ki_ro_ccr_stop(msg, &s_direction, code, &s_reason);
}
```

Then the `w_ro_ccr_stop()` remains exported to kamailio.cfg native scripting and `ki_ro_ccr_stop()` is exported to kemi. You see that `w_ro_ccr_stop()` keeps only the code related to fixing the parameters given by kamailio.cfg interpreter and then calls the `ki_ro_ccr_stop()` which retains more or less the rest of the code from the initial function.

Note that the split of the code done above was done without any checking, aiming to give hints on how should be done, without any compiling or other checking. Optimizations can also be done, by getting rid of the c_direction and  s_reason inside ki_ro_ccr_stop() and use the function parameters directly.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/pull/2704#issuecomment-815985102
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.kamailio.org/pipermail/sr-dev/attachments/20210408/59d8a893/attachment-0001.htm>


More information about the sr-dev mailing list