kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
kinetic_request.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 #include "kinetic_request.h"
21 #include <pthread.h>
22 
23 #include "kinetic_logger.h"
24 #include "kinetic_session.h"
25 #include "kinetic_auth.h"
26 #include "kinetic_nbo.h"
27 #include "kinetic_controller.h"
28 #include "byte_array.h"
29 #include "bus.h"
30 
31 #ifdef TEST
32 uint8_t *cmdBuf = NULL;
33 uint8_t *msg = NULL;
34 #endif
35 
36 size_t KineticRequest_PackCommand(KineticRequest* request)
37 {
38  size_t expectedLen = com__seagate__kinetic__proto__command__get_packed_size(&request->message.command);
39  #ifndef TEST
40  uint8_t *cmdBuf = (uint8_t*)malloc(expectedLen);
41  #endif
42  if (cmdBuf == NULL)
43  {
44  LOGF0("Failed to allocate command bytes: %zd", expectedLen);
46  }
47  request->message.message.commandbytes.data = cmdBuf;
48 
50  &request->message.command, cmdBuf);
51  KINETIC_ASSERT(packedLen == expectedLen);
52  request->message.message.commandbytes.len = packedLen;
53  request->message.message.has_commandbytes = true;
54  KineticLogger_LogByteArray(3, "commandbytes", (ByteArray){
55  .data = request->message.message.commandbytes.data,
56  .len = request->message.message.commandbytes.len,
57  });
58 
59  return packedLen;
60 }
61 
63  KineticRequest *request, ByteArray *pin)
64 {
65  if (pin != NULL) {
66  return KineticAuth_PopulatePin(config, request, *pin);
67  } else {
68  return KineticAuth_PopulateHmac(config, request);
69  }
70 }
71 
72 KineticStatus KineticRequest_PackMessage(KineticOperation *operation,
73  uint8_t **out_msg, size_t *msgSize)
74 {
75  // Configure PDU header
76  Com__Seagate__Kinetic__Proto__Message* proto = &operation->request->message.message;
77  KineticPDUHeader header = {
78  .versionPrefix = 'F',
80  };
81  header.valueLength = operation->value.len;
82  uint32_t nboProtoLength = KineticNBO_FromHostU32(header.protobufLength);
83  uint32_t nboValueLength = KineticNBO_FromHostU32(header.valueLength);
84 
85  // Allocate and pack protobuf message
86  size_t offset = 0;
87  #ifndef TEST
88  uint8_t *msg = malloc(PDU_HEADER_LEN + header.protobufLength + header.valueLength);
89  #endif
90  if (msg == NULL) {
91  LOG0("Failed to allocate outgoing message!");
93  }
94 
95  // Pack header
96  KineticRequest* request = operation->request;
97  msg[offset] = header.versionPrefix;
98  offset += sizeof(header.versionPrefix);
99  memcpy(&msg[offset], &nboProtoLength, sizeof(nboProtoLength));
100  offset += sizeof(nboProtoLength);
101  memcpy(&msg[offset], &nboValueLength, sizeof(nboValueLength));
102  offset += sizeof(nboValueLength);
103  size_t len = com__seagate__kinetic__proto__message__pack(&request->message.message, &msg[offset]);
104  KINETIC_ASSERT(len == header.protobufLength);
105  offset += header.protobufLength;
106 
107  #ifndef TEST
108  // Log protobuf per configuration
109  LOGF2("[PDU TX] pdu: %p, session: %p, bus: %p, "
110  "fd: %6d, seq: %8lld, protoLen: %8u, valueLen: %8u, op: %p, msgType: %02x",
111  (void*)operation->request,
112  (void*)operation->session, (void*)operation->session->messageBus,
113  operation->session->socket, (long long)request->message.header.sequence,
114  header.protobufLength, header.valueLength,
115  (void*)operation, request->message.header.messagetype);
116  KineticLogger_LogHeader(3, &header);
117  KineticLogger_LogProtobuf(3, proto);
118  #endif
119 
120  // Pack value payload, if supplied
121  if (header.valueLength > 0) {
122  memcpy(&msg[offset], operation->value.data, operation->value.len);
123  offset += operation->value.len;
124  }
125  KINETIC_ASSERT((PDU_HEADER_LEN + header.protobufLength + header.valueLength) == offset);
126 
127  *out_msg = msg;
128  *msgSize = offset;
129  return KINETIC_STATUS_SUCCESS;
130 }
131 
132 bool KineticRequest_SendRequest(KineticOperation *operation,
133  uint8_t *msg, size_t msgSize)
134 {
135  KINETIC_ASSERT(msg);
136  KINETIC_ASSERT(msgSize > 0);
137  bus_user_msg bus_msg = {
138  .fd = operation->session->socket,
139  .type = BUS_SOCKET_PLAIN,
140  .seq_id = operation->request->message.header.sequence,
141  .msg = msg,
142  .msg_size = msgSize,
144  .udata = operation,
145  .timeout_sec = operation->timeoutSeconds,
146  };
147  return Bus_SendRequest(operation->session->messageBus, &bus_msg);
148 }
149 
150 bool KineticRequest_LockSend(KineticSession* session)
151 {
152  KINETIC_ASSERT(session);
153  return 0 == pthread_mutex_lock(&session->sendMutex);
154 }
155 
156 bool KineticRequest_UnlockSend(KineticSession* session)
157 {
158  KINETIC_ASSERT(session);
159  return 0 == pthread_mutex_unlock(&session->sendMutex);
160 }
Structure for handling generic arrays of bytes.
Definition: byte_array.h:34
void KineticLogger_LogHeader(int log_level, const KineticPDUHeader *header)
KineticStatus KineticRequest_PackMessage(KineticOperation *operation, uint8_t **out_msg, size_t *msgSize)
KineticStatus KineticRequest_PopulateAuthentication(KineticSessionConfig *config, KineticRequest *request, ByteArray *pin)
Operation successful.
uint32_t KineticNBO_FromHostU32(uint32_t valueHost)
Definition: kinetic_nbo.c:32
Structure used to specify the configuration for a session.
void KineticController_HandleResult(bus_msg_result_t *res, void *udata)
bool Bus_SendRequest(struct bus *b, bus_user_msg *msg)
Send a request.
Definition: bus.c:297
size_t KineticRequest_PackCommand(KineticRequest *request)
Failed allocating/deallocating memory.
bool KineticRequest_LockSend(KineticSession *session)
size_t com__seagate__kinetic__proto__command__get_packed_size(const Com__Seagate__Kinetic__Proto__Command *message)
Definition: kinetic.pb-c.c:247
KineticStatus KineticAuth_PopulatePin(KineticSessionConfig const *const config, KineticRequest *const pdu, ByteArray pin)
Definition: kinetic_auth.c:76
#define KINETIC_ASSERT(cond)
#define LOG0(message)
#define LOGF0(message,...)
#define PDU_HEADER_LEN
void KineticLogger_LogProtobuf(int log_level, const Com__Seagate__Kinetic__Proto__Message *msg)
KineticStatus
Kinetic status codes.
size_t com__seagate__kinetic__proto__command__pack(const Com__Seagate__Kinetic__Proto__Command *message, uint8_t *out)
Definition: kinetic.pb-c.c:253
void KineticLogger_LogByteArray(int log_level, const char *title, ByteArray bytes)
KineticStatus KineticAuth_PopulateHmac(KineticSessionConfig const *const config, KineticRequest *const pdu)
Definition: kinetic_auth.c:33
#define KINETIC_REQUEST_PACK_FAILURE
size_t com__seagate__kinetic__proto__message__pack(const Com__Seagate__Kinetic__Proto__Message *message, uint8_t *out)
Definition: kinetic.pb-c.c:78
size_t com__seagate__kinetic__proto__message__get_packed_size(const Com__Seagate__Kinetic__Proto__Message *message)
Definition: kinetic.pb-c.c:72
bool KineticRequest_SendRequest(KineticOperation *operation, uint8_t *msg, size_t msgSize)
bool KineticRequest_UnlockSend(KineticSession *session)
#define LOGF2(message,...)