otrv4/libotr-ng

Add message events

Closed this issue · 7 comments

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. */

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: otrv4/pidgin-otrng#49 We can also tweak what we have to generate the same thing, though...

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

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.

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:

  • OTRL_MSGEVENT_ENCRYPTION_REQUIRED (for the policy)
  • OTRL_MSGEVENT_ENCRYPTION_ERROR (encryption error)
  • OTRL_MSGEVENT_CONNECTION_ENDED (unsure if we need this one..)
  • OTRL_MSGEVENT_SETUP_ERROR (a gcry_error_t error)
  • OTRL_MSGEVENT_MSG_REFLECTED (unsure if we will need it)
  • OTRL_MSGEVENT_MSG_RESENT
  • OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE (this is prob already covered by the error)
  • OTRL_MSGEVENT_RCVDMSG_UNREADABLE (this is prob already covered by the error)
  • OTRL_MSGEVENT_RCVDMSG_MALFORMED (this is prob already covered by the error)
  • OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD
  • OTRL_MSGEVENT_LOG_HEARTBEAT_SENT
  • OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR
  • OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED
  • OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED (unsure of needed, as we default everything to plaintext)
  • OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE

What do you think?

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

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

Finished now.