strophe / libstrophe

A simple, lightweight C library for writing XMPP clients
http://strophe.im/libstrophe
Other
401 stars 163 forks source link

Sending a message to a user #193

Closed ughstudios closed 2 years ago

ughstudios commented 2 years ago
void send_message(std::string msg)
{
    if (context == NULL)
        return;

    xmpp_stanza_t* message = xmpp_stanza_new(context);
    xmpp_stanza_set_text(message, msg.c_str());
    xmpp_stanza_set_to(message, "daniel@xmpp.ughstudios.com");
        xmpp_stanza_set_type(message, "chat");
    xmpp_send(connection, message);
    LOG(ERROR) << message;
}

I wrote this code, but for some reason it's not sending. There's no errors, and I know it's connected.

ughstudios commented 2 years ago

Is there a way to print out the entire stanza in a human readable format so I can visually make sure it looks right? :)

ughstudios commented 2 years ago

I'm basing this off of the examples on here: https://www.oreilly.com/library/view/xmpp-the-definitive/9780596157524/ch04.html

jubalh commented 2 years ago

And I think you can find this out yourself by looking at the provided example code. And looking at other projects that use libstrophe. Like:

sjaeckel commented 2 years ago

And please have a look at the examples provided in the examples/ folder of the library.

ughstudios commented 2 years ago

Yeah this is based off of the examples. Here is my cpp file:

#include "xmpp_service.h"

xmpp_conn_t* connection;
xmpp_ctx_t* context;

void send_message(std::string msg)
{
    if (context == NULL)
        return;

    xmpp_stanza_t* message = xmpp_stanza_new(context);
    xmpp_stanza_set_text(message, msg.c_str());
    xmpp_stanza_set_to(message, "daniel@xmpp.ughstudios.com");
    xmpp_stanza_set_type(message, "chat");
    xmpp_send(connection, message);
    LOG(ERROR) << message;
}

void conn_handler(xmpp_conn_t* conn, xmpp_conn_event_t status, int error, xmpp_stream_error_t* stream_error, void* userdata)
{
    xmpp_ctx_t* ctx = (xmpp_ctx_t*)userdata;
    xmpp_stanza_t* iq, * query;

    (void)error;
    (void)stream_error;

    if (status == XMPP_CONN_CONNECT) {
        LOG(INFO) << "Connected to XMPP server.";
        send_message("test");
    }
    else {
        LOG(ERROR) << "Could not connect to xmpp server.";
        xmpp_stop(ctx);
    }
}

void start_chat()
{
    /* initialize lib */
    xmpp_initialize();

    /* create a context */
    context = xmpp_ctx_new(NULL, NULL);

    /* create a connection */
    connection = xmpp_conn_new(context);

    /*
    * also you can disable TLS support or force legacy SSL
    * connection without STARTTLS
    *
    * see xmpp_conn_set_flags() or examples/basic.c
    */

    /* setup authentication information */
    xmpp_conn_set_flags(connection, XMPP_CONN_FLAG_TRUST_TLS);

    xmpp_conn_set_jid(connection, "davidxmpp.ughstudios.com")
    xmpp_conn_set_pass(connection, "removed");

    /* initiate connection */
    xmpp_connect_client(connection, NULL, 0, conn_handler, context);

    /* start the event loop */
    xmpp_run(context);

    /* release our connection and context */
    xmpp_conn_release(connection);
    xmpp_ctx_free(context);

    /* shutdown lib */
    xmpp_shutdown();
}
#pragma once

#include <stdio.h>
#include <string.h>
#include "strophe.h"
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <glog/logging.h>

extern xmpp_conn_t* connection;
extern xmpp_ctx_t* context;

void conn_handler(xmpp_conn_t* conn, xmpp_conn_event_t status, int error, xmpp_stream_error_t* stream_error, void* userdata);
void send_message(std::string msg);
void start_chat();

I based this on the bot.c example

ughstudios commented 2 years ago

I then call send_message() from main, like so:

int main(int argc, char *argv[])
{
    google::InitGoogleLogging(argv[0]);
    QApplication a(argc, argv);
    LoginScreen login;
    login.show();

    std::thread chat_thread(start_chat);
    send_message("test");
    return a.exec();
}
pasis commented 2 years ago

Send_message() is incorrect, I will describe in more details once I'm near to PC.

You can see what's sending in human readable format if you enable logs and check console output. Check basic.c under examples directory, near to xmpp_ctx_new().

sjaeckel commented 2 years ago

Send_message() is incorrect

Ah right, send_message() should start by calling xmpp_message_new()

pasis commented 2 years ago

Also if you call send_message() from main() without synchronization you will likely execute send_message() before context is initialized, so it will simply exit due to the condition check at the top. So you should expect that actually running send_message() is from conn_handler().

ughstudios commented 2 years ago

Also if you call send_message() from main() without synchronization you will likely execute send_message() before context is initialized, so it will simply exit due to the condition check at the top. So you should expect that actually running send_message() is from conn_handler().

Yeah I thought of this! So I created a button in my Qt application which also calls send_message() when I click it, this also did not work.

sjaeckel commented 2 years ago

Then enable logging as shown here https://github.com/strophe/libstrophe/blob/master/examples/basic.c#L175-L178 and tell us what your log output looks like.

xmpp_ctx_set_verbosity(ctx, verbosity); where verbosity can be something between 0-3, 0 makes sense to start with.

ughstudios commented 2 years ago

It doesn't actually seem to print to the output. I am using a custom logger solution which I believe is overriding the stderr and stdout for the application, so I am not seeing any output. I'm going to have to make some custom modifications probably to get the output to actually works adly, printf isn't printing anything :D

sjaeckel commented 2 years ago

should be sufficient to replace the call to printf_style_log_function() with your logging command

static const char *your_custom_log_level_name[4] = {"DEBUG", "INFO", "WARN", "ERROR"};
static const xmpp_log_level_t your_custom_log_level[] = {
    XMPP_LEVEL_DEBUG, XMPP_LEVEL_INFO, XMPP_LEVEL_WARN, XMPP_LEVEL_ERROR};

static void custom_logger(void *userdata,
                                xmpp_log_level_t level,
                                const char *area,
                                const char *msg)
{
    xmpp_log_level_t filter_level = *(xmpp_log_level_t *)userdata;
    if (level >= filter_level)
        printf_style_log_function("%s %s %s\n", area, your_custom_log_level_name[level], msg);
}

static const xmpp_log_t your_custom_loggers[] = {
    {&custom_logger,
     (void *)&your_custom_log_level[XMPP_LEVEL_DEBUG]},
    {&custom_logger,
     (void *)&your_custom_log_level[XMPP_LEVEL_INFO]},
    {&custom_logger,
     (void *)&your_custom_log_level[XMPP_LEVEL_WARN]},
    {&custom_logger,
     (void *)&your_custom_log_level[XMPP_LEVEL_ERROR]}};

and then use ctx = xmpp_ctx_new(NULL, your_custom_loggers); in your setup code

ughstudios commented 2 years ago

Yeah I was able to get the logging working. Although, I'm still unable to get a message to be sent to me. I have two xmpp accounts, one called david@xmpp.ughstudios.com and one called `daniel@xmpp.ughstudios.com``` I know that it's all setup correctly because I was able to send a message using another library in python (https://github.com/horazont/aioxmpp) and also I can use different gui clients. So I know the server is setup correctly. It says it connected but then it also says that the person is not online when I look in a gui client.

Here's the output:

xmpp DEBUG SRV lookup failed, connecting via domain.
xmpp DEBUG sock_connect() to xmpp.ughstudios.com:5222 returned 1132
xmpp DEBUG Attempting to connect to xmpp.ughstudios.com
xmpp DEBUG connection successful
conn DEBUG QUEUED: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">
conn DEBUG Added queue element: 4d79f7e0
conn DEBUG SENT: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">
xmpp DEBUG Finished writing queue element: 4d79f7e0.
xmpp DEBUG RECV: <stream:stream id="13435078664167221260" version="1.0" lang="en" from="xmpp.ughstudios.com">
xmpp DEBUG RECV: <features xmlns="http://etherx.jabber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></features>
conn DEBUG QUEUED: <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
conn DEBUG Added queue element: 4d7a0260
conn DEBUG SENT: <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
xmpp DEBUG Finished writing queue element: 4d7a0260.
xmpp DEBUG RECV: <proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
xmpp DEBUG handle proceedtls called for proceed
xmpp DEBUG proceeding with TLS
tls DEBUG Certificate verification FAILED, result=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT(18)
tls DEBUG User decided to connect anyways
tls DEBUG Subject=/O=us-west-1.compute.internal/OU=ip-10-0-1-208/CN=ejabberd/emailAddress=root@ip-10-0-1-208.us-west-1.compute.internal
tls DEBUG Issuer=/O=us-west-1.compute.internal/OU=ip-10-0-1-208/CN=ejabberd/emailAddress=root@ip-10-0-1-208.us-west-1.compute.internal
conn DEBUG QUEUED: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="david@xmpp.ughstudios.com">
conn DEBUG Added queue element: 4d7a0740
conn DEBUG SENT: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="david@xmpp.ughstudios.com">
xmpp DEBUG Finished writing queue element: 4d7a0740.
xmpp DEBUG RECV: <stream:stream id="8501826055782983833" version="1.0" lang="en" to="david@xmpp.ughstudios.com" from="xmpp.ughstudios.com">
xmpp DEBUG RECV: <features xmlns="http://etherx.jabber.org/streams"><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>SCRAM-SHA-1</mechanism></mechanisms></features>
conn DEBUG QUEUED: <auth mechanism="SCRAM-SHA-1" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">biwsbj1kYXZpZCxyPUFFMjQ0MkRGNzQxNDk2MEQ0NjI5MDZCQjAxM0Y3NDY=</auth>
conn DEBUG Added queue element: 4d7a1700
conn DEBUG SENT: <auth mechanism="SCRAM-SHA-1" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">biwsbj1kYXZpZCxyPUFFMjQ0MkRGNzQxNDk2MEQ0NjI5MDZCQjAxM0Y3NDY=</auth>
xmpp DEBUG Finished writing queue element: 4d7a1700.
xmpp DEBUG RECV: <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cj1BRTI0NDJERjc0MTQ5NjBENDYyOTA2QkIwMTNGNzQ2MjlsV3MrbksvTDI2aktjU3FEWnNCUT09LHM9dUFKMk9vYzQ1Vnk5RVFyT0dlY3lYdz09LGk9NDA5Ng==</challenge>
xmpp DEBUG handle SCRAM-SHA-1 (challenge) called for challenge
conn DEBUG QUEUED: <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">Yz1iaXdzLHI9QUUyNDQyREY3NDE0OTYwRDQ2MjkwNkJCMDEzRjc0NjI5bFdzK25LL0wyNmpLY1NxRFpzQlE9PSxwPWlZdGMwS3RXdVoyUDdiTjg5NFV5azFpVndUQT0=</response>
conn DEBUG Added queue element: 4d7a0aa0
conn DEBUG SENT: <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">Yz1iaXdzLHI9QUUyNDQyREY3NDE0OTYwRDQ2MjkwNkJCMDEzRjc0NjI5bFdzK25LL0wyNmpLY1NxRFpzQlE9PSxwPWlZdGMwS3RXdVoyUDdiTjg5NFV5azFpVndUQT0=</response>
xmpp DEBUG Finished writing queue element: 4d7a0aa0.
xmpp DEBUG RECV: <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dj15TmNObFZ3YWpCbndwN3pSQ3VsMWR5ek1MeTQ9</success>
xmpp DEBUG handle SCRAM-SHA-1 (challenge) called for success
xmpp DEBUG SASL SCRAM-SHA-1 auth successful
conn DEBUG QUEUED: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="david@xmpp.ughstudios.com">
conn DEBUG Added queue element: 4d7a1700
conn DEBUG SENT: <?xml version="1.0"?><stream:stream to="xmpp.ughstudios.com" xml:lang="en" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="david@xmpp.ughstudios.com">
xmpp DEBUG Finished writing queue element: 4d7a1700.
xmpp DEBUG RECV: <stream:stream id="18163949562258342369" version="1.0" lang="en" to="david@xmpp.ughstudios.com" from="xmpp.ughstudios.com">
xmpp DEBUG Reopened stream successfully.
xmpp DEBUG RECV: <features xmlns="http://etherx.jabber.org/streams"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"><optional/></session><c hash="sha-1" xmlns="http://jabber.org/protocol/caps" node="http://www.process-one.net/en/ejabberd/" ver="8jd5C1sQ6WIVpNs9yDrehFA+SIQ="/><sm xmlns="urn:xmpp:sm:2"/><sm xmlns="urn:xmpp:sm:3"/><ver xmlns="urn:xmpp:features:rosterver"/><csi xmlns="urn:xmpp:csi:0"/></features>
conn DEBUG QUEUED: <iq id="_xmpp_bind1" type="set"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></iq>
conn DEBUG Added queue element: 4d7a3080
conn DEBUG SENT: <iq id="_xmpp_bind1" type="set"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></iq>
xmpp DEBUG Finished writing queue element: 4d7a3080.
xmpp DEBUG RECV: <iq id="_xmpp_bind1" type="result"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>david@xmpp.ughstudios.com/18728370348788724423426</jid></bind></iq>
xmpp DEBUG Bind successful.
conn DEBUG QUEUED: test
conn DEBUG Added queue element: 4d7a2a80
conn DEBUG SENT: test
xmpp DEBUG Finished writing queue element: 4d7a2a80.
conn DEBUG QUEUED: test
conn DEBUG Added queue element: 4d79fd20
conn DEBUG SENT: test
xmpp DEBUG Finished writing queue element: 4d79fd20.
ughstudios commented 2 years ago
void send_message(std::string msg)
{
    if (context == NULL)
        return;

    xmpp_stanza_t* message = xmpp_message_new(context, "chat", "daniel@xmpp.ughstudios.com", "");
    xmpp_message_set_body(message, msg.c_str());
    xmpp_send(connection, message);
    xmpp_stanza_release(message);
}

I was finally able to get it to work, I left the "id" field blank in the xmpp_message_new method, I don't know if this is safe? I haven't looked into the method itself, will do when I have time.

pasis commented 2 years ago

Not sure if empty id is acceptable, need to read xmpp rfc for that. However, you can set any string there, for example "1" or "id1" or even a UUID value.

pasis commented 2 years ago

By the way, xmpp_message_new() is a wrapper on top of basic API which is xmpp_stanza_new() and others. If you check its implementation you will see how to work with the API.

pasis commented 2 years ago

Also check this post: https://xmpp.pasis.pp.ua/en/libstrophe-first-xmpp-program/ It describes some libstrophe basics

jubalh commented 2 years ago

@Bdoom would you mind closing this issue if your question got answered?

ughstudios commented 2 years ago

@Bdoom would you mind closing this issue if your question got answered?

Sure. However, I do think it would be cool to leave it open as I think it would be useful for other people. If it's closed, when people go to the issues tab, by default, closed issues are hidden.

pasis commented 2 years ago

It's still should be closed, the same for visual studio issue. Links are reachable from search engines and people will find the info. And leaving tickets open will make harder to track what needs to be addressed.