/luni/src/main/java/java/net/PlainDatagramSocketImpl.java
Java | 240 lines | 171 code | 32 blank | 37 comment | 10 complexity | 4e0b127a3f2c2e565edfde8d964e91ab MD5 | raw file
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package java.net;
- import dalvik.system.CloseGuard;
- import java.io.FileDescriptor;
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocketImpl;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import java.net.NetworkInterface;
- import java.net.SocketAddress;
- import java.net.SocketException;
- import java.net.UnknownHostException;
- import libcore.io.ErrnoException;
- import libcore.io.IoBridge;
- import libcore.io.Libcore;
- import libcore.io.StructGroupReq;
- import libcore.util.EmptyArray;
- import static libcore.io.OsConstants.*;
- /**
- * @hide used in java.nio.
- */
- public class PlainDatagramSocketImpl extends DatagramSocketImpl {
- private volatile boolean isNativeConnected;
- private final CloseGuard guard = CloseGuard.get();
- /**
- * used to keep address to which the socket was connected to at the native
- * level
- */
- private InetAddress connectedAddress;
- private int connectedPort = -1;
- public PlainDatagramSocketImpl(FileDescriptor fd, int localPort) {
- this.fd = fd;
- this.localPort = localPort;
- if (fd.valid()) {
- guard.open("close");
- }
- }
- public PlainDatagramSocketImpl() {
- fd = new FileDescriptor();
- }
- @Override public void bind(int port, InetAddress address) throws SocketException {
- IoBridge.bind(fd, address, port);
- if (port != 0) {
- localPort = port;
- } else {
- localPort = IoBridge.getSocketLocalPort(fd);
- }
- try {
- setOption(SocketOptions.SO_BROADCAST, Boolean.TRUE);
- } catch (IOException ignored) {
- }
- }
- @Override
- public synchronized void close() {
- guard.close();
- try {
- IoBridge.closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
- @Override
- public void create() throws SocketException {
- this.fd = IoBridge.socket(false);
- }
- @Override protected void finalize() throws Throwable {
- try {
- if (guard != null) {
- guard.warnIfOpen();
- }
- close();
- } finally {
- super.finalize();
- }
- }
- @Override public Object getOption(int option) throws SocketException {
- return IoBridge.getSocketOption(fd, option);
- }
- @Override
- public int getTimeToLive() throws IOException {
- return (Integer) getOption(IoBridge.JAVA_IP_MULTICAST_TTL);
- }
- @Override
- public byte getTTL() throws IOException {
- return (byte) getTimeToLive();
- }
- private static StructGroupReq makeGroupReq(InetAddress gr_group, NetworkInterface networkInterface) {
- int gr_interface = (networkInterface != null) ? networkInterface.getIndex() : 0;
- return new StructGroupReq(gr_interface, gr_group);
- }
- @Override
- public void join(InetAddress addr) throws IOException {
- setOption(IoBridge.JAVA_MCAST_JOIN_GROUP, makeGroupReq(addr, null));
- }
- @Override
- public void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
- if (addr instanceof InetSocketAddress) {
- InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
- setOption(IoBridge.JAVA_MCAST_JOIN_GROUP, makeGroupReq(groupAddr, netInterface));
- }
- }
- @Override
- public void leave(InetAddress addr) throws IOException {
- setOption(IoBridge.JAVA_MCAST_LEAVE_GROUP, makeGroupReq(addr, null));
- }
- @Override
- public void leaveGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
- if (addr instanceof InetSocketAddress) {
- InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
- setOption(IoBridge.JAVA_MCAST_LEAVE_GROUP, makeGroupReq(groupAddr, netInterface));
- }
- }
- @Override
- protected int peek(InetAddress sender) throws IOException {
- // We don't actually want the data: we just want the DatagramPacket's filled-in address.
- DatagramPacket packet = new DatagramPacket(EmptyArray.BYTE, 0);
- int result = peekData(packet);
- // Note: evil side-effect on InetAddress! This method should have returned InetSocketAddress!
- sender.ipaddress = packet.getAddress().getAddress();
- return result;
- }
- private void doRecv(DatagramPacket pack, int flags) throws IOException {
- IoBridge.recvfrom(false, fd, pack.getData(), pack.getOffset(), pack.getLength(), flags, pack, isNativeConnected);
- if (isNativeConnected) {
- updatePacketRecvAddress(pack);
- }
- }
- @Override
- public void receive(DatagramPacket pack) throws IOException {
- doRecv(pack, 0);
- }
- @Override
- public int peekData(DatagramPacket pack) throws IOException {
- doRecv(pack, MSG_PEEK);
- return pack.getPort();
- }
- @Override
- public void send(DatagramPacket packet) throws IOException {
- int port = isNativeConnected ? 0 : packet.getPort();
- InetAddress address = isNativeConnected ? null : packet.getAddress();
- IoBridge.sendto(fd, packet.getData(), packet.getOffset(), packet.getLength(), 0, address, port);
- }
- public void setOption(int option, Object value) throws SocketException {
- IoBridge.setSocketOption(fd, option, value);
- }
- @Override
- public void setTimeToLive(int ttl) throws IOException {
- setOption(IoBridge.JAVA_IP_MULTICAST_TTL, Integer.valueOf(ttl));
- }
- @Override
- public void setTTL(byte ttl) throws IOException {
- setTimeToLive((int) ttl & 0xff); // Avoid sign extension.
- }
- @Override
- public void connect(InetAddress inetAddr, int port) throws SocketException {
- IoBridge.connect(fd, inetAddr, port); // Throws on failure.
- try {
- connectedAddress = InetAddress.getByAddress(inetAddr.getAddress());
- } catch (UnknownHostException e) {
- // this is never expected to happen as we should not have gotten
- // here if the address is not resolvable
- throw new SocketException("Host is unresolved: " + inetAddr.getHostName());
- }
- connectedPort = port;
- isNativeConnected = true;
- }
- @Override
- public void disconnect() {
- try {
- Libcore.os.connect(fd, InetAddress.UNSPECIFIED, 0);
- } catch (ErrnoException errnoException) {
- throw new AssertionError(errnoException);
- } catch (SocketException ignored) {
- // Thrown if the socket has already been closed, but this method can't throw anything.
- }
- connectedPort = -1;
- connectedAddress = null;
- isNativeConnected = false;
- }
- /**
- * Set the received address and port in the packet. We do this when the
- * Datagram socket is connected at the native level and the
- * recvConnnectedDatagramImpl does not update the packet with address from
- * which the packet was received
- *
- * @param packet
- * the packet to be updated
- */
- private void updatePacketRecvAddress(DatagramPacket packet) {
- packet.setAddress(connectedAddress);
- packet.setPort(connectedPort);
- }
- }