Input processing:
Input processing used to keep all data in one single input buffer, which makes it hard to handle nested events as well as reading directly from the socket into the application buffer without an extra copy. Create a new iscsi_in_pdu structure where we store the header, and any data for the recevied pdu and store them in a proper input queue. Change the signature for all processing functions to tahe a iscsi_in_pdu structure for the received pdu instead of just a pointer to a buffer.
This commit is contained in:
@@ -21,6 +21,25 @@
|
||||
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
|
||||
#endif
|
||||
|
||||
#define ISCSI_RAW_HEADER_SIZE 48
|
||||
#define ISCSI_DIGEST_SIZE 4
|
||||
|
||||
#define ISCSI_HEADER_SIZE (ISCSI_RAW_HEADER_SIZE \
|
||||
+ (iscsi->header_digest == ISCSI_HEADER_DIGEST_NONE?0:ISCSI_DIGEST_SIZE))
|
||||
|
||||
|
||||
struct iscsi_in_pdu {
|
||||
struct iscsi_in_pdu *next;
|
||||
|
||||
long long hdr_pos;
|
||||
unsigned char hdr[ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE];
|
||||
|
||||
long long data_pos;
|
||||
unsigned char *data;
|
||||
};
|
||||
void iscsi_free_iscsi_in_pdu(struct iscsi_in_pdu *in);
|
||||
void iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue);
|
||||
|
||||
struct iscsi_context {
|
||||
const char *initiator_name;
|
||||
const char *target_name;
|
||||
@@ -45,16 +64,10 @@ struct iscsi_context {
|
||||
struct iscsi_pdu *outqueue;
|
||||
struct iscsi_pdu *waitpdu;
|
||||
|
||||
int insize;
|
||||
int inpos;
|
||||
unsigned char *inbuf;
|
||||
struct iscsi_in_pdu *incoming;
|
||||
struct iscsi_in_pdu *inqueue;
|
||||
};
|
||||
|
||||
#define ISCSI_RAW_HEADER_SIZE 48
|
||||
|
||||
#define ISCSI_HEADER_SIZE (ISCSI_RAW_HEADER_SIZE \
|
||||
+ (iscsi->header_digest == ISCSI_HEADER_DIGEST_NONE?0:4))
|
||||
|
||||
#define ISCSI_PDU_IMMEDIATE 0x40
|
||||
|
||||
#define ISCSI_PDU_TEXT_FINAL 0x80
|
||||
@@ -139,29 +152,28 @@ int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
|
||||
struct scsi_task;
|
||||
void iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task);
|
||||
|
||||
int iscsi_get_pdu_size(struct iscsi_context *iscsi, const unsigned char *hdr);
|
||||
int iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
int size);
|
||||
int iscsi_get_pdu_data_size(const unsigned char *hdr);
|
||||
int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in);
|
||||
|
||||
int iscsi_process_login_reply(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size);
|
||||
struct iscsi_in_pdu *in);
|
||||
int iscsi_process_text_reply(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size);
|
||||
struct iscsi_in_pdu *in);
|
||||
int iscsi_process_logout_reply(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size);
|
||||
struct iscsi_in_pdu *in);
|
||||
int iscsi_process_scsi_reply(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size);
|
||||
struct iscsi_in_pdu *in);
|
||||
int iscsi_process_scsi_data_in(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size,
|
||||
struct iscsi_in_pdu *in,
|
||||
int *is_finished);
|
||||
int iscsi_process_nop_out_reply(struct iscsi_context *iscsi,
|
||||
struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size);
|
||||
struct iscsi_in_pdu *in);
|
||||
|
||||
void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string,
|
||||
...);
|
||||
|
||||
@@ -94,27 +94,25 @@ iscsi_free_discovery_addresses(struct iscsi_discovery_address *addresses)
|
||||
|
||||
int
|
||||
iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size)
|
||||
struct iscsi_in_pdu *in)
|
||||
{
|
||||
struct iscsi_discovery_address *targets = NULL;
|
||||
unsigned char *ptr = in->data;
|
||||
int size = in->data_pos;
|
||||
|
||||
/* verify the response looks sane */
|
||||
if (hdr[1] != ISCSI_PDU_TEXT_FINAL) {
|
||||
if (in->hdr[1] != ISCSI_PDU_TEXT_FINAL) {
|
||||
iscsi_set_error(iscsi, "unsupported flags in text "
|
||||
"reply %02x", hdr[1]);
|
||||
"reply %02x", in->hdr[1]);
|
||||
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
|
||||
pdu->private_data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* skip past the header */
|
||||
hdr += ISCSI_HEADER_SIZE;
|
||||
size -= ISCSI_HEADER_SIZE;
|
||||
|
||||
while (size > 0) {
|
||||
int len;
|
||||
|
||||
len = strlen((char *)hdr);
|
||||
len = strlen((char *)ptr);
|
||||
|
||||
if (len == 0) {
|
||||
break;
|
||||
@@ -130,7 +128,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
|
||||
/* parse the strings */
|
||||
if (!strncmp((char *)hdr, "TargetName=", 11)) {
|
||||
if (!strncmp((char *)ptr, "TargetName=", 11)) {
|
||||
struct iscsi_discovery_address *target;
|
||||
|
||||
target = malloc(sizeof(struct iscsi_discovery_address));
|
||||
@@ -144,7 +142,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
return -1;
|
||||
}
|
||||
bzero(target, sizeof(struct iscsi_discovery_address));
|
||||
target->target_name = strdup((char *)hdr+11);
|
||||
target->target_name = strdup((char *)ptr+11);
|
||||
if (target->target_name == NULL) {
|
||||
iscsi_set_error(iscsi, "Failed to allocate "
|
||||
"data for new discovered "
|
||||
@@ -158,8 +156,8 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
target->next = targets;
|
||||
targets = target;
|
||||
} else if (!strncmp((char *)hdr, "TargetAddress=", 14)) {
|
||||
targets->target_address = strdup((char *)hdr+14);
|
||||
} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
|
||||
targets->target_address = strdup((char *)ptr+14);
|
||||
if (targets->target_address == NULL) {
|
||||
iscsi_set_error(iscsi, "Failed to allocate "
|
||||
"data for new discovered "
|
||||
@@ -171,14 +169,14 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
} else {
|
||||
iscsi_set_error(iscsi, "Dont know how to handle "
|
||||
"discovery string : %s", hdr);
|
||||
"discovery string : %s", ptr);
|
||||
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
|
||||
pdu->private_data);
|
||||
iscsi_free_discovery_addresses(targets);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr += len + 1;
|
||||
ptr += len + 1;
|
||||
size -= len + 1;
|
||||
}
|
||||
|
||||
|
||||
12
lib/init.c
12
lib/init.c
@@ -143,11 +143,11 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
|
||||
free(discard_const(iscsi->alias));
|
||||
iscsi->alias = NULL;
|
||||
|
||||
if (iscsi->inbuf != NULL) {
|
||||
free(iscsi->inbuf);
|
||||
iscsi->inbuf = NULL;
|
||||
iscsi->insize = 0;
|
||||
iscsi->inpos = 0;
|
||||
if (iscsi->incoming != NULL) {
|
||||
iscsi_free_iscsi_in_pdu(iscsi->incoming);
|
||||
}
|
||||
if (iscsi->inqueue != NULL) {
|
||||
iscsi_free_iscsi_inqueue(iscsi->inqueue);
|
||||
}
|
||||
|
||||
free(iscsi->error_string);
|
||||
@@ -205,3 +205,5 @@ iscsi_is_logged_in(struct iscsi_context *iscsi)
|
||||
{
|
||||
return iscsi->is_loggedin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
lib/login.c
21
lib/login.c
@@ -245,9 +245,11 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
|
||||
|
||||
int
|
||||
iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size)
|
||||
struct iscsi_in_pdu *in)
|
||||
{
|
||||
int status;
|
||||
unsigned char *ptr = in->data;
|
||||
int size = in->data_pos;
|
||||
|
||||
if (size < ISCSI_HEADER_SIZE) {
|
||||
iscsi_set_error(iscsi, "dont have enough data to read status "
|
||||
@@ -255,28 +257,25 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = ntohs(*(uint16_t *)&hdr[36]);
|
||||
status = ntohs(*(uint16_t *)&in->hdr[36]);
|
||||
if (status != 0) {
|
||||
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
|
||||
pdu->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iscsi->statsn = ntohs(*(uint16_t *)&hdr[24]);
|
||||
iscsi->statsn = ntohs(*(uint16_t *)&in->hdr[24]);
|
||||
|
||||
/* XXX here we should parse the data returned in case the target
|
||||
* renegotiated some some parameters.
|
||||
* we should also do proper handshaking if the target is not yet
|
||||
* prepared to transition to the next stage
|
||||
*/
|
||||
/* skip past the header */
|
||||
hdr += ISCSI_HEADER_SIZE;
|
||||
size -= ISCSI_HEADER_SIZE;
|
||||
|
||||
while (size > 0) {
|
||||
int len;
|
||||
|
||||
len = strlen((char *)hdr);
|
||||
len = strlen((char *)ptr);
|
||||
|
||||
if (len == 0) {
|
||||
break;
|
||||
@@ -291,8 +290,8 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
|
||||
/* parse the strings */
|
||||
if (!strncmp((char *)hdr, "HeaderDigest=", 13)) {
|
||||
if (!strcmp((char *)hdr + 13, "CRC32C")) {
|
||||
if (!strncmp((char *)ptr, "HeaderDigest=", 13)) {
|
||||
if (!strcmp((char *)ptr + 13, "CRC32C")) {
|
||||
iscsi->header_digest
|
||||
= ISCSI_HEADER_DIGEST_CRC32C;
|
||||
} else {
|
||||
@@ -301,7 +300,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
}
|
||||
|
||||
hdr += len + 1;
|
||||
ptr += len + 1;
|
||||
size -= len + 1;
|
||||
}
|
||||
|
||||
@@ -354,7 +353,7 @@ iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
|
||||
|
||||
int
|
||||
iscsi_process_logout_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr _U_, int size _U_)
|
||||
struct iscsi_in_pdu *in _U_)
|
||||
{
|
||||
iscsi->is_loggedin = 0;
|
||||
pdu->callback(iscsi, SCSI_STATUS_GOOD, NULL, pdu->private_data);
|
||||
|
||||
@@ -73,16 +73,16 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
|
||||
|
||||
int
|
||||
iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size)
|
||||
struct iscsi_in_pdu *in)
|
||||
{
|
||||
struct iscsi_data data;
|
||||
|
||||
data.data = NULL;
|
||||
data.size = 0;
|
||||
|
||||
if (size > ISCSI_HEADER_SIZE) {
|
||||
data.data = discard_const(&hdr[ISCSI_HEADER_SIZE]);
|
||||
data.size = size - ISCSI_HEADER_SIZE;
|
||||
if (in->data_pos > ISCSI_HEADER_SIZE) {
|
||||
data.data = in->data;
|
||||
data.size = in->data_pos;
|
||||
}
|
||||
pdu->callback(iscsi, SCSI_STATUS_GOOD, &data, pdu->private_data);
|
||||
|
||||
|
||||
30
lib/pdu.c
30
lib/pdu.c
@@ -158,11 +158,11 @@ iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
}
|
||||
|
||||
int
|
||||
iscsi_get_pdu_size(struct iscsi_context *iscsi, const unsigned char *hdr)
|
||||
iscsi_get_pdu_data_size(const unsigned char *hdr)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = (ntohl(*(uint32_t *)&hdr[4])&0x00ffffff) + ISCSI_HEADER_SIZE;
|
||||
size = (ntohl(*(uint32_t *)&hdr[4])&0x00ffffff);
|
||||
size = (size+3)&0xfffffffc;
|
||||
|
||||
return size;
|
||||
@@ -170,17 +170,16 @@ iscsi_get_pdu_size(struct iscsi_context *iscsi, const unsigned char *hdr)
|
||||
|
||||
|
||||
int
|
||||
iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
int size)
|
||||
iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
|
||||
{
|
||||
uint32_t itt;
|
||||
enum iscsi_opcode opcode;
|
||||
struct iscsi_pdu *pdu;
|
||||
uint8_t ahslen;
|
||||
|
||||
opcode = hdr[0] & 0x3f;
|
||||
ahslen = hdr[4];
|
||||
itt = ntohl(*(uint32_t *)&hdr[16]);
|
||||
opcode = in->hdr[0] & 0x3f;
|
||||
ahslen = in->hdr[4];
|
||||
itt = ntohl(*(uint32_t *)&in->hdr[16]);
|
||||
|
||||
if (ahslen != 0) {
|
||||
iscsi_set_error(iscsi, "cant handle expanded headers yet");
|
||||
@@ -212,8 +211,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
switch (opcode) {
|
||||
case ISCSI_PDU_LOGIN_RESPONSE:
|
||||
if (iscsi_process_login_reply(iscsi, pdu, hdr, size)
|
||||
!= 0) {
|
||||
if (iscsi_process_login_reply(iscsi, pdu, in) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
iscsi_set_error(iscsi, "iscsi login reply "
|
||||
@@ -222,8 +220,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
break;
|
||||
case ISCSI_PDU_TEXT_RESPONSE:
|
||||
if (iscsi_process_text_reply(iscsi, pdu, hdr, size)
|
||||
!= 0) {
|
||||
if (iscsi_process_text_reply(iscsi, pdu, in) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
iscsi_set_error(iscsi, "iscsi text reply "
|
||||
@@ -232,8 +229,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
break;
|
||||
case ISCSI_PDU_LOGOUT_RESPONSE:
|
||||
if (iscsi_process_logout_reply(iscsi, pdu, hdr, size)
|
||||
!= 0) {
|
||||
if (iscsi_process_logout_reply(iscsi, pdu, in) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
iscsi_set_error(iscsi, "iscsi logout reply "
|
||||
@@ -242,8 +238,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
break;
|
||||
case ISCSI_PDU_SCSI_RESPONSE:
|
||||
if (iscsi_process_scsi_reply(iscsi, pdu, hdr, size)
|
||||
!= 0) {
|
||||
if (iscsi_process_scsi_reply(iscsi, pdu, in) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
iscsi_set_error(iscsi, "iscsi response reply "
|
||||
@@ -252,7 +247,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
break;
|
||||
case ISCSI_PDU_DATA_IN:
|
||||
if (iscsi_process_scsi_data_in(iscsi, pdu, hdr, size,
|
||||
if (iscsi_process_scsi_data_in(iscsi, pdu, in,
|
||||
&is_finished) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
@@ -262,8 +257,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, const unsigned char *hdr,
|
||||
}
|
||||
break;
|
||||
case ISCSI_PDU_NOP_IN:
|
||||
if (iscsi_process_nop_out_reply(iscsi, pdu, hdr, size)
|
||||
!= 0) {
|
||||
if (iscsi_process_nop_out_reply(iscsi, pdu, in) != 0) {
|
||||
SLIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||
iscsi_free_pdu(iscsi, pdu);
|
||||
iscsi_set_error(iscsi, "iscsi nop-in failed");
|
||||
|
||||
@@ -196,18 +196,18 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
|
||||
|
||||
int
|
||||
iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size)
|
||||
struct iscsi_in_pdu *in)
|
||||
{
|
||||
int statsn, flags, response, status;
|
||||
struct iscsi_scsi_cbdata *scsi_cbdata = pdu->scsi_cbdata;
|
||||
struct scsi_task *task = scsi_cbdata->task;
|
||||
|
||||
statsn = ntohl(*(uint32_t *)&hdr[24]);
|
||||
statsn = ntohl(*(uint32_t *)&in->hdr[24]);
|
||||
if (statsn > (int)iscsi->statsn) {
|
||||
iscsi->statsn = statsn;
|
||||
}
|
||||
|
||||
flags = hdr[1];
|
||||
flags = in->hdr[1];
|
||||
if ((flags&ISCSI_PDU_DATA_FINAL) == 0) {
|
||||
iscsi_set_error(iscsi, "scsi response pdu but Final bit is "
|
||||
"not set: 0x%02x.", flags);
|
||||
@@ -223,9 +223,9 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
return -1;
|
||||
}
|
||||
|
||||
response = hdr[2];
|
||||
response = in->hdr[2];
|
||||
|
||||
status = hdr[3];
|
||||
status = in->hdr[3];
|
||||
|
||||
switch (status) {
|
||||
case SCSI_STATUS_GOOD:
|
||||
@@ -239,14 +239,13 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
pdu->private_data);
|
||||
break;
|
||||
case SCSI_STATUS_CHECK_CONDITION:
|
||||
task->datain.size = size - ISCSI_HEADER_SIZE;
|
||||
task->datain.size = in->data_pos;
|
||||
task->datain.data = malloc(task->datain.size);
|
||||
if (task->datain.data == NULL) {
|
||||
iscsi_set_error(iscsi, "failed to allocate blob for "
|
||||
"sense data");
|
||||
}
|
||||
memcpy(task->datain.data, hdr + ISCSI_HEADER_SIZE,
|
||||
task->datain.size);
|
||||
memcpy(task->datain.data, in->data, task->datain.size);
|
||||
|
||||
task->sense.error_type = task->datain.data[2] & 0x7f;
|
||||
task->sense.key = task->datain.data[4] & 0x0f;
|
||||
@@ -274,19 +273,19 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
|
||||
int
|
||||
iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
const unsigned char *hdr, int size _U_, int *is_finished)
|
||||
struct iscsi_in_pdu *in, int *is_finished)
|
||||
{
|
||||
int statsn, flags, status;
|
||||
struct iscsi_scsi_cbdata *scsi_cbdata = pdu->scsi_cbdata;
|
||||
struct scsi_task *task = scsi_cbdata->task;
|
||||
int dsl;
|
||||
|
||||
statsn = ntohl(*(uint32_t *)&hdr[24]);
|
||||
statsn = ntohl(*(uint32_t *)&in->hdr[24]);
|
||||
if (statsn > (int)iscsi->statsn) {
|
||||
iscsi->statsn = statsn;
|
||||
}
|
||||
|
||||
flags = hdr[1];
|
||||
flags = in->hdr[1];
|
||||
if ((flags&ISCSI_PDU_DATA_ACK_REQUESTED) != 0) {
|
||||
iscsi_set_error(iscsi, "scsi response asked for ACK "
|
||||
"0x%02x.", flags);
|
||||
@@ -294,10 +293,10 @@ iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
pdu->private_data);
|
||||
return -1;
|
||||
}
|
||||
dsl = ntohl(*(uint32_t *)&hdr[4])&0x00ffffff;
|
||||
dsl = ntohl(*(uint32_t *)&in->hdr[4])&0x00ffffff;
|
||||
|
||||
if (iscsi_add_data(iscsi, &pdu->indata,
|
||||
discard_const(hdr + ISCSI_HEADER_SIZE), dsl, 0)
|
||||
in->data, dsl, 0)
|
||||
!= 0) {
|
||||
iscsi_set_error(iscsi, "Out-of-memory: failed to add data "
|
||||
"to pdu in buffer.");
|
||||
@@ -320,7 +319,7 @@ iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||
/* this was the final data-in packet in the sequence and it has
|
||||
* the s-bit set, so invoke the callback.
|
||||
*/
|
||||
status = hdr[3];
|
||||
status = in->hdr[3];
|
||||
task->datain.data = pdu->indata.data;
|
||||
task->datain.size = pdu->indata.size;
|
||||
|
||||
|
||||
150
lib/socket.c
150
lib/socket.c
@@ -167,81 +167,85 @@ iscsi_which_events(struct iscsi_context *iscsi)
|
||||
static int
|
||||
iscsi_read_from_socket(struct iscsi_context *iscsi)
|
||||
{
|
||||
int available;
|
||||
int size;
|
||||
unsigned char *buf;
|
||||
ssize_t count;
|
||||
struct iscsi_in_pdu *in;
|
||||
ssize_t data_size, count;
|
||||
|
||||
if (ioctl(iscsi->fd, FIONREAD, &available) != 0) {
|
||||
iscsi_set_error(iscsi, "ioctl FIONREAD returned error : "
|
||||
"%d", errno);
|
||||
return -1;
|
||||
}
|
||||
if (available == 0) {
|
||||
iscsi_set_error(iscsi, "no data readable in socket, "
|
||||
"socket is closed");
|
||||
return -1;
|
||||
}
|
||||
size = iscsi->insize - iscsi->inpos + available;
|
||||
buf = malloc(size);
|
||||
if (buf == NULL) {
|
||||
iscsi_set_error(iscsi, "failed to allocate %d bytes for "
|
||||
"input buffer", size);
|
||||
return -1;
|
||||
}
|
||||
if (iscsi->insize > iscsi->inpos) {
|
||||
memcpy(buf, iscsi->inbuf + iscsi->inpos,
|
||||
iscsi->insize - iscsi->inpos);
|
||||
iscsi->insize -= iscsi->inpos;
|
||||
iscsi->inpos = 0;
|
||||
}
|
||||
|
||||
count = read(iscsi->fd, buf + iscsi->insize, available);
|
||||
if (count == -1) {
|
||||
if (errno == EINTR) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
return 0;
|
||||
if (iscsi->incoming == NULL) {
|
||||
iscsi->incoming = malloc(sizeof(struct iscsi_in_pdu));
|
||||
if (iscsi->incoming == NULL) {
|
||||
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
|
||||
return -1;
|
||||
}
|
||||
iscsi_set_error(iscsi, "read from socket failed, "
|
||||
bzero(iscsi->incoming, sizeof(struct iscsi_in_pdu));
|
||||
}
|
||||
in = iscsi->incoming;
|
||||
|
||||
/* first we must read the header, including any digests */
|
||||
if (in->hdr_pos < ISCSI_HEADER_SIZE) {
|
||||
count = read(iscsi->fd, &in->hdr[in->hdr_pos], ISCSI_HEADER_SIZE - in->hdr_pos);
|
||||
if (count < 0) {
|
||||
if (errno == EINTR) {
|
||||
return 0;
|
||||
}
|
||||
iscsi_set_error(iscsi, "read from socket failed, "
|
||||
"errno:%d", errno);
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(iscsi->inbuf);
|
||||
|
||||
iscsi->inbuf = buf;
|
||||
iscsi->insize += count;
|
||||
|
||||
while (1) {
|
||||
if (iscsi->insize - iscsi->inpos < ISCSI_RAW_HEADER_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
count = iscsi_get_pdu_size(iscsi,
|
||||
iscsi->inbuf + iscsi->inpos);
|
||||
if (iscsi->insize + iscsi->inpos < count) {
|
||||
return 0;
|
||||
}
|
||||
if (iscsi_process_pdu(iscsi, iscsi->inbuf + iscsi->inpos,
|
||||
count) != 0) {
|
||||
iscsi->inpos += count;
|
||||
return -1;
|
||||
}
|
||||
iscsi->inpos += count;
|
||||
if (iscsi->inpos == iscsi->insize) {
|
||||
free(iscsi->inbuf);
|
||||
iscsi->inbuf = NULL;
|
||||
iscsi->insize = 0;
|
||||
iscsi->inpos = 0;
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (iscsi->inpos > iscsi->insize) {
|
||||
iscsi_set_error(iscsi, "inpos > insize. bug!");
|
||||
in->hdr_pos += count;
|
||||
}
|
||||
|
||||
if (in->hdr_pos < ISCSI_HEADER_SIZE) {
|
||||
/* we dont have the full header yet, so return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
|
||||
if (data_size != 0) {
|
||||
if (in->data == NULL) {
|
||||
in->data = malloc(data_size);
|
||||
if (in->data == NULL) {
|
||||
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
count = read(iscsi->fd, &in->data[in->data_pos], data_size - in->data_pos);
|
||||
if (count < 0) {
|
||||
if (errno == EINTR) {
|
||||
return 0;
|
||||
}
|
||||
iscsi_set_error(iscsi, "read from socket failed, "
|
||||
"errno:%d", errno);
|
||||
return -1;
|
||||
}
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
in->data_pos += count;
|
||||
}
|
||||
|
||||
if (in->data_pos < data_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLIST_ADD_END(&iscsi->inqueue, in);
|
||||
iscsi->incoming = NULL;
|
||||
|
||||
|
||||
while (iscsi->inqueue != NULL) {
|
||||
struct iscsi_in_pdu *in = iscsi->inqueue;
|
||||
|
||||
if (iscsi_process_pdu(iscsi, in) != 0) {
|
||||
return -1;
|
||||
}
|
||||
SLIST_REMOVE(&iscsi->inqueue, in);
|
||||
iscsi_free_iscsi_in_pdu(in);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -353,3 +357,19 @@ iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
iscsi_free_iscsi_in_pdu(struct iscsi_in_pdu *in)
|
||||
{
|
||||
free(in->data);
|
||||
free(in);
|
||||
}
|
||||
|
||||
void
|
||||
iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue)
|
||||
{
|
||||
while (inqueue != NULL) {
|
||||
struct iscsi_in_pdu *next = inqueue->next;
|
||||
iscsi_free_iscsi_in_pdu(inqueue);
|
||||
inqueue = next;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user