#include <string.h>
#include "frescan_bwres_messages.h"
+#include "frescan_bwres_requests.h"
+#include "frescan.h"
#include "frescan_config.h"
#include "frescan_debug.h"
-#include "frescan_requests.h"
-#include "frescan_servers.h"
/**
*
- * NEG MESSAGE
+ * FRESCAN_REQ_NEG MESSAGE
+ * =======================
+ * This message is sent from a SLAVE to the MASTER when the slave wants
+ * to negotiate a new contract. It contains the type (a negotiation 'NEG'
+ * request), the LOCAL request id (so the MASTER can use it in the reply
+ * to identify to which request is replying), a preallocated sporadic
+ * server id (the MASTER will store it in its table together with the
+ * node so we can perform renegotiations and spare capacity distribution
+ * in the future) and the contract.
*
- * 1 2 N
- * +-----------------------+
- * | 'NEG' | ID | CONTRACT |
- * +-----------------------+
- *
- * REP_NEG MESSAGE
- *
- * +----------------------------------------+
- * | 'REPNEG' | ID | ACCEPTED | SC_CONTRACT |
- * +----------------------------------------+
- *
- * RENEGOTIATE = NEG but with different type
- *
- * CANCEL MESSAGE
- *
- * +--------------------------------+
- * | 'CANCEL' | ID | CONTRACT_LABEL |
- * +--------------------------------+
- *
- * REP_CANCEL MESSAGE
- *
- * +---------------------------+
- * | 'REP_CANCEL' | ID | ERROR |
- * +---------------------------+
- *
- * ID: the id of the request
+ * 1 2 2 N
+ * +-----------------------------+
+ * | 'NEG' | REQ | SS | CONTRACT |
+ * +-----------------------------+
*
*/
-typedef enum {
- FRESCAN_MSG_TYPE_NEG = 0,
- FRESCAN_MSG_TYPE_RENEG = 1,
- FRESCAN_MSG_TYPE_CANCEL = 2,
- FRESCAN_MSG_TYPE_REP_NEG = 3,
- FRESCAN_MSG_TYPE_REP_RENEG = 4,
- FRESCAN_MSG_TYPE_REP_CANCEL = 5
-} frescan_msg_type_t;
-
-int frescan_neg_message_create(uint8_t *msg,
- frescan_request_id_t id,
- const frescan_contract_t *contract)
+struct frescan_req_neg_message_t {
+ frescan_request_type_t type;
+ frescan_request_id_t req;
+ frescan_ss_t ss;
+ frescan_contract_t contract;
+} __attribute__ ((packed));
+
+static int frescan_request_to_neg_message(const frescan_request_data_t *data,
+ uint8_t *msg)
{
- size_t num, bytes_written;
- uint8_t *tmp = msg;
+ struct frescan_req_neg_message_t *neg_msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "creating a negotiation request message\n");
+ neg_msg = (struct frescan_req_neg_message_t *)msg;
- *tmp = (uint8_t)FRESCAN_MSG_TYPE_NEG;
- tmp++;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "type: %d (1 byte)\n", FRESCAN_MSG_TYPE_NEG);
+ neg_msg->type = FRESCAN_REQ_NEG;
+ neg_msg->req = data->req;
+ neg_msg->ss = data->ss;
+ neg_msg->contract = *(data->contract);
- num = 2;
- memcpy(tmp, &id, num);
- tmp = tmp + num;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "request id: %d (2 bytes)\n", id);
+ return 0;
+}
- num = sizeof(frescan_contract_t);
- memcpy(tmp, contract, num);
- tmp = tmp + num;
+static int frescan_neg_message_to_request(const uint8_t *msg,
+ frescan_request_data_t *data)
+{
+ struct frescan_req_neg_message_t *neg_msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "contract (%d bytes)\n", num);
+ neg_msg = (struct frescan_req_neg_message_t *)msg;
- bytes_written = tmp - msg;
+ data->type = FRESCAN_REQ_NEG;
+ data->req = neg_msg->req;
+ data->ss = neg_msg->ss;
+ *(data->contract) = neg_msg->contract;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "total bytes_written: %d\n", bytes_written);
+ return 0;
+}
- return (int)bytes_written;
+/**
+ *
+ * FRESCAN_REQ_RENEG MESSAGE
+ * =========================
+ * This message is sent from a SLAVE to the MASTER when the slave wants
+ * to renegotiate a contract. It contains the type (a renegotiation 'RENEG'
+ * request), the LOCAL request id (so the MASTER can use it in the reply
+ * to identify to which request is replying), the sporadic server id
+ * (the MASTER will look up its table together with the node to find the
+ * appropiate entry) and the contract.
+ *
+ * 1 2 2 N
+ * +-------------------------------+
+ * | 'RENEG' | REQ | SS | CONTRACT |
+ * +-------------------------------+
+ *
+ */
+
+struct frescan_req_reneg_message_t {
+ frescan_request_type_t type;
+ frescan_request_id_t req;
+ frescan_ss_t ss;
+ frescan_contract_t contract;
+} __attribute__ ((packed));
+
+static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
+ uint8_t *msg)
+{
+ struct frescan_req_reneg_message_t *reneg_msg;
+
+ reneg_msg = (struct frescan_req_reneg_message_t *)msg;
+
+ reneg_msg->type = FRESCAN_REQ_RENEG;
+ reneg_msg->req = data->req;
+ reneg_msg->ss = data->ss;
+ reneg_msg->contract = *(data->contract);
+
+ return 0;
}
-int frescan_repneg_message_create(uint8_t *msg,
- frescan_request_id_t id,
- int accepted,
- frescan_server_params_t *params)
+static int frescan_reneg_message_to_request(const uint8_t *msg,
+ frescan_request_data_t *data)
{
- size_t num, bytes_written;
- uint8_t *tmp = msg;
+ struct frescan_req_reneg_message_t *reneg_msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "creating a negotiation reply message\n");
+ reneg_msg = (struct frescan_req_reneg_message_t *)msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "type: %d (1 byte)\n", FRESCAN_MSG_TYPE_REP_NEG);
- *tmp = (uint8_t)FRESCAN_MSG_TYPE_REP_NEG;
- tmp++;
+ data->type = FRESCAN_REQ_RENEG;
+ data->req = reneg_msg->req;
+ data->ss = reneg_msg->ss;
+ *(data->contract) = reneg_msg->contract;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "request id: %d (2 bytes)\n", id);
- num = 2;
- memcpy(tmp, &id, num);
- tmp = tmp + num;
+ return 0;
+}
- *tmp = (uint8_t)accepted;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG, "accepted:%u\n", *tmp);
- tmp++;
+/**
+ * FRESCAN_REQ_CANCEL MESSAGE
+ * ==========================
+ * This message is sent from a SLAVE to the MASTER to cancel a contract.
+ * It contains the type, 'CANCEL' and the sporadic server id (the MASTER will
+ * have to look it up in the table). The MASTER doesnt need to reply this
+ * message.
+ *
+ * +---------------+
+ * | 'CANCEL' | SS |
+ * +---------------+
+ *
+ */
- num = sizeof(frescan_budget_period_t);
- memcpy(tmp, ¶ms->values, num);
- tmp = tmp + num;
+struct frescan_req_cancel_message_t {
+ frescan_request_type_t type;
+ frescan_ss_t ss;
+} __attribute__ ((packed));
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "budget_period (%d bytes)\n", num);
+static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
+ uint8_t *msg)
+{
+ struct frescan_req_cancel_message_t *cancel_msg;
- num = 1;
- memcpy(tmp, ¶ms->prio, num);
- tmp = tmp + num;
+ cancel_msg = (struct frescan_req_cancel_message_t *)msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "server prio:%u\n", params->prio);
+ cancel_msg->type = FRESCAN_REQ_CANCEL;
+ cancel_msg->ss = data->ss;
+
+ return 0;
+}
+
+static int frescan_cancel_message_to_request(const uint8_t *msg,
+ frescan_request_data_t *data)
+{
+ struct frescan_req_cancel_message_t *cancel_msg;
- bytes_written = tmp - msg;
+ cancel_msg = (struct frescan_req_cancel_message_t *)msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "total bytes_written: %d\n", bytes_written);
+ data->type = FRESCAN_REQ_CANCEL;
+ data->ss = cancel_msg->ss;
- return (int)bytes_written;
+ return 0;
}
-int frescan_reneg_message_create(uint8_t *msg,
- frescan_request_id_t id,
- const frescan_contract_t *contract)
+/**
+ *
+ * FRESCAN_REP_NEG MESSAGE
+ * =======================
+ * This message is sent from the MASTER to a slave as a reply to a
+ * FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
+ * It contains the type 'REPNEG', the request ID of the slave and a
+ * return value to say if the contract is admited, not admited or if
+ * there was an error.
+ *
+ * +-------------------------------+
+ * | 'REPNEG' | REQ | RETURN_VALUE |
+ * +-------------------------------+
+ *
+ */
+
+struct frescan_rep_neg_message_t {
+ frescan_request_type_t type;
+ frescan_request_id_t req;
+ frescan_request_retval_t return_value;
+} __attribute__ ((packed));
+
+static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
+ uint8_t *msg)
{
- size_t num, bytes_written;
- uint8_t *tmp = msg;
+ struct frescan_rep_neg_message_t *repneg_msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "creating a renegotiation request message\n");
+ repneg_msg = (struct frescan_rep_neg_message_t *)msg;
- *tmp = (uint8_t)FRESCAN_MSG_TYPE_RENEG;
- tmp++;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "type: %d (1 byte)\n", FRESCAN_MSG_TYPE_RENEG);
+ repneg_msg->type = FRESCAN_REP_NEG;
+ repneg_msg->req = data->req;
+ repneg_msg->return_value = data->return_value;
- num = 2;
- memcpy(tmp, &id, num);
- tmp = tmp + num;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "request id: %d (2 bytes)\n", id);
+ return 0;
+}
- num = sizeof(frescan_contract_t);
- memcpy(tmp, contract, num);
- tmp = tmp + num;
+static int frescan_repneg_message_to_request(const uint8_t *msg,
+ frescan_request_data_t *data)
+{
+ struct frescan_rep_neg_message_t *repneg_msg;
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "contract (%d bytes)\n", num);
+ repneg_msg = (struct frescan_rep_neg_message_t *)msg;
- // TODO: ADD server id? or look up the label??
+ data->type = FRESCAN_REP_NEG;
+ data->req = repneg_msg->req;
+ data->return_value = repneg_msg->return_value;
- bytes_written = tmp - msg;
+ return 0;
+}
- DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
- "total bytes_written: %d\n", bytes_written);
+/**
+ * frescan_request_to_message() - converts a request into a network message
+ *
+ * this function converts a request with the necessary data into a message
+ * that can be sent through the network.
+ *
+ * @req_data: the request data to fill the message bytes (in)
+ * @msg: buffer with the bytes that will be sent to the network (out)
+ *
+ */
- return (int)bytes_written;
+int frescan_request_to_message(const frescan_request_data_t *req_data,
+ uint8_t *msg)
+{
+ switch(req_data->type) {
+ case FRESCAN_REQ_NEG:
+ return frescan_request_to_neg_message(req_data, msg);
+ case FRESCAN_REQ_RENEG:
+ return frescan_request_to_reneg_message(req_data, msg);
+ case FRESCAN_REQ_CANCEL:
+ return frescan_request_to_cancel_message(req_data, msg);
+ case FRESCAN_REP_NEG:
+ return frescan_request_to_repneg_message(req_data, msg);
+ default:
+ ERROR("request type not supported\n");
+ return -1;
+ }
}
+/**
+ * frescan_message_to_request() - converts a network message into a request
+ *
+ * this function is the opposite to the previous one. It will be used by
+ * the acceptor threads to transform messages received from the network
+ * into requests.
+ *
+ * @msg: buffer with the bytes received from the network (in)
+ * @req_data: the request data to fill from the message bytes (out)
+ *
+ */
+
+int frescan_message_to_request(const uint8_t *msg,
+ frescan_request_data_t *req_data)
+{
+ switch(*((frescan_request_type_t *)msg)) {
+ case FRESCAN_REQ_NEG:
+ return frescan_neg_message_to_request(msg, req_data);
+ case FRESCAN_REQ_RENEG:
+ return frescan_reneg_message_to_request(msg, req_data);
+ case FRESCAN_REQ_CANCEL:
+ return frescan_cancel_message_to_request(msg, req_data);
+ case FRESCAN_REP_NEG:
+ return frescan_repneg_message_to_request(msg, req_data);
+ default:
+ ERROR("request type not supported\n");
+ return -1;
+ }
+}
+
+/*
+
int frescan_message_parse(frescan_network_t net,
const uint8_t *msg,
size_t size,
}
return 0;
-}
+}*/