1919
2020import java .beans .*;
2121import java .io .*;
22+ import java .lang .ref .*;
2223import java .net .*;
2324import java .util .*;
2425import java .util .concurrent .*;
@@ -160,6 +161,17 @@ public class Component
160161 */
161162 private BufferHandler bufferCallback = null ;
162163
164+ /**
165+ * The remote address of the last received payload packet.
166+ */
167+ private SocketAddress lastReceivedFrom = null ;
168+
169+ /**
170+ * A reference to the last {@link CandidatePair} that was used to send a packet to. If the remote address that
171+ * we receive payload from changes, this reference is cleared.
172+ */
173+ private WeakReference <CandidatePair > lastUsedPair = new WeakReference <>(null );
174+
163175 /**
164176 * Creates a new <tt>Component</tt> with the specified <tt>componentID</tt>
165177 * as a child of the specified <tt>IceMediaStream</tt>.
@@ -1207,17 +1219,59 @@ public Logger getLogger()
12071219 public void send (byte [] buffer , int offset , int length )
12081220 throws IOException
12091221 {
1210- CandidatePair pair = getSelectedPair ();
1222+ CandidatePair pair = lastUsedPair . get ();
12111223 if (pair == null )
12121224 {
1213- logger .debug ("No selected pair, will try valid for sending" );
1214- pair = parentStream .getValidPair (this );
1215- if (pair == null )
1225+ pair = findPair (lastReceivedFrom );
1226+ lastUsedPair = new WeakReference <>(pair );
1227+ }
1228+
1229+ if (pair == null )
1230+ {
1231+ throw new IOException ("No valid pair." );
1232+ }
1233+
1234+ AddressAndSocket addressAndSocket = getAddressAndSocket (pair );
1235+ if (addressAndSocket == null )
1236+ {
1237+ throw new IOException ("No valid socket." );
1238+ }
1239+
1240+ DatagramPacket p = new DatagramPacket (buffer , offset , length );
1241+ p .setSocketAddress (addressAndSocket .remoteAddress );
1242+ addressAndSocket .socket .send (p );
1243+ }
1244+
1245+ private CandidatePair findPair (SocketAddress remoteAddress )
1246+ {
1247+ CandidatePair pair = null ;
1248+ if (AgentConfig .config .getSendToLastReceivedFromAddress () && remoteAddress != null )
1249+ {
1250+ for (CandidatePair keepAlivePair : keepAlivePairs )
12161251 {
1217- throw new IOException ("No valid pair." );
1252+ if (keepAlivePair .getState () == CandidatePairState .SUCCEEDED
1253+ && remoteAddress .equals (keepAlivePair .getRemoteCandidate ().getTransportAddress ()))
1254+ {
1255+ pair = keepAlivePair ;
1256+ break ;
1257+ }
12181258 }
12191259 }
1260+ if (pair == null )
1261+ {
1262+ pair = getSelectedPair ();
1263+ }
1264+ if (pair == null )
1265+ {
1266+ logger .debug ("No selected pair, will try valid for sending" );
1267+ pair = parentStream .getValidPair (this );
1268+ }
1269+
1270+ return pair ;
1271+ }
12201272
1273+ private AddressAndSocket getAddressAndSocket (CandidatePair pair )
1274+ {
12211275 LocalCandidate localCandidate = pair .getLocalCandidate ();
12221276 if (localCandidate != null && localCandidate .getBase () != null )
12231277 {
@@ -1229,12 +1283,9 @@ public void send(byte[] buffer, int offset, int length)
12291283
12301284 if (socket == null )
12311285 {
1232- throw new IOException ( "No socket found to send on." ) ;
1286+ return null ;
12331287 }
1234-
1235- DatagramPacket p = new DatagramPacket (buffer , offset , length );
1236- p .setSocketAddress (remoteAddress );
1237- socket .send (p );
1288+ return new AddressAndSocket (remoteAddress , socket );
12381289 }
12391290
12401291 /**
@@ -1256,6 +1307,12 @@ public void handleBuffer(@NotNull Buffer buffer)
12561307
12571308 try
12581309 {
1310+ SocketAddress remoteAddress = buffer .getRemoteAddress ();
1311+ if (remoteAddress == null || !remoteAddress .equals (lastReceivedFrom ))
1312+ {
1313+ lastUsedPair = new WeakReference <>(null );
1314+ lastReceivedFrom = buffer .getRemoteAddress ();
1315+ }
12591316 bufferCallback .handleBuffer (buffer );
12601317 }
12611318 catch (Exception e )
@@ -1273,4 +1330,16 @@ public void setBufferCallback(BufferHandler bufferCallback)
12731330 {
12741331 this .bufferCallback = bufferCallback ;
12751332 }
1333+
1334+ private static class AddressAndSocket
1335+ {
1336+ private final SocketAddress remoteAddress ;
1337+ private final IceSocketWrapper socket ;
1338+
1339+ private AddressAndSocket (SocketAddress remoteAddress , IceSocketWrapper socket )
1340+ {
1341+ this .remoteAddress = remoteAddress ;
1342+ this .socket = socket ;
1343+ }
1344+ }
12761345}
0 commit comments