示例#1
0
/*! 
 * This function initializes a given table of symbol.
 *
 * \param table A pointer to a symbol table or NULL.
 * \return A pointer to the initialized symbol table
 */
kb_symbol_table_t * kb_create_symbol_table( kb_symbol_table_t * table )
{
  unsigned int index;

  if ( table == NULL ) 
    table = KB_ALLOC(kb_symbol_table_t,1);
 
  (void)pthread_mutex_init( &table->lock , 0 );
  table->count = 0;

  for (index=0; index<KB_SYMBOL_TABLE_SIZE; index++) {
    table->symbols[index] = NULL;
  }
  
  return table;
}
示例#2
0
/*
 * SD PDU / SOS_READY Processor
 *
 * Arguments:
 *	sop	pointer to sscop connection block
 *	m	pointer to PDU buffer (without trailer)
 *	trlr	pointer to PDU trailer
 *
 * Returns:
 *	none
 *
 */
static void
sscop_sd_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
{
	struct sd_pdu	*sp = (struct sd_pdu *)trlr;
	struct pdu_hdr	*php;
	KBuffer		*n;
	sscop_seq	ns;
	int		err, space;

	/*
	 * Get PDU sequence number
	 */
	SEQ_SET(ns, ntohl(sp->sd_ns));

	/*
	 * Ensure that the sequence number fits within the window
	 */
	if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
		/*
		 * It doesn't, drop received data
		 */
		KB_FREEALL(m);

		/*
		 * If next highest PDU hasn't reached window end yet,
		 * then send a USTAT to inform transmitter of this gap
		 */
		if (SEQ_LT(sop->so_rcvhigh, sop->so_rcvmax, sop->so_rcvnext)) { 
			sscop_send_ustat(sop, sop->so_rcvmax);
			sop->so_rcvhigh = sop->so_rcvmax;
		}
		return;
	}

	/*
	 * If this is the next in-sequence PDU, hand it to user
	 */
	if (ns == sop->so_rcvnext) {
		STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
			sop->so_connvc, (int)m, ns, err);
		if (err) {
			KB_FREEALL(m);
			return;
		}

		/*
		 * Bump next expected sequence number
		 */
		SEQ_INCR(sop->so_rcvnext, 1);

		/*
		 * Slide receive window down
		 */
		SEQ_INCR(sop->so_rcvmax, 1);

		/*
		 * Is this the highest sequence PDU we've received??
		 */
		if (ns == sop->so_rcvhigh) {
			/*
			 * Yes, bump the limit and exit
			 */
			sop->so_rcvhigh = sop->so_rcvnext;
			return;
		}

		/*
		 * This is a retransmitted PDU, so see if we have
		 * more in-sequence PDUs already queued up
		 */
		while ((php = sop->so_recv_hd) &&
		       (php->ph_ns == sop->so_rcvnext)) {

			/*
			 * Yup we do, so remove next PDU from queue and
			 * pass it up to the user as well
			 */
			sop->so_recv_hd = php->ph_recv_lk;
			if (sop->so_recv_hd == NULL)
				sop->so_recv_tl = NULL;
			STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
				sop->so_connvc, (int)php->ph_buf, php->ph_ns,
				err);
			if (err) {
				/*
				 * Should never happen, but...
				 */
				KB_FREEALL(php->ph_buf);
				sscop_abort(sop, "stack memory\n");
				return;
			}

			/*
			 * Bump next expected sequence number
			 */
			SEQ_INCR(sop->so_rcvnext, 1);

			/*
			 * Slide receive window down
			 */
			SEQ_INCR(sop->so_rcvmax, 1);
		}

		/*
		 * Finished with data delivery...
		 */
		return;
	}

	/*
	 * We're gonna have to queue this PDU, so find space
	 * for the PDU header
	 */
	KB_HEADROOM(m, space);

	/*
	 * If there's not enough room in the received buffer,
	 * allocate & link a new buffer for the header
	 */
	if (space < sizeof(struct pdu_hdr)) {

		KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
		if (n == NULL) {
			KB_FREEALL(m);
			return;
		}
		KB_HEADSET(n, sizeof(struct pdu_hdr));
		KB_LEN(n) = 0;
		KB_LINKHEAD(n, m);
		m = n;
	}

	/*
	 * Build PDU header
	 *
	 * We can at least assume/require that the start of
	 * the user data is aligned.  Also note that we don't
	 * include this header in the buffer len/offset fields.
	 */
	KB_DATASTART(m, php, struct pdu_hdr *);
	php--;
	php->ph_ns = ns;
	php->ph_buf = m;

	/*
	 * Insert PDU into the receive queue
	 */
	if (sscop_recv_insert(sop, php)) {
		/*
		 * Oops, a duplicate sequence number PDU is already on
		 * the queue, somethings wrong here.
		 */
		sscop_maa_error(sop, 'Q');

		/*
		 * Free buffers
		 */
		KB_FREEALL(m);

		/*
		 * Go into recovery mode
		 */
		q2110_error_recovery(sop);

		return;
	}

	/*
	 * Are we at the high-water mark??
	 */
	if (ns == sop->so_rcvhigh) {
		/*
		 * Yes, just bump the mark
		 */
		SEQ_INCR(sop->so_rcvhigh, 1);

		return;
	}

	/*
	 * Are we beyond the high-water mark??
	 */
	if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
		/*
		 * Yes, then there's a missing PDU, so inform the transmitter
		 */
		sscop_send_ustat(sop, ns);

		/*
		 * Update high-water mark
		 */
		sop->so_rcvhigh = SEQ_ADD(ns, 1);
	}

	return;
}
示例#3
0
/*
 * Get or put the next byte of a signalling message
 *
 * Arguments:
 *	usf	pointer to a unisig formatting structure
 *	c	pointer to the byte to send from or receive into
 *
 * Returns:
 *	0	success
 *	errno	error encountered
 *
 */
int
usf_byte(struct usfmt *usf, u_char *c)
{
	u_char		*mp;
	KBuffer		*m = usf->usf_m_addr, *m1;
	int		space;

	switch (usf->usf_op) {

	case USF_DECODE:
		/*
		 * Make sure we're not past the end of the buffer
		 * (allowing for zero-length buffers)
		 */
		while (usf->usf_loc >= KB_LEN(m)) {
			if (KB_NEXT(usf->usf_m_addr)) {
				usf->usf_m_addr = m = KB_NEXT(usf->usf_m_addr);
				usf->usf_loc = 0;
			} else {
				return(EMSGSIZE);
			}
		}

		/*
		 * Get the data from the buffer
		 */
		KB_DATASTART(m, mp, u_char *);
		*c = mp[usf->usf_loc];
		usf->usf_loc++;
		break;

	case USF_ENCODE:
		/*
		 * If the current buffer is full, get another
		 */
		KB_TAILROOM(m, space);
		if (space == 0) {
			KB_ALLOC(m1, USF_MIN_ALLOC, KB_F_NOWAIT, KB_T_DATA);
			if (m1 == NULL)
				return(ENOMEM);
			KB_LEN(m1) = 0;
			KB_LINK(m1, m);
			usf->usf_m_addr = m = m1;
			usf->usf_loc = 0;
		}

		/*
		 * Put the data into the buffer
		 */
		KB_DATASTART(m, mp, u_char *);
		mp[usf->usf_loc] = *c;
		KB_TAILADJ(m, 1);
		usf->usf_loc++;
		break;

	default:
		/*
		 * Invalid operation code
		 */
		return(EINVAL);
	}

	return(0);

}