int main(int argc, char **argv) { wool_init(&argc, &argv); os_recv(); return 0; }
/** * Receive header and buffer if any * * @param[in] fd socket in which to perform the receive * @param[in] request the request describing the receive operation * * @return DATA_TRANSFER_ERROR socket invalid or closed. * DATA_TRANSFER_COMPLETE if successfully transferred all pending * data (header and buffer if any) * DATA_TRANSFER_PENDING if some remaining data to transfer */ static int request_receive(int fd, struct pending_request *request) { int ret; if (request->nb_readwrite < sizeof(payload_t)) { void *buffer = request->payload + request->nb_readwrite; int size = sizeof(payload_t) - request->nb_readwrite; do ret = os_recv(fd, buffer, size, 0); while (ret == -EINTR); } else { void *buffer = request->payload->buffer + request->nb_readwrite - sizeof(payload_t); int size = request->payload->size2 - (request->nb_readwrite - sizeof(payload_t)); do ret = os_recv(fd, buffer, size, 0); while (ret == -EINTR); } /* recv returning 0 means the peer disconnected: this is an error */ if (ret <= 0) return DATA_TRANSFER_ERROR; request->nb_readwrite += ret; /* If header was not fully retrieved, pending data are remaining */ if (request->nb_readwrite < sizeof(payload_t)) return DATA_TRANSFER_PENDING; /* If we are here, this means that the header was fully received, thus we * can check if more data are coming with this request. */ if (request->payload->size2 > 0 && !request->big_buffer) return DATA_TRANSFER_NEED_BIG_BUFFER; if (request->nb_readwrite < sizeof(payload_t) + request->payload->size2) return DATA_TRANSFER_PENDING; return DATA_TRANSFER_COMPLETE; }
/** * \brief receive a data from a socket. * When returning EXA_SUCCESS, xml_tree points on a valid xml tree. * * \param[in] sock_fd socket file descriptor of the incoming data * \param[out] xml_tree Pointer on the xmlDocPtr pointing on a XML tree * extracted from the data read on the socket. * * \return EXA_SUCCESS or a negative error. */ static int receive(int sock_fd, char **buffer) { int current_read = 0; char *buffer_receiving = NULL; EXA_ASSERT(buffer); *buffer = NULL; exalog_debug("SOCKET %d: XML Message processing", sock_fd); /* We read and merge each chunk of incomming data in the hope to get * the END of command. Here the input buffer is sized as to handle * all the command in one chunk, so not having the end of command is * an error. */ do { int nb_car; char *new_buffer_receiving; if (current_read > PROTOCOL_BUFFER_MAX_SIZE) { cl_error_desc_t error; set_error(&error, -EXA_ERR_CMD_PARSING, "Received command is bigger than our internal limit (%d bytes)", PROTOCOL_BUFFER_MAX_SIZE); exalog_error("Socket %d peer '%s': %s", sock_fd, cli_peer_from_fd(sock_fd), error.msg); cli_command_end_complete(sock_fd, &error); /* Don't need the receiving buffer any more */ os_free(buffer_receiving); return -EXA_ERR_CMD_PARSING; } new_buffer_receiving = os_realloc(buffer_receiving, PROTOCOL_BUFFER_LEN + current_read + sizeof(char) /* for '\0' */); if (!new_buffer_receiving) { os_free(buffer_receiving); exalog_error("Socket %d peer '%s': Failed to realloc()", sock_fd, cli_peer_from_fd(sock_fd)); return -ENOMEM; } buffer_receiving = new_buffer_receiving; do nb_car = os_recv(sock_fd, buffer_receiving + current_read, PROTOCOL_BUFFER_LEN, 0); while (nb_car == -EINTR); if (nb_car == 0) { exalog_debug("SOCKET %d: Error = Client did disconnect itself", sock_fd); os_free(buffer_receiving); return -ECONNABORTED; } if (nb_car < 0 && errno != EAGAIN) { if (nb_car == -ECONNRESET) exalog_debug("SOCKET %d: Error %d", sock_fd, nb_car); else exalog_error("Socket %d peer '%s': %s (%d)", sock_fd, cli_peer_from_fd(sock_fd), exa_error_msg(nb_car), nb_car); os_free(buffer_receiving); return nb_car; } if(nb_car > 0) current_read += nb_car; /* Make sure to be properly ended */ buffer_receiving[current_read] = '\0'; /* Make sure the XML input is complete */ } while(xml_buffer_is_partial(buffer_receiving)); exalog_debug("SOCKET %d: Receive Message lg = %" PRIzu " : [%s]", sock_fd, strlen(buffer_receiving), buffer_receiving); *buffer = buffer_receiving; return EXA_SUCCESS; }