#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <scsi/iscsi.h>
#include <errno.h>
#include <event.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include "iscsid.h"
#include "log.h"
void
task_init(struct task *t, struct session *s, int immediate, void *carg,
void (*c)(struct connection *, void *, struct pdu *),
void (*f)(void *))
{
TAILQ_INIT(&t->sendq);
TAILQ_INIT(&t->recvq);
t->callback = c;
t->failback = f;
t->callarg = carg;
if (s->itt == 0xffffffff || s->itt == 0)
s->itt = 1;
t->itt = s->itt++;
t->cmdseqnum = s->cmdseqnum;
if (!immediate)
s->cmdseqnum++;
}
void
taskq_cleanup(struct taskq *tq)
{
struct task *t;
while ((t = TAILQ_FIRST(tq))) {
TAILQ_REMOVE(tq, t, entry);
if (t->failback)
t->failback(t->callarg);
conn_task_cleanup(NULL, t);
free(t);
}
}
void
task_pdu_add(struct task *t, struct pdu *p)
{
struct iscsi_pdu *ipdu;
ipdu = pdu_getbuf(p, NULL, PDU_HEADER);
ipdu->itt = ntohl(t->itt);
switch (ISCSI_PDU_OPCODE(ipdu->opcode)) {
case ISCSI_OP_I_NOP:
case ISCSI_OP_SCSI_REQUEST:
case ISCSI_OP_TASK_REQUEST:
case ISCSI_OP_LOGIN_REQUEST:
case ISCSI_OP_TEXT_REQUEST:
case ISCSI_OP_LOGOUT_REQUEST:
ipdu->cmdsn = ntohl(t->cmdseqnum);
break;
}
TAILQ_INSERT_TAIL(&t->sendq, p, entry);
}
void
task_pdu_cb(struct connection *c, struct pdu *p)
{
struct task *t;
struct iscsi_pdu *ipdu;
u_int32_t itt;
ipdu = pdu_getbuf(p, NULL, PDU_HEADER);
switch (ISCSI_PDU_OPCODE(ipdu->opcode)) {
case ISCSI_OP_T_NOP:
itt = ntohl(ipdu->itt);
if (itt == 0xffffffff) {
c->expstatsn = ntohl(ipdu->cmdsn) + 1;
initiator_nop_in_imm(c, p);
break;
}
case ISCSI_OP_LOGIN_RESPONSE:
case ISCSI_OP_TEXT_RESPONSE:
case ISCSI_OP_LOGOUT_RESPONSE:
case ISCSI_OP_SCSI_RESPONSE:
case ISCSI_OP_R2T:
case ISCSI_OP_DATA_IN:
itt = ntohl(ipdu->itt);
c->expstatsn = ntohl(ipdu->cmdsn) + 1;
TAILQ_FOREACH(t, &c->tasks, entry) {
if (itt == t->itt)
break;
}
if (t)
t->callback(c, t->callarg, p);
else {
log_debug("no task for PDU found");
log_pdu(p, 1);
pdu_free(p);
}
break;
default:
log_warnx("not handled yet. fix me");
log_pdu(p, 1);
pdu_free(p);
}
}