mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.8 KiB
106 lines
2.8 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/****************************************************************************** |
|
******************************************************************************* |
|
** |
|
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
|
** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
|
** |
|
** |
|
******************************************************************************* |
|
******************************************************************************/ |
|
|
|
/* |
|
* midcomms.c |
|
* |
|
* This is the appallingly named "mid-level" comms layer. |
|
* |
|
* Its purpose is to take packets from the "real" comms layer, |
|
* split them up into packets and pass them to the interested |
|
* part of the locking mechanism. |
|
* |
|
* It also takes messages from the locking layer, formats them |
|
* into packets and sends them to the comms layer. |
|
*/ |
|
|
|
#include <asm/unaligned.h> |
|
|
|
#include "dlm_internal.h" |
|
#include "lowcomms.h" |
|
#include "config.h" |
|
#include "lock.h" |
|
#include "midcomms.h" |
|
|
|
/* |
|
* Called from the low-level comms layer to process a buffer of |
|
* commands. |
|
*/ |
|
|
|
int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len) |
|
{ |
|
const unsigned char *ptr = buf; |
|
const struct dlm_header *hd; |
|
uint16_t msglen; |
|
int ret = 0; |
|
|
|
while (len >= sizeof(struct dlm_header)) { |
|
hd = (struct dlm_header *)ptr; |
|
|
|
/* no message should be more than this otherwise we |
|
* cannot deliver this message to upper layers |
|
*/ |
|
msglen = get_unaligned_le16(&hd->h_length); |
|
if (msglen > DEFAULT_BUFFER_SIZE || |
|
msglen < sizeof(struct dlm_header)) { |
|
log_print("received invalid length header: %u from node %d, will abort message parsing", |
|
msglen, nodeid); |
|
return -EBADMSG; |
|
} |
|
|
|
/* caller will take care that leftover |
|
* will be parsed next call with more data |
|
*/ |
|
if (msglen > len) |
|
break; |
|
|
|
switch (hd->h_cmd) { |
|
case DLM_MSG: |
|
if (msglen < sizeof(struct dlm_message)) { |
|
log_print("dlm msg too small: %u, will skip this message", |
|
msglen); |
|
goto skip; |
|
} |
|
|
|
break; |
|
case DLM_RCOM: |
|
if (msglen < sizeof(struct dlm_rcom)) { |
|
log_print("dlm rcom msg too small: %u, will skip this message", |
|
msglen); |
|
goto skip; |
|
} |
|
|
|
break; |
|
default: |
|
log_print("unsupported h_cmd received: %u, will skip this message", |
|
hd->h_cmd); |
|
goto skip; |
|
} |
|
|
|
/* for aligned memory access, we just copy current message |
|
* to begin of the buffer which contains already parsed buffer |
|
* data and should provide align access for upper layers |
|
* because the start address of the buffer has a aligned |
|
* address. This memmove can be removed when the upperlayer |
|
* is capable of unaligned memory access. |
|
*/ |
|
memmove(buf, ptr, msglen); |
|
dlm_receive_buffer((union dlm_packet *)buf, nodeid); |
|
|
|
skip: |
|
ret += msglen; |
|
len -= msglen; |
|
ptr += msglen; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
|