Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

event refactoring #3018

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open

event refactoring #3018

wants to merge 37 commits into from

Conversation

cspiel1
Copy link
Collaborator

@cspiel1 cspiel1 commented Apr 29, 2024

Idea got from:

This PR involved now to a backwards compatible solution. Old and new event API exist in parallel.

For now only updated three modules.

include/baresip.h Outdated Show resolved Hide resolved
src/event.c Outdated
@@ -333,29 +424,27 @@ void uag_event_unregister(ua_event_h *h)
* @param fmt Formatted arguments
* @param ... Variable arguments
*/
void ua_event(struct ua *ua, enum ua_event ev, struct call *call,
const char *fmt, ...)
void ua_event(enum ua_event ev, const char *fmt, ...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure if mixing formatting args and optional args is a good idea. It's very confusing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SInce this is ua_event, I would prefer to keep struct ua *ua param and add event_param (without struct ua *ua; in union).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

And maybe we should not directly drop the current API.

I'll try a multi function solution for emitting events:

/**
 * @deprecated
 */
void ua_event(struct ua *ua, enum ua_event ev, struct call *call, const char *fmt, ...);

void ua_event_app(enum ua_event ev, const char *fmt, ...);
void ua_event_ua(enum ua_event ev, struct ua *ua, const char *fmt, ...);
void ua_event_call(enum ua_event ev, struct call *call, const char *fmt, ...);
void ua_event_sip_msg(enum ua_event ev, struct sip_msg *msg, const char *fmt, ...);

This could be extended without breaking the API.

@cspiel1
Copy link
Collaborator Author

cspiel1 commented Apr 30, 2024

I completely replaced the commits

@cspiel1 cspiel1 force-pushed the event_refactoring branch 2 times, most recently from 559faa7 to f129576 Compare April 30, 2024 11:09
@cspiel1
Copy link
Collaborator Author

cspiel1 commented Apr 30, 2024

This commit shows how DnD could be solved: 881af62

@juha-h
Copy link
Collaborator

juha-h commented May 1, 2024

Still don't understand why new event (UA_EVENT_SIP_INCOMING) is needed. Also, better name would be UA_EVENT_INVITE_INCOMING.

Now when I read ua.c code, I noticed that call blocking based on contacts does not belong to core either and should be moved to menu.

src/event.c Outdated
va_list ap;
int err;

if (event_class(ev) != EVENT_CLASS_CALL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is EVENT_CLASS_CALL right here?

Copy link
Collaborator Author

@cspiel1 cspiel1 May 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

	if (event_class(ev) != EVENT_CLASS_SIP)
		return EINVAL;

is correct.

Explanation

@juha-h
The event class selects the union field.

event class union field
EVENT_CLASS_UA event.u.ua
EVENT_CLASS_CALL event.u.call
EVENT_CLASS_APP event.nothing
EVENT_CLASS_SIP event.u.msg

Problem

The function ua_event_class_name() returns some incongruous class names

  • register, better would be ua
  • mwi --> better ua
  • UA_EVENT_CREATE returns application --> better ua
  • VU_REPORT --> better call

But maybe there are already applications which event parsing rely on the current texts. Thus I didn't touch this function. The function is used in event_encode_dict() which I would mark as deprecated.

The new function odict_encode_event() uses event_class_name() that returns logical fitting class names. This should also make parsing of events simpler for applications.

src/event.c Outdated Show resolved Hide resolved
@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 2, 2024

Module events

The commit 9542c48 should be discussed, and maybe dropped.

A replacement for function module_event() could be event_module_emit().
Does an extra API function event_module_emit for Module events really have enough benefit for the extra code?

	/* new module event */
	event_module_emit("ctrl_dbus", modev->event, NULL, "%s", modev->txt);
	/* or we use the other event functions, like */
	event_app_emit(UA_EVENT_MODULE, NULL, "ctrl_dbus,%s,%s",
		       modev->event, modev->txt);

Note: event_module_emit() currently untested

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 6, 2024

If an incoming INVITE is rejected by an event handler, then no further event handler should process the event. My proposition is to return true if the event processing should be stopped. We could also add a stop flag to struct bevent.

Isn't it possible to return a bool from a Kotlin callback function?

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 6, 2024

Instead of the return value I put the stop flag to struct bevent. Now there are the options:

  • setting bevent.err to an error code -> stops event processing with an error,
  • setting bevent.stop=true -> stop event processing without an error,
  • by default the next event handler is called. This removes also the need for return false; at multiple locations.

@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024 via email

@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024

Why these are not done before bevent_sip_msg_emit(UA_EVENT_SIPSESS_CONN, msg, "") call?

        /* handle multiple calls */
	if (config->call.max_calls &&
	    uag_call_count() + 1 > config->call.max_calls) {

		info("ua: rejected call from %r (maximum %d calls)\n",
		     &msg->from.auri, config->call.max_calls);
		(void)sip_treply(NULL, uag_sip(), msg, 486, "Max Calls");
		return;
	}

	/* Handle Require: header, check for any required extensions */
	hdr = sip_msg_hdr_apply(msg, true, SIP_HDR_REQUIRE,
				require_handler, ua);
	if (hdr) {
		info("ua: call from %r rejected with 420"
			     " -- option-tag '%r' not supported\n",
			     &msg->from.auri, &hdr->val);

		(void)sip_treplyf(NULL, NULL, uag_sip(), msg, false,
				  420, "Bad Extension",
				  "Unsupported: %r\r\n"
				  "Content-Length: 0\r\n\r\n",
				  &hdr->val);
		return;
	}

	if (ua->acc->rel100_mode == REL100_REQUIRED &&
	    !(sip_msg_hdr_has_value(msg, SIP_HDR_SUPPORTED, "100rel") ||
	      sip_msg_hdr_has_value(msg, SIP_HDR_REQUIRE, "100rel"))) {

		info("ua: call from %r rejected with 421"
			     " -- option-tag '%s' not supported by remote\n",
			     &msg->from.auri, "100rel");
		(void)sip_treplyf(NULL, NULL, uag_sip(), msg, false,
				  421, "Extension required",
				  "Require: 100rel\r\n"
				  "Content-Length: 0\r\n\r\n");
		return;
	}

@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024

Why can't there be ua_accept API function that would be called from the app? Then there would be no need to process anything in sipsess_conn_handler after bevent_sip_msg_emit(UA_EVENT_SIPSESS_CONN, msg, "");

@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024

So when INVITE comes in, ipsess_conn_handler does the checks and (if they succees) sends UA_EVENT_SIPSESS_CONN event. When the app receives it, it calls ua_hangup, ua_answer (when auto answering), or ua_accept. That would be clean without any implicit actions.

@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024

... but I'm ready to give up as long there API documentation is clear.

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 6, 2024

I'll add Doxygen to the API

@cspiel1 cspiel1 force-pushed the event_refactoring branch 3 times, most recently from a379ef4 to aae140c Compare May 6, 2024 10:26
@juha-h
Copy link
Collaborator

juha-h commented May 6, 2024

Once you move these #3018 (comment), I can add new API function ua_accept and can always stop processing after UA_EVENT_SIPSESS_CONN event.

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 6, 2024

Yes, this would be possible from App side.

@cspiel1 cspiel1 added this to the v3.13.0 milestone May 13, 2024
@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 13, 2024

updated the description

@juha-h
Copy link
Collaborator

juha-h commented May 13, 2024

Could you move this

err = bevent_sip_msg_emit(UA_EVENT_SIPSESS_CONN, msg, "");
	if (err == ENOENT)
		return;

down after all checks?

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 14, 2024

Yes, it can be moved to line 760.

Also in following PRs we could move the max_calls check to the application e.g. module menu. We could discuss this.

@@ -881,6 +886,7 @@ enum answer_method {
/** Defines the User-Agent event handler */
typedef void (ua_event_h)(struct ua *ua, enum ua_event ev,
struct call *call, const char *prm, void *arg);
typedef void (bevent_h)(struct bevent *event, void *arg);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggested signature:

typedef void (bevent_h)(struct ua_event ev, struct bevent_payload *event, void *arg);

All events must have a valid EV event set.

The payload is optional and type dependent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean?

typedef void (bevent_h)(enum ua_event ev, struct bevent_payload *event, void *arg);

Rename struct bevent -> struct bevent_payload?

} u;
};


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps rename this file to bevent.c ?

@cspiel1
Copy link
Collaborator Author

cspiel1 commented May 21, 2024

@alfredh Now I changed to

typedef void (bevent_h)(enum ua_event ev, struct bevent *event, void *arg);

Can we keep the shorter name struct bevent?

All events must have a valid EV event set.
The payload is optional and type dependent.

The .._emit(enum ua_event ev, ...) functions ensure that a valid ev is given. Everything else is optional.

@alfredh
Copy link
Collaborator

alfredh commented May 24, 2024

I would like to suggest that we split this up into logical blocks (many PRs).

  1. add core bevent
  2. add backwards wrapper
  3. update function calls
  4. add new features like DND

For example a small PR can be to just rename event.c to bevent.c

Is there a need to update all the calls that are sending the event ?
It would be nice if the PR is small and easy to read.

@@ -167,7 +167,7 @@ set(SRCS
src/custom_hdrs.c
src/descr.c
src/dial_number.c
src/event.c
src/bevent.c
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be a separate PR

@@ -866,10 +866,15 @@ enum ua_event {
UA_EVENT_MODULE,
UA_EVENT_END_OF_FILE,
UA_EVENT_CUSTOM,
UA_EVENT_SIPSESS_CONN,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change and related changes can be separate PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants