Как сохранить 32-разрядное целое число со знаком с прямым порядком байтов в bash? - PullRequest
0 голосов
/ 05 октября 2018

(* В следующем посте все IP, порты и пароли были изменены. Извините за форматирование этого поста, редактору не нравятся новые строки.)

Вопрос: Как сделатьЯ храню целые числа как 32-битные числа с прямым порядком байтов со знаком?

Справочная информация: Я пытаюсь использовать RCon для соединения с сервером Minecraft в bash.Пока сервер показывает, что соединение получено, но я не могу правильно отформатировать пакет.Я могу подключиться к серверу с помощью mcrcon и увидеть пакеты в wireshark, но когда я пытаюсь использовать мой bash-скрипт, значения длины пакета, requesttid и type выглядят неправильно.

Ниже приведены некоторые из моих источников, устранение неполадокданные и мой код, которые могут помочь в ответе на вопрос.

Источник: https://wiki.vg/RCON

Реализация: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol

Консоль сервера:

[22:24:09 ВНИМАНИЕ]: Не успеваю!Сервер перегружен?Выполнение 3190 мс или 63 тика позади

[22:24:23 ИНФОРМАЦИЯ]: Rcon соединение от: /164.256.8.10

[22:24:34 ПРЕДУПРЕЖДЕНИЕ]: Не может идти в ногу!Сервер перегружен?Выполнение 9961 мс или 199 тиков позади

[22:24:55 ВНИМАНИЕ]: Не успеваю!Сервер перегружен?Запуск 2006 мс или 40 тиков позади

[22:25:12 ИНФОРМАЦИЯ]: Rcon соединение от: /164.256.8.10

.

Wireshark: (данные mcrcon) mcrcon packets

Код:

#!/bin/bash

# Length    int     Length of remainder of packet
# Request ID    int     Client-generated ID
# Type  int     3 for login, 2 to run a command, 0 for a multi-packet response
# Payload   byte[]  ASCII text
# 2-byte pad    byte, byte  Two null bytes 

# Connection details
RCON_HEADER=$(echo -e "\xff\xff\xff\xff")
HOST="192.168.0.173"
PORT=12345  
LENGTH=0 # Length of packet
REQUESTID=$RANDOM
PASSWORD="$1"
RES=0
COM=2
AUTH=3
NULL="\0"
COMMAND=${@:2}
echo "command: $COMMAND"



## Packet Format as per docs
#Packet Size in Bytes
#Request ID any int
#Type as above
#Body null terminated ascii string
#Empty string null terminated

build_packet()
{
    local TYPE="$1";
    $([ "$TYPE" == "$AUTH" ]) && local BODY="$PASSWORD" || local BODY=$COMMAND;
    local DATA="$REQUESTID$TYPE$BODY";    
    local LENGTH=${#DATA};
    local PACKET="$LENGTH$DATA";    
    echo $PACKET;
}



send()
{
    #local PACKET="$1"
    echo "sending: $PACKET"
    printf "$PACKET%s\0%s\0" >&5 &
}

read ()
{
    LENGTH="$1"
    RETURN=`dd bs=$1 count=1 <&5 2> /dev/null`
}


echo "trying to open socket"
# try to connect
if ! exec 5<> /dev/tcp/$HOST/$PORT; then
  echo "`basename $0`: unable to connect to $HOST:$PORT"
  exit 1
fi
echo "socket is open"


PACKET=$(build_packet $AUTH $PASSWORD);
echo "Command: $COMMAND"
echo "Packet: $PACKET"

send $PACKET

read 7
echo "RETURN: $RETURN"


PACKET=$(build_packet $COM $COMMAND);
echo "Command: $COMMAND"
echo "Packet: $PACKET"


send $PACKET

read 7
echo "RETURN: $RETURN"

.

Код ссылки: https://blog.chris007.de/using-bash-for-network-socket-operation/

1 Ответ

0 голосов
/ 15 октября 2018

Решением было шестнадцатеричное кодирование и декодирование следующим образом:

build_packet()
{
    local TYPE="$1"
    local BODY=""
    $([ "$TYPE" == "$AUTH" ]) && BODY="$PASSWORD" || BODY="$COMMAND"

    # Add null chars "\0" and hex encode to preserve them "xxd -p".
    # David C Rankin also mentioned, you could possibly printf them in using flags.
    local DATA=`echo -ne "$ID\0\0\0\0$TYPE\0\0\0$BODY\0\0" | xxd -p | tr -d '\n'`

    local LEN="${#DATA}"
    LEN=$((LEN / 2))
    LEN="$(asc $LEN)"  
    LEN=`echo -ne "$LEN\0\0\0" | xxd -p | tr -d '\n'`
    local PACKET="$LEN$DATA"    
    echo $PACKET
}

Примечания: # (asc) - это пользовательская функция, которая преобразует LEN в ascii char.Я понятия не имею, почему длина пакета должна быть символом ascii, а тип, который также является целым числом, - нет.Возможно, кто-то еще может ответить на этот вопрос.

Во время передачи гекс декодируется "echo -ne" $ PACKET "| xxd -r -p> & 5 &".

...