1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-26 08:12:05 +01:00

Don't throw an IOException if IBBStream got closed by the remote

Smack should not throw an IOException in case a stream got closed by
the remote peer and the user is trying to read() from the stream. This
commit fixes that, by making Smack return '-1' if the stream got
closed by the remote. An IOException will only be thrown if the user
tries to read from a stream that got already closed by *himself*.

SMACK-468
This commit is contained in:
Florian Schmaus 2014-05-20 14:18:47 +02:00
parent a19181ce04
commit d790db5729
2 changed files with 4 additions and 56 deletions

View file

@ -395,8 +395,9 @@ public class InBandBytestreamSession implements BytestreamSession {
* @throws IOException if stream is closed and no data should be read anymore * @throws IOException if stream is closed and no data should be read anymore
*/ */
private void checkClosed() throws IOException { private void checkClosed() throws IOException {
/* throw no exception if there is data available, but not if close method was invoked */ // Throw an exception if, and only if, this stream has been already
if ((isClosed && this.dataQueue.isEmpty()) || closeInvoked) { // closed by the user using the close() method
if (closeInvoked) {
// clear data queue in case additional data was received after stream was closed // clear data queue in case additional data was received after stream was closed
this.dataQueue.clear(); this.dataQueue.clear();
throw new IOException("Stream is closed"); throw new IOException("Stream is closed");
@ -408,7 +409,7 @@ public class InBandBytestreamSession implements BytestreamSession {
} }
public void close() throws IOException { public void close() throws IOException {
if (isClosed) { if (closeInvoked) {
return; return;
} }

View file

@ -609,59 +609,6 @@ public class InBandBytestreamSessionTest {
} }
/**
* If the session is closed the input stream and output stream should be closed as well.
*
* @throws Exception should not happen
*/
@Test
public void shouldCloseBothStreamsIfSessionIsClosed() throws Exception {
// acknowledgment for data packet
IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID);
protocol.addResponse(resultIQ);
// acknowledgment for close request
protocol.addResponse(resultIQ, Verification.correspondingSenderReceiver,
Verification.requestTypeSET);
// get IBB sessions data packet listener
InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream,
initiatorJID);
InputStream inputStream = session.getInputStream();
PacketListener listener = Whitebox.getInternalState(inputStream, PacketListener.class);
// build data packet
String base64Data = StringUtils.encodeBase64("Data");
DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, base64Data);
Data data = new Data(dpe);
// add data packets
listener.processPacket(data);
session.close();
protocol.verifyAll();
try {
while (inputStream.read() != -1) {
}
inputStream.read();
fail("should throw an exception");
}
catch (IOException e) {
assertTrue(e.getMessage().contains("closed"));
}
try {
session.getOutputStream().flush();
fail("should throw an exception");
}
catch (IOException e) {
assertTrue(e.getMessage().contains("closed"));
}
}
/** /**
* If the input stream is closed concurrently there should be no deadlock. * If the input stream is closed concurrently there should be no deadlock.
* *