void *abcsp_malloc(uint16 n) { void *ret = ABCSP_MALLOC(n); /* Moan if the pool has run dry. */ if(ret == (void*)(NULL)) ABCSP_EVENT(ABCSP_EVT_MALLOC); return(ret); }
unsigned abcsp_sendmsg(ABCSP_TXMSG *msg, unsigned chan, unsigned rel) { TXMSG *m; /* Reject all traffic if the choke is applied. BCSP-LE messages are transmitted from code below this entry point. The choke should be applied at the "mux" layer. Applying it here means that if the choke is turned on while messages are queued for transmission then those messages will drain out. This is strictly incorrect, but this won't harm any real system as the choke is only set TRUE by abcsp library init, so any peer is going to see disrupted traffic for a while anyway. (Ideally, bcsp-le messages from here will tell the peer that we've restarted, so it should reinit and rechoke.) */ if(abcsp_txrx.choke) { ABCSP_EVENT(ABCSP_EVT_TX_CHOKE_DISCARD); return(0); } /* Parameter sanity checks. */ if(rel > 1 || chan < 2 || chan > 15 || msg == (ABCSP_TXMSG*)(NULL)) return(0); /* We queue enough reliable messages to fill the WINSIZE window. */ if(rel && msgq_len(relq) >= ABCSP_TXWINSIZE) { ABCSP_EVENT(ABCSP_EVT_TX_WINDOW_FULL_DISCARD); return(0); } /* Package the message. */ if((m = ZNEW(TXMSG)) == (TXMSG*)(NULL)) return(0); m->m = msg; m->chan = chan; if(rel) { /* We've already checked the reliable queue has room. */ m->seq = msgq_txseq; msgq_txseq = incrmod8(msgq_txseq); msgq_add(&relq, m); } else { /* The unreliable channel is biased towards supporting sco, for which the data has to be fresh. The queue holds only one message, so we displace any message that's already in the queue. */ (void) msgq_pop_destroy(&unrelq); msgq_add(&unrelq, m); } /* Tell external code that it needs to call abcsp_pumptxmsgs(). */ ABCSP_REQ_PUMPTXMSGS(); /* Report message accepted. */ return(1); }
static void abcsp_lm_fsm(abcsp *_this, lemsgid msg) { switch(_this->le.state) { case state_shy: switch(msg) { case lemsgid_tshy_timeout: if (!_this->txrx.bcsple_muzzled) req_bcsple_msg(_this, lemsgid_sync); ABCSP_START_TSHY_TIMER(_this); break; case lemsgid_sync: _this->txrx.bcsple_muzzled = FALSE; req_bcsple_msg(_this, lemsgid_sync_resp); break; case lemsgid_sync_resp: ABCSP_EVENT(_this, ABCSP_EVT_LE_SYNC); #ifdef ABCSP_USE_OLD_BCSP_LE _this->txrx.choke = FALSE; _this->le.conf_cnt = 0; #else req_bcsple_msg(_this, lemsgid_conf); #endif ABCSP_START_TCONF_TIMER(_this); _this->le.state = state_curious; break; default: break; } break; case state_curious: switch(msg) { case lemsgid_tconf_timeout: #ifdef ABCSP_USE_OLD_BCSP_LE if(_this->le.conf_cnt < ABCSP_USE_BCSP_LE_CONF_CNT_LIMIT) { ++_this->le.conf_cnt; req_bcsple_msg(_this, lemsgid_conf); ABCSP_START_TCONF_TIMER(_this); } #else req_bcsple_msg(_this, lemsgid_conf); ABCSP_START_TCONF_TIMER(_this); #endif break; case lemsgid_sync: req_bcsple_msg(_this, lemsgid_sync_resp); break; case lemsgid_conf: req_bcsple_msg(_this, lemsgid_conf_resp); break; case lemsgid_conf_resp: ABCSP_EVENT(_this, ABCSP_EVT_LE_CONF); #ifndef ABCSP_USE_OLD_BCSP_LE _this->txrx.choke = FALSE; #endif _this->le.state = state_garrulous; break; default: break; } break; case state_garrulous: switch(msg) { case lemsgid_conf: req_bcsple_msg(_this, lemsgid_conf_resp); break; case lemsgid_sync: /* Peer has apparently restarted. */ ABCSP_EVENT(_this, ABCSP_EVT_LE_SYNC_LOST); /* HERE Re-do the link establishment */ abcsp_bcsple_init(_this); break; default: break; } break; default: break; } }