otrv4 / libotr-ng

A new implementation of OTR with support for version 4. This is a mirror of https://bugs.otr.im/otrv4/libotr-ng
Other
43 stars 9 forks source link

Add message events #166

Closed claucece closed 3 years ago

claucece commented 5 years ago

We can use:

/* Handle and send the appropriate message(s) to the sender/recipient
 * depending on the message events. All the events only require an opdata,
 * the event, and the context. The message and err will be NULL except for
 * some events (see below). The possible events are:
 * - OTRL_MSGEVENT_ENCRYPTION_REQUIRED
 *      Our policy requires encryption but we are trying to send
 *      an unencrypted message out.
 * - OTRL_MSGEVENT_ENCRYPTION_ERROR
 *      An error occured while encrypting a message and the message
 *      was not sent.
 * - OTRL_MSGEVENT_CONNECTION_ENDED
 *      Message has not been sent because our buddy has ended the
 *      private conversation. We should either close the connection,
 *      or refresh it.
 * - OTRL_MSGEVENT_SETUP_ERROR
 *      A private conversation could not be set up. A gcry_error_t
 *      will be passed.
 * - OTRL_MSGEVENT_MSG_REFLECTED
 *      Received our own OTR messages.
 * - OTRL_MSGEVENT_MSG_RESENT
 *      The previous message was resent.
 * - OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE
 *      Received an encrypted message but cannot read
 *      it because no private connection is established yet.
 * - OTRL_MSGEVENT_RCVDMSG_UNREADABLE
 *      Cannot read the received message.
 * - OTRL_MSGEVENT_RCVDMSG_MALFORMED
 *      The message received contains malformed data.
 * - OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD
 *      Received a heartbeat.
 * - OTRL_MSGEVENT_LOG_HEARTBEAT_SENT
 *      Sent a heartbeat.
 * - OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR
 *      Received a general OTR error. The argument 'message' will
 *      also be passed and it will contain the OTR error message.
 * - OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED
 *      Received an unencrypted message. The argument 'message' will
  *      also be passed and it will contain the plaintext message.
  * - OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED
  *      Cannot recognize the type of OTR message received.
  * - OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE
  *      Received and discarded a message intended for another instance. */
claucece commented 5 years ago

Ok, so we don't necessarily need them; but message events are used, from a client level, to generate notifications to the user, like the ones stated here: https://github.com/otrv4/pidgin-otrng/issues/49 We can also tweak what we have to generate the same thing, though...

claucece commented 5 years ago

Any ideas? @olabini @DrWhax .. I can explain more in detail...

olabini commented 5 years ago

Ah, I see. Yeah, those notifications are useful to have, and events definitely feel like the cleanest way of doing them. Do you have alternatives? Otherwise I think this is good.

claucece commented 5 years ago

Well, in libotr, message events are handled in the "top" sending and receiving funcs. So when, for example, a hearbeat message is sent, the event is also raised:

            } else if (edata.ignore_message != 1 &&
                context->context_priv->their_keyid > 0) {
            /* If it's *not* a heartbeat, and we haven't
             * sent anything in a while, also send a
             * heartbeat. */
            time_t now = time(NULL);
            if (context->context_priv->lastsent <
                (now - HEARTBEAT_INTERVAL)) {
                char *heartbeat;

                /* Create the heartbeat message */
                err = otrl_proto_create_data(&heartbeat,
                    context, "", NULL,
                    OTRL_MSGFLAGS_IGNORE_UNREADABLE,
                    NULL);
                if (!err) {
                /* Send it, and inject a debug message */
                if (ops->inject_message) {
                    ops->inject_message(opdata, accountname,
                        protocol, sender, heartbeat);
                }
                free(heartbeat);

                context->context_priv->lastsent = now;
                otrl_context_update_recent_child(context, 1);

                /* Signal an event for the heartbeat message */
                if (ops->handle_msg_event) {
                    ops->handle_msg_event(opdata,
                        OTRL_MSGEVENT_LOG_HEARTBEAT_SENT,
                        context, NULL,
                        gcry_error(GPG_ERR_NO_ERROR));
                }
                }
            }
            }

Our code is different, and we don't have major functions that handle everything; but rather small functions, like this:

if (otr->client->should_heartbeat(otr->last_sent)) {
      otrng_debug_enter("trying to send a heartbeat message");
      if (!otrng_send_message(&response->to_send, "", warn, NULL,
                              MSG_FLAGS_IGNORE_UNREADABLE, otr)) {
        otrng_secure_wipe(mac_key, MAC_KEY_BYTES);
        otrng_data_message_free(msg);
        return OTRNG_ERROR;
      }
      otrng_debug_exit("heartbeat message sent");
      otr->last_sent = time(NULL);
    }

    otrng_secure_wipe(mac_key, MAC_KEY_BYTES);
    otrng_data_message_free(msg);

my idea is that there we can create a callback handle_msg_event which does the same as in libotr, like this one:

tstatic void display_error_message_cb(const otrng_error_event event,
                                      string_p *to_display,
                                      const otrng_s *conv) {
  otrng_client_callbacks_display_error_message(
      conv->client->global_state->callbacks, event, to_display, conv);
}

which is used every time an error message is received:

tstatic otrng_result receive_error_message(otrng_response_s *response,
                                           const string_p msg, otrng_s *otr) {
  otrng_error_event error_event = OTRNG_ERROR_NONE;

  if (strncmp(msg, "ERROR_1:", 8) == 0) {
    error_event = OTRNG_ERROR_UNREADABLE_EVENT;
    display_error_message_cb(error_event, &response->to_display, otr);

    if (otr->policy_type & OTRNG_ERROR_START_DAKE) {
      return otrng_build_query_message(&response->to_send, "", otr);
    }

We can use the same callback for every event required:

What do you think?

claucece commented 5 years ago

Ok, I have added most of them. I need to document and check if we will support the other ones.

claucece commented 5 years ago

I'll stop the work on this until we have the groups of policies in place.

claucece commented 3 years ago

Finished now.