source: qutecom-2.2/libs/sipwrapper/src/phapi/PhApiCallbacks.cpp @ 577:3da5f4484c80

Last change on this file since 577:3da5f4484c80 was 577:3da5f4484c80, checked in by laurent@…, 3 years ago

implement rfc 4480 for presence

File size: 30.7 KB
Line 
1/*
2 * WengoPhone, a voice over Internet phone
3 * Copyright (C) 2004-2007  Wengo
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#include "PhApiCallbacks.h"
21
22#include "PhApiWrapper.h"
23#include "PhApiIMChat.h"
24
25#include <sipwrapper/WebcamVideoFrame.h>
26
27#include <sipwrapper/SipWrapper.h>
28#include <imwrapper/IMPresence.h>
29#include <imwrapper/EnumPresenceState.h>
30#include <imwrapper/IMChatSession.h>
31
32#include <util/StringList.h>
33#include <util/Logger.h>
34
35#ifdef ENABLE_VIDEO
36        #include <pixertool/pixertool.h>
37#endif
38
39#include <QtXml/QtXml>
40
41using namespace std;
42
43extern "C" {
44
45        static int phApiEventsHandler(OWPL_EVENT_CATEGORY category, void* pInfo, void* pUserData) {
46                switch(category) {
47                        case EVENT_CATEGORY_CALLSTATE :
48                                PhApiCallbacks::getInstance().callProgress((OWPL_CALLSTATE_INFO *)pInfo);
49                                break;
50
51                        case EVENT_CATEGORY_LINESTATE :
52                                PhApiCallbacks::getInstance().registerProgress((OWPL_LINESTATE_INFO *)pInfo);
53                                break;
54
55                        case EVENT_CATEGORY_MESSAGE :
56                                PhApiCallbacks::getInstance().messageProgress((OWPL_MESSAGE_INFO *)pInfo);
57                                break;
58
59                        case EVENT_CATEGORY_SUB_STATUS :
60                                PhApiCallbacks::getInstance().subscriptionProgress((OWPL_SUBSTATUS_INFO *)pInfo);
61                                break;
62
63                        case EVENT_CATEGORY_NOTIFY :
64                                PhApiCallbacks::getInstance().onNotify((OWPL_NOTIFICATION_INFO *)pInfo);
65                                break;
66
67                        case EVENT_CATEGORY_ERROR :
68                                PhApiCallbacks::getInstance().errorNotify((OWPL_ERROR_INFO *)pInfo);
69                                break;
70
71                        default :
72                                break;
73                }
74
75                return 0;
76        }
77
78}
79
80PhApiCallbacks::PhApiCallbacks() {}
81
82PhApiCallbacks::~PhApiCallbacks() {}
83
84void PhApiCallbacks::startListeningPhApiEvents() {
85        owplEventListenerAdd(phApiEventsHandler, NULL);
86}
87
88void PhApiCallbacks::callProgress(OWPL_CALLSTATE_INFO * info) {
89        if(info != NULL) {
90                PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
91                std::string from;
92                phVideoFrameReceivedEvent_t * video_data = NULL;
93                switch(info->event) {
94                        case CALLSTATE_UNKNOWN :
95                                break;
96
97                        case CALLSTATE_NEWCALL :
98                                switch(info->cause) {
99                                        case CALLSTATE_NEW_CALL_NORMAL :
100                                                break;
101
102                                        case CALLSTATE_NEW_CALL_TRANSFERRED :
103                                                break;
104
105                                        case CALLSTATE_NEW_CALL_TRANSFER :
106                                                break;
107
108                                        default :
109                                                break;
110                                }
111                                break;
112
113                        case CALLSTATE_REMOTE_OFFERING :
114                                switch(info->cause) {
115                                        case CALLSTATE_REMOTE_OFFERING_NORMAL :
116                                                if (!info->szRemoteIdentity) {
117                                                        from = "unknown@unknown.unknown";
118                                                }
119                                                else {
120                                                        from = info->szRemoteIdentity;
121                                                }
122
123                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateDialing, from);
124                                                break;
125
126                                        default :
127                                                break;
128                                }
129                                break;
130
131                        case CALLSTATE_REMOTE_ALERTING :
132                                switch(info->cause) {
133                                        case CALLSTATE_REMOTE_ALERTING_NORMAL :
134                                                if (!info->szRemoteIdentity) {
135                                                        from = "unknown@unknown.unknown";
136                                                }
137                                                else {
138                                                        from = info->szRemoteIdentity;
139                                                }
140                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateRinging, from);
141                                                break;
142
143                                        case CALLSTATE_REMOTE_ALERTING_MEDIA_START :
144                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateRingingStart, from);
145                                                break;
146
147                                        case CALLSTATE_REMOTE_ALERTING_MEDIA_STOP :
148                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateRingingStop, from);
149                                                break;
150
151                                        default :
152                                                break;
153                                }
154                                break;
155
156                        case CALLSTATE_CONNECTED :
157                                switch(info->cause) {
158                                        case CALLSTATE_CONNECTED_ACTIVE :
159                                                if (!info->szRemoteIdentity) {
160                                                        from = "unknown@unknown.unknown";
161                                                }
162                                                else {
163                                                        from = info->szRemoteIdentity;
164                                                }
165
166                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateTalking, from);
167                                                break;
168
169                                        case CALLSTATE_CONNECTED_ACTIVE_HELD :
170                                                break;
171
172                                        case CALLSTATE_CONNECTED_INACTIVE :
173                                                break;
174
175                                        default :
176                                                break;
177                                }
178                                break;
179
180                        case CALLSTATE_DISCONNECTED :
181                                switch(info->cause) {
182                                        case CALLSTATE_DISCONNECTED_BADADDRESS :
183                                                break;
184
185                                        case CALLSTATE_DISCONNECTED_BUSY :
186                                                if (!info->szRemoteIdentity) {
187                                                        from = "unknown@unknown.unknown";
188                                                }
189                                                else {
190                                                        from = info->szRemoteIdentity;
191                                                }
192                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateBusy, from);
193                                                break;
194
195                                        case CALLSTATE_DISCONNECTED_REJECTED :
196                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateRejected, from);
197                                                break;
198
199                                        case CALLSTATE_DISCONNECTED_USER_NOT_FOUND :
200                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateUserNotFound, from);
201                                                break;
202
203                                        case CALLSTATE_DISCONNECTED_USER_NOT_AVAILABLE :
204                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateUserNotAvailable, from);
205                                                break;
206
207                                        case CALLSTATE_DISCONNECTED_NORMAL :
208                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateClosed, from);
209                                                break;
210
211                                        case CALLSTATE_DISCONNECTED_RESOURCES :
212                                                break;
213
214                                        case CALLSTATE_DISCONNECTED_NETWORK :
215                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateError, from);
216                                                break;
217
218                                        case CALLSTATE_DISCONNECTED_REDIRECTED :
219                                                break;
220
221                                        case CALLSTATE_DISCONNECTED_NO_RESPONSE :
222                                                from = info->szRemoteIdentity;
223                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateClosed, from);
224                                                break;
225
226                                        case CALLSTATE_DISCONNECTED_AUTH :
227                                                break;
228
229                                        case CALLSTATE_DISCONNECTED_UNKNOWN :
230                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateError, from);
231                                                break;
232
233                                        default :
234                                                break;
235                                }
236                                break;
237
238                        case CALLSTATE_OFFERING :
239                                switch(info->cause) {
240                                        case CALLSTATE_OFFERING_ACTIVE :
241                                                if (!info->szRemoteIdentity) {
242                                                        from = "unknown@unknown.unknown";
243                                                }
244                                                else {
245                                                        from = info->szRemoteIdentity;
246                                                }
247                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateIncoming, from);
248                                                break;
249
250                                        default :
251                                                break;
252                                }
253                                break;
254
255                        case CALLSTATE_ALERTING :
256                                switch(info->cause) {
257                                        case CALLSTATE_ALERTING_NORMAL :
258                                                break;
259
260                                        default :
261                                                break;
262                                }
263                                break;
264
265                        case CALLSTATE_DESTROYED :
266                                switch(info->cause) {
267                                        case CALLSTATE_DESTROYED_NORMAL :
268                                                break;
269
270                                        default :
271                                                break;
272                                }
273                                break;
274
275                        case CALLSTATE_AUDIO_EVENT :
276                                switch(info->cause) {
277                                        case CALLSTATE_AUDIO_START :
278                                                break;
279
280                                        case CALLSTATE_AUDIO_STOP :
281                                                break;
282
283                                        case CALLSTATE_AUDIO_DTMF :
284                                                break;
285
286                                        default :
287                                                break;
288                                }
289                                break;
290
291                        case CALLSTATE_VIDEO_EVENT :
292                                switch(info->cause) {
293                                        case CALLSTATE_VIDEO_START :
294                                                break;
295
296                                        case CALLSTATE_VIDEO_STOP :
297                                                break;
298
299                                        case CALLSTATE_VIDEO_FRAME_RCV :
300                                                if(info->pData != NULL) {
301                                                        video_data = (phVideoFrameReceivedEvent_t *) info->pData;
302#ifdef ENABLE_VIDEO
303                                                        if(video_data != NULL) {
304                                                                p->videoFrameReceivedEvent(*p, info->hCall, video_data->frame_remote, video_data->frame_local);
305                                                        }
306#endif
307                                                }
308                                                break;
309
310                                        default :
311                                                break;
312                                }
313                                break;
314
315                        case CALLSTATE_TRANSFER :
316                                switch(info->cause) {
317                                        case CALLSTATE_TRANSFER_INITIATED :
318                                                break;
319
320                                        case CALLSTATE_TRANSFER_ACCEPTED :
321                                                break;
322
323                                        case CALLSTATE_TRANSFER_TRYING :
324                                                break;
325
326                                        case CALLSTATE_TRANSFER_RINGING :
327                                                break;
328
329                                        case CALLSTATE_TRANSFER_SUCCESS :
330                                                break;
331
332                                        case CALLSTATE_TRANSFER_FAILURE :
333                                                break;
334
335                                        default :
336                                                break;
337                                }
338                                break;
339
340                        case CALLSTATE_REDIRECTED :
341                                switch(info->cause) {
342                                        case CALLSTATE_REDIRECTED_NORMAL :
343                                                from = info->szRemoteIdentity;
344                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateRedirected, from);
345                                                break;
346
347                                        default :
348                                                break;
349                                }
350                                break;
351
352                        case CALLSTATE_HOLD :
353                                switch(info->cause) {
354                                        case CALLSTATE_HOLD_STARTED :
355                                                from = info->szRemoteIdentity;
356                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateHold, from);
357                                                break;
358
359                                        case CALLSTATE_HOLD_RESUMED :
360                                                from = info->szRemoteIdentity;
361                                                p->phoneCallStateChangedEvent(*p, info->hCall, EnumPhoneCallState::PhoneCallStateResumed, from);
362                                                break;
363
364                                        default :
365                                                break;
366                                }
367                                break;
368
369                        case CALLSTATE_SECURITY_EVENT :
370                                switch(info->cause) {
371                                        case CALLSTATE_SECURITY_SELF_SIGNED_CERT :
372                                                break;
373
374                                        case CALLSTATE_SECURITY_SESSION_NOT_SECURED :
375                                                break;
376
377                                        case CALLSTATE_SECURITY_REMOTE_SMIME_UNSUPPORTED :
378                                                break;
379
380                                        default :
381                                                break;
382                                }
383                                break;
384
385                        case CALLSTATE_IDENTITY_CHANGE :
386                                switch(info->cause) {
387                                        case CALLSTATE_IDENTITY_CHANGE_UNKNOWN :
388                                                break;
389
390                                        default :
391                                                break;
392                                }
393                                break;
394
395                        default :
396                                break;
397                }
398        }
399}
400
401void PhApiCallbacks::registerProgress(OWPL_LINESTATE_INFO * info) {
402        PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
403        switch(info->event) {
404                case LINESTATE_UNKNOWN :
405                        p->setRegistered(false);
406                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateUnknown);
407                        break;
408
409                case LINESTATE_REGISTERING :
410                        switch(info->cause) {
411                                case LINESTATE_CAUSE_NORMAL :
412                                        break;
413
414                                default :
415                                        break;
416                        }
417                        break;
418
419                case LINESTATE_REGISTERED :
420                        switch(info->cause) {
421                                case LINESTATE_CAUSE_NORMAL :
422                                if(!p->isRegistered()) {
423                                        p->setRegistered(true);
424                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateOk);
425                                        p->connectedEvent(*p);
426                                        for (std::set<std::string>::const_iterator it = p->getSubscribedContacts().begin();
427                                                it != p->getSubscribedContacts().end();
428                                                ++it) {
429                                                        p->subscribeToPresenceOf(*it);
430                                        }
431                                }
432                                break;
433
434                                default :
435                                break;
436                        }
437                        break;
438
439                case LINESTATE_UNREGISTERING :
440                        switch(info->cause) {
441                                case LINESTATE_CAUSE_NORMAL :
442                                        break;
443
444                                default :
445                                        break;
446                        }
447                        break;
448
449                case LINESTATE_UNREGISTERED :
450                        switch(info->cause) {
451                                case LINESTATE_CAUSE_NORMAL :
452                                        p->setRegistered(false);
453                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateClosed);
454                                        break;
455
456                                default :
457                                        break;
458                        }
459                        break;
460
461                case LINESTATE_REGISTER_FAILED :
462                        switch(info->cause) {
463                                case LINESTATE_CAUSE_COULD_NOT_CONNECT :
464                                        if (p->isRegistered()) {
465                                                p->setRegistered(false);
466                                                p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateTimeout);
467                                                p->disconnectedEvent(*p, true, "No response from server");
468                                        }
469                                        break;
470
471                                case LINESTATE_CAUSE_NOT_AUTHORIZED :
472                                        p->setRegistered(false);
473                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateAuthenticationError);
474                                        p->disconnectedEvent(*p, true, "Bad login or password");
475                                        break;
476
477                                case LINESTATE_CAUSE_TIMEOUT :
478                                        p->setRegistered(false);
479                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateTimeout);
480                                        p->disconnectedEvent(*p, true, "No response from server");
481                                        break;
482
483                                case LINESTATE_CAUSE_NOT_FOUND :
484                                        p->setRegistered(false);
485                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateAuthenticationError);
486                                        p->disconnectedEvent(*p, true, "Bad login or password");
487                                        break;
488
489                                default :
490                                        p->setRegistered(false);
491                                        LOG_ERROR("unknown phApi event");
492                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateServerError);
493                                        p->disconnectedEvent(*p, true, "No response from server");
494                                        break;
495                        }
496                        for (std::set<std::string>::const_iterator it = p->getSubscribedContacts().begin();
497                                it != p->getSubscribedContacts().end(); ++it) {
498                                p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateUnknown, "", *it);
499                        }
500                        break;
501
502                case LINESTATE_UNREGISTER_FAILED :
503                        p->setRegistered(false);
504                        switch(info->cause) {
505                                /*
506                                case LINESTATE_CAUSE_COULD_NOT_CONNECT:
507                                        break;
508
509                                case LINESTATE_CAUSE_NOT_AUTHORIZED:
510                                        break;
511                                */
512                                case LINESTATE_CAUSE_TIMEOUT:
513                                        //p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateTimeout);
514                                        break;
515                                /*
516                                case LINESTATE_CAUSE_NOT_FOUND:
517                                        break;
518                                */
519                                default :
520                                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateClosed);
521                                        break;
522                        }
523                        break;
524
525                case LINESTATE_PROVISIONED :
526                        switch(info->cause) {
527                                case LINESTATE_CAUSE_NORMAL :
528                                        break;
529
530                                default :
531                                        break;
532                        }
533                        break;
534
535                default :
536                        p->setRegistered(false);
537                        LOG_ERROR("unknown phApi event");
538                        p->phoneLineStateChangedEvent(*p, info->hLine, EnumPhoneLineState::PhoneLineStateServerError);
539                        break;
540        }
541}
542
543void PhApiCallbacks::messageProgress(OWPL_MESSAGE_INFO * info) {
544        PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
545
546        if ((info->event == MESSAGE_SUCCESS && info->cause == MESSAGE_SUCCESS_NORMAL) ||
547                (info->event == MESSAGE_FAILURE && info->cause == MESSAGE_FAILURE_UNKNOWN)){
548                //We drop status message
549                return;
550        }
551
552        std::string content;
553        if(info->szContent) {
554                content = info->szContent;
555        }
556
557        // Wengo case: somebody <sip:somebody@voip.wengo.fr>;tag=b6e249633711def8c2dbe3c2d4f39996-e1d6
558        // Standard case: "Mister somebody" <sip:somebody@sipprovider.com>;tag=b6e249633711def1d6
559        String from = p->parseFromHeader(std::string(info->szRemoteIdentity));
560        String alias = p->getDisplayNameFromHeader(std::string(info->szRemoteIdentity));
561
562        std::string ctype;
563        if (info->szContentType) {
564                ctype = info->szContentType;
565        }
566
567        std::string subtype;
568        if (info->szSubContentType) {
569                subtype = info->szSubContentType;
570        }
571
572        //Getting buddy icon
573        if ((info->event == MESSAGE_NEW) && (ctype == "buddyicon")) {
574                if (!subtype.empty()) {
575                        p->contactIconChangedEvent(*p, from, subtype);
576                }
577                return;
578        }
579
580        // Is there already an IMChatSession with this contact?
581        IMChatSession *imChatSession = p->getIMChatSession(from);
582
583        //Drop typingstate packet if there is no chat session created
584        if (!imChatSession && (ctype == "typingstate" || (ctype == "application" && subtype == "im-iscomposing+xml"))) {
585                return;
586        } else if (!imChatSession) {
587                LOG_DEBUG("creating new IMChatSession");
588                imChatSession = new IMChatSession(*PhApiIMChat::PhApiIMChatHack);
589                p->addContact(*imChatSession, from,alias);
590                p->newIMChatSessionCreatedEvent(*p, *imChatSession);
591                p->sendMyIcon(from, p->_iconFilename);
592        }
593
594        switch(info->event) {
595        case MESSAGE_NEW : {
596
597                if (ctype == "typingstate") {
598                        IMChat::TypingState state;
599
600                        if (subtype == "typing") {
601                                state = IMChat::TypingStateTyping;
602                        } else if (subtype == "stoptyping") {
603                                state = IMChat::TypingStateStopTyping;
604                        } else {
605                                state = IMChat::TypingStateNotTyping;
606                        }
607
608                        p->typingStateChangedEvent(*p, *imChatSession, from, state);
609                } else if (ctype == "application" && subtype == "im-iscomposing+xml") {
610                        IMChat::TypingState state;
611
612                        //TiXmlDocument doc;
613                        //doc.Parse(content.c_str());
614                        //TiXmlHandle docHandle(&doc);
615                        //TiXmlText * basicText = docHandle.FirstChild("isComposing").FirstChild("state").FirstChild().Text();
616                        std::string basic;
617                        QDomDocument doc("composing");
618                        if (doc.setContent(QString::fromStdString(content), true)) 
619                        {
620                                QDomNodeList nl1 = doc.elementsByTagName("isComposing");
621                                if (nl1.length() > 0) 
622                                {
623                                        QDomNodeList nl2 = nl1.item(0).toElement().elementsByTagName("state");
624                                        if (nl2.length() > 0) 
625                                                basic = nl2.item(0).toElement().text().toLower().toStdString();
626                                }
627                        }
628                        if (basic == "active")
629                                state = IMChat::TypingStateTyping;
630                        else if (basic == "idle")
631                                state = IMChat::TypingStateStopTyping;
632                        else
633                                state = IMChat::TypingStateNotTyping;
634               
635                        p->typingStateChangedEvent(*p, *imChatSession, from, state);
636                } else {
637                        // once a message is received, typing is inferred off
638                        p->typingStateChangedEvent(*p, *imChatSession, from, IMChat::TypingStateNotTyping);
639                        p->messageReceivedEvent(*p, *imChatSession, from, content);
640                }
641
642                break;
643        case MESSAGE_FAILURE :
644                LOG_DEBUG("message could not be sent");
645                p->statusMessageReceivedEvent(*p, *imChatSession, PhApiIMChat::StatusMessageError, content);
646                break;
647        }
648
649        default:
650                LOG_WARN("unknown message event=" + String::fromNumber(info->event));
651        }
652}
653
654/*
655TODO for future use ?
656void PhApiCallbacks::messageProgress(OWPL_MESSAGE_INFO * info) {
657        PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
658        IMChatSession * imChatSession;
659        string from;
660        int atPos = 0;
661        std::string buddyIcon;
662        std::map<const std::string, IMChatSession *>::const_iterator sessionIt;
663        switch(info->event) {
664                case MESSAGE_UNKNOWN :
665                        break;
666
667                case MESSAGE_NEW :
668                        switch(info->cause) {
669                                case MESSAGE_NEW_NORMAL :
670                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
671                                        from = String(info->szRemoteIdentity).split(" ")[0];
672                                        sessionIt = contactChatMap.find(from);
673                                        if (sessionIt != contactChatMap.end()) {
674                                                imChatSession = (*sessionIt).second;
675                                        } else {
676                                                LOG_DEBUG("creating new IMChatSession");
677                                                imChatSession = new IMChatSession(*PhApiIMChat::PhApiIMChatHack);
678                                                contactChatMap[from] = imChatSession;
679                                                p->addContact(*imChatSession, from);
680                                                p->newIMChatSessionCreatedEvent(*p, *imChatSession);
681                                                p->sendMyIcon(from, p->_iconFilename);
682                                        }
683                                        p->messageReceivedEvent(*p, *imChatSession, from, std::string(info->szContent));
684                                        break;
685
686                                case MESSAGE_NEW_BUDDY_ICON :
687                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
688                                        from = String(info->szRemoteIdentity).split(" ")[0];
689                                        buddyIcon = info->szSubContentType;
690                                        if(!buddyIcon.empty()) {
691                                                p->contactIconChangedEvent(*p, from, buddyIcon);
692                                        }
693                                        break;
694
695                                case MESSAGE_NEW_TYPING :
696                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
697                                        from = String(info->szRemoteIdentity).split(" ")[0];
698                                        sessionIt = contactChatMap.find(from);
699                                        if (sessionIt != contactChatMap.end()) {
700                                                imChatSession = (*sessionIt).second;
701                                                p->typingStateChangedEvent(*p, *imChatSession, from, IMChat::TypingStateTyping);
702                                        }
703                                        break;
704
705                                case MESSAGE_NEW_STOP_TYPING :
706                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
707                                        from = String(info->szRemoteIdentity).split(" ")[0];
708                                        sessionIt = contactChatMap.find(from);
709                                        if (sessionIt != contactChatMap.end()) {
710                                                imChatSession = (*sessionIt).second;
711                                                p->typingStateChangedEvent(*p, *imChatSession, from, IMChat::TypingStateStopTyping);
712                                        }
713                                        break;
714
715                                case MESSAGE_NEW_NOT_TYPING :
716                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
717                                        from = String(info->szRemoteIdentity).split(" ")[0];
718                                        sessionIt = contactChatMap.find(from);
719                                        if (sessionIt != contactChatMap.end()) {
720                                                imChatSession = (*sessionIt).second;
721                                                p->typingStateChangedEvent(*p, *imChatSession, from, IMChat::TypingStateNotTyping);
722                                        }
723                                        break;
724
725                                default :
726                                        break;
727                        }
728                        break;
729
730                case MESSAGE_SUCCESS :
731                        switch(info->cause) {
732                                case MESSAGE_SUCCESS_NORMAL :
733                                        // do nothing : drop the status message
734                                        break;
735
736                                default :
737                                        break;
738                        }
739                        break;
740
741                case MESSAGE_FAILURE :
742                        switch(info->cause) {
743                                case MESSAGE_FAILURE_UNKNOWN :
744                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
745                                        atPos = String(info->szLocalIdentity).find("@");
746                                        from = String(info->szLocalIdentity).substr(5, atPos - 5);
747                                        sessionIt = contactChatMap.find(from);
748                                        if (sessionIt != contactChatMap.end()) {
749                                                imChatSession = (*sessionIt).second;
750                                        } else {
751                                                LOG_DEBUG("creating new IMChatSession");
752                                                imChatSession = new IMChatSession(*PhApiIMChat::PhApiIMChatHack);
753                                                contactChatMap[from] = imChatSession;
754                                                p->addContact(*imChatSession, from);
755                                                p->newIMChatSessionCreatedEvent(*p, *imChatSession);
756                                                p->sendMyIcon(from, p->_iconFilename);
757                                        }
758                                        LOG_DEBUG("message could not be sent");
759                                        p->statusMessageReceivedEvent(*p, *imChatSession, PhApiIMChat::StatusMessageError, std::string(info->szContent));
760                                        break;
761
762                                case MESSAGE_FAILURE_COULD_NOT_SEND :
763                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
764                                        atPos = String(info->szLocalIdentity).find("@");
765                                        from = String(info->szLocalIdentity).substr(5, atPos - 5);
766                                        sessionIt = contactChatMap.find(from);
767                                        if (sessionIt != contactChatMap.end()) {
768                                                imChatSession = (*sessionIt).second;
769                                        } else {
770                                                LOG_DEBUG("creating new IMChatSession");
771                                                imChatSession = new IMChatSession(*PhApiIMChat::PhApiIMChatHack);
772                                                contactChatMap[from] = imChatSession;
773                                                p->addContact(*imChatSession, from);
774                                                p->newIMChatSessionCreatedEvent(*p, *imChatSession);
775                                                p->sendMyIcon(from, p->_iconFilename);
776                                        }
777                                        LOG_DEBUG("message could not be sent");
778                                        p->statusMessageReceivedEvent(*p, *imChatSession, PhApiIMChat::StatusMessageError, std::string(info->szContent));
779                                        break;
780
781                                default :
782                                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
783                                        LOG_DEBUG("message could not be sent : unknown failure cause=" + String::fromNumber(info->cause));
784                                        break;
785                        }
786                        break;
787
788                default :
789                        LOG_DEBUG("message received from=" + std::string(info->szRemoteIdentity) + " content=" + std::string(info->szContent));
790                        LOG_FATAL("unknown message event=" + String::fromNumber(info->event));
791                        break;
792        }
793}
794*/
795
796void PhApiCallbacks::subscriptionProgress(OWPL_SUBSTATUS_INFO * info) {
797        PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
798        std::string from(info->szRemoteIdentity);
799
800        switch (info->state) {
801
802                case OWPL_SUBSCRIPTION_PENDING :
803                        switch (info->cause) {
804                                case SUBSCRIPTION_CAUSE_NORMAL :
805                                        break;
806
807                                default:
808                                        break;
809                        }
810                        break;
811
812                case OWPL_SUBSCRIPTION_ACTIVE :
813                        switch (info->cause) {
814                                case SUBSCRIPTION_CAUSE_NORMAL :
815                                        p->subscribeStatusEvent(*p, from, IMPresence::SubscribeStatusOk);
816                                        break;
817
818                                default:
819                                        break;
820                        }
821                        break;
822
823                case OWPL_SUBSCRIPTION_FAILED :
824                        switch (info->cause) {
825                                case SUBSCRIPTION_CAUSE_UNKNOWN :
826                                        p->subscribeStatusEvent(*p, from, IMPresence::SubscribeStatusError);
827                                        break;
828
829                                default:
830                                        break;
831                        }
832                        break;
833
834                case OWPL_SUBSCRIPTION_EXPIRED :
835                        switch (info->cause) {
836                                case SUBSCRIPTION_CAUSE_UNKNOWN :
837                                        break;
838
839                                case SUBSCRIPTION_CAUSE_NORMAL :
840                                        break;
841
842                                default:
843                                        break;
844                        }
845                        break;
846
847                case OWPL_SUBSCRIPTION_CLOSED :
848                        switch (info->cause) {
849
850                                case SUBSCRIPTION_CAUSE_UNKNOWN :
851                                        break;
852
853                                case SUBSCRIPTION_CAUSE_NORMAL :
854                                        {
855                                                std::string buddy = computeContactId(info->szRemoteIdentity);
856                                                if (buddy.empty()) {
857                                                        return;
858                                                }
859                                               
860                                                p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateUnknown, "", buddy);
861                                        }
862                                        break;
863
864                                default:
865                                        break;
866                        }
867                        break;
868
869                 case OWPL_INSUBSCRIPTION_NEW: 
870                   p->handleIncomingSubscribe(info->hSub, info->szRemoteIdentity, info->szEvtType);
871                   break;
872
873                 case OWPL_INSUBSCRIPTION_CLOSE:
874                   p->terminateIncomingSubscribe(info->hSub);
875                   break;
876
877                default :
878                        break;
879        }
880}
881void parseXmlPresence(std::string content , bool * isOpen, std::string * presence, std::string * note )
882{
883        QDomDocument doc("presence");
884        *isOpen = false;
885       
886        // You want the person tuple's status/basic node as well as the activities sub-node.
887        // If the activities sub-node actually has content, you want the content.
888        if (doc.setContent(QString::fromStdString(content), true)) 
889        {
890                QDomNodeList nl1 = doc.elementsByTagName("tuple");
891                if (nl1.length() > 0) 
892                {
893                        QDomNodeList nl12 = nl1.item(0).toElement().elementsByTagName("status");
894                        if (nl12.length() > 0) 
895                        {
896                                QDomNodeList nl13 = nl12.item(0).toElement().elementsByTagName("basic");               
897                                if (nl13.length() > 0)
898                                {
899                                        QDomElement qde2 = nl13.item(0).toElement();
900                                        if (!qde2.isNull()) 
901                                        {
902                                                if( qde2.text().indexOf("open") != -1)
903                                                        *isOpen =true;
904                                        }
905                                }
906                        }
907                        //keep compatibility with Wengo prensence
908                        /*QDomNodeList nl22 = nl1.item(0).toElement().elementsByTagName("note");
909                        if (nl22.length() > 0)
910                        {
911                                qDebug() << "found " << nl22.length() << " note node";
912                                QDomElement qde22 = nl22.item(0).toElement();
913                                if (!qde22.isNull())
914                                {
915                                        *note = qde22.text().toStdString();
916                                }
917                        }*/
918                }
919                QDomNodeList nl = doc.elementsByTagNameNS("urn:ietf:params:xml:ns:pidf:data-model","person");
920                for (int i=0; i<nl.count(); ++i) 
921                {                       
922                        QDomElement qde = nl.item(i).toElement();
923                        if (!qde.isNull()) 
924                        {
925                                QDomNodeList nl2 = qde.elementsByTagNameNS("urn:ietf:params:xml:ns:pidf:data-model", "note");
926                                if (nl2.length() > 0) 
927                                {
928                                        if (!nl2.item(0).toElement().isNull()) 
929                                        {
930                                                *note =nl2.item(0).toElement().text().toStdString();
931                                        }
932                                }
933                               
934                                nl2 = qde.elementsByTagNameNS("urn:ietf:params:xml:ns:pidf:rpid", "activities");
935                                if (nl2.length() > 0) 
936                                {
937                                        QDomNode gok = nl2.item(0).firstChild();
938                                        if ( gok.isText() ) 
939                                        {
940                                                *presence = gok.toText().data().toStdString();
941                                                break;
942                                        }
943
944                                        if(gok.localName()  == "activity") 
945                                            *presence = gok.toElement().text().toStdString();
946                                        else
947                                           *presence = gok.localName().toStdString();
948                               
949                                        break;
950                                }       
951                        }
952                }
953        }
954}
955
956void PhApiCallbacks::onNotify(OWPL_NOTIFICATION_INFO * info) {
957        PhApiWrapper * p = PhApiWrapper::PhApiWrapperHack;
958        QDomDocument doc;
959        std::string note;
960        std::string presence;
961        std::string buddy;
962        bool isOpen = false;
963        parseXmlPresence(info->szXmlContent,&isOpen , &presence, &note);
964
965        switch(info->event) {
966                //A buddy presence
967                case NOTIFICATION_PRESENCE :
968                        buddy = computeContactId(info->Data.StatusInfo->szRemoteIdentity);
969
970                        if (buddy.empty()) {
971                                return;
972                        }
973
974                        switch(info->cause) {
975                                case NOTIFICATION_PRESENCE_ONLINE :
976                                        //if(presence.empty()) //Wengo
977                                        //      presence = note;
978
979                                        if(isOpen)
980                                        {
981                                                if (presence == "unknow" || presence.empty())
982                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateOnline, note, buddy);
983                                                else if (presence == PhApiWrapper::PresenceStateAway)
984                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateAway, note, buddy);
985                                                else if (presence == PhApiWrapper::PresenceStateDoNotDisturb || note == PhApiWrapper::PresenceStateBusy)
986                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateDoNotDisturb, note, buddy);
987                                                else
988                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateUserDefined, note, buddy);
989                                        }
990                                        else
991                                        {
992                                                if (presence == PhApiWrapper::PresenceStateBusy)
993                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateDoNotDisturb, note, buddy);
994                                                else
995                                                        p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateOffline, note, buddy);
996                                        }
997                                        break;
998
999                                case NOTIFICATION_PRESENCE_WATCHER :
1000                                        LOG_DEBUG("buddy=" + buddy + " notification=presence.winfo content=" + std::string(info->szXmlContent));                                       
1001                                        // You want the person tuple's status/basic node as well as the activities sub-node.
1002                                        // If the activities sub-node actually has content, you want the content.
1003                                        if (doc.setContent(QString::fromStdString(info->szXmlContent), true)) 
1004                                        {
1005                                                QDomNodeList nl1 = doc.elementsByTagName("watcher");
1006                                                for (int i=0; i<nl1.count(); ++i) 
1007                                                {
1008                                                        p->allowWatcher(nl1.item(i).toElement().text().toStdString());
1009                                                }
1010                                        }
1011                                        break;
1012
1013                                default :
1014                                        break;
1015                        }
1016
1017                        //basicText = docHandle.FirstChild("presence").FirstChild("tuple").FirstChild("status").FirstChild("basic").FirstChild().Text();
1018                        //if (basicText) {
1019                        //      std::string basic = basicText->Value();
1020
1021                        //      //buddy is offline
1022                        //      if (String(basic).toLowerCase() == "closed") {
1023                        //              p->presenceStateChangedEvent(*p,  EnumPresenceState::PresenceStateOffline, String::null, buddy);
1024                        //      }
1025
1026                        //      //buddy is online
1027                        //      else if (String(basic).toLowerCase() == "open") {
1028                        //              noteText = docHandle.FirstChild("presence").FirstChild("tuple").FirstChild("status").FirstChild("note").FirstChild().Text();
1029                        //              if (!noteText) {
1030                        //                      noteText = docHandle.FirstChild("presence").FirstChild("tuple").FirstChild("status").FirstChild("value").FirstChild().Text();
1031                        //              }
1032                        //              if (noteText) {
1033                        //                      std::string note = noteText->Value();
1034                        //                      if (note == PhApiWrapper::PresenceStateOnline) {
1035                        //                              p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateOnline, note, buddy);
1036                        //                      } else if (note == PhApiWrapper::PresenceStateAway) {
1037                        //                              p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateAway, note, buddy);
1038                        //                      } else if (note == PhApiWrapper::PresenceStateDoNotDisturb) {
1039                        //                              p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateDoNotDisturb, note, buddy);
1040                        //                      } else {
1041                        //                              p->presenceStateChangedEvent(*p, EnumPresenceState::PresenceStateUserDefined, note, buddy);
1042                        //                      }
1043                        //              }
1044                        //      }
1045                        //}
1046                        break;
1047
1048                //watcher list
1049                /*case NOTIFICATION_WATCHER :
1050                        LOG_DEBUG("buddy=" + buddy + " notification=presence.winfo content=" + std::string(info->szXmlContent));
1051                        watcherinfoElement = doc.FirstChildElement("watcherinfo");
1052                        if (watcherinfoElement) {
1053
1054                                watcherElement = watcherinfoElement->FirstChildElement("watcher");
1055                                while (watcherElement) {
1056
1057                                        std::string watcher(watcherElement->Value());
1058                                        p->allowWatcher(watcher);
1059
1060                                        watcherElement = watcherinfoElement->NextSiblingElement("watcher");
1061                                }
1062                        }
1063                        break;*/
1064
1065                // TODO: To complete
1066                case NOTIFICATION_MWI :
1067                        break;
1068
1069                case NOTIFICATION_UNKNOWN :
1070                        LOG_FATAL("unknown message event with content=" + std::string(info->szXmlContent));
1071                        break;
1072
1073                default :
1074                        LOG_FATAL("unknown message event with content=" + std::string(info->szXmlContent));
1075                        break;
1076        }
1077}
1078
1079void PhApiCallbacks::errorNotify(OWPL_ERROR_INFO * info) {
1080        switch(info->event) {
1081                case OWPL_ERROR :
1082                        break;
1083
1084                case OWPL_ERROR_NO_AUDIO_DEVICE :
1085                        break;
1086
1087                default :
1088                        break;
1089        }
1090}
1091
1092std::string PhApiCallbacks::computeContactId(const std::string & contactFromPhApi) {
1093        std::string buddyTmp(contactFromPhApi);
1094        size_t colonIndex = buddyTmp.find(':', 0);
1095        size_t greaterIndex = buddyTmp.find('>');
1096
1097        if (colonIndex != std::string::npos) {
1098                std::string wengoRealm = PhApiWrapper::PhApiWrapperHack->getWengoRealm();
1099                return buddyTmp.substr(colonIndex + 1, greaterIndex - colonIndex - 1);
1100        }
1101
1102        return "";
1103}
Note: See TracBrowser for help on using the repository browser.