| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * libjingle | |
| 3 * Copyright 2004--2005, Google Inc. | |
| 4 * | |
| 5 * Redistribution and use in source and binary forms, with or without | |
| 6 * modification, are permitted provided that the following conditions are met: | |
| 7 * | |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | |
| 9 * this list of conditions and the following disclaimer. | |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 11 * this list of conditions and the following disclaimer in the documentation | |
| 12 * and/or other materials provided with the distribution. | |
| 13 * 3. The name of the author may not be used to endorse or promote products | |
| 14 * derived from this software without specific prior written permission. | |
| 15 * | |
| 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
| 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
| 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
| 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
| 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
| 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 */ | |
| 27 | |
| 28 #include "talk/examples/call/presencepushtask.h" | |
| 29 | |
| 30 #include "talk/examples/call/muc.h" | |
| 31 #include "webrtc/libjingle/xmpp/constants.h" | |
| 32 #include "webrtc/base/stringencode.h" | |
| 33 | |
| 34 | |
| 35 | |
| 36 namespace buzz { | |
| 37 | |
| 38 // string helper functions ----------------------------------------------------- | |
| 39 | |
| 40 static bool | |
| 41 IsXmlSpace(int ch) { | |
| 42 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; | |
| 43 } | |
| 44 | |
| 45 static bool ListContainsToken(const std::string & list, | |
| 46 const std::string & token) { | |
| 47 size_t i = list.find(token); | |
| 48 if (i == std::string::npos || token.empty()) | |
| 49 return false; | |
| 50 bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1])); | |
| 51 bool boundary_after = (i == list.length() - token.length() || | |
| 52 IsXmlSpace(list[i + token.length()])); | |
| 53 return boundary_before && boundary_after; | |
| 54 } | |
| 55 | |
| 56 | |
| 57 bool PresencePushTask::HandleStanza(const XmlElement * stanza) { | |
| 58 if (stanza->Name() != QN_PRESENCE) | |
| 59 return false; | |
| 60 QueueStanza(stanza); | |
| 61 return true; | |
| 62 } | |
| 63 | |
| 64 static bool IsUtf8FirstByte(int c) { | |
| 65 return (((c)&0x80)==0) || // is single byte | |
| 66 ((unsigned char)((c)-0xc0)<0x3e); // or is lead byte | |
| 67 } | |
| 68 | |
| 69 int PresencePushTask::ProcessStart() { | |
| 70 const XmlElement * stanza = NextStanza(); | |
| 71 if (stanza == NULL) | |
| 72 return STATE_BLOCKED; | |
| 73 | |
| 74 Jid from(stanza->Attr(QN_FROM)); | |
| 75 std::map<Jid, buzz::Muc*>::const_iterator elem = | |
| 76 client_->mucs().find(from.BareJid()); | |
| 77 if (elem == client_->mucs().end()) { | |
| 78 HandlePresence(from, stanza); | |
| 79 } else { | |
| 80 HandleMucPresence(elem->second, from, stanza); | |
| 81 } | |
| 82 | |
| 83 return STATE_START; | |
| 84 } | |
| 85 | |
| 86 void PresencePushTask::HandlePresence(const Jid& from, | |
| 87 const XmlElement* stanza) { | |
| 88 if (stanza->Attr(QN_TYPE) == STR_ERROR) | |
| 89 return; | |
| 90 | |
| 91 PresenceStatus s; | |
| 92 FillStatus(from, stanza, &s); | |
| 93 SignalStatusUpdate(s); | |
| 94 } | |
| 95 | |
| 96 void PresencePushTask::HandleMucPresence(buzz::Muc* muc, | |
| 97 const Jid& from, | |
| 98 const XmlElement* stanza) { | |
| 99 if (from == muc->local_jid()) { | |
| 100 if (!stanza->HasAttr(QN_TYPE)) { | |
| 101 // We joined the MUC. | |
| 102 const XmlElement* elem = stanza->FirstNamed(QN_MUC_USER_X); | |
| 103 // Status code=110 or 100 is not guaranteed to be present, so we | |
| 104 // only check the item element and Muc join status. | |
| 105 if (elem) { | |
| 106 if (elem->FirstNamed(QN_MUC_USER_ITEM) && | |
| 107 muc->state() == buzz::Muc::MUC_JOINING) { | |
| 108 SignalMucJoined(muc->jid()); | |
| 109 } | |
| 110 } | |
| 111 } else { | |
| 112 // We've been kicked. Bye. | |
| 113 int error = 0; | |
| 114 if (stanza->Attr(QN_TYPE) == STR_ERROR) { | |
| 115 const XmlElement* elem = stanza->FirstNamed(QN_ERROR); | |
| 116 if (elem && elem->HasAttr(QN_CODE)) { | |
| 117 error = atoi(elem->Attr(QN_CODE).c_str()); | |
| 118 } | |
| 119 } | |
| 120 SignalMucLeft(muc->jid(), error); | |
| 121 } | |
| 122 } else { | |
| 123 MucPresenceStatus s; | |
| 124 FillMucStatus(from, stanza, &s); | |
| 125 SignalMucStatusUpdate(muc->jid(), s); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 void PresencePushTask::FillStatus(const Jid& from, const XmlElement* stanza, | |
| 130 PresenceStatus* s) { | |
| 131 s->set_jid(from); | |
| 132 if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) { | |
| 133 s->set_available(false); | |
| 134 } else { | |
| 135 s->set_available(true); | |
| 136 const XmlElement * status = stanza->FirstNamed(QN_STATUS); | |
| 137 if (status != NULL) { | |
| 138 s->set_status(status->BodyText()); | |
| 139 | |
| 140 // Truncate status messages longer than 300 bytes | |
| 141 if (s->status().length() > 300) { | |
| 142 size_t len = 300; | |
| 143 | |
| 144 // Be careful not to split legal utf-8 chars in half | |
| 145 while (!IsUtf8FirstByte(s->status()[len]) && len > 0) { | |
| 146 len -= 1; | |
| 147 } | |
| 148 std::string truncated(s->status(), 0, len); | |
| 149 s->set_status(truncated); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY); | |
| 154 if (priority != NULL) { | |
| 155 int pri; | |
| 156 if (rtc::FromString(priority->BodyText(), &pri)) { | |
| 157 s->set_priority(pri); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 const XmlElement * show = stanza->FirstNamed(QN_SHOW); | |
| 162 if (show == NULL || show->FirstChild() == NULL) { | |
| 163 s->set_show(PresenceStatus::SHOW_ONLINE); | |
| 164 } | |
| 165 else { | |
| 166 if (show->BodyText() == "away") { | |
| 167 s->set_show(PresenceStatus::SHOW_AWAY); | |
| 168 } | |
| 169 else if (show->BodyText() == "xa") { | |
| 170 s->set_show(PresenceStatus::SHOW_XA); | |
| 171 } | |
| 172 else if (show->BodyText() == "dnd") { | |
| 173 s->set_show(PresenceStatus::SHOW_DND); | |
| 174 } | |
| 175 else if (show->BodyText() == "chat") { | |
| 176 s->set_show(PresenceStatus::SHOW_CHAT); | |
| 177 } | |
| 178 else { | |
| 179 s->set_show(PresenceStatus::SHOW_ONLINE); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C); | |
| 184 if (caps != NULL) { | |
| 185 std::string node = caps->Attr(QN_NODE); | |
| 186 std::string ver = caps->Attr(QN_VER); | |
| 187 std::string exts = caps->Attr(QN_EXT); | |
| 188 | |
| 189 s->set_know_capabilities(true); | |
| 190 s->set_caps_node(node); | |
| 191 s->set_version(ver); | |
| 192 | |
| 193 if (ListContainsToken(exts, "voice-v1")) { | |
| 194 s->set_voice_capability(true); | |
| 195 } | |
| 196 if (ListContainsToken(exts, "video-v1")) { | |
| 197 s->set_video_capability(true); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 const XmlElement* delay = stanza->FirstNamed(kQnDelayX); | |
| 202 if (delay != NULL) { | |
| 203 // Ideally we would parse this according to the Psuedo ISO-8601 rules | |
| 204 // that are laid out in JEP-0082: | |
| 205 // http://www.jabber.org/jeps/jep-0082.html | |
| 206 std::string stamp = delay->Attr(kQnStamp); | |
| 207 s->set_sent_time(stamp); | |
| 208 } | |
| 209 | |
| 210 const XmlElement* nick = stanza->FirstNamed(QN_NICKNAME); | |
| 211 if (nick) { | |
| 212 s->set_nick(nick->BodyText()); | |
| 213 } | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 void PresencePushTask::FillMucStatus(const Jid& from, const XmlElement* stanza, | |
| 218 MucPresenceStatus* s) { | |
| 219 FillStatus(from, stanza, s); | |
| 220 } | |
| 221 | |
| 222 } | |
| OLD | NEW |