32
32
import java .io .OutputStream ;
33
33
import java .io .FileDescriptor ;
34
34
35
+ /* J2ObjC removed
36
+ import dalvik.annotation.optimization.ReachabilitySensitive;
37
+ */
35
38
import dalvik .system .BlockGuard ;
36
39
import dalvik .system .CloseGuard ;
37
40
import dalvik .system .SocketTagger ;
@@ -50,8 +53,8 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
50
53
{
51
54
/* instance variable for SO_TIMEOUT */
52
55
int timeout ; // timeout in millisec
53
- // traffic class
54
- int trafficClass ;
56
+ // Android-removed: traffic class is set through socket.
57
+ // private int trafficClass;
55
58
56
59
private boolean shut_rd = false ;
57
60
private boolean shut_wr = false ;
@@ -237,121 +240,139 @@ public void setOption(int opt, Object val) throws SocketException {
237
240
if (isClosedOrPending ()) {
238
241
throw new SocketException ("Socket Closed" );
239
242
}
243
+ // BEGIN Android-removed: Logic dealing with value type moved to socketSetOption.
244
+ /*
240
245
boolean on = true;
241
246
switch (opt) {
242
247
/* check type safety b4 going native. These should never
243
248
* fail, since only java.Socket* has access to
244
249
* PlainSocketImpl.setOption().
245
- */
246
- case SO_LINGER :
247
- if (val == null || (!(val instanceof Integer ) && !(val instanceof Boolean )))
248
- throw new SocketException ("Bad parameter for option" );
249
- if (val instanceof Boolean ) {
250
- /* true only if disabling - enabling should be Integer */
251
- on = false ;
252
- }
253
- break ;
254
- case SO_TIMEOUT :
255
- if (val == null || (!(val instanceof Integer )))
256
- throw new SocketException ("Bad parameter for SO_TIMEOUT" );
257
- int tmp = ((Integer ) val ).intValue ();
258
- if (tmp < 0 )
259
- throw new IllegalArgumentException ("timeout < 0" );
260
- timeout = tmp ;
261
- break ;
262
- case IP_TOS :
263
- if (val == null || !(val instanceof Integer )) {
264
- throw new SocketException ("bad argument for IP_TOS" );
265
- }
266
- trafficClass = ((Integer )val ).intValue ();
267
- break ;
268
- case SO_BINDADDR :
269
- throw new SocketException ("Cannot re-bind socket" );
270
- case TCP_NODELAY :
271
- if (val == null || !(val instanceof Boolean ))
272
- throw new SocketException ("bad parameter for TCP_NODELAY" );
273
- on = ((Boolean )val ).booleanValue ();
274
- break ;
275
- case SO_SNDBUF :
276
- case SO_RCVBUF :
277
- if (val == null || !(val instanceof Integer ) ||
278
- !(((Integer )val ).intValue () > 0 )) {
279
- throw new SocketException ("bad parameter for SO_SNDBUF " +
280
- "or SO_RCVBUF" );
281
- }
282
- break ;
283
- case SO_KEEPALIVE :
284
- if (val == null || !(val instanceof Boolean ))
285
- throw new SocketException ("bad parameter for SO_KEEPALIVE" );
286
- on = ((Boolean )val ).booleanValue ();
287
- break ;
288
- case SO_OOBINLINE :
289
- if (val == null || !(val instanceof Boolean ))
290
- throw new SocketException ("bad parameter for SO_OOBINLINE" );
291
- on = ((Boolean )val ).booleanValue ();
292
- break ;
293
- case SO_REUSEADDR :
294
- if (val == null || !(val instanceof Boolean ))
295
- throw new SocketException ("bad parameter for SO_REUSEADDR" );
296
- on = ((Boolean )val ).booleanValue ();
297
- break ;
298
- default :
299
- throw new SocketException ("unrecognized TCP option: " + opt );
250
+ *
251
+ case SO_LINGER:
252
+ if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
253
+ throw new SocketException("Bad parameter for option");
254
+ if (val instanceof Boolean) {
255
+ /* true only if disabling - enabling should be Integer *
256
+ on = false;
257
+ }
258
+ break;
259
+ case SO_TIMEOUT:
260
+ if (val == null || (!(val instanceof Integer)))
261
+ throw new SocketException("Bad parameter for SO_TIMEOUT");
262
+ int tmp = ((Integer) val).intValue();
263
+ if (tmp < 0)
264
+ throw new IllegalArgumentException("timeout < 0");
265
+ timeout = tmp;
266
+ break;
267
+ case IP_TOS:
268
+ if (val == null || !(val instanceof Integer)) {
269
+ throw new SocketException("bad argument for IP_TOS");
270
+ }
271
+ trafficClass = ((Integer)val).intValue();
272
+ break;
273
+ case SO_BINDADDR:
274
+ throw new SocketException("Cannot re-bind socket");
275
+ case TCP_NODELAY:
276
+ if (val == null || !(val instanceof Boolean))
277
+ throw new SocketException("bad parameter for TCP_NODELAY");
278
+ on = ((Boolean)val).booleanValue();
279
+ break;
280
+ case SO_SNDBUF:
281
+ case SO_RCVBUF:
282
+ if (val == null || !(val instanceof Integer) ||
283
+ !(((Integer)val).intValue() > 0)) {
284
+ throw new SocketException("bad parameter for SO_SNDBUF " +
285
+ "or SO_RCVBUF");
286
+ }
287
+ break;
288
+ case SO_KEEPALIVE:
289
+ if (val == null || !(val instanceof Boolean))
290
+ throw new SocketException("bad parameter for SO_KEEPALIVE");
291
+ on = ((Boolean)val).booleanValue();
292
+ break;
293
+ case SO_OOBINLINE:
294
+ if (val == null || !(val instanceof Boolean))
295
+ throw new SocketException("bad parameter for SO_OOBINLINE");
296
+ on = ((Boolean)val).booleanValue();
297
+ break;
298
+ case SO_REUSEADDR:
299
+ if (val == null || !(val instanceof Boolean))
300
+ throw new SocketException("bad parameter for SO_REUSEADDR");
301
+ on = ((Boolean)val).booleanValue();
302
+ break;
303
+ default:
304
+ throw new SocketException("unrecognized TCP option: " + opt);
300
305
}
301
306
socketSetOption(opt, on, val);
307
+ */
308
+ // END Android-removed: Logic dealing with value type moved to socketSetOption.
309
+ // Android-added: Keep track of timeout value not handled by socketSetOption.
310
+ if (opt == SO_TIMEOUT ) {
311
+ timeout = (Integer ) val ;
312
+ }
313
+ socketSetOption (opt , val );
302
314
}
303
-
304
315
public Object getOption (int opt ) throws SocketException {
305
316
if (isClosedOrPending ()) {
306
317
throw new SocketException ("Socket Closed" );
307
318
}
308
319
if (opt == SO_TIMEOUT ) {
309
320
return new Integer (timeout );
310
321
}
322
+ // BEGIN Android-changed: Logic dealing with value type moved to socketGetOption.
323
+ /*
311
324
int ret = 0;
312
325
/*
313
326
* The native socketGetOption() knows about 3 options.
314
327
* The 32 bit value it returns will be interpreted according
315
328
* to what we're asking. A return of -1 means it understands
316
329
* the option but its turned off. It will raise a SocketException
317
330
* if "opt" isn't one it understands.
318
- */
331
+ *
319
332
320
333
switch (opt) {
321
- case TCP_NODELAY :
322
- ret = socketGetOption (opt , null );
323
- return Boolean .valueOf (ret != -1 );
324
- case SO_OOBINLINE :
325
- ret = socketGetOption (opt , null );
326
- return Boolean .valueOf (ret != -1 );
327
- case SO_LINGER :
328
- ret = socketGetOption (opt , null );
329
- return (ret == -1 ) ? Boolean .FALSE : (Object )(new Integer (ret ));
330
- case SO_REUSEADDR :
331
- ret = socketGetOption (opt , null );
332
- return Boolean .valueOf (ret != -1 );
333
- case SO_BINDADDR :
334
- InetAddressContainer in = new InetAddressContainer ();
335
- ret = socketGetOption (opt , in );
336
- return in .addr ;
337
- case SO_SNDBUF :
338
- case SO_RCVBUF :
339
- ret = socketGetOption (opt , null );
340
- return new Integer (ret );
341
- case IP_TOS :
334
+ case TCP_NODELAY:
335
+ ret = socketGetOption(opt, null);
336
+ return Boolean.valueOf(ret != -1);
337
+ case SO_OOBINLINE:
338
+ ret = socketGetOption(opt, null);
339
+ return Boolean.valueOf(ret != -1);
340
+ case SO_LINGER:
341
+ ret = socketGetOption(opt, null);
342
+ return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
343
+ case SO_REUSEADDR:
344
+ ret = socketGetOption(opt, null);
345
+ return Boolean.valueOf(ret != -1);
346
+ case SO_BINDADDR:
347
+ InetAddressContainer in = new InetAddressContainer();
348
+ ret = socketGetOption(opt, in);
349
+ return in.addr;
350
+ case SO_SNDBUF:
351
+ case SO_RCVBUF:
352
+ ret = socketGetOption(opt, null);
353
+ return new Integer(ret);
354
+ case IP_TOS:
355
+ try {
342
356
ret = socketGetOption(opt, null);
343
357
if (ret == -1) { // ipv6 tos
344
- return new Integer ( trafficClass ) ;
358
+ return trafficClass;
345
359
} else {
346
- return new Integer ( ret ) ;
360
+ return ret;
347
361
}
348
- case SO_KEEPALIVE :
349
- ret = socketGetOption (opt , null );
350
- return Boolean .valueOf (ret != -1 );
351
- // should never get here
352
- default :
353
- return null ;
362
+ } catch (SocketException se) {
363
+ // TODO - should make better effort to read TOS or TCLASS
364
+ return trafficClass; // ipv6 tos
365
+ }
366
+ case SO_KEEPALIVE:
367
+ ret = socketGetOption(opt, null);
368
+ return Boolean.valueOf(ret != -1);
369
+ // should never get here
370
+ default:
371
+ return null;
354
372
}
373
+ */
374
+ return socketGetOption (opt );
375
+ // END Android-changed: Logic dealing with value type moved to socketGetOption.
355
376
}
356
377
357
378
/**
@@ -542,12 +563,44 @@ protected void close() throws IOException {
542
563
if (!stream ) {
543
564
ResourceManager .afterUdpClose ();
544
565
}
545
- if (closePending ) {
546
- return ;
566
+ // Android-changed: Socket should be untagged before the preclose.
567
+ // After preclose, socket will dup2-ed to marker_fd, therefore, it won't describe
568
+ // the same file. If closingPending is true, then the socket has been preclosed.
569
+ //
570
+ // Also, close the CloseGuard when the #close is called.
571
+ if (!closePending ) {
572
+ closePending = true ;
573
+ guard .close ();
574
+
575
+ if (fdUseCount == 0 ) {
576
+ /*
577
+ * We close the FileDescriptor in two-steps - first the
578
+ * "pre-close" which closes the socket but doesn't
579
+ * release the underlying file descriptor. This operation
580
+ * may be lengthy due to untransmitted data and a long
581
+ * linger interval. Once the pre-close is done we do the
582
+ * actual socket to release the fd.
583
+ */
584
+ try {
585
+ socketPreClose ();
586
+ } finally {
587
+ socketClose ();
588
+ }
589
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
590
+ // socketClose invalidates the fd by closing the fd.
591
+ // fd = null;
592
+ return ;
593
+ } else {
594
+ /*
595
+ * If a thread has acquired the fd and a close
596
+ * isn't pending then use a deferred close.
597
+ * Also decrement fdUseCount to signal the last
598
+ * thread that releases the fd to close it.
599
+ */
600
+ fdUseCount --;
601
+ socketPreClose ();
602
+ }
547
603
}
548
- closePending = true ;
549
- socketClose ();
550
- return ;
551
604
}
552
605
}
553
606
}
@@ -701,40 +754,45 @@ public int getTimeout() {
701
754
return timeout ;
702
755
}
703
756
757
+ /*
758
+ * "Pre-close" a socket by dup'ing the file descriptor - this enables
759
+ * the socket to be closed without releasing the file descriptor.
760
+ */
761
+ private void socketPreClose () throws IOException {
762
+ socketClose0 (true );
763
+ }
764
+
704
765
/*
705
766
* Close the socket (and release the file descriptor).
706
767
*/
707
768
protected void socketClose () throws IOException {
708
- guard .close ();
709
-
710
- socketClose0 ();
769
+ socketClose0 (false );
711
770
}
712
771
713
772
abstract void socketCreate (boolean isServer ) throws IOException ;
714
773
abstract void socketConnect (InetAddress address , int port , int timeout )
715
- throws IOException ;
774
+ throws IOException ;
716
775
abstract void socketBind (InetAddress address , int port )
717
- throws IOException ;
776
+ throws IOException ;
718
777
abstract void socketListen (int count )
719
- throws IOException ;
778
+ throws IOException ;
720
779
abstract void socketAccept (SocketImpl s )
721
- throws IOException ;
780
+ throws IOException ;
722
781
abstract int socketAvailable ()
723
- throws IOException ;
724
- abstract void socketClose0 ()
725
- throws IOException ;
782
+ throws IOException ;
783
+ abstract void socketClose0 (boolean useDeferredClose )
784
+ throws IOException ;
726
785
abstract void socketShutdown (int howto )
727
- throws IOException ;
728
- abstract void socketSetOption (int cmd , boolean on , Object value )
729
- throws SocketException ;
730
- abstract int socketGetOption (int opt , Object iaContainerObj ) throws SocketException ;
786
+ throws IOException ;
787
+
788
+ // Android-changed: Method signature changes.
789
+ // socket{Get,Set}Option work directly with Object values.
790
+ abstract void socketSetOption (int cmd , Object value ) throws SocketException ;
791
+ abstract Object socketGetOption (int opt ) throws SocketException ;
792
+
731
793
abstract void socketSendUrgentData (int data )
732
- throws IOException ;
794
+ throws IOException ;
733
795
734
796
public final static int SHUT_RD = 0 ;
735
797
public final static int SHUT_WR = 1 ;
736
798
}
737
-
738
- class InetAddressContainer {
739
- InetAddress addr ;
740
- }
0 commit comments