1363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/*
2363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Copyright (C) 2010 The Android Open Source Project
3363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
4363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License");
5363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * you may not use this file except in compliance with the License.
6363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * You may obtain a copy of the License at
7363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
8363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *      http://www.apache.org/licenses/LICENSE-2.0
9363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang *
10363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Unless required by applicable law or agreed to in writing, software
11363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS,
12363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * See the License for the specific language governing permissions and
14363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * limitations under the License.
15363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */
16363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
17363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpackage android.net.rtp;
18363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
19363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.InetAddress;
20363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.Inet4Address;
21363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.Inet6Address;
22363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.SocketException;
23363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
24363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/**
2532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * RtpStream represents the base class of streams which send and receive network
2632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * packets with media payloads over Real-time Transport Protocol (RTP).
2753aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh *
2853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * <p class="note">Using this class requires
2953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p>
30363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */
31363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class RtpStream {
3232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
3332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * This mode indicates that the stream sends and receives packets at the
3432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * same time. This is the initial mode for new streams.
3532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
36363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public static final int MODE_NORMAL = 0;
3732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
3932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * This mode indicates that the stream only sends packets.
4032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
41363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public static final int MODE_SEND_ONLY = 1;
4232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh
4332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh    /**
4432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * This mode indicates that the stream only receives packets.
4532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     */
46363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public static final int MODE_RECEIVE_ONLY = 2;
47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
4853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh    private static final int MODE_LAST = 2;
4953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh
50363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private final InetAddress mLocalAddress;
51363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private final int mLocalPort;
52363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
53363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private InetAddress mRemoteAddress;
54363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private int mRemotePort = -1;
55363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private int mMode = MODE_NORMAL;
56363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
57e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh    private int mSocket = -1;
58363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    static {
59363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        System.loadLibrary("rtp_jni");
60363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
61363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Creates a RtpStream on the given local address. Note that the local
64363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * port is assigned automatically to conform with RFC 3550.
65363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param address The network address of the local host to bind to.
67363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws SocketException if the address cannot be bound or a problem
68363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *     occurs during binding.
69363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
70363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    RtpStream(InetAddress address) throws SocketException {
71363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mLocalPort = create(address.getHostAddress());
72363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mLocalAddress = address;
73363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
74363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
75363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    private native int create(String address) throws SocketException;
76363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
77363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
78363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Returns the network address of the local host.
79363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
80363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public InetAddress getLocalAddress() {
81363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mLocalAddress;
82363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
83363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
84363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
85363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Returns the network port of the local host.
86363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
87363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public int getLocalPort() {
88363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mLocalPort;
89363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
90363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
91363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
92363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Returns the network address of the remote host or {@code null} if the
93363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * stream is not associated.
94363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
95363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public InetAddress getRemoteAddress() {
96363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mRemoteAddress;
97363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
98363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
99363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
100363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Returns the network port of the remote host or {@code -1} if the stream
101363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * is not associated.
102363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
103363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public int getRemotePort() {
104363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mRemotePort;
105363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
106363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
107363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
10832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Returns {@code true} if the stream is busy. In this case most of the
10932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * setter methods are disabled. This method is intended to be overridden
11032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * by subclasses.
111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
112363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public boolean isBusy() {
113363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return false;
114363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
115363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
116363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
11732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Returns the current mode.
118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
119363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public int getMode() {
120363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        return mMode;
121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
122363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
123363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Changes the current mode. It must be one of {@link #MODE_NORMAL},
125363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * {@link #MODE_SEND_ONLY}, and {@link #MODE_RECEIVE_ONLY}.
126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
127363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param mode The mode to change to.
128363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalArgumentException if the mode is invalid.
129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is busy.
130363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @see #isBusy()
131363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
132363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public void setMode(int mode) {
133363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (isBusy()) {
134363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalStateException("Busy");
135363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
13653aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh        if (mode < 0 || mode > MODE_LAST) {
137363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalArgumentException("Invalid mode");
138363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
139363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mMode = mode;
140363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
141363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
142363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
14332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * Associates with a remote host. This defines the destination of the
14432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh     * outgoing packets.
145363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
146363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param address The network address of the remote host.
147363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @param port The network port of the remote host.
148363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalArgumentException if the address is not supported or the
149363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *     port is invalid.
150363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is busy.
151363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @see #isBusy()
152363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
153363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public void associate(InetAddress address, int port) {
154363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (isBusy()) {
155363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalStateException("Busy");
156363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
157363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (!(address instanceof Inet4Address && mLocalAddress instanceof Inet4Address) &&
158363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang                !(address instanceof Inet6Address && mLocalAddress instanceof Inet6Address)) {
159363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalArgumentException("Unsupported address");
160363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
161363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        if (port < 0 || port > 65535) {
162363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang            throw new IllegalArgumentException("Invalid port");
163363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
164363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mRemoteAddress = address;
165363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        mRemotePort = port;
166363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
167363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
168e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh    int getSocket() {
169e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh        return mSocket;
170e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh    }
171363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
172363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    /**
173363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * Releases allocated resources. The stream becomes inoperable after calling
174363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * this method.
175363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     *
176363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @throws IllegalStateException if the stream is busy.
177363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     * @see #isBusy()
178363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang     */
179363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    public void release() {
180e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh        synchronized (this) {
181e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh            if (isBusy()) {
182e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh                throw new IllegalStateException("Busy");
183e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh            }
184e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh            close();
185363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        }
186363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
187363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
188e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh    private native void close();
189363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang
190363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    @Override
191363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    protected void finalize() throws Throwable {
192363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        close();
193363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang        super.finalize();
194363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang    }
195363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang}
196