kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
kinetic_builder.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_builder.h"
21 #include "kinetic_operation.h"
22 #include "kinetic_controller.h"
23 #include "kinetic_session.h"
24 #include "kinetic_message.h"
25 #include "kinetic_bus.h"
26 #include "kinetic_response.h"
27 #include "kinetic_device_info.h"
28 #include "kinetic_allocator.h"
29 #include "kinetic_logger.h"
30 #include "kinetic_request.h"
31 #include "kinetic_acl.h"
32 #include "kinetic_callbacks.h"
33 
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <sys/time.h>
37 #include <stdio.h>
38 
39 #include "kinetic_acl.h"
40 
41 /*******************************************************************************
42  * Standard Client Operations
43 *******************************************************************************/
44 
45 KineticStatus KineticBuilder_BuildNoop(KineticOperation* const op)
46 {
48  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__NOOP;
49  op->request->message.command.header->has_messagetype = true;
50  op->opCallback = &KineticCallbacks_Basic;
52 }
53 
54 KineticStatus KineticBuilder_BuildPut(KineticOperation* const op,
55  KineticEntry* const entry)
56 {
58 
59  if (entry->value.bytesUsed > KINETIC_OBJ_SIZE) {
60  LOGF2("Value exceeds maximum size. Packed size is: %d, Max size is: %d", entry->value.bytesUsed, KINETIC_OBJ_SIZE);
62  }
63 
64  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PUT;
65  op->request->message.command.header->has_messagetype = true;
66  op->entry = entry;
67 
68  KineticMessage_ConfigureKeyValue(&op->request->message, op->entry);
69 
70  op->value.data = op->entry->value.array.data;
71  op->value.len = op->entry->value.bytesUsed;
72  op->opCallback = &KineticCallbacks_Put;
73 
75 }
76 
77 static void build_get_command(KineticOperation* const op,
78  KineticEntry* const entry,
81 {
83 
84  op->request->message.command.header->messagetype = command_id;
85  op->request->message.command.header->has_messagetype = true;
86  op->entry = entry;
87 
88  KineticMessage_ConfigureKeyValue(&op->request->message, entry);
89 
90  if (op->entry->value.array.data != NULL) {
91  ByteBuffer_Reset(&op->entry->value);
92  op->value.data = op->entry->value.array.data;
93  op->value.len = op->entry->value.bytesUsed;
94  }
95 
96  op->opCallback = cb;
97 }
98 
99 KineticStatus KineticBuilder_BuildGet(KineticOperation* const op,
100  KineticEntry* const entry)
101 {
104 
105  return KINETIC_STATUS_SUCCESS;
106 }
107 
109  KineticEntry* const entry)
110 {
113 
114  return KINETIC_STATUS_SUCCESS;
115 }
116 
117 KineticStatus KineticBuilder_BuildGetNext(KineticOperation* const op,
118  KineticEntry* const entry)
119 {
122 
123  return KINETIC_STATUS_SUCCESS;
124 }
125 
126 KineticStatus KineticBuilder_BuildFlush(KineticOperation* const op)
127 {
129 
130  op->request->message.command.header->messagetype =
132  op->request->message.command.header->has_messagetype = true;
133  op->opCallback = &KineticCallbacks_Basic;
134 
135  return KINETIC_STATUS_SUCCESS;
136 }
137 
138 KineticStatus KineticBuilder_BuildDelete(KineticOperation* const op,
139  KineticEntry* const entry)
140 {
142 
143  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__DELETE;
144  op->request->message.command.header->has_messagetype = true;
145  op->entry = entry;
146 
147  KineticMessage_ConfigureKeyValue(&op->request->message, op->entry);
148 
149  if (op->entry->value.array.data != NULL) {
150  ByteBuffer_Reset(&op->entry->value);
151  op->value.data = op->entry->value.array.data;
152  op->value.len = op->entry->value.bytesUsed;
153  }
154 
155  op->opCallback = &KineticCallbacks_Delete;
156 
157  return KINETIC_STATUS_SUCCESS;
158 }
159 
161  KineticKeyRange* range, ByteBufferArray* buffers)
162 {
164  KINETIC_ASSERT(range != NULL);
165  KINETIC_ASSERT(buffers != NULL);
166 
167  op->request->command->header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETKEYRANGE;
168  op->request->command->header->has_messagetype = true;
169 
170  KineticMessage_ConfigureKeyRange(&op->request->message, range);
171 
172  op->buffers = buffers;
173  op->opCallback = &KineticCallbacks_GetKeyRange;
174 
175  return KINETIC_STATUS_SUCCESS;
176 }
177 
178 Com__Seagate__Kinetic__Proto__Command__P2POperation* build_p2pOp(uint32_t nestingLevel, KineticP2P_Operation const * const p2pOp)
179 {
180  // limit nesting level to KINETIC_P2P_MAX_NESTING
181  if (nestingLevel >= KINETIC_P2P_MAX_NESTING) {
182  LOGF0("P2P op nesting level is too deep. Max is %d.", KINETIC_P2P_MAX_NESTING);
183  return NULL;
184  }
185 
186  Com__Seagate__Kinetic__Proto__Command__P2POperation* proto_p2pOp = calloc(1, sizeof(Com__Seagate__Kinetic__Proto__Command__P2POperation));
187  if (proto_p2pOp == NULL) { goto error_cleanup; }
188 
190 
191  proto_p2pOp->peer = calloc(1, sizeof(Com__Seagate__Kinetic__Proto__Command__P2POperation__Peer));
192  if (proto_p2pOp->peer == NULL) { goto error_cleanup; }
193 
195 
196  proto_p2pOp->peer->hostname = p2pOp->peer.hostname;
197  proto_p2pOp->peer->has_port = true;
198  proto_p2pOp->peer->port = p2pOp->peer.port;
199  proto_p2pOp->peer->has_tls = true;
200  proto_p2pOp->peer->tls = p2pOp->peer.tls;
201 
202  proto_p2pOp->n_operation = p2pOp->numOperations;
203  proto_p2pOp->operation = calloc(p2pOp->numOperations, sizeof(Com__Seagate__Kinetic__Proto__Command__P2POperation__Operation*));
204  if (proto_p2pOp->operation == NULL) { goto error_cleanup; }
205 
206  for(size_t i = 0; i < proto_p2pOp->n_operation; i++) {
207  KINETIC_ASSERT(!ByteBuffer_IsNull(p2pOp->operations[i].key)); // TODO return invalid operand?
208 
209  Com__Seagate__Kinetic__Proto__Command__P2POperation__Operation * p2p_op_op = calloc(1, sizeof(Com__Seagate__Kinetic__Proto__Command__P2POperation__Operation));
210  if (p2p_op_op == NULL) { goto error_cleanup; }
211 
213 
214  p2p_op_op->has_key = true;
215  p2p_op_op->key.data = p2pOp->operations[i].key.array.data;
216  p2p_op_op->key.len = p2pOp->operations[i].key.bytesUsed;
217 
218  p2p_op_op->has_newkey = !ByteBuffer_IsNull(p2pOp->operations[i].newKey);
219  p2p_op_op->newkey.data = p2pOp->operations[i].newKey.array.data;
220  p2p_op_op->newkey.len = p2pOp->operations[i].newKey.bytesUsed;
221 
222  p2p_op_op->has_version = !ByteBuffer_IsNull(p2pOp->operations[i].version);
223  p2p_op_op->version.data = p2pOp->operations[i].version.array.data;
224  p2p_op_op->version.len = p2pOp->operations[i].version.bytesUsed;
225 
226  // force if no version was specified
227  p2p_op_op->has_force = ByteBuffer_IsNull(p2pOp->operations[i].version);
228  p2p_op_op->force = ByteBuffer_IsNull(p2pOp->operations[i].version);
229 
230  if (p2pOp->operations[i].chainedOperation == NULL) {
231  p2p_op_op->p2pop = NULL;
232  } else {
233  p2p_op_op->p2pop = build_p2pOp(nestingLevel + 1, p2pOp->operations[i].chainedOperation);
234  if (p2p_op_op->p2pop == NULL) { goto error_cleanup; }
235  }
236 
237  p2p_op_op->status = NULL;
238 
239  proto_p2pOp->operation[i] = p2p_op_op;
240  }
241  return proto_p2pOp;
242 
243 error_cleanup:
245  return NULL;
246 }
247 
249  KineticP2P_Operation* const p2pOp)
250 {
252 
253  op->request->command->header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PEER2PEERPUSH;
254  op->request->command->header->has_messagetype = true;
255  op->request->command->body = &op->request->message.body;
256  op->p2pOp = p2pOp;
257  op->opCallback = &KineticCallbacks_P2POperation;
258 
259  op->request->command->body->p2poperation = build_p2pOp(0, p2pOp);
260 
261  if (op->request->command->body->p2poperation == NULL) {
263  }
264 
265  if (p2pOp->numOperations >= KINETIC_P2P_OPERATION_LIMIT) {
267  }
268 
269  return KINETIC_STATUS_SUCCESS;
270 }
271 
272 
273 
274 /*******************************************************************************
275  * Admin Client Operations
276 *******************************************************************************/
277 
278 KineticStatus KineticBuilder_BuildGetLog(KineticOperation* const op,
280 {
282 
283  op->request->command->header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETLOG;
284  op->request->command->header->has_messagetype = true;
285  op->request->command->body = &op->request->message.body;
286  op->request->command->body->getlog = &op->request->message.getLog;
287  op->request->command->body->getlog->types = &op->request->message.getLogType;
288  op->request->command->body->getlog->types[0] = type;
289  op->request->command->body->getlog->n_types = 1;
290 
292  if (name.data == NULL || name.len == 0) {
294  }
295  op->request->message.getLogDevice.name.data = name.data;
296  op->request->message.getLogDevice.name.len = name.len;
297  op->request->message.getLogDevice.has_name = true;
298  op->request->command->body->getlog->device = &op->request->message.getLogDevice;
299  }
300 
301  op->deviceInfo = info;
302  op->opCallback = &KineticCallbacks_GetLog;
303 
304  return KINETIC_STATUS_SUCCESS;
305 }
306 
307 KineticStatus KineticBuilder_BuildSetPin(KineticOperation* const op, ByteArray old_pin, ByteArray new_pin, bool lock)
308 {
310 
311  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SECURITY;
312  op->request->message.command.header->has_messagetype = true;
313  op->request->command->body = &op->request->message.body;
314  op->request->command->body->security = &op->request->message.security;
315 
316  if (lock) {
317  op->request->message.security.oldlockpin = (ProtobufCBinaryData) {
318  .data = old_pin.data, .len = old_pin.len };
319  op->request->message.security.has_oldlockpin = true;
320  op->request->message.security.newlockpin = (ProtobufCBinaryData) {
321  .data = new_pin.data, .len = new_pin.len };
322  op->request->message.security.has_newlockpin = true;
323  }
324  else {
325  op->request->message.security.olderasepin = (ProtobufCBinaryData) {
326  .data = old_pin.data, .len = old_pin.len };
327  op->request->message.security.has_olderasepin = true;
328  op->request->message.security.newerasepin = (ProtobufCBinaryData) {
329  .data = new_pin.data, .len = new_pin.len };
330  op->request->message.security.has_newerasepin = true;
331  }
332 
333  op->opCallback = &KineticCallbacks_Basic;
334  op->request->pinAuth = false;
335  op->timeoutSeconds = KineticOperation_TimeoutSetPin;
336 
337  return KINETIC_STATUS_SUCCESS;
338 }
339 
340 KineticStatus KineticBuilder_BuildErase(KineticOperation* const op, bool secure_erase, ByteArray* pin)
341 {
343 
344  op->pin = pin;
345  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PINOP;
346  op->request->message.command.header->has_messagetype = true;
347  op->request->command->body = &op->request->message.body;
348  op->request->command->body->pinop = &op->request->message.pinOp;
349  op->request->command->body->pinop->pinoptype = secure_erase ?
352  op->request->command->body->pinop->has_pinoptype = true;
353 
354  op->opCallback = &KineticCallbacks_Basic;
355  op->request->pinAuth = true;
356  op->timeoutSeconds = KineticOperation_TimeoutErase;
357 
358  return KINETIC_STATUS_SUCCESS;
359 }
360 
361 KineticStatus KineticBuilder_BuildLockUnlock(KineticOperation* const op, bool lock, ByteArray* pin)
362 {
364 
365  op->pin = pin;
366  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PINOP;
367  op->request->message.command.header->has_messagetype = true;
368  op->request->command->body = &op->request->message.body;
369  op->request->command->body->pinop = &op->request->message.pinOp;
370 
371  op->request->command->body->pinop->pinoptype = lock ?
374  op->request->command->body->pinop->has_pinoptype = true;
375 
376  op->opCallback = &KineticCallbacks_Basic;
377  op->request->pinAuth = true;
378  op->timeoutSeconds = KineticOperation_TimeoutLockUnlock;
379 
380  return KINETIC_STATUS_SUCCESS;
381 }
382 
383 KineticStatus KineticBuilder_BuildSetClusterVersion(KineticOperation* op, int64_t new_cluster_version)
384 {
386 
387  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SETUP;
388  op->request->message.command.header->has_messagetype = true;
389  op->request->command->body = &op->request->message.body;
390 
391  op->request->command->body->setup = &op->request->message.setup;
392  op->request->command->body->setup->newclusterversion = new_cluster_version;
393  op->request->command->body->setup->has_newclusterversion = true;
394 
395  op->opCallback = &KineticCallbacks_SetClusterVersion;
396  op->pendingClusterVersion = new_cluster_version;
397 
398  return KINETIC_STATUS_SUCCESS;
399 }
400 
401 KineticStatus KineticBuilder_BuildSetACL(KineticOperation* const op,
402  struct ACL *ACLs)
403 {
405 
406  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SECURITY;
407  op->request->message.command.header->has_messagetype = true;
408  op->request->command->body = &op->request->message.body;
409  op->request->command->body->security = &op->request->message.security;
410 
411  op->request->command->body->security->n_acl = ACLs->ACL_count;
412  op->request->command->body->security->acl = ACLs->ACLs;
413 
414  op->opCallback = &KineticCallbacks_SetACL;
415  op->timeoutSeconds = KineticOperation_TimeoutSetACL;
416 
417  return KINETIC_STATUS_SUCCESS;
418 }
419 
420 KineticStatus KineticBuilder_BuildUpdateFirmware(KineticOperation* const op, const char* fw_path)
421 {
423 
425  FILE* fp = NULL;
426 
427  if (fw_path == NULL) {
428  LOG0("ERROR: FW update file was NULL");
430  goto cleanup;
431  }
432 
433  fp = fopen(fw_path, "r");
434  if (fp == NULL) {
435  LOG0("ERROR: Specified FW update file could not be opened");
437  goto cleanup;
438  }
439 
440  if (fseek(fp, 0L, SEEK_END) != 0) {
441  LOG0("ERROR: Specified FW update file could not be seek");
443  goto cleanup;
444  }
445 
446  long len = ftell(fp);
447  if (len < 1) {
448  LOG0("ERROR: Specified FW update file could not be queried for length");
450  goto cleanup;
451  }
452  if (fseek(fp, 0L, SEEK_SET) != 0) {
453  LOG0("ERROR: Specified FW update file could not be seek back to start");
455  goto cleanup;
456  }
457 
458  op->value.data = calloc(len, 1);
459  if (op->value.data == NULL) {
460  LOG0("ERROR: Failed allocating memory to store FW update image");
462  goto cleanup;
463  }
464 
465  size_t read = fread(op->value.data, 1, len, fp);
466  if ((long)read != len) {
467  LOGF0("ERROR: Expected to read %ld bytes from FW file, but read %zu", len, read);
469  goto cleanup;
470  }
471  fclose(fp);
472 
473  op->value.len = len;
474 
475  op->request->message.command.header->messagetype = COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SETUP;
476  op->request->message.command.header->has_messagetype = true;
477  op->request->command->body = &op->request->message.body;
478 
479  op->request->command->body->setup = &op->request->message.setup;
480  op->request->command->body->setup->firmwaredownload = true;
481  op->request->command->body->setup->has_firmwaredownload = true;
482 
483  op->opCallback = &KineticCallbacks_UpdateFirmware;
484 
485  return KINETIC_STATUS_SUCCESS;
486 
487 cleanup:
488  if (fp != NULL) {
489  fclose(fp);
490  }
491  return status;
492 }
KineticStatus KineticBuilder_BuildLockUnlock(KineticOperation *const op, bool lock, ByteArray *pin)
Structure for handling generic arrays of bytes.
Definition: byte_array.h:34
void ByteBuffer_Reset(ByteBuffer *buffer)
Definition: byte_array.c:62
void com__seagate__kinetic__proto__command__p2_poperation__peer__init(Com__Seagate__Kinetic__Proto__Command__P2POperation__Peer *message)
Definition: kinetic.pb-c.c:151
Com__Seagate__Kinetic__Proto__Command__MessageType
Definition: kinetic.pb-c.h:304
void KineticMessage_ConfigureKeyRange(KineticMessage *const message, const KineticKeyRange *range)
One or more of byte buffers did not fit all data.
KineticStatus KineticBuilder_BuildSetACL(KineticOperation *const op, struct ACL *ACLs)
KineticStatus KineticBuilder_BuildGetLog(KineticOperation *const op, Com__Seagate__Kinetic__Proto__Command__GetLog__Type type, ByteArray name, KineticLogInfo **info)
Operation successful.
KineticStatus KineticBuilder_BuildGetPrevious(KineticOperation *const op, KineticEntry *const entry)
KineticStatus KineticCallbacks_Get(KineticOperation *const operation, KineticStatus const status)
void com__seagate__kinetic__proto__command__p2_poperation__operation__init(Com__Seagate__Kinetic__Proto__Command__P2POperation__Operation *message)
Definition: kinetic.pb-c.c:145
#define KINETIC_OBJ_SIZE
Max object/value size.
Definition: kinetic_types.h:47
Com__Seagate__Kinetic__Proto__Command__P2POperation * build_p2pOp(uint32_t nestingLevel, KineticP2P_Operation const *const p2pOp)
KineticStatus KineticCallbacks_Delete(KineticOperation *const operation, KineticStatus const status)
#define KINETIC_P2P_MAX_NESTING
Limit for P2P operation nesting.
Failed allocating/deallocating memory.
void KineticOperation_ValidateOperation(KineticOperation *op)
KineticStatus KineticBuilder_BuildSetPin(KineticOperation *const op, ByteArray old_pin, ByteArray new_pin, bool lock)
void KineticMessage_ConfigureKeyValue(KineticMessage *const message, const KineticEntry *entry)
void com__seagate__kinetic__proto__command__p2_poperation__init(Com__Seagate__Kinetic__Proto__Command__P2POperation *message)
Definition: kinetic.pb-c.c:157
Com__Seagate__Kinetic__Proto__Command__GetLog__Type
Definition: kinetic.pb-c.h:161
Kinetic object instance.
KineticStatus KineticBuilder_BuildPut(KineticOperation *const op, KineticEntry *const entry)
KineticStatus KineticBuilder_BuildUpdateFirmware(KineticOperation *const op, const char *fw_path)
Kinetic Key Range request structure.
KineticStatus KineticBuilder_BuildGet(KineticOperation *const op, KineticEntry *const entry)
void KineticAllocator_FreeP2PProtobuf(Com__Seagate__Kinetic__Proto__Command__P2POperation *proto_p2pOp)
Base log info structure which is allocated by client and passed to KineticAdminClient_GetLog.
KineticStatus(* KineticOperationCallback)(KineticOperation *const operation, KineticStatus const status)
#define KINETIC_ASSERT(cond)
KineticStatus KineticBuilder_BuildNoop(KineticOperation *const op)
Specified file does not exist or could not be read/writtten.
KineticStatus KineticBuilder_BuildGetKeyRange(KineticOperation *const op, KineticKeyRange *range, ByteBufferArray *buffers)
#define LOG0(message)
KineticStatus KineticCallbacks_SetACL(KineticOperation *const operation, KineticStatus const status)
KineticStatus KineticCallbacks_GetKeyRange(KineticOperation *const operation, KineticStatus const status)
Operation was invalid.
size_t len
Number of bytes in the data field.
Definition: byte_array.h:35
Com__Seagate__Kinetic__Proto__Command__Security__ACL ** ACLs
ACL struct array.
#define LOGF0(message,...)
KineticStatus KineticCallbacks_P2POperation(KineticOperation *const operation, KineticStatus const status)
bool ByteBuffer_IsNull(ByteBuffer const buffer)
Definition: byte_array.c:249
KineticStatus KineticBuilder_BuildGetNext(KineticOperation *const op, KineticEntry *const entry)
static void build_get_command(KineticOperation *const op, KineticEntry *const entry, KineticOperationCallback cb, Com__Seagate__Kinetic__Proto__Command__MessageType command_id)
uint8_t * data
Pointer to an allocated array of data bytes.
Definition: byte_array.h:36
KineticStatus KineticCallbacks_Basic(KineticOperation *const operation, KineticStatus const status)
KineticStatus KineticCallbacks_Put(KineticOperation *const operation, KineticStatus const status)
Status not available (no reponse/status available)
A device name is required, but was empty.
size_t ACL_count
How many ACL * structs are in ACLs[].
KineticStatus
Kinetic status codes.
KineticStatus KineticBuilder_BuildErase(KineticOperation *const op, bool secure_erase, ByteArray *pin)
KineticStatus KineticCallbacks_SetClusterVersion(KineticOperation *const operation, KineticStatus const status)
size_t bytesUsed
Reflects the number of bytes used from the array
Definition: byte_array.h:55
KineticStatus KineticBuilder_BuildSetClusterVersion(KineticOperation *op, int64_t new_cluster_version)
#define KINETIC_P2P_OPERATION_LIMIT
Limit for P2P operations.
KineticStatus KineticCallbacks_UpdateFirmware(KineticOperation *const operation, KineticStatus const status)
KineticStatus KineticBuilder_BuildP2POperation(KineticOperation *const op, KineticP2P_Operation *const p2pOp)
KineticStatus KineticBuilder_BuildDelete(KineticOperation *const op, KineticEntry *const entry)
KineticStatus KineticBuilder_BuildFlush(KineticOperation *const op)
KineticStatus KineticCallbacks_GetLog(KineticOperation *const operation, KineticStatus const status)
#define LOGF2(message,...)
ByteBuffer value
Value data associated with the key.