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.jingle.provider;
018
019import org.jivesoftware.smack.packet.PacketExtension;
020import org.jivesoftware.smack.provider.PacketExtensionProvider;
021import org.jivesoftware.smackx.jingle.nat.ICECandidate;
022import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
023import org.jivesoftware.smackx.jingle.packet.JingleTransport;
024import org.jivesoftware.smackx.jingle.packet.JingleTransport.JingleTransportCandidate;
025import org.xmlpull.v1.XmlPullParser;
026
027/**
028 * Provider for a Jingle transport element
029 *
030 * @author Alvaro Saurin <alvaro.saurin@gmail.com>
031 */
032public abstract class JingleTransportProvider implements PacketExtensionProvider {
033
034    /**
035     * Creates a new provider. ProviderManager requires that every
036     * PacketExtensionProvider has a public, no-argument constructor
037     */
038    public JingleTransportProvider() {
039        super();
040    }
041
042    /**
043     * Obtain the corresponding TransportNegotiator instance.
044     *
045     * @return a new TransportNegotiator instance
046     */
047    protected JingleTransport getInstance() {
048        return new JingleTransport();
049    }
050
051    /**
052     * Parse a iq/jingle/transport element.
053     *
054     * @param parser the structure to parse
055     * @return a transport element.
056     * @throws Exception
057     */
058    public PacketExtension parseExtension(final XmlPullParser parser) throws Exception {
059        boolean done = false;
060        JingleTransport trans = getInstance();
061
062        while (!done) {
063            int eventType = parser.next();
064            String name = parser.getName();
065
066            if (eventType == XmlPullParser.START_TAG) {
067                if (name.equals(JingleTransportCandidate.NODENAME)) {
068                    JingleTransportCandidate jtc = parseCandidate(parser);
069                    if (jtc != null) trans.addCandidate(jtc);
070                }
071                else {
072                    throw new Exception("Unknown tag \"" + name + "\" in transport element.");
073                }
074            }
075            else if (eventType == XmlPullParser.END_TAG) {
076                if (name.equals(JingleTransport.NODENAME)) {
077                    done = true;
078                }
079            }
080        }
081
082        return trans;
083    }
084
085    protected abstract JingleTransportCandidate parseCandidate(final XmlPullParser parser)
086            throws Exception;
087
088    /**
089     * RTP-ICE profile
090     */
091    public static class Ice extends JingleTransportProvider {
092
093        /**
094         * Defauls constructor.
095         */
096        public Ice() {
097            super();
098        }
099
100        /**
101         * Obtain the corresponding TransportNegotiator.Ice instance.
102         *
103         * @return a new TransportNegotiator.Ice instance
104         */
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         * @throws Exception
115         */
116        protected JingleTransportCandidate parseCandidate(XmlPullParser parser) throws Exception {
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                try {
137                    mt.setGeneration(Integer.parseInt(generation));
138                }
139                catch (Exception e) {
140                }
141            }
142
143            if (ip != null) {
144                mt.setIp(ip);
145            }
146            else {
147                return null;
148            }
149
150            if (name != null) {
151                mt.setName(name);
152            }
153
154            if (network != null) {
155                try {
156                    mt.setNetwork(Integer.parseInt(network));
157                }
158                catch (Exception e) {
159                }
160            }
161
162            if (username != null) {
163                mt.setUsername(username);
164            }
165
166            if (password != null) {
167                mt.setPassword(password);
168            }
169
170            if (port != null) {
171                try {
172                    mt.setPort(Integer.parseInt(port));
173                }
174                catch (Exception e) {
175                }
176            }
177
178            if (preference != null) {
179                try {
180                    mt.setPreference(Integer.parseInt(preference));
181                }
182                catch (Exception e) {
183                }
184            }
185
186            if (proto != null) {
187                mt.setProto(new TransportCandidate.Protocol(proto));
188            }
189
190            if (type != null) {
191                mt.setType(ICECandidate.Type.valueOf(type));
192            }
193
194            return new JingleTransport.Ice.Candidate(mt);
195        }
196    }
197
198    /**
199     * Raw UDP profile
200     */
201    public static class RawUdp extends JingleTransportProvider {
202
203        /**
204         * Defauls constructor.
205         */
206        public RawUdp() {
207            super();
208        }
209
210        /**
211         * Obtain the corresponding TransportNegotiator.RawUdp instance.
212         *
213         * @return a new TransportNegotiator.RawUdp instance
214         */
215        protected JingleTransport getInstance() {
216            return new JingleTransport.RawUdp();
217        }
218
219        /**
220         * Parse a iq/jingle/transport/candidate element.
221         *
222         * @param parser the structure to parse
223         * @return a candidate element
224         * @throws Exception
225         */
226        protected JingleTransportCandidate parseCandidate(XmlPullParser parser) throws Exception {
227            TransportCandidate.Fixed mt = new TransportCandidate.Fixed();
228
229            String generation = parser.getAttributeValue("", "generation");
230            String ip = parser.getAttributeValue("", "ip");
231            String name = parser.getAttributeValue("", "name");
232            String port = parser.getAttributeValue("", "port");
233
234            //LOGGER.debug();
235
236            if (generation != null) {
237                try {
238                    mt.setGeneration(Integer.parseInt(generation));
239                }
240                catch (Exception e) {
241                }
242            }
243
244            if (ip != null) {
245                mt.setIp(ip);
246            }
247
248            if (name != null) {
249                mt.setName(name);
250            }
251
252            if (port != null) {
253                try {
254                    mt.setPort(Integer.parseInt(port));
255                }
256                catch (Exception e) {
257                }
258            }
259            return new JingleTransport.RawUdp.Candidate(mt);
260        }
261    }
262}