static int rpc_write_to_socket(struct rpc_context *rpc) { int32_t count; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->fd == -1) { rpc_set_error(rpc, "trying to write but not connected"); return -1; } while (rpc->outqueue != NULL) { int64_t total; total = rpc->outqueue->outdata.size; count = send(rpc->fd, rpc->outqueue->outdata.data + rpc->outqueue->written, total - rpc->outqueue->written, 0); if (count == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; } rpc_set_error(rpc, "Error when writing to socket :%s(%d)", strerror(errno), errno); return -1; } rpc->outqueue->written += count; if (rpc->outqueue->written == total) { struct rpc_pdu *pdu = rpc->outqueue; SLIST_REMOVE(&rpc->outqueue, pdu); SLIST_ADD_END(&rpc->waitpdu, pdu); } } return 0; }
static int iscsi_write_to_socket(struct iscsi_context *iscsi) { ssize_t count; if (iscsi->fd == -1) { iscsi_set_error(iscsi, "trying to write but not connected"); return -1; } while (iscsi->outqueue) { ssize_t total; if (iscsi->outqueue->cmdsn > iscsi->maxcmdsn) { /* stop sending. maxcmdsn is reached */ return 0; } total = iscsi->outqueue->outdata.size; total = (total + 3) & 0xfffffffc; count = send(iscsi->fd, iscsi->outqueue->outdata.data + iscsi->outqueue->written, total - iscsi->outqueue->written, 0); if (count == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; } iscsi_set_error(iscsi, "Error when writing to " "socket :%d", errno); return -1; } iscsi->outqueue->written += count; if (iscsi->outqueue->written == total) { struct iscsi_pdu *pdu = iscsi->outqueue; SLIST_REMOVE(&iscsi->outqueue, pdu); if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) { iscsi_free_pdu(iscsi, pdu); } else { SLIST_ADD_END(&iscsi->waitpdu, pdu); } } } return 0; }
int rpc_add_fragment(struct rpc_context *rpc, char *data, uint64_t size) { struct rpc_fragment *fragment; assert(rpc->magic == RPC_CONTEXT_MAGIC); fragment = malloc(sizeof(struct rpc_fragment)); if (fragment == NULL) { return -1; } fragment->size = size; fragment->data = malloc(fragment->size); if(fragment->data == NULL) { free(fragment); return -1; } memcpy(fragment->data, data, fragment->size); SLIST_ADD_END(&rpc->fragments, fragment); return 0; }
static int iscsi_read_from_socket(struct iscsi_context *iscsi) { struct iscsi_in_pdu *in; ssize_t data_size, count; 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; } memset(iscsi->incoming, 0, sizeof(struct iscsi_in_pdu)); } in = iscsi->incoming; /* first we must read the header, including any digests */ if (in->hdr_pos < ISCSI_HEADER_SIZE) { /* try to only read the header, the socket is nonblocking, so * no need to limit the read to what is available in the socket */ count = ISCSI_HEADER_SIZE - in->hdr_pos; count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0); if (count == 0) { return -1; } if (count < 0) { if (errno == EINTR || errno == EAGAIN) { return 0; } iscsi_set_error(iscsi, "read from socket failed, " "errno:%d", errno); return -1; } 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 || data_size > iscsi->initiator_max_recv_data_segment_length) { iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size); return -1; } if (data_size != 0) { unsigned char *buf = NULL; count = data_size - in->data_pos; /* first try to see if we already have a user buffer */ buf = iscsi_get_user_in_buffer(iscsi, in, in->data_pos, &count); /* if not, allocate one */ if (buf == NULL) { 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; } } buf = &in->data[in->data_pos]; } count = recv(iscsi->fd, buf, count, 0); if (count == 0) { return -1; } if (count < 0) { if (errno == EINTR || errno == EAGAIN) { return 0; } iscsi_set_error(iscsi, "read from socket failed, " "errno:%d", errno); return -1; } 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 *current = iscsi->inqueue; if (iscsi_process_pdu(iscsi, current) != 0) { return -1; } SLIST_REMOVE(&iscsi->inqueue, current); iscsi_free_iscsi_in_pdu(current); } return 0; }