1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package android.net.ip; 19 20 import android.os.Handler; 21 22 import androidx.annotation.NonNull; 23 24 import com.android.net.module.util.InterfaceParams; 25 import com.android.net.module.util.PacketReader; 26 27 import java.io.FileDescriptor; 28 29 /** 30 * Monitor IGMP/MLD report packets and notify listeners the multicast address changes. 31 * 32 * <p>This class uses a {@link PacketReader} to listen for IGMP/MLD report packets on a given 33 * interface. When a packet is received, it notifies the provided {@link Callback} of the change 34 * in the multicast address. 35 * 36 * <p>To use this class, create a new instance with the desired {@link Handler}, 37 * {@link InterfaceParams}, {@link Callback}, and {@link FileDescriptor}. Then, call {@link #start()} 38 * to start listening for packets. To stop listening, call {@link #stop()}. 39 */ 40 public class MulticastReportMonitor { 41 public interface Callback { 42 /** 43 * Notifies the system or other components about a change in the multicast address. 44 */ notifyMulticastAddrChange()45 void notifyMulticastAddrChange(); 46 } 47 48 private static final String TAG = MulticastReportMonitor.class.getSimpleName(); 49 private final PacketReader mPacketListener; 50 51 /** 52 * Creates a new {@link MulticastReportMonitor}. 53 * 54 * @param handler The {@link Handler} to use for the {@link PacketReader}. 55 * @param ifParams The {@link InterfaceParams} for the interface to listen on. 56 * @param callback The {@link Callback} to notify the multicast address changes. 57 * @param fd The {@link FileDescriptor} to use for the {@link PacketReader}. 58 */ MulticastReportMonitor( @onNull Handler handler, @NonNull InterfaceParams ifParams, @NonNull Callback callback, @NonNull FileDescriptor fd)59 public MulticastReportMonitor( 60 @NonNull Handler handler, 61 @NonNull InterfaceParams ifParams, 62 @NonNull Callback callback, 63 @NonNull FileDescriptor fd) { 64 mPacketListener = new PacketListener(handler, ifParams, callback, fd); 65 } 66 67 /** 68 * Starts the packet listener. 69 */ start()70 public void start() { 71 mPacketListener.start(); 72 } 73 74 /** 75 * Stops the packet listener. 76 */ stop()77 public void stop() { 78 mPacketListener.stop(); 79 } 80 81 private static final class PacketListener extends PacketReader { 82 private final Callback mCallback; 83 private final FileDescriptor mFd; 84 PacketListener(Handler h, InterfaceParams ifParams, Callback callback, FileDescriptor fd)85 PacketListener(Handler h, InterfaceParams ifParams, Callback callback, FileDescriptor fd) { 86 super(h, ifParams.defaultMtu); 87 mCallback = callback; 88 mFd = fd; 89 } 90 91 @Override createFd()92 protected FileDescriptor createFd() { 93 return mFd; 94 } 95 96 @Override handlePacket(@onNull byte[] recvbuf, int length)97 protected void handlePacket(@NonNull byte[] recvbuf, int length) { 98 mCallback.notifyMulticastAddrChange(); 99 } 100 } 101 } 102