/*! * 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; }
/* * 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; }
/* * 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); }