001/*
002 *
003 * Copyright 2003-2005 Jive Software.
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.jingleold.provider;
018
019import java.io.IOException;
020
021import org.jivesoftware.smack.packet.XmlEnvironment;
022import org.jivesoftware.smack.provider.ExtensionElementProvider;
023import org.jivesoftware.smack.xml.XmlPullParser;
024import org.jivesoftware.smack.xml.XmlPullParserException;
025
026import org.jivesoftware.smackx.jingleold.nat.ICECandidate;
027import org.jivesoftware.smackx.jingleold.nat.TransportCandidate;
028import org.jivesoftware.smackx.jingleold.packet.JingleTransport;
029import org.jivesoftware.smackx.jingleold.packet.JingleTransport.JingleTransportCandidate;
030
031import org.jxmpp.JxmppContext;
032
033/**
034 * Provider for a Jingle transport element.
035 *
036 * @author Alvaro Saurin
037 */
038public abstract class JingleTransportProvider extends ExtensionElementProvider<JingleTransport> {
039
040    /**
041     * Obtain the corresponding TransportNegotiator instance.
042     *
043     * @return a new TransportNegotiator instance
044     */
045    protected JingleTransport getInstance() {
046        return new JingleTransport();
047    }
048
049    /**
050     * Parse a iq/jingle/transport element.
051     *
052     * @param parser the structure to parse
053     * @return a transport element.
054     * @throws IOException if an I/O error occurred.
055     * @throws XmlPullParserException if an error in the XML parser occurred.
056     */
057    @Override
058    public JingleTransport parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException  {
059        JingleTransport trans = getInstance();
060
061        outerloop: while (true) {
062            XmlPullParser.Event eventType = parser.next();
063
064            if (eventType == XmlPullParser.Event.START_ELEMENT) {
065                String name = parser.getName();
066                if (name.equals(JingleTransportCandidate.NODENAME)) {
067                    JingleTransportCandidate jtc = parseCandidate(parser);
068                    if (jtc != null) trans.addCandidate(jtc);
069                }
070                else {
071                    // TODO: Should be SmackParseException.
072                    throw new IOException("Unknown tag \"" + name + "\" in transport element.");
073                }
074            }
075            else if (eventType == XmlPullParser.Event.END_ELEMENT) {
076                if (parser.getDepth() == initialDepth) {
077                    break outerloop;
078                }
079            }
080        }
081
082        return trans;
083    }
084
085    protected abstract JingleTransportCandidate parseCandidate(XmlPullParser parser);
086
087    /**
088     * RTP-ICE profile.
089     */
090    public static class Ice extends JingleTransportProvider {
091
092        /**
093         * Default constructor.
094         */
095        public Ice() {
096            super();
097        }
098
099        /**
100         * Obtain the corresponding TransportNegotiator.Ice instance.
101         *
102         * @return a new TransportNegotiator.Ice instance
103         */
104        @Override
105        protected JingleTransport getInstance() {
106            return new JingleTransport.Ice();
107        }
108
109        /**
110         * Parse a iq/jingle/transport/candidate element.
111         *
112         * @param parser the structure to parse
113         * @return a candidate element
114         */
115        @Override
116        protected JingleTransportCandidate parseCandidate(XmlPullParser parser) {
117            ICECandidate mt = new ICECandidate();
118
119            String channel = parser.getAttributeValue("", "channel");
120            String generation = parser.getAttributeValue("", "generation");
121            String ip = parser.getAttributeValue("", "ip");
122            String name = parser.getAttributeValue("", "name");
123            String network = parser.getAttributeValue("", "network");
124            String username = parser.getAttributeValue("", "username");
125            String password = parser.getAttributeValue("", "password");
126            String port = parser.getAttributeValue("", "port");
127            String preference = parser.getAttributeValue("", "preference");
128            String proto = parser.getAttributeValue("", "proto");
129            String type = parser.getAttributeValue("", "type");
130
131            if (channel != null) {
132                mt.setChannel(new TransportCandidate.Channel(channel));
133            }
134
135            if (generation != null) {
136                mt.setGeneration(Integer.parseInt(generation));
137            }
138
139            if (ip != null) {
140                mt.setIp(ip);
141            }
142            else {
143                return null;
144            }
145
146            if (name != null) {
147                mt.setName(name);
148            }
149
150            if (network != null) {
151                mt.setNetwork(Integer.parseInt(network));
152            }
153
154            if (username != null) {
155                mt.setUsername(username);
156            }
157
158            if (password != null) {
159                mt.setPassword(password);
160            }
161
162            if (port != null) {
163                mt.setPort(Integer.parseInt(port));
164            }
165
166            if (preference != null) {
167                mt.setPreference(Integer.parseInt(preference));
168            }
169
170            if (proto != null) {
171                mt.setProto(new TransportCandidate.Protocol(proto));
172            }
173
174            if (type != null) {
175                mt.setType(ICECandidate.Type.valueOf(type));
176            }
177
178            return new JingleTransport.Ice.Candidate(mt);
179        }
180    }
181
182    /**
183     * Raw UDP profile.
184     */
185    public static class RawUdp extends JingleTransportProvider {
186
187        /**
188         * Default constructor.
189         */
190        public RawUdp() {
191            super();
192        }
193
194        /**
195         * Obtain the corresponding TransportNegotiator.RawUdp instance.
196         *
197         * @return a new TransportNegotiator.RawUdp instance
198         */
199        @Override
200        protected JingleTransport getInstance() {
201            return new JingleTransport.RawUdp();
202        }
203
204        /**
205         * Parse a iq/jingle/transport/candidate element.
206         *
207         * @param parser the structure to parse
208         * @return a candidate element
209         */
210        @Override
211        protected JingleTransportCandidate parseCandidate(XmlPullParser parser) {
212            TransportCandidate.Fixed mt = new TransportCandidate.Fixed();
213
214            String generation = parser.getAttributeValue("", "generation");
215            String ip = parser.getAttributeValue("", "ip");
216            String name = parser.getAttributeValue("", "name");
217            String port = parser.getAttributeValue("", "port");
218
219            // LOGGER.debug();
220
221            if (generation != null) {
222                mt.setGeneration(Integer.parseInt(generation));
223            }
224
225            if (ip != null) {
226                mt.setIp(ip);
227            }
228
229            if (name != null) {
230                mt.setName(name);
231            }
232
233            if (port != null) {
234                mt.setPort(Integer.parseInt(port));
235            }
236            return new JingleTransport.RawUdp.Candidate(mt);
237        }
238    }
239}