Skip to content

Port dlg event subscription#4328

Merged
sauwming merged 6 commits intopjsip:masterfrom
thanhloi2603:port_dlg_event_subscription
Mar 2, 2025
Merged

Port dlg event subscription#4328
sauwming merged 6 commits intopjsip:masterfrom
thanhloi2603:port_dlg_event_subscription

Conversation

@thanhloi2603
Copy link
Copy Markdown
Contributor

Hi all, following up the PR #3754 for implementing the Dialog Event subscription (client only) which is working fine and present in 2.15.1.

But there is no porting to the applications to use the feature (python3 in my case).

So please preview this PR as I'm currently having it working with my setup.

I'm not sure how to setup automated unit tests (if there is any) in opening this PR, so feel free to correct me then.

Thank you.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 27, 2025

CLA assistant check
All committers have signed the CLA.

@sauwming
Copy link
Copy Markdown
Member

While you are at it, also add API Buddy::subscribeDlgEvent() and updateDlgEvent()?
Actually there's one more API getDlgEventInfo(), but that one is a bit long since it requires porting of pjsua_buddy_dlg_event_info as well, so it's optional.

@thanhloi2603
Copy link
Copy Markdown
Contributor Author

@sauwming, Buddy::subscribeDlgEvent() and updateDlgEvent()? added.

Copy link
Copy Markdown
Member

@sauwming sauwming left a comment

Choose a reason for hiding this comment

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

You also need to sign the CLA.

@sauwming sauwming merged commit 19ce099 into pjsip:master Mar 2, 2025
42 checks passed
@palla89
Copy link
Copy Markdown

palla89 commented Mar 4, 2025

Hi @sauwming and @thanhloi2603 , I hope I'm not doing this comment in the wrong place, but I can't get the onBuddyDlgEventState callback called, even if after this new PR I can successfully see the NOTIFY messages and their updates in the logs.
Can you help me understand if there's a bug or if I'm incapable of letting it work? 😄

this is my subscribe function in my app:

void PJSua2::subscribeDialogEvent(const std::string& uri, bool subscribe) {
    if (!acc) {
        std::cout << "Error: No account not available" << std::endl;
        return;
    }

    try {
        std::cout << "Setting up dialog event subscription for: " << uri << std::endl;

        // Create a buddy object for subscription
        BuddyConfig cfg;
        cfg.uri = uri;
        cfg.subscribe = false;  // Don't subscribe to presence
        cfg.subscribe_dlg_event = subscribe;  // Subscribe to dialog events

        // Create and store the buddy using our custom class
        MyBuddy* buddy = new MyBuddy();
        
        std::cout << "Creating buddy with config..." << std::endl;
        buddy->create(*acc, cfg);
        
        // Store the buddy to prevent destruction
        buddies.push_back(buddy);
        
        // Explicitly subscribe to dialog events
        if (subscribe) {
            std::cout << "Initiating dialog event subscription..." << std::endl;
            buddy->subscribeDlgEvent(true);
                        
            std::cout << "Updating dialog event subscription..." << std::endl;
            buddy->updateDlgEvent();
                        
            // Get and print buddy info to verify subscription
            BuddyInfo bi = buddy->getInfo();
            std::cout << "Subscription state: " << bi.subState << std::endl;
            std::cout << "Subscription termination reason: " << bi.subTermReason << std::endl;
        }

    } catch(Error& err) {
        std::cout << "Error subscribing to dialog events: " << err.info() << std::endl;
    }
}

and it's working perfectly as it should. The problematic part is that even when the dialog event arrives with another state (and I can see it from the logs) I can't reach my function:

class MyBuddy : public Buddy {
public:
    MyBuddy() {
        std::cout << "MyBuddy constructor called" << std::endl;
    }

    // Add this method to handle general buddy state changes
     void onBuddyState() override {
        std::cout << "MyBuddy::onBuddyState called" << std::endl;
        
        try {
            BuddyInfo bi = getInfo();
            std::cout << "Buddy state changed for: " << bi.uri << std::endl;
            std::cout << "Subscription state: " << bi.subState << std::endl;
            std::cout << "Subscription termination reason: " << bi.subTermReason << std::endl;
        } catch(Error& err) {
            std::cout << "Error in onBuddyState: " << err.info() << std::endl;
        }
    }

    // Override the base virtual method for dialog state
     void onBuddyDlgEventState() override {
        std::cout << "MyBuddy::onBuddyDlgEventState called" << std::endl;
        
        try {
            BuddyInfo bi = getInfo();
            std::cout << "Dialog state changed for buddy: " << bi.uri << std::endl;
            
            // Get subscription state
            pjsip_evsub_state state = bi.subState;
            std::cout << "Subscription state: " << state << std::endl;
            
            // Get presence status
            std::cout << "Presence status: " << bi.presStatus.status << std::endl;
        } catch(Error& err) {
            std::cout << "Error in onBuddyDlgEventState: " << err.info() << std::endl;
        }
    }

What am I doing wrong?

@thanhloi2603
Copy link
Copy Markdown
Contributor Author

I guess you have to rebuild both pjproject and pjsua2 porting apps, I suggest you do it at master as the commits were already merged.

@palla89
Copy link
Copy Markdown

palla89 commented Mar 5, 2025

I already did that and infact now I can see in the console the NOTIFY messages arriving (before your PR I couldn't), but I can't get the callback function onBuddyDlgEventState to get called and so I can't intercept events 😢

@thanhloi2603
Copy link
Copy Markdown
Contributor Author

@palla89
onBuddyDlgEventState is for checking the status of the subscription.
If you want the watched parties` dialog info, you have to check them in onBuddyEvSubDlgEventState

@palla89
Copy link
Copy Markdown

palla89 commented Mar 6, 2025

I didn't post the code of it but both of the functions are not getting triggered unfortunately 😔 I really can't understand why

virtual void onBuddyEvSubDlgEventState(OnBuddyEvSubStateParam &prm) override {
        std::cout << "MyBuddy::onBuddyEvSubDlgEventState called with event type: " << prm.e.type << std::endl;
        
        try {
            BuddyInfo bi = getInfo();
            
            // Parse the XML from the NOTIFY body if available
            if (prm.e.type == PJSIP_EVENT_RX_MSG) {
                std::cout << "Received RX_MSG event" << std::endl;
                pjsip_rx_data *rdata = (pjsip_rx_data*)prm.e.body.rxMsg.rdata.pjRxData;
                if (rdata && rdata->msg_info.msg->body) {
                    std::string body((char*)rdata->msg_info.msg->body->data,
                                   rdata->msg_info.msg->body->len);
                    std::cout << "Received dialog body: " << body << std::endl;
                    
                    // Parse dialog state
                    if (body.find("<state>early</state>") != std::string::npos) {
                        std::cout << "Dialog state: early (ringing)" << std::endl;
                        if (dialogStateChangedPtr) {
                            dialogStateChangedPtr(bi.uri.c_str(), 1);
                        }
                    } else if (body.find("<state>confirmed</state>") != std::string::npos) {
                        std::cout << "Dialog state: confirmed (in call)" << std::endl;
                        if (dialogStateChangedPtr) {
                            dialogStateChangedPtr(bi.uri.c_str(), 2);
                        }
                    } else if (body.find("<state>terminated</state>") != std::string::npos) {
                        std::cout << "Dialog state: terminated (available)" << std::endl;
                        if (dialogStateChangedPtr) {
                            dialogStateChangedPtr(bi.uri.c_str(), 0);
                        }
                    }
                }
            }
        } catch(Error& err) {
            std::cout << "Error in onBuddyEvSubDlgEventState: " << err.info() << std::endl;
        }
    }

I'm not sure the function content is totally correct but I'm at the point where I just would be happy if it would called 😃

@thanhloi2603
Copy link
Copy Markdown
Contributor Author

thanhloi2603 commented Mar 6, 2025

ah my bad @palla89, @sauwming , this PR is missing the declaration for the callback function in endpoint's libInit.
I added them in this commit 3787746

Also created another PR #4342 waiting for preview.

My apologies again for the missing.

@palla89
Copy link
Copy Markdown

palla89 commented Mar 6, 2025

No need to apologize, you made a great work! thank you very much for checking my issue, I'm gonna try it today or at worst tomorrow and let you know 😄

BarryYin pushed a commit to BarryYin/pjproject that referenced this pull request Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants