use of org.jivesoftware.smackx.jingleold.packet.Jingle in project Smack by igniterealtime.
the class TransportNegotiator method delayedCheckBestCandidate.
/**
* Launch a thread that checks, after some time, if any of the candidates
* offered by the other endpoint is usable. The thread does not check the
* candidates: it just checks if we have got a valid one and sends an Accept
* in that case.
*/
private void delayedCheckBestCandidate(final JingleSession js, final Jingle jin) {
//
if (resultThread == null && !getRemoteCandidates().isEmpty()) {
resultThread = new Thread(new Runnable() {
@Override
public void run() {
// Sleep for some time, waiting for the candidates checks
int totalTime = (CANDIDATES_ACCEPT_PERIOD + TransportResolver.CHECK_TIMEOUT);
int tries = (int) Math.ceil(totalTime / 1000);
for (int i = 0; i < tries - 1; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "exception", e);
}
// Once we are in pending state, look for any valid remote
// candidate, and send an "accept" if we have one...
TransportCandidate bestRemote = getBestRemoteCandidate();
if ((bestRemote != null) && ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
// Accepting the remote candidate
if (!acceptedRemoteCandidates.contains(bestRemote)) {
Jingle jout = new Jingle(JingleActionEnum.CONTENT_ACCEPT);
JingleContent content = parentNegotiator.getJingleContent();
content.addJingleTransport(getJingleTransport(bestRemote));
jout.addContent(content);
// Send the packet
try {
js.sendFormattedJingle(jin, jout);
} catch (InterruptedException | NotConnectedException e) {
throw new IllegalStateException(e);
}
acceptedRemoteCandidates.add(bestRemote);
}
if ((isEstablished()) && (getNegotiatorState() == JingleNegotiatorState.PENDING)) {
setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
try {
triggerTransportEstablished(getAcceptedLocalCandidate(), bestRemote);
} catch (InterruptedException | NotConnectedException e) {
throw new IllegalStateException(e);
}
break;
}
}
}
// Once we are in pending state, look for any valid remote
// candidate, and send an "accept" if we have one...
TransportCandidate bestRemote = getBestRemoteCandidate();
if (bestRemote == null) {
boolean foundRemoteRelay = false;
for (TransportCandidate candidate : remoteCandidates) {
if (candidate instanceof ICECandidate) {
ICECandidate iceCandidate = (ICECandidate) candidate;
if (iceCandidate.getType().equals(Type.relay)) {
//TODO Check if the relay is reacheable
addValidRemoteCandidate(iceCandidate);
foundRemoteRelay = true;
}
}
}
// We should accept the Public One if we received it, otherwise, accepts any.
if (!foundRemoteRelay) {
boolean foundLocalRelay = false;
for (TransportCandidate candidate : offeredCandidates) {
if (candidate instanceof ICECandidate) {
ICECandidate iceCandidate = (ICECandidate) candidate;
if (iceCandidate.getType().equals(Type.relay)) {
foundLocalRelay = true;
}
}
}
if (foundLocalRelay) {
boolean foundRemotePublic = false;
for (TransportCandidate candidate : remoteCandidates) {
if (candidate instanceof ICECandidate) {
ICECandidate iceCandidate = (ICECandidate) candidate;
if (iceCandidate.getType().equals(ICECandidate.Type.srflx)) {
addValidRemoteCandidate(iceCandidate);
foundRemotePublic = true;
}
}
}
if (!foundRemotePublic) {
for (TransportCandidate candidate : remoteCandidates) {
if (candidate instanceof ICECandidate) {
ICECandidate iceCandidate = (ICECandidate) candidate;
addValidRemoteCandidate(iceCandidate);
}
}
}
}
}
}
for (int i = 0; i < 6; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "exception", e);
}
bestRemote = getBestRemoteCandidate();
//State state = getState();
if ((bestRemote != null) && ((getNegotiatorState() == JingleNegotiatorState.PENDING))) {
if (!acceptedRemoteCandidates.contains(bestRemote)) {
Jingle jout = new Jingle(JingleActionEnum.CONTENT_ACCEPT);
JingleContent content = parentNegotiator.getJingleContent();
content.addJingleTransport(getJingleTransport(bestRemote));
jout.addContent(content);
// Send the packet
try {
js.sendFormattedJingle(jin, jout);
} catch (InterruptedException | NotConnectedException e) {
throw new IllegalStateException(e);
}
acceptedRemoteCandidates.add(bestRemote);
}
if (isEstablished()) {
setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
break;
}
}
}
if (getNegotiatorState() != JingleNegotiatorState.SUCCEEDED) {
try {
session.terminate("Unable to negotiate session. This may be caused by firewall configuration problems.");
} catch (Exception e) {
LOGGER.log(Level.WARNING, "exception", e);
}
}
}
}, "Waiting for all the transport candidates checks...");
resultThread.setName("Transport Resolver Result");
resultThread.start();
}
}
use of org.jivesoftware.smackx.jingleold.packet.Jingle in project Smack by igniterealtime.
the class TransportNegotiator method dispatchIncomingPacket.
/**
* Dispatch an incoming packet. The method is responsible for recognizing
* the stanza(/packet) type and, depending on the current state, deliverying the
* stanza(/packet) to the right event handler and wait for a response.
*
* @param iq the stanza(/packet) received
* @return the new Jingle stanza(/packet) to send.
* @throws XMPPException
* @throws SmackException
* @throws InterruptedException
*/
@Override
public final List<IQ> dispatchIncomingPacket(IQ iq, String id) throws XMPPException, SmackException, InterruptedException {
List<IQ> responses = new ArrayList<IQ>();
IQ response = null;
if (iq != null) {
if (iq.getType().equals(IQ.Type.error)) {
// Process errors
setNegotiatorState(JingleNegotiatorState.FAILED);
triggerTransportClosed(null);
// This next line seems wrong, and may subvert the normal closing process.
throw new JingleException(iq.getError().getDescriptiveText());
} else if (iq.getType().equals(IQ.Type.result)) {
// Process ACKs
if (isExpectedId(iq.getStanzaId())) {
response = receiveResult(iq);
removeExpectedId(iq.getStanzaId());
}
} else if (iq instanceof Jingle) {
// Get the action from the Jingle packet
Jingle jingle = (Jingle) iq;
JingleActionEnum action = jingle.getAction();
switch(action) {
case CONTENT_ACCEPT:
response = receiveContentAcceptAction(jingle);
break;
case CONTENT_MODIFY:
break;
case CONTENT_REMOVE:
break;
case SESSION_INFO:
break;
case SESSION_INITIATE:
response = receiveSessionInitiateAction(jingle);
break;
case SESSION_ACCEPT:
response = receiveSessionAcceptAction(jingle);
break;
case TRANSPORT_INFO:
response = receiveTransportInfoAction(jingle);
break;
default:
break;
}
}
}
if (response != null) {
addExpectedId(response.getStanzaId());
responses.add(response);
}
return responses;
}
use of org.jivesoftware.smackx.jingleold.packet.Jingle in project Smack by igniterealtime.
the class JingleManager method initJingleSessionRequestListeners.
/**
* Register the listenerJingles, waiting for a Jingle stanza(/packet) that tries to
* establish a new session.
*/
private void initJingleSessionRequestListeners() {
StanzaFilter initRequestFilter = new StanzaFilter() {
// Return true if we accept this packet
@Override
public boolean accept(Stanza pin) {
if (pin instanceof IQ) {
IQ iq = (IQ) pin;
if (iq.getType().equals(IQ.Type.set)) {
if (iq instanceof Jingle) {
Jingle jin = (Jingle) pin;
if (jin.getAction().equals(JingleActionEnum.SESSION_INITIATE)) {
return true;
}
}
}
}
return false;
}
};
jingleSessionRequestListeners = new ArrayList<JingleSessionRequestListener>();
// Start a packet listener for session initiation requests
connection.addAsyncStanzaListener(new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
triggerSessionRequested((Jingle) packet);
}
}, initRequestFilter);
}
use of org.jivesoftware.smackx.jingleold.packet.Jingle in project Smack by igniterealtime.
the class JingleSession method dispatchIncomingPacket.
/**
* Dispatch an incoming packet. The method is responsible for recognizing
* the stanza(/packet) type and, depending on the current state, delivering the
* stanza(/packet) to the right event handler and wait for a response.
*
* @param iq
* the stanza(/packet) received
* @return the new Jingle stanza(/packet) to send.
* @throws XMPPException
* @throws SmackException
* @throws InterruptedException
*/
@Override
public List<IQ> dispatchIncomingPacket(IQ iq, String id) throws XMPPException, SmackException, InterruptedException {
List<IQ> responses = new ArrayList<IQ>();
IQ response = null;
if (iq != null) {
if (iq.getType().equals(IQ.Type.error)) {
// Process errors
// TODO getState().eventError(iq);
} else if (iq.getType().equals(IQ.Type.result)) {
// Process ACKs
if (isExpectedId(iq.getStanzaId())) {
// Kick off some negotiators.
if (iq.getStanzaId().equals(sessionInitPacketID)) {
startNegotiators();
}
removeExpectedId(iq.getStanzaId());
}
} else if (iq instanceof Jingle) {
// It is not an error: it is a Jingle packet...
Jingle jin = (Jingle) iq;
JingleActionEnum action = jin.getAction();
// Depending on the state we're in we'll get different processing actions.
// (See Design Patterns AKA GoF State behavioral pattern.)
response = getSessionState().processJingle(this, jin, action);
}
}
if (response != null) {
// Save the packet id, for recognizing ACKs...
addExpectedId(response.getStanzaId());
responses.add(response);
}
return responses;
}
use of org.jivesoftware.smackx.jingleold.packet.Jingle in project Smack by igniterealtime.
the class JingleProvider method parse.
/**
* Parse a iq/jingle element.
* @throws Exception
*/
@Override
public Jingle parse(XmlPullParser parser, int intialDepth) throws Exception {
Jingle jingle = new Jingle();
String sid = "";
JingleActionEnum action;
Jid initiator = null;
Jid responder = null;
boolean done = false;
JingleContent currentContent = null;
// Sub-elements providers
JingleContentProvider jcp = new JingleContentProvider();
JingleDescriptionProvider jdpAudio = new JingleDescriptionProvider.Audio();
JingleTransportProvider jtpRawUdp = new JingleTransportProvider.RawUdp();
JingleTransportProvider jtpIce = new JingleTransportProvider.Ice();
ExtensionElementProvider<?> jmipAudio = new JingleContentInfoProvider.Audio();
int eventType;
String elementName;
String namespace;
// Get some attributes for the <jingle> element
sid = parser.getAttributeValue("", "sid");
action = JingleActionEnum.getAction(parser.getAttributeValue("", "action"));
initiator = ParserUtils.getJidAttribute(parser, "initiator");
responder = ParserUtils.getJidAttribute(parser, "responder");
jingle.setSid(sid);
jingle.setAction(action);
jingle.setInitiator(initiator);
jingle.setResponder(responder);
// Start processing sub-elements
while (!done) {
eventType = parser.next();
elementName = parser.getName();
namespace = parser.getNamespace();
if (eventType == XmlPullParser.START_TAG) {
if (elementName.equals(JingleContent.NODENAME)) {
// Add a new <content> element to the jingle
currentContent = jcp.parse(parser);
jingle.addContent(currentContent);
} else if (elementName.equals(JingleDescription.NODENAME) && namespace.equals(JingleDescription.Audio.NAMESPACE)) {
// Set the <description> element of the <content>
currentContent.setDescription(jdpAudio.parse(parser));
} else if (elementName.equals(JingleTransport.NODENAME)) {
// Parse the possible transport namespaces
if (namespace.equals(JingleTransport.RawUdp.NAMESPACE)) {
currentContent.addJingleTransport(jtpRawUdp.parse(parser));
} else if (namespace.equals(JingleTransport.Ice.NAMESPACE)) {
currentContent.addJingleTransport(jtpIce.parse(parser));
} else {
throw new SmackException("Unknown transport namespace \"" + namespace + "\" in Jingle packet.");
}
} else if (namespace.equals(JingleContentInfo.Audio.NAMESPACE)) {
jingle.setContentInfo((JingleContentInfo) jmipAudio.parse(parser));
} else {
throw new SmackException("Unknown combination of namespace \"" + namespace + "\" and element name \"" + elementName + "\" in Jingle packet.");
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(Jingle.getElementName())) {
done = true;
}
}
}
return jingle;
}
Aggregations