⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sctp_msg.c

📁 No7信令,我需要交换类似的代码, 请店长审核,谢谢了,急着交换,谢谢
💻 C
📖 第 1 页 / 共 5 页
字号:
	return;}/* *  COOKIE TIMEOUT *  ------------------------------------------------------------------------- *  The cookie timer has expired indicating that we have not yet received a *  COOKIE ACK within timer T1-cookie.  This means that we should attempt to *  retransmit the COOKIE ECHO until we have attempted Path.Max.Retrans times. */static void sctp_cookie_timeout(data)	caddr_t data;{	mblk_t *mp;	sctp_t *sp;	sctp_daddr_t *sd;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sp->timer_cookie = timeout(sctp_cookie_timeout, (caddr_t)sd, 1);		return;	}	sp->timer_cookie = 0;	if ( sp->s_state != SCTP_COOKIE_ECHOED ) { rare();		return;	}	if ( sctp_assoc_timedout(sp, sd, sp->max_retrans) ) { seldom();		return;	}	/* See RFC 2960 6.3.3 E3 */	for ( mp = bufq_head(&sp->rtxq); mp; mp = mp->b_next )	{		sctp_tcb_t *cb = SCTP_TCB(mp);		seldom();		if ( cb->daddr == sd				&& (cb->flags & SCTPCB_FLAG_SENT)				&& !(cb->flags & SCTPCB_FLAG_RETRANS) )		{			cb->flags |= SCTPCB_FLAG_RETRANS;			sp->nrtxs++;			cb->sacks = 0;		}	}	sd = sp->taddr;	/* might have new primary */	ensure( sd, return );	set_timeout(&sp->timer_cookie, sctp_cookie_timeout, sd, sd->rto);	usual( sp->retry );	sctp_send_msg(sp, sd, sp->retry);	return;}/* *  RETRANS TIMEOUT (T3-rtx) *  ------------------------------------------------------------------------- *  This means that we have not received an ack for a DATA chunk within timer *  T3-rtx.  This means that we should mark all outstanding DATA chunks for *  retransmission and start a retransmission cycle. */static void sctp_retrans_timeout(data)	caddr_t data;{	mblk_t *mp;	sctp_t *sp;	sctp_daddr_t *sd;	int retransmits = 0;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sd->timer_retrans = timeout(sctp_retrans_timeout, (caddr_t)sd, 1);		return;	}	sd->timer_retrans = 0;	if ( !((1<<sp->s_state) & (SCTPF_CONNECTED)) ) { rare();		return;	}	if ( sctp_assoc_timedout(sp, sd, sp->max_retrans) ) { seldom();		return;	}	/* See RFC 2960 6.3.3 E3 */	for ( mp = bufq_head(&sp->rtxq); mp; mp = mp->b_next )	{		sctp_tcb_t *cb = SCTP_TCB(mp);		size_t dlen = cb->dlen;		if ( cb->daddr == sd				&& (cb->flags & SCTPCB_FLAG_SENT)				&& !(cb->flags & SCTPCB_FLAG_RETRANS)				&& !(cb->flags & SCTPCB_FLAG_SACKED) )		{			cb->flags |= SCTPCB_FLAG_RETRANS;			sp->nrtxs++;			cb->sacks = 0;			normal( sd->in_flight >= dlen );			normal( sp->in_flight >= dlen );			sd->in_flight = sd->in_flight > dlen ? sd->in_flight - dlen : 0; /* credit dest  */			sp->in_flight = sp->in_flight > dlen ? sp->in_flight - dlen : 0; /* credit assoc */			retransmits++;		}	}	normal(retransmits);	sctp_transmit_wakeup(sp);	return;}/* *  SACK TIMEOUT *  ------------------------------------------------------------------------- *  This timer is the 200ms timer which ensures that a SACK is sent within *  200ms of the receipt of an unacknoweldged DATA chunk.  When an *  unacknowledged DATA chunks i receive and the timer is not running, the *  timer is set.  Whenever a DATA chunks(s) are acknowledged, the timer is *  stopped. */static void sctp_sack_timeout(data)	caddr_t data;{	sctp_t *sp;	sp = (sctp_t *)data;	assert( sp );	if ( sctp_locked(sp) ) { seldom();		sp->timer_sack = timeout(sctp_sack_timeout, (caddr_t)sp, 1);		return;	}	sp->timer_sack = 0;	if ( !((1<<sp->s_state) & (SCTPF_RECEIVING)) ) { rare();		return;	}	sp->sackf |= SCTP_SACKF_TIM; /* RFC 2960 6.2 */	sctp_transmit_wakeup(sp);	return;}/* *  IDLE TIMEOUT *  ------------------------------------------------------------------------- *  This means that a destination has been idle for longer than the hb.itvl or *  the interval for which we must send heartbeats.  This timer is reset every *  time we do an RTT calculation for a destination.  It is stopped while *  sending heartbeats and started again whenever an RTT calculation is done. *  While this timer is stopped, heartbeats will be sent until they are *  acknowledged. */static void sctp_idle_timeout(data)	caddr_t data;{	sctp_t *sp;	sctp_daddr_t *sd;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sd->timer_idle = timeout(&sctp_idle_timeout, (caddr_t)sd, 1);		return;	}	sd->timer_idle = 0;	if ( !((1<<sp->s_state) & (SCTPF_CONNECTED|SCTPF_CLOSING)) ) { rare();		return;	}	sctp_send_heartbeat(sp, sd);	return;}/* *  HEARTBEAT TIMEOUT *  ------------------------------------------------------------------------- *  If we get a heartbeat timeout we adjust RTO the same as we do for *  retransmit (and the congestion window) and resend the heartbeat.  Once we *  have sent Path.Max.Retrans heartbeats unsuccessfully, we mark the *  destination as unusable, but continue heartbeating until they get *  acknowledged.  (Well!  That's not really true, is it?) */static void sctp_heartbeat_timeout(data)	caddr_t data;{	sctp_t *sp;	sctp_daddr_t *sd;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sd->timer_heartbeat = timeout(sctp_heartbeat_timeout, (caddr_t)sd, 1);		return;	}	sd->timer_heartbeat = 0;	if ( !((1<<sp->s_state) & (SCTPF_CONNECTED|SCTPF_CLOSING)) )  { rare();		return;	}	if ( sctp_assoc_timedout(sp, sd, 0) ) { seldom();		return;	}	sctp_send_heartbeat(sp, sd);	return;}/* *  SHUTDOWN TIMEOUT *  ------------------------------------------------------------------------- *  This means that we have timedout on sending a SHUTDOWN or a SHUTDOWN ACK *  message.  We simply resend the message. */static void sctp_shutdown_timeout(data)	caddr_t data;{	sctp_t *sp;	sctp_daddr_t *sd;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sp->timer_shutdown = timeout(sctp_shutdown_timeout, (caddr_t)sd, 1);		return;	}	sp->timer_shutdown = 0;	if ( !((1<<sp->s_state) & (SCTPF_CLOSING)) ) { rare();		return;	}	if ( sctp_assoc_timedout(sp, sd, sp->max_retrans) ) { seldom();		return;	}	sd = sp->taddr;	ensure( sd, return );	set_timeout(&sp->timer_shutdown, sctp_shutdown_timeout, (caddr_t)sd, sd->rto);	usual(sp->retry);	sctp_send_msg(sp, sd, sp->retry);	return;}/* *  SEND DATA *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  This function slaps a chunk header onto the M_DATA blocks which form the *  data and places it onto the stream's write queue.  The message blocks *  input to this function already have a chunk control block prepended. */static int sctp_send_data(sp, st, flags, dp)	sctp_t *sp;	sctp_strm_t *st;	ulong flags;	mblk_t *dp;{	uint *more;	mblk_t **head;	uint32_t ppi;	size_t mlen, dlen;	ulong dflags = flags;	uint urg  = (dflags & SCTPCB_FLAG_URG);	assert(sp);	assert(st);	assert(dp);	if ( urg ) { more = &st->x.more; head = &st->x.head; ppi = st->x.ppi; }	else	   { more = &st->n.more; head = &st->n.head; ppi = st->n.ppi; }	for ( mlen = msgdsize(dp); mlen; mlen -= dlen, dflags &= ~SCTPCB_FLAG_FIRST_FRAG )	{		mblk_t *bp;		struct sctp_daddr *sd;		if ( !(sd = sctp_route_normal(sp)) )			return(-EHOSTUNREACH);/* *  If there is not enough room in the current send window to handle all or at *  least 1/2 MTU of the data and the current send backlog then return (-EBUSY) *  and put the message back on the queue so that backpressure will result.  We *  only do this separately for normal data and urgent data (urgent data will be *  expedited ahead of even retransmissions). */	{		size_t cwnd, rwnd, swnd, awnd, plen, amps, dmps, used;		plen = PADC(sizeof(struct sctp_data) + mlen);		amps = sp->pmtu - sizeof(struct iphdr) - sizeof(struct sctphdr);		dmps = sd->mtu  - sizeof(struct iphdr) - sizeof(struct sctphdr);		used = urg ? sp->urgq.q_count : sp->sndq.q_count;		cwnd = sd->cwnd + dmps;		cwnd = cwnd > sd->in_flight ? cwnd - sd->in_flight : 0;		rwnd = sp->p_rwnd;		rwnd = rwnd > sp->in_flight ? rwnd - sp->in_flight : 0;		swnd = cwnd < rwnd ? cwnd : rwnd;		awnd = sp->in_flight ? swnd : cwnd;		awnd = awnd > used ? awnd - used : 0;		if ( plen > awnd || plen > amps ) {		if ( plen > amps && awnd >= amps>>1 ) {		if ( (bp = dupmsg(dp)) ) {			dlen = awnd < amps ? amps>>1 : amps;			ensure( dlen > sizeof(struct sctp_data), freemsg(bp); return(-EFAULT) );			dlen -= sizeof(struct sctp_data);			ensure( dlen < mlen, freemsg(bp); return(-EFAULT) );#if 1			{				int ret;				ret = trimhead(dp, dlen);   /* trim original */				unless( ret, freemsg(bp); return(-EFAULT) );				ret = trimtail(bp, dlen);   /* trim fragment */				unless( ret, freemsg(bp); return(-EFAULT) );			}#else			fixme(("Should consider multiple mblks\n"));			dp->b_rptr = dp->b_rptr + dlen; /* trim original */			bp->b_wptr = bp->b_rptr + dlen; /* trim fragment */#endif			dflags &= ~SCTPCB_FLAG_LAST_FRAG;		} else { rare(); return(-ENOBUFS);  }		} else { rare(); return(-EBUSY);    }		} else {			bp = dp; dlen = mlen;	/* use entire */			dflags |= flags & SCTPCB_FLAG_LAST_FRAG;			/*			 *  If we have an existing SDU being built that hasn't			 *  been transmitted yet, we just tack data onto it.  We			 *  concatenate only to an MTU.			 */			if ( *more && *head && plen + SCTP_TCB(*head)->dlen <= amps )			{				struct sctp_data *m;				sctp_tcb_t *cb = SCTP_TCB(*head);				cb->flags   |= (dflags & 0x7);				cb->dlen    += dlen;				m = (struct sctp_data *)(*head)->b_rptr;				m->ch.flags = cb->flags & 0x7;				m->ch.len   = htons( sizeof(*m)+cb->dlen );				linkb(*head, bp);				normal( cb->dlen == msgdsize((*head)->b_cont) );				if ( dflags & SCTPCB_FLAG_LAST_FRAG ) {					*head = NULL; *more = 0;				}				return(0);			}		}	}	{		mblk_t *mp;		sctp_tcb_t *cb;		struct sctp_data *m;		if ( (mp = allocb(sizeof(*cb)+sizeof(*m), BPRI_MED)) )		{			mp->b_datap->db_type = M_DATA;			cb = (sctp_tcb_t *)mp->b_wptr;			bzero(cb, sizeof(*cb));			cb->mp		= mp;			cb->dlen	= dlen;			cb->flags	= dflags;			cb->st		= st;			cb->when	= jiffies;			cb->daddr	= NULL;	    /* set when transmitted */			cb->ppi		= ppi;			cb->sid		= st->sid;			cb->ssn		= urg ? 0 : st->ssn;			mp->b_rptr += sizeof(*cb);  /* hide control block */			mp->b_wptr += sizeof(*cb);			m = (struct sctp_data *)mp->b_wptr;			m->ch.type  = SCTP_CTYPE_DATA;			m->ch.flags = dflags;			m->ch.len   = htons( sizeof(*m)+dlen );			m->tsn	    = 0;	    /* assign before transmission */			m->sid	    = htons( cb->sid );			m->ssn	    = htons( cb->ssn );			m->ppi	    = htonl( cb->ppi );			mp->b_wptr += sizeof(*m);			mp->b_cont = bp;			normal( cb->dlen == msgdsize(mp->b_cont) );			/*			 *  Remember where we can add more data in case data			 *  completing a SDU comes before we are forced to bundle the			 *  DATA.			 */			*more = (dflags & SCTPCB_FLAG_LAST_FRAG) ? 0    : 1 ;			*head = (dflags & SCTPCB_FLAG_LAST_FRAG) ? NULL : mp;			if ( urg ) {				bufq_queue(&sp->urgq, mp);			} else {				if ( dflags & SCTPCB_FLAG_LAST_FRAG )					st->ssn = (st->ssn+1)&0xffff;				bufq_queue(&sp->sndq, mp);			}		} else { rare(); return(-ENOBUFS); }	}	}	return(0);}/* *  SEND SACK *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */static void sctp_send_sack(sp)	sctp_t *sp;{	sp->sackf |= SCTP_SACKF_NOD;}/* *  SEND ERROR *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  We just queue the error, we don't send it out...  It gets bundled with *  other things. */static int sctp_send_error(sp, ecode, eptr, elen)	sctp_t *sp;	uint ecode;	caddr_t eptr;	size_t elen;{	mblk_t *mp;	sctp_tcb_t *cb;	struct sctp_error *m;	struct sctpehdr *eh;	size_t clen = sizeof(*m)+sizeof(*eh)+elen;	size_t plen = PADC(clen);	assert(sp);	if ( (mp = allocb(sizeof(*cb)+plen, BPRI_MED)) )	{		mp->b_datap->db_type = M_DATA;		cb = (sctp_tcb_t *)mp->b_wptr;		bzero(cb, sizeof(*cb));		cb->mp	    = mp;		mp->b_rptr += sizeof(*cb);  /* hide control block */		mp->b_wptr  = mp->b_rptr;		bzero(mp->b_wptr+clen,plen-clen);			m = (struct sctp_error *)mp->b_wptr;		m->ch.type  = SCTP_CTYPE_ERROR;		m->ch.flags = 0;		m->ch.len   = htons(clen);		eh = (struct sctpehdr *)(m+1);		eh->code    = htons(ecode);		eh->len	    = htons(sizeof(*eh)+elen);		bcopy(eptr, (eh+1), elen);		mp->b_wptr += plen;		bufq_queue(&sp->errq, mp);		return(0);	}	rare(); return(-ENOBUFS);}/* *  SEND INIT *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  If we fail to launch the INIT and get timers started, we must return an *  error to the user interface calling this function. */static int sctp_send_init(sp)	sctp_t *sp;{	sctp_daddr_t *sd;		assert(sp);	if ( (sd = sp->daddr) )	{		mblk_t *mp;		struct sctp_init *m;		struct sctp_addr_type *at;		struct sctp_ipv4_addr *ap;		struct sctp_cookie_psrv *cp;		size_t sanum = sp->sanum;		size_t clen = sizeof(*m)			+ ( sanum * PADC(sizeof(*ap)) )			+ ( sp->ck_inc ? PADC(sizeof(*cp)) : 0 )			+ ( sizeof(*at) + sizeof(at->type[0]) );				if ( (mp = sctp_alloc_msg(sp, clen)) )		{			sctp_saddr_t *ss;			m = (struct sctp_init *)mp->b_wptr;			m->ch.type  = SCTP_CTYPE_INIT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -