FULL PRODUCT VERSION :
oracle jdk 1.7.0.51
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 13.10
uname -a
Linux 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
sctp packages installed
A DESCRIPTION OF THE PROBLEM :
When SctpChannel is obtained by calling branch on SctpMultiChannel, then shutdown does not send sctp SHUTDOWN message over the network. In fact the socket is closed for writing but the remote endpoint is not notified that the shutdown has been called.
If the channel is established without SctpMultiChannel - shutdown works correctly.
if branch is not called, and instead shutdown on SctpMultiChannel is closed - shutdown works correctly.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Example source code which replicates the condition is included.
Trace from wireshark shows that if application is called with "true" argument, then
shutdown message is not sent to remote party.
If it's called with "false" then shutdown message is transmitted.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
SCTP SHUTDOWN message sent to the remote party after calling shutdown on SctpChannel obtained by branch on SctpMultiChannel.
ACTUAL -
Nothing is sent after shutdown is called.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
***********************************CLIENT
package testa;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import com.sun.nio.sctp.Association;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.Notification;
import com.sun.nio.sctp.NotificationHandler;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpMultiChannel;
public class T4Cs implements NotificationHandler<T4Cs> {
public static void main(String s[]) throws Exception {
T4Cs t=new T4Cs(s);
t.process();
}
SctpChannel c;
private SctpMultiChannel smc;
private Association a;
boolean useBranch=true;
T4Cs(String arg[]) {
if(arg.length>0)
useBranch=Boolean.parseBoolean(arg[0]);
}
void process() throws Exception {
smc=SctpMultiChannel.open();
// smc.configureBlocking(false);
smc.bind(new InetSocketAddress("127.0.0.1",50110));
ByteBuffer bb=ByteBuffer.allocate(1024);
for(int i=0;i<100;i++)
bb.put((byte)0).put((byte)1);
bb.flip();
MessageInfo i=MessageInfo.createOutgoing(new InetSocketAddress("127.0.0.1",50220), 0);
i.unordered(true);
smc.send(bb,i);
while(a==null) {
MessageInfo info = smc.receive(bb,
this, this);
}
System.out.println("out of loop");
Thread.sleep(2000);
System.out.println("calling shutdown");
if(useBranch) {
c=smc.branch(a);
c.shutdown();
} else {
smc.shutdown(a);
}
Thread.sleep(20000);
System.out.println("calling close");
if(c!=null)
c.close();
smc.close();
}
@Override
public HandlerResult handleNotification(Notification n, T4Cs arg1) {
System.out.println(n);
if (n instanceof AssociationChangeNotification) {
AssociationChangeNotification acn = (AssociationChangeNotification) n;
try {
if (acn.event() == AssocChangeEvent.COMM_UP) {
a = acn.association();
// c = smc.branch(a);
return HandlerResult.RETURN;
}
} catch(Exception e) {
e.printStackTrace();
}
}
return HandlerResult.CONTINUE;
}
}
*********************** SERVER
package testa;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import com.sun.nio.sctp.*;
public class T4S implements NotificationHandler<T4S>{
public static void main(String s[]) throws Exception {
T4S t=new T4S();
t.processRx();
}
SctpChannel c;
T4S() throws Exception {
SctpServerChannel sc=SctpServerChannel.open();
sc.bind(new InetSocketAddress("127.0.0.1",50220));
c=sc.accept();
System.out.println("Connection established");
processRx();
}
public void processRx() {
ByteBuffer bb=ByteBuffer.allocate(1024);
try {
while(c!=null) {
MessageInfo info = c.receive(bb,
this, this);
}
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
}
@Override
public HandlerResult handleNotification(Notification n, T4S arg1) {
System.out.println(n);
if(n instanceof sun.nio.ch.SctpShutdown) {
try {
c.shutdown();
c=null;
} catch (IOException e) {
e.printStackTrace();
}
}
return HandlerResult.CONTINUE;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Calling close of course works.
But after close has been called it's not possible to retrieve undelivered messages, which is a problem for reliable transmission.
oracle jdk 1.7.0.51
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 13.10
uname -a
Linux 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
sctp packages installed
A DESCRIPTION OF THE PROBLEM :
When SctpChannel is obtained by calling branch on SctpMultiChannel, then shutdown does not send sctp SHUTDOWN message over the network. In fact the socket is closed for writing but the remote endpoint is not notified that the shutdown has been called.
If the channel is established without SctpMultiChannel - shutdown works correctly.
if branch is not called, and instead shutdown on SctpMultiChannel is closed - shutdown works correctly.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Example source code which replicates the condition is included.
Trace from wireshark shows that if application is called with "true" argument, then
shutdown message is not sent to remote party.
If it's called with "false" then shutdown message is transmitted.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
SCTP SHUTDOWN message sent to the remote party after calling shutdown on SctpChannel obtained by branch on SctpMultiChannel.
ACTUAL -
Nothing is sent after shutdown is called.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
***********************************CLIENT
package testa;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import com.sun.nio.sctp.Association;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.Notification;
import com.sun.nio.sctp.NotificationHandler;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpMultiChannel;
public class T4Cs implements NotificationHandler<T4Cs> {
public static void main(String s[]) throws Exception {
T4Cs t=new T4Cs(s);
t.process();
}
SctpChannel c;
private SctpMultiChannel smc;
private Association a;
boolean useBranch=true;
T4Cs(String arg[]) {
if(arg.length>0)
useBranch=Boolean.parseBoolean(arg[0]);
}
void process() throws Exception {
smc=SctpMultiChannel.open();
// smc.configureBlocking(false);
smc.bind(new InetSocketAddress("127.0.0.1",50110));
ByteBuffer bb=ByteBuffer.allocate(1024);
for(int i=0;i<100;i++)
bb.put((byte)0).put((byte)1);
bb.flip();
MessageInfo i=MessageInfo.createOutgoing(new InetSocketAddress("127.0.0.1",50220), 0);
i.unordered(true);
smc.send(bb,i);
while(a==null) {
MessageInfo info = smc.receive(bb,
this, this);
}
System.out.println("out of loop");
Thread.sleep(2000);
System.out.println("calling shutdown");
if(useBranch) {
c=smc.branch(a);
c.shutdown();
} else {
smc.shutdown(a);
}
Thread.sleep(20000);
System.out.println("calling close");
if(c!=null)
c.close();
smc.close();
}
@Override
public HandlerResult handleNotification(Notification n, T4Cs arg1) {
System.out.println(n);
if (n instanceof AssociationChangeNotification) {
AssociationChangeNotification acn = (AssociationChangeNotification) n;
try {
if (acn.event() == AssocChangeEvent.COMM_UP) {
a = acn.association();
// c = smc.branch(a);
return HandlerResult.RETURN;
}
} catch(Exception e) {
e.printStackTrace();
}
}
return HandlerResult.CONTINUE;
}
}
*********************** SERVER
package testa;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import com.sun.nio.sctp.*;
public class T4S implements NotificationHandler<T4S>{
public static void main(String s[]) throws Exception {
T4S t=new T4S();
t.processRx();
}
SctpChannel c;
T4S() throws Exception {
SctpServerChannel sc=SctpServerChannel.open();
sc.bind(new InetSocketAddress("127.0.0.1",50220));
c=sc.accept();
System.out.println("Connection established");
processRx();
}
public void processRx() {
ByteBuffer bb=ByteBuffer.allocate(1024);
try {
while(c!=null) {
MessageInfo info = c.receive(bb,
this, this);
}
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
}
@Override
public HandlerResult handleNotification(Notification n, T4S arg1) {
System.out.println(n);
if(n instanceof sun.nio.ch.SctpShutdown) {
try {
c.shutdown();
c=null;
} catch (IOException e) {
e.printStackTrace();
}
}
return HandlerResult.CONTINUE;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Calling close of course works.
But after close has been called it's not possible to retrieve undelivered messages, which is a problem for reliable transmission.