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.transports.jingle_s5b.provider;
018
019import static org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.Mode.tcp;
020import static org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.Mode.udp;
021import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_CID;
022import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_HOST;
023import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_JID;
024import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_PORT;
025import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_PRIORITY;
026import static org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate.ATTR_TYPE;
027
028import java.io.IOException;
029
030import org.jivesoftware.smack.packet.XmlEnvironment;
031import org.jivesoftware.smack.util.ParserUtils;
032import org.jivesoftware.smack.xml.XmlPullParser;
033import org.jivesoftware.smack.xml.XmlPullParserException;
034
035import org.jivesoftware.smackx.jingle.element.JingleContentTransportCandidate;
036import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider;
037import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransport;
038import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportCandidate;
039import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportInfo;
040import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportInfo.JingleS5BCandidateTransportInfo;
041
042/**
043 * Provider for JingleSocks5BytestreamTransport elements.
044 */
045public class JingleS5BTransportProvider extends JingleContentTransportProvider<JingleS5BTransport> {
046
047    @Override
048    public JingleS5BTransport parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException {
049        JingleS5BTransport.Builder builder = JingleS5BTransport.getBuilder();
050
051        String streamId = parser.getAttributeValue(null, JingleS5BTransport.ATTR_SID);
052        builder.setStreamId(streamId);
053
054        String dstAddr = parser.getAttributeValue(null, JingleS5BTransport.ATTR_DSTADDR);
055        builder.setDestinationAddress(dstAddr);
056
057        String mode = parser.getAttributeValue(null, JingleS5BTransport.ATTR_MODE);
058        if (mode != null) {
059            builder.setMode(mode.equals(udp.toString()) ? udp : tcp);
060        }
061
062        JingleS5BTransportCandidate.Builder cb;
063        outerloop: while (true) {
064            XmlPullParser.TagEvent tag = parser.nextTag();
065            switch (tag) {
066                case START_ELEMENT: {
067                    String name = parser.getName();
068                    switch (name) {
069
070                        case JingleContentTransportCandidate.ELEMENT:
071                            cb = JingleS5BTransportCandidate.getBuilder();
072                            cb.setCandidateId(parser.getAttributeValue(null, ATTR_CID));
073                            cb.setHost(ParserUtils.getInternetAddressIngoringZoneIdAttribute(parser, ATTR_HOST));
074                            cb.setJid(parser.getAttributeValue(null, ATTR_JID));
075                            cb.setPriority(Integer.parseInt(parser.getAttributeValue(null, ATTR_PRIORITY)));
076
077                            String portString = parser.getAttributeValue(null, ATTR_PORT);
078                            if (portString != null) {
079                                cb.setPort(Integer.parseInt(portString));
080                            }
081
082                            String typeString = parser.getAttributeValue(null, ATTR_TYPE);
083                            if (typeString != null) {
084                                cb.setType(JingleS5BTransportCandidate.Type.fromString(typeString));
085                            }
086                            builder.addTransportCandidate(cb.build());
087                            break;
088
089                        case JingleS5BTransportInfo.CandidateActivated.ELEMENT:
090                            builder.setTransportInfo(new JingleS5BTransportInfo.CandidateActivated(
091                                    parser.getAttributeValue(null,
092                                            JingleS5BCandidateTransportInfo.ATTR_CID)));
093                            break;
094
095                        case JingleS5BTransportInfo.CandidateUsed.ELEMENT:
096                            builder.setTransportInfo(new JingleS5BTransportInfo.CandidateUsed(
097                                    parser.getAttributeValue(null,
098                                            JingleS5BCandidateTransportInfo.ATTR_CID)));
099                            break;
100
101                        case JingleS5BTransportInfo.CandidateError.ELEMENT:
102                            builder.setTransportInfo(JingleS5BTransportInfo.CandidateError.INSTANCE);
103                            break;
104
105                        case JingleS5BTransportInfo.ProxyError.ELEMENT:
106                            builder.setTransportInfo(JingleS5BTransportInfo.ProxyError.INSTANCE);
107                            break;
108                    }
109                }
110                break;
111
112                case END_ELEMENT: {
113                    if (parser.getDepth() == initialDepth) {
114                            break outerloop;
115                    }
116                }
117                    break;
118            }
119        }
120        return builder.build();
121    }
122}