channel_*

v0.5.xx
Alexander Vdolainen 9 years ago
parent b76c7610c5
commit 2868ee8f95

@ -100,3 +100,152 @@ uint8_t _channel_close(conn_t *co, uint16_t chid)
return SNE_SUCCESS;
}
chnl_t *sxchannel_open(conn_t *co, int type)
{
chnl_t *chan = NULL;
sxmsg_t *msg = NULL;
sntllv2_head_t *head;
int msgidx, r;
if(!co) {
r = SNE_FAILED;
goto __reterr;
}
if(!(chan = malloc(sizeof(chnl_t)))) {
__enomem:
r = SNE_ENOMEM;
goto __reterr;
}
if(!(msg = malloc(sizeof(sxmsg_t)))) goto __enomem;
/* early init for the channel */
chan->connection = co;
chan->flags = 0;
/* early init for the message */
pthread_mutex_init(&msg->wait, NULL);
pthread_mutex_lock(&msg->wait);
msg->pch = chan;
msg->payload = NULL;
memset(&msg->mhead, 0, sizeof(sntllv2_head_t));
head = &msg->mhead;
/* form a header */
head->attr = SXMSG_PROTO | SXMSG_REPLYREQ | SXMSG_OPEN;
head->payload_length = 0;
head->reserve = (uint16_t)type;
/* try to alloc a message */
pthread_mutex_lock(&co->idx_msg_lock);
msgidx = idx_allocate(&co->idx_msg);
if(msgidx != IDX_INVAL) co->messages[msgidx] = msg;
pthread_mutex_unlock(&co->idx_msg_lock);
if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; }
/* now we're ready to write it */
r = _sntll_writemsg(co, msg);
if(r == SNE_SUCCESS) pthread_mutex_lock(&msg->wait);
else goto __reterr3;
/* we will wakeup on return */
if(msg->mhead.opcode != SNE_SUCCESS) { r = msg->mhead.opcode; goto __reterr3; }
/* ok all is fine */
chan->cid = msg->mhead.reserve;
pthread_mutex_lock(&co->idx_ch_lock);
idx_reserve(&co->idx_ch, msg->mhead.reserve);
co->channels[msg->mhead.reserve] = chan;
pthread_mutex_unlock(&co->idx_ch_lock);
/* destroy a message */
pthread_mutex_lock(&co->idx_msg_lock);
idx_free(&co->idx_msg, msgidx);
co->messages[msgidx] = NULL;
pthread_mutex_unlock(&co->idx_msg_lock);
/* free allocated resources */
pthread_mutex_unlock(&msg->wait);
pthread_mutex_destroy(&msg->wait);
free(msg);
return chan;
__reterr3:
pthread_mutex_lock(&co->idx_msg_lock);
idx_free(&co->idx_msg, msgidx);
co->messages[msgidx] = NULL;
pthread_mutex_unlock(&co->idx_msg_lock);
__reterr2:
pthread_mutex_unlock(&msg->wait);
pthread_mutex_destroy(&msg->wait);
__reterr:
if(chan) free(chan);
if(msg) free(msg);
errno = r;
return NULL;
}
int sxchannel_close(chnl_t *channel)
{
int r = SNE_SUCCESS;
sxmsg_t *msg;
sntllv2_head_t *head;
conn_t *co;
int msgidx;
/* check channel validity */
if(!channel) return SNE_FAILED;
else if(!(co = channel->connection)) return SNE_FAILED;
if(channel->cid > 512) return SNE_IGNORED;
if(channel != co->channels[channel->cid]) return SNE_IGNORED;
if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM;
head = &msg->mhead;
memset(head, 0, sizeof(sntllv2_head_t));
/* setup head */
head->attr = SXMSG_PROTO | SXMSG_REPLYREQ; /* close channel */
head->reserve = channel->cid;
/* setup message */
pthread_mutex_init(&msg->wait, NULL);
pthread_mutex_lock(&msg->wait);
msg->pch = channel;
/* allocate it */
pthread_mutex_lock(&co->idx_msg_lock);
msgidx = idx_allocate(&co->idx_msg);
if(msgidx != IDX_INVAL) co->messages[msgidx] = msg;
pthread_mutex_unlock(&co->idx_msg_lock);
if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; }
r = _sntll_writemsg(co, msg);
if(r == SNE_SUCCESS) {
pthread_mutex_lock(&msg->wait);
r = head->opcode;
/* we will free this anyway */
pthread_mutex_lock(&co->idx_ch_lock);
idx_free(&co->idx_ch, channel->cid);
co->channels[channel->cid] = NULL;
pthread_mutex_unlock(&co->idx_ch_lock);
free(channel);
}
pthread_mutex_lock(&co->idx_msg_lock);
idx_free(&co->idx_msg, msgidx);
co->messages[msgidx] = NULL;
pthread_mutex_unlock(&co->idx_msg_lock);
__reterr2:
pthread_mutex_unlock(&msg->wait);
pthread_mutex_destroy(&msg->wait);
free(msg);
return r;
}

Loading…
Cancel
Save