public void setUp() { DatagramTransport _fakedt = new DatagramTransportImpl(); _fakeAssociation = new AssociationImpl(_fakedt, null); _fakeStream = new SCTPStreamImpl(_fakeAssociation, 22); }
public SCTPMessage(SCTPStream s, SortedArray <DataChunk> chunks) { _stream = s; int tot = 0; if ((chunks.First.getFlags() & DataChunk.BEGINFLAG) == 0) { throw new Exception("[IllegalArgumentException] must start with 'start' chunk"); } if ((chunks.Last.getFlags() & DataChunk.ENDFLAG) == 0) { throw new Exception("[IllegalArgumentException] must end with 'end' chunk"); } _pPid = chunks.First.getPpid(); foreach (DataChunk dc in chunks) { tot += dc.getDataSize(); if (_pPid != dc.getPpid()) { // aaagh throw new Exception("[IllegalArgumentException] chunk has wrong ppid" + dc.getPpid() + " vs " + _pPid); } } _data = new byte[tot]; int offs = 0; foreach (DataChunk dc in chunks) { Array.Copy(dc.getData(), 0, _data, offs, dc.getDataSize()); offs += dc.getDataSize(); } }
public void closeStream(SCTPStream st) { Chunk[] cs = new Chunk[1]; if (canSend()) { Logger.Debug("due to reconfig stream " + st); cs[0] = reconfigState.makeClose(st); } this.send(cs); }
public SCTPMessage(SCTPStream s, DataChunk singleChunk) { _stream = s; int flags = singleChunk.getFlags(); if ((flags & DataChunk.SINGLEFLAG) > 0) { _data = singleChunk.getData(); _pPid = singleChunk.getPpid(); } else { throw new Exception("[IllegalArgumentException] must use a 'single' chunk"); } }
/* we can only demand they close their outbound streams */ /* we can request they start to close inbound (ie ask us to shut our outbound */ /* DCEP treats streams as bi-directional - so this is somewhat of an inpedance mis-match */ /* resulting in a temporary 'half closed' state */ /* mull this over.... */ public ReConfigChunk makeClose(SCTPStream st) { ReConfigChunk ret = null; Logger.Debug("building reconfig so close stream " + st); st.setClosing(true); lock (listOfStreamsToReset) { listOfStreamsToReset.Enqueue(st); } if (!timerIsRunning()) { ret = makeSSNResets(); } return(ret); }
// todo should be in a behave block // then we wouldn't be messing with stream seq numbers. private Chunk[] dcepDeal(SCTPStream s, DataChunk dc, DCOpen dcep) { Chunk[] rep = null; Logger.Debug("dealing with a decp for stream " + dc.getDataAsString()); if (!dcep.isAck()) { Logger.Debug("decp is not an ack... "); SCTPStreamBehaviour behave = dcep.mkStreamBehaviour(); s.setBehave(behave); s.setLabel(dcep.getLabel()); lock (s) { int seqIn = s.getNextMessageSeqIn(); s.setNextMessageSeqIn(seqIn + 1); int seqOut = s.getNextMessageSeqOut(); s.setNextMessageSeqOut(seqOut + 1); } rep = new Chunk[1]; DataChunk ack = dc.mkAck(dcep); s.outbound(ack); ack.setTsn(_nearTSN++); // check rollover - will break at maxint. rep[0] = ack; } else { Logger.Debug("got a dcep ack for " + s.getLabel()); SCTPStreamBehaviour behave = dcep.mkStreamBehaviour(); s.setBehave(behave); lock (s) { int seqIn = s.getNextMessageSeqIn(); s.setNextMessageSeqIn(seqIn + 1); int seqOut = s.getNextMessageSeqOut(); s.setNextMessageSeqOut(seqOut + 1); } } return(rep); }
public SCTPMessage(string data, SCTPStream s) { _data = (data.Length > 0) ? System.Text.Encoding.ASCII.GetBytes(data) : new byte[1]; _stream = s; _pPid = (data.Length > 0) ? DataChunk.WEBRTCstring : DataChunk.WEBRTCstringEMPTY; }
/** * Outbound message - note that we assume no one will mess with data between * calls to fill() * * @param data * @param s */ public SCTPMessage(byte[] data, SCTPStream s) { _data = (data.Length > 0) ? data : new byte[1]; _stream = s; _pPid = (data.Length > 0) ? DataChunk.WEBRTCBINARY : DataChunk.WEBRTCBINARYEMPTY; }
/* * https://tools.ietf.org/html/rfc6525 */ public Chunk[] deal(ReConfigChunk rconf) { Chunk[] ret = new Chunk[1]; ReConfigChunk reply = null; Logger.Debug("Got a reconfig message to deal with"); if (haveSeen(rconf)) { // if not - is this a repeat reply = getPrevious(rconf); // then send the same reply } if (reply == null) { // not a repeat then reply = new ReConfigChunk(); // create a new thing if (rconf.hasOutgoingReset()) { OutgoingSSNResetRequestParameter oreset = rconf.getOutgoingReset(); int[] streams = oreset.getStreams(); if (streams.Length == 0) { streams = assoc.allStreams(); } if (timerIsRunning()) { markAsAcked(rconf); } // if we are behind, we are supposed to wait untill we catch up. if (oreset.getLastAssignedTSN() > assoc.getCumAckPt()) { Logger.Debug("Last assigned > farTSN " + oreset.getLastAssignedTSN() + " v " + assoc.getCumAckPt()); foreach (int s in streams) { SCTPStream defstr = assoc.getStream(s); defstr.setDeferred(true); } ReconfigurationResponseParameter rep = new ReconfigurationResponseParameter(); rep.setSeq(oreset.getReqSeqNo()); rep.setResult(ReconfigurationResponseParameter.IN_PROGRESS); reply.addParam(rep); } else { // somehow invoke this when TSN catches up ?!?! ToDo Logger.Debug("we are up-to-date "); ReconfigurationResponseParameter rep = new ReconfigurationResponseParameter(); rep.setSeq(oreset.getReqSeqNo()); int result = streams.Length > 0 ? ReconfigurationResponseParameter.SUCCESS_PERFORMED : ReconfigurationResponseParameter.SUCCESS_NOTHING_TO_DO; rep.setResult((uint)result); // assume all good foreach (int s in streams) { SCTPStream cstrm = assoc.delStream(s); if (cstrm == null) { Logger.Error("Close a non existant stream"); rep.setResult(ReconfigurationResponseParameter.ERROR_WRONG_SSN); break; // bidriectional might be a problem here... } else { cstrm.reset(); } } reply.addParam(rep); } } // ponder putting this in a second chunk ? if (rconf.hasIncomingReset()) { IncomingSSNResetRequestParameter ireset = rconf.getIncomingReset(); /*The Re-configuration * Response Sequence Number of the Outgoing SSN Reset Request * Parameter MUST be the Re-configuration Request Sequence Number * of the Incoming SSN Reset Request Parameter. */ OutgoingSSNResetRequestParameter rep = new OutgoingSSNResetRequestParameter(nextNearNo(), ireset.getReqNo(), assoc.getNearTSN()); int[] streams = ireset.getStreams(); rep.setStreams(streams); if (streams.Length == 0) { streams = assoc.allStreams(); } foreach (int s in streams) { SCTPStream st = assoc.getStream(s); if (st != null) { st.setClosing(true); } } reply.addParam(rep); // set outbound timer running here ??? Logger.Debug("Ireset " + ireset); } } if (reply.hasParam()) { ret[0] = reply; // todo should add sack here Logger.Debug("about to reply with " + reply.ToString()); } else { ret = null; } return(ret); }
public ReConfigChunk addToCloseList(SCTPStream st) { return(reconfigState.makeClose(st)); }