001/** 002 * 003 * Copyright 2017 Paul Schaub 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.jingle; 018 019import org.jivesoftware.smack.SmackException; 020import org.jivesoftware.smack.XMPPConnection; 021import org.jivesoftware.smack.XMPPException; 022import org.jivesoftware.smack.packet.IQ; 023import org.jivesoftware.smack.packet.StanzaError; 024import org.jivesoftware.smackx.jingle.element.Jingle; 025import org.jivesoftware.smackx.jingle.element.JingleAction; 026import org.jivesoftware.smackx.jingle.element.JingleContent; 027import org.jivesoftware.smackx.jingle.element.JingleContentDescription; 028import org.jivesoftware.smackx.jingle.element.JingleContentTransport; 029import org.jivesoftware.smackx.jingle.element.JingleError; 030import org.jivesoftware.smackx.jingle.element.JingleReason; 031 032import org.jxmpp.jid.FullJid; 033 034/** 035 * Util to quickly create and send jingle stanzas. 036 */ 037public class JingleUtil { 038 039 private final XMPPConnection connection; 040 041 public JingleUtil(XMPPConnection connection) { 042 this.connection = connection; 043 } 044 045 public Jingle createSessionInitiate(FullJid recipient, 046 String sessionId, 047 JingleContent.Creator contentCreator, 048 String contentName, 049 JingleContent.Senders contentSenders, 050 JingleContentDescription description, 051 JingleContentTransport transport) { 052 053 Jingle.Builder jb = Jingle.getBuilder(); 054 jb.setAction(JingleAction.session_initiate) 055 .setSessionId(sessionId) 056 .setInitiator(connection.getUser()); 057 058 JingleContent.Builder cb = JingleContent.getBuilder(); 059 cb.setCreator(contentCreator) 060 .setName(contentName) 061 .setSenders(contentSenders) 062 .setDescription(description) 063 .setTransport(transport); 064 065 Jingle jingle = jb.addJingleContent(cb.build()).build(); 066 jingle.setFrom(connection.getUser()); 067 jingle.setTo(recipient); 068 069 return jingle; 070 } 071 072 public Jingle createSessionInitiateFileOffer(FullJid recipient, 073 String sessionId, 074 JingleContent.Creator contentCreator, 075 String contentName, 076 JingleContentDescription description, 077 JingleContentTransport transport) { 078 return createSessionInitiate(recipient, sessionId, contentCreator, contentName, 079 JingleContent.Senders.initiator, description, transport); 080 } 081 082 public IQ sendSessionInitiateFileOffer(FullJid recipient, 083 String sessionId, 084 JingleContent.Creator contentCreator, 085 String contentName, 086 JingleContentDescription description, 087 JingleContentTransport transport) 088 throws SmackException.NotConnectedException, InterruptedException, 089 XMPPException.XMPPErrorException, SmackException.NoResponseException { 090 091 Jingle jingle = createSessionInitiateFileOffer(recipient, sessionId, contentCreator, contentName, description, transport); 092 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 093 } 094 095 public IQ sendSessionInitiate(FullJid recipient, 096 String sessionId, 097 JingleContent.Creator contentCreator, 098 String contentName, 099 JingleContent.Senders contentSenders, 100 JingleContentDescription description, 101 JingleContentTransport transport) 102 throws SmackException.NotConnectedException, InterruptedException { 103 104 Jingle jingle = createSessionInitiate(recipient, sessionId, contentCreator, contentName, contentSenders, 105 description, transport); 106 107 return connection.createStanzaCollectorAndSend(jingle).nextResult(); 108 } 109 110 public Jingle createSessionAccept(FullJid recipient, 111 String sessionId, 112 JingleContent.Creator contentCreator, 113 String contentName, 114 JingleContent.Senders contentSenders, 115 JingleContentDescription description, 116 JingleContentTransport transport) { 117 118 Jingle.Builder jb = Jingle.getBuilder(); 119 jb.setResponder(connection.getUser()) 120 .setAction(JingleAction.session_accept) 121 .setSessionId(sessionId); 122 123 JingleContent.Builder cb = JingleContent.getBuilder(); 124 cb.setCreator(contentCreator) 125 .setName(contentName) 126 .setSenders(contentSenders) 127 .setDescription(description) 128 .setTransport(transport); 129 130 Jingle jingle = jb.addJingleContent(cb.build()).build(); 131 jingle.setTo(recipient); 132 jingle.setFrom(connection.getUser()); 133 134 return jingle; 135 } 136 137 public IQ sendSessionAccept(FullJid recipient, 138 String sessionId, 139 JingleContent.Creator contentCreator, 140 String contentName, 141 JingleContent.Senders contentSenders, 142 JingleContentDescription description, 143 JingleContentTransport transport) 144 throws SmackException.NotConnectedException, InterruptedException { 145 146 Jingle jingle = createSessionAccept(recipient, sessionId, contentCreator, contentName, contentSenders, 147 description, transport); 148 149 return connection.createStanzaCollectorAndSend(jingle).nextResult(); 150 } 151 152 public Jingle createSessionTerminate(FullJid recipient, String sessionId, JingleReason reason) { 153 Jingle.Builder jb = Jingle.getBuilder(); 154 jb.setAction(JingleAction.session_terminate) 155 .setSessionId(sessionId) 156 .setReason(reason); 157 158 Jingle jingle = jb.build(); 159 jingle.setFrom(connection.getUser()); 160 jingle.setTo(recipient); 161 162 return jingle; 163 } 164 165 public Jingle createSessionTerminate(FullJid recipient, String sessionId, JingleReason.Reason reason) { 166 return createSessionTerminate(recipient, sessionId, new JingleReason(reason)); 167 } 168 169 public Jingle createSessionTerminateDecline(FullJid recipient, String sessionId) { 170 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.decline); 171 } 172 173 public IQ sendSessionTerminateDecline(FullJid recipient, String sessionId) 174 throws SmackException.NotConnectedException, InterruptedException, 175 XMPPException.XMPPErrorException, SmackException.NoResponseException { 176 177 Jingle jingle = createSessionTerminateDecline(recipient, sessionId); 178 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 179 } 180 181 public Jingle createSessionTerminateSuccess(FullJid recipient, String sessionId) { 182 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.success); 183 } 184 185 public IQ sendSessionTerminateSuccess(FullJid recipient, String sessionId) 186 throws InterruptedException, XMPPException.XMPPErrorException, 187 SmackException.NotConnectedException, SmackException.NoResponseException { 188 189 Jingle jingle = createSessionTerminateSuccess(recipient, sessionId); 190 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 191 } 192 193 public Jingle createSessionTerminateBusy(FullJid recipient, String sessionId) { 194 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.busy); 195 } 196 197 public IQ sendSessionTerminateBusy(FullJid recipient, String sessionId) 198 throws InterruptedException, XMPPException.XMPPErrorException, 199 SmackException.NotConnectedException, SmackException.NoResponseException { 200 201 Jingle jingle = createSessionTerminateBusy(recipient, sessionId); 202 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 203 } 204 205 public Jingle createSessionTerminateAlternativeSession(FullJid recipient, String sessionId, String altSessionId) { 206 return createSessionTerminate(recipient, sessionId, JingleReason.AlternativeSession(altSessionId)); 207 } 208 209 public IQ sendSessionTerminateAlternativeSession(FullJid recipient, String sessionId, String altSessionId) 210 throws InterruptedException, XMPPException.XMPPErrorException, 211 SmackException.NotConnectedException, SmackException.NoResponseException { 212 213 Jingle jingle = createSessionTerminateAlternativeSession(recipient, sessionId, altSessionId); 214 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 215 } 216 217 public Jingle createSessionTerminateCancel(FullJid recipient, String sessionId) { 218 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.cancel); 219 } 220 221 public IQ sendSessionTerminateCancel(FullJid recipient, 222 String sessionId) 223 throws InterruptedException, XMPPException.XMPPErrorException, 224 SmackException.NotConnectedException, SmackException.NoResponseException { 225 226 Jingle jingle = createSessionTerminateCancel(recipient, sessionId); 227 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 228 } 229 230 public Jingle createSessionTerminateContentCancel(FullJid recipient, String sessionId, 231 JingleContent.Creator contentCreator, String contentName) { 232 Jingle.Builder jb = Jingle.getBuilder(); 233 jb.setAction(JingleAction.session_terminate) 234 .setSessionId(sessionId); 235 236 JingleContent.Builder cb = JingleContent.getBuilder(); 237 cb.setCreator(contentCreator).setName(contentName); 238 239 Jingle jingle = jb.addJingleContent(cb.build()).build(); 240 jingle.setFrom(connection.getUser()); 241 jingle.setTo(recipient); 242 243 return jingle; 244 } 245 246 public IQ sendSessionTerminateContentCancel(FullJid recipient, String sessionId, 247 JingleContent.Creator contentCreator, String contentName) 248 throws SmackException.NotConnectedException, InterruptedException, 249 XMPPException.XMPPErrorException, SmackException.NoResponseException { 250 Jingle jingle = createSessionTerminateContentCancel(recipient, sessionId, contentCreator, contentName); 251 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 252 } 253 254 public Jingle createSessionTerminateUnsupportedTransports(FullJid recipient, String sessionId) { 255 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.unsupported_transports); 256 } 257 258 public IQ sendSessionTerminateUnsupportedTransports(FullJid recipient, String sessionId) 259 throws InterruptedException, XMPPException.XMPPErrorException, 260 SmackException.NotConnectedException, SmackException.NoResponseException { 261 Jingle jingle = createSessionTerminateUnsupportedTransports(recipient, sessionId); 262 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 263 } 264 265 public Jingle createSessionTerminateFailedTransport(FullJid recipient, String sessionId) { 266 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.failed_transport); 267 } 268 269 public IQ sendSessionTerminateFailedTransport(FullJid recipient, String sessionId) 270 throws InterruptedException, XMPPException.XMPPErrorException, 271 SmackException.NotConnectedException, SmackException.NoResponseException { 272 Jingle jingle = createSessionTerminateFailedTransport(recipient, sessionId); 273 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 274 } 275 276 public Jingle createSessionTerminateUnsupportedApplications(FullJid recipient, String sessionId) { 277 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.unsupported_applications); 278 } 279 280 public IQ sendSessionTerminateUnsupportedApplications(FullJid recipient, String sessionId) 281 throws InterruptedException, XMPPException.XMPPErrorException, 282 SmackException.NotConnectedException, SmackException.NoResponseException { 283 Jingle jingle = createSessionTerminateUnsupportedApplications(recipient, sessionId); 284 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 285 } 286 287 public Jingle createSessionTerminateFailedApplication(FullJid recipient, String sessionId) { 288 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.failed_application); 289 } 290 291 public IQ sendSessionTerminateFailedApplication(FullJid recipient, String sessionId) 292 throws InterruptedException, XMPPException.XMPPErrorException, 293 SmackException.NotConnectedException, SmackException.NoResponseException { 294 Jingle jingle = createSessionTerminateFailedApplication(recipient, sessionId); 295 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 296 } 297 298 public Jingle createSessionTerminateIncompatibleParameters(FullJid recipient, String sessionId) { 299 return createSessionTerminate(recipient, sessionId, JingleReason.Reason.incompatible_parameters); 300 } 301 302 public IQ sendSessionTerminateIncompatibleParameters(FullJid recipient, String sessionId) 303 throws InterruptedException, XMPPException.XMPPErrorException, 304 SmackException.NotConnectedException, SmackException.NoResponseException { 305 Jingle jingle = createSessionTerminateIncompatibleParameters(recipient, sessionId); 306 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 307 } 308 309 public IQ sendContentRejectFileNotAvailable(FullJid recipient, String sessionId, JingleContentDescription description) { 310 return null; //TODO Later 311 } 312 313 public Jingle createSessionPing(FullJid recipient, String sessionId) { 314 Jingle.Builder jb = Jingle.getBuilder(); 315 jb.setSessionId(sessionId) 316 .setAction(JingleAction.session_info); 317 318 Jingle jingle = jb.build(); 319 jingle.setFrom(connection.getUser()); 320 jingle.setTo(recipient); 321 322 return jingle; 323 } 324 325 public IQ sendSessionPing(FullJid recipient, String sessionId) 326 throws SmackException.NotConnectedException, InterruptedException, 327 XMPPException.XMPPErrorException, SmackException.NoResponseException { 328 Jingle jingle = createSessionPing(recipient, sessionId); 329 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 330 } 331 332 public IQ createAck(Jingle jingle) { 333 return IQ.createResultIQ(jingle); 334 } 335 336 public void sendAck(Jingle jingle) throws SmackException.NotConnectedException, InterruptedException { 337 connection.sendStanza(createAck(jingle)); 338 } 339 340 public Jingle createTransportReplace(FullJid recipient, FullJid initiator, String sessionId, 341 JingleContent.Creator contentCreator, String contentName, 342 JingleContentTransport transport) { 343 Jingle.Builder jb = Jingle.getBuilder(); 344 jb.setInitiator(initiator) 345 .setSessionId(sessionId) 346 .setAction(JingleAction.transport_replace); 347 348 JingleContent.Builder cb = JingleContent.getBuilder(); 349 cb.setName(contentName).setCreator(contentCreator).setTransport(transport); 350 Jingle jingle = jb.addJingleContent(cb.build()).build(); 351 352 jingle.setTo(recipient); 353 jingle.setFrom(connection.getUser()); 354 355 return jingle; 356 } 357 358 public IQ sendTransportReplace(FullJid recipient, FullJid initiator, String sessionId, 359 JingleContent.Creator contentCreator, String contentName, 360 JingleContentTransport transport) 361 throws SmackException.NotConnectedException, InterruptedException, 362 XMPPException.XMPPErrorException, SmackException.NoResponseException { 363 Jingle jingle = createTransportReplace(recipient, initiator, sessionId, contentCreator, contentName, transport); 364 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 365 } 366 367 public Jingle createTransportAccept(FullJid recipient, FullJid initiator, String sessionId, 368 JingleContent.Creator contentCreator, String contentName, 369 JingleContentTransport transport) { 370 Jingle.Builder jb = Jingle.getBuilder(); 371 jb.setAction(JingleAction.transport_accept) 372 .setInitiator(initiator) 373 .setSessionId(sessionId); 374 375 JingleContent.Builder cb = JingleContent.getBuilder(); 376 cb.setCreator(contentCreator).setName(contentName).setTransport(transport); 377 378 Jingle jingle = jb.addJingleContent(cb.build()).build(); 379 jingle.setTo(recipient); 380 jingle.setFrom(connection.getUser()); 381 382 return jingle; 383 } 384 385 public IQ sendTransportAccept(FullJid recipient, FullJid initiator, String sessionId, 386 JingleContent.Creator contentCreator, String contentName, 387 JingleContentTransport transport) 388 throws SmackException.NotConnectedException, InterruptedException, 389 XMPPException.XMPPErrorException, SmackException.NoResponseException { 390 Jingle jingle = createTransportAccept(recipient, initiator, sessionId, contentCreator, contentName, transport); 391 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 392 } 393 394 public Jingle createTransportReject(FullJid recipient, FullJid initiator, String sessionId, 395 JingleContent.Creator contentCreator, String contentName, 396 JingleContentTransport transport) { 397 Jingle.Builder jb = Jingle.getBuilder(); 398 jb.setAction(JingleAction.transport_reject) 399 .setInitiator(initiator) 400 .setSessionId(sessionId); 401 402 JingleContent.Builder cb = JingleContent.getBuilder(); 403 cb.setCreator(contentCreator).setName(contentName).setTransport(transport); 404 405 Jingle jingle = jb.addJingleContent(cb.build()).build(); 406 jingle.setTo(recipient); 407 jingle.setFrom(connection.getUser()); 408 409 return jingle; 410 } 411 412 public IQ sendTransportReject(FullJid recipient, FullJid initiator, String sessionId, 413 JingleContent.Creator contentCreator, String contentName, 414 JingleContentTransport transport) 415 throws SmackException.NotConnectedException, InterruptedException, 416 XMPPException.XMPPErrorException, SmackException.NoResponseException { 417 Jingle jingle = createTransportReject(recipient, initiator, sessionId, contentCreator, contentName, transport); 418 return connection.createStanzaCollectorAndSend(jingle).nextResultOrThrow(); 419 } 420 421 /* 422 * #################################################################################################### 423 */ 424 425 public IQ createErrorUnknownSession(Jingle request) { 426 StanzaError.Builder error = StanzaError.getBuilder(); 427 error.setCondition(StanzaError.Condition.item_not_found) 428 .addExtension(JingleError.UNKNOWN_SESSION); 429 return IQ.createErrorResponse(request, error); 430 } 431 432 public void sendErrorUnknownSession(Jingle request) 433 throws SmackException.NotConnectedException, InterruptedException { 434 connection.sendStanza(createErrorUnknownSession(request)); 435 } 436 437 public IQ createErrorUnknownInitiator(Jingle request) { 438 return IQ.createErrorResponse(request, StanzaError.Condition.service_unavailable); 439 } 440 441 public void sendErrorUnknownInitiator(Jingle request) 442 throws SmackException.NotConnectedException, InterruptedException { 443 connection.sendStanza(createErrorUnknownInitiator(request)); 444 } 445 446 public IQ createErrorUnsupportedInfo(Jingle request) { 447 StanzaError.Builder error = StanzaError.getBuilder(); 448 error.setCondition(StanzaError.Condition.feature_not_implemented) 449 .addExtension(JingleError.UNSUPPORTED_INFO); 450 return IQ.createErrorResponse(request, error); 451 } 452 453 public void sendErrorUnsupportedInfo(Jingle request) 454 throws SmackException.NotConnectedException, InterruptedException { 455 connection.sendStanza(createErrorUnsupportedInfo(request)); 456 } 457 458 public IQ createErrorTieBreak(Jingle request) { 459 StanzaError.Builder error = StanzaError.getBuilder(); 460 error.setCondition(StanzaError.Condition.conflict) 461 .addExtension(JingleError.TIE_BREAK); 462 return IQ.createErrorResponse(request, error); 463 } 464 465 public void sendErrorTieBreak(Jingle request) 466 throws SmackException.NotConnectedException, InterruptedException { 467 connection.sendStanza(createErrorTieBreak(request)); 468 } 469 470 public IQ createErrorOutOfOrder(Jingle request) { 471 StanzaError.Builder error = StanzaError.getBuilder(); 472 error.setCondition(StanzaError.Condition.unexpected_request) 473 .addExtension(JingleError.OUT_OF_ORDER); 474 return IQ.createErrorResponse(request, error); 475 } 476 477 public void sendErrorOutOfOrder(Jingle request) 478 throws SmackException.NotConnectedException, InterruptedException { 479 connection.sendStanza(createErrorOutOfOrder(request)); 480 } 481 482 public IQ createErrorMalformedRequest(Jingle request) { 483 return IQ.createErrorResponse(request, StanzaError.Condition.bad_request); 484 } 485 486 public void sendErrorMalformedRequest(Jingle request) 487 throws SmackException.NotConnectedException, InterruptedException { 488 connection.sendStanza(createErrorMalformedRequest(request)); 489 } 490}