198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/*
298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Copyright (C) 2010 The Android Open Source Project
398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *
498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License");
598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * you may not use this file except in compliance with the License.
698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * You may obtain a copy of the License at
798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *
898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      http://www.apache.org/licenses/LICENSE-2.0
998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *
1098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Unless required by applicable law or agreed to in writing, software
1198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS,
1298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * See the License for the specific language governing permissions and
1498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * limitations under the License.
1598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */
1698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
1798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpackage android.net.rtp;
1898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
1998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.InetAddress;
2098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.Inet4Address;
2198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.Inet6Address;
2298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.SocketException;
2398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
2498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/**
257f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * RtpStream represents the base class of streams which send and receive network
267f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * packets with media payloads over Real-time Transport Protocol (RTP).
27a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh *
28a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * <p class="note">Using this class requires
29a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p>
3098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */
3198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class RtpStream {
327f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh    /**
337f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * This mode indicates that the stream sends and receives packets at the
347f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * same time. This is the initial mode for new streams.
357f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     */
3698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final int MODE_NORMAL = 0;
377f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh
387f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh    /**
397f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * This mode indicates that the stream only sends packets.
407f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     */
4198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final int MODE_SEND_ONLY = 1;
427f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh
437f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh    /**
447f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * This mode indicates that the stream only receives packets.
457f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     */
4698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final int MODE_RECEIVE_ONLY = 2;
4798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
48a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh    private static final int MODE_LAST = 2;
49a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh
5098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private final InetAddress mLocalAddress;
5198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private final int mLocalPort;
5298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
5398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private InetAddress mRemoteAddress;
5498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private int mRemotePort = -1;
5598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private int mMode = MODE_NORMAL;
5698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
572bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh    private int mSocket = -1;
5898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    static {
5998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        System.loadLibrary("rtp_jni");
6098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
6198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
6298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
6398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a RtpStream on the given local address. Note that the local
6498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * port is assigned automatically to conform with RFC 3550.
6598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
6698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param address The network address of the local host to bind to.
6798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SocketException if the address cannot be bound or a problem
6898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *     occurs during binding.
6998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
7098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    RtpStream(InetAddress address) throws SocketException {
7198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mLocalPort = create(address.getHostAddress());
7298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mLocalAddress = address;
7398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
7498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
7598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private native int create(String address) throws SocketException;
7698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
7798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
7898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Returns the network address of the local host.
7998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
8098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public InetAddress getLocalAddress() {
8198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return mLocalAddress;
8298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
8398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
8498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
8598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Returns the network port of the local host.
8698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
8798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public int getLocalPort() {
8898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return mLocalPort;
8998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
9098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
9198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
9298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Returns the network address of the remote host or {@code null} if the
9398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * stream is not associated.
9498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
9598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public InetAddress getRemoteAddress() {
9698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return mRemoteAddress;
9798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
9898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
9998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
10098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Returns the network port of the remote host or {@code -1} if the stream
10198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * is not associated.
10298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
10398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public int getRemotePort() {
10498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return mRemotePort;
10598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
10698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
10798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
1087f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * Returns {@code true} if the stream is busy. In this case most of the
1097f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * setter methods are disabled. This method is intended to be overridden
1107f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * by subclasses.
11198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
11298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public boolean isBusy() {
11398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return false;
11498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
11598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
11698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
1177f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * Returns the current mode.
11898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
11998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public int getMode() {
12098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return mMode;
12198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
12298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
12398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
12498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Changes the current mode. It must be one of {@link #MODE_NORMAL},
12598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link #MODE_SEND_ONLY}, and {@link #MODE_RECEIVE_ONLY}.
12698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
12798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param mode The mode to change to.
12898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws IllegalArgumentException if the mode is invalid.
12998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws IllegalStateException if the stream is busy.
13098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @see #isBusy()
13198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
13298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void setMode(int mode) {
13398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (isBusy()) {
13498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new IllegalStateException("Busy");
13598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
136a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh        if (mode < 0 || mode > MODE_LAST) {
13798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new IllegalArgumentException("Invalid mode");
13898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
13998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mMode = mode;
14098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
14198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
14298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
1437f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * Associates with a remote host. This defines the destination of the
1447f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh     * outgoing packets.
14598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
14698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param address The network address of the remote host.
14798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param port The network port of the remote host.
14898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws IllegalArgumentException if the address is not supported or the
14998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *     port is invalid.
15098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws IllegalStateException if the stream is busy.
15198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @see #isBusy()
15298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
15398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void associate(InetAddress address, int port) {
15498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (isBusy()) {
15598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new IllegalStateException("Busy");
15698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
15798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (!(address instanceof Inet4Address && mLocalAddress instanceof Inet4Address) &&
15898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                !(address instanceof Inet6Address && mLocalAddress instanceof Inet6Address)) {
15998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new IllegalArgumentException("Unsupported address");
16098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
16198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (port < 0 || port > 65535) {
16298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new IllegalArgumentException("Invalid port");
16398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
16498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mRemoteAddress = address;
16598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mRemotePort = port;
16698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
16798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
1682bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh    int getSocket() {
1692bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh        return mSocket;
1702bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh    }
17198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
17298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
17398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Releases allocated resources. The stream becomes inoperable after calling
17498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * this method.
17598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
17698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws IllegalStateException if the stream is busy.
17798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @see #isBusy()
17898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
17998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void release() {
1802bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh        synchronized (this) {
1812bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh            if (isBusy()) {
1822bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh                throw new IllegalStateException("Busy");
1832bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh            }
1842bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh            close();
18598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
18698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
18798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
1882bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh    private native void close();
18998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
19098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    @Override
19198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    protected void finalize() throws Throwable {
19298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        close();
19398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        super.finalize();
19498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
19598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang}
196