header 8 bytes:
unsigned short unk0; // version?
unsigned short size; // data size
unsigned short unk1; //
unsigned short unk2; //
data:
AMF3 correct data: 0x0a 0x0b 0x01 ...
It's not standart AMF: http://en.wikipedia.org/wiki/Action_Message_Format
What is the AMF format?
Flex use AMF to remote call, it transport on HTTP, and you can use HTTP monitor tool like Charles or Fiddler(with FiddlerAmfParser) to see more AMF data.
Related
How can I improve the following code, that is, make it more robust with respect to type safety and endianness using the functions and macros in the Linux kernel's API? For instance, in the following example src_data is an array of two 16-bit signed integers (typically stored in little endian order) and is to be sent out via UART in big endian byte order.
s16 src_data[2] = {...}; /* note: this is signed data! */
u8 tx_data[4];
u8* src_data_u8 = (u8*)src_data;
tx_data[0] = src_data_u8[1];
tx_data[1] = src_data_u8[0];
tx_data[2] = src_data_u8[3];
tx_data[3] = src_data_u8[2];
I think the functions cpu_to_be16 and cpu_to_be16p should play a role in doing this conversion. Although I'm not sure how I can use them in a way that is safe and robust to endianness.
As I understand, two 16-bit words, to be sent, one after another, after converting each into bigendian format.
I think following should be ok.
s16 src_data[2] = {...}; /* note: this is signed data! */
s16 tx_data[2];
tx_data[0] = cpu_to_be16(src_data_u8[0]);
tx_data[1] = cpu_to_be16(src_data_u8[1]);
Your issue with safety seems to be that the htons(x) function/macro expects an unsigned integer, but you possess a signed one. Not an issue:
union {
int16_t signed_repr;
uint16_t unsigned_repr;
} data;
data.signed_repr = ...;
u16 unsigned_big_endian_data = htons(data.unsigned_repr);
memcpy(tx_data, &unsigned_big_endian_data,
min(sizeof tx_data, sizeof unsigned_big_endian_data));
PS. Type-punning via unions is perfectly well-defined.
I believe the following is one of the best answers to my question. I have used the links provided by #0andriy to existing examples in the kernel source code.
Converting a signed 16-bit value for transmitting
s16 src = -5;
u8 dst[2];
__be16 tx_buf;
*(__be16*)dst = cpu_to_be16(src);
Converting multiple signed 16-bit values for transmitting
s16 src[2] = {-5,-2};
u8 dst[4];
s16* psrc = src;
u8* pdst = dst;
int len = sizeof(src);
for ( ; len > 1; len -= 2) {
*(__be16 *)pdst = cpu_to_be16p(psrc++);
pdst += 2;
}
A quick disclaimer, I still need to check if this code is correct / compiles.
Overall, I'm a bit unsatisfied with the solution for copying and converting the endianness of multiple values since it is prone to typos and could easily be implemented into a macro.
If the Linux machine will always be little endian, and the protocol will always be big endian, then the code works fine and you don't need to change anything.
If you for some reason need to make the Linux code endian-independent, then you'd use:
tx_data[0] = ((unsigned int)src_data[0] >> 8) & 0xFF;
tx_data[1] = ((unsigned int)src_data[0] >> 0) & 0xFF;
tx_data[2] = ((unsigned int)src_data[1] >> 8) & 0xFF;
tx_data[3] = ((unsigned int)src_data[1] >> 0) & 0xFF;
Where the cast is there to ensure that the right shifts are not carried out on a signed type, which would invoke non-portable implementation defined behavior.
The advantage of bit shifts compared to any other version is that they work on an abstraction level above the hardware and endianess, letting the specific compiler generate the instructions for the underlying memory access. Code such as u16 >> 8 always means "give me the least significant byte" regardless of where that byte is stored in memory.
I'm creating a 4 bit and 8 bit colour encoding for font. This includes a foreground, background, style, and format. My hope is to use the following struct to represent the data in a 4-byte pack. My intent is to extract it as a single uint32_t that can be converted to binary data and saved in a file.
This is what I currently have:
struct font_pack {
uint8_t : 8;
struct {
uint8_t format : 4;
uint8_t style : 4;
} header;
uint8_t foreground;
uint8_t background;
}
The header contains two half-bytes. format says the colour codes are either 4-bit or 8-bit colour. style is a bit flag set that declares formatter such as bolding and underline.
I am then using the following union to get the raw binary for both writing to file, as well to set or print the data as hex.
union font_raw {
font_pack pack;
uint32_t data;
}
Unfortunately when I print out the hex I get 0x04032100 when I was expecting 0x00120304. Which makes me feel like byte alignment is not guaranteed within a union and endianness is catching me. I was really just hoping to have simple method of packing and unpacking the data into 3 bytes.
Is there any other easy way to do it or am I stuck with making a more traditional function that does the packing and unpacking?
This looks like an endianness issue, for sure. I'm guessing you're on x86/x64 (Intel-like) architecture, which is little-endian and will pack bytes from least-significant to most significant. Provided you are writing and reading the data on the same architecture (so little-endian systems) the endianness will ensure you get byte packing read back in the same order, so your font_pack members should still come out correctly. However if you'll be loading these files on a big-endian system you'll need to go the more traditional route. But if you're on the same endian-ness guaranteed, I'd go with your method. It's nicely elegant :)
edit: If you are reading or writing between different endianness machines, then you could always do something like the following:
#ifdef LITTLE_ENDIAN
struct font_pack {
uint8_t : 8;
struct {
uint8_t format : 4;
uint8_t style : 4;
} header;
uint8_t foreground;
uint8_t background;
}
#else
struct font_pack {
uint8_t background;
uint8_t foreground;
struct {
uint8_t format : 4;
uint8_t style : 4;
} header;
uint8_t : 8;
}
#endif
And then define LITTLE_ENDIAN on your x86 or similar system, and not on the big-endian system. Hope that helps.
I'm running a number of SNMP queries to a Hytera dmr repeater. However, the SNMP object definition looks like this:
rptVswr OBJECT-TYPE
SYNTAX OCTET STRING(SIZE(4))
MAX-ACCESS read-only
STATUS mandatory
DESCRIPTION
"The VSWR.
It should be changed to float format. "
-- 1.3.6.1.4.1.40297.1.2.1.2.4
::= { rptDataInfo 4 }
After running the query, I got an result like this:
Name/OID: rptVswr.0;
Value (OctetString): 0x76 D5 8B 3F
Does anyone have an idea how to convert that string into a readable format?
It should be something like this : 1.15 or 2.15
Many thanks for your help,
BR - Nils
Here is pretty simple C++ app that decodes hex data and converts it to float:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
unsigned char ptr[] = {0x76, 0xD5, 0x8B, 0x3F};
reverse(ptr, ptr + 4);
float f = *reinterpret_cast<float*>(ptr);
cout << f << endl;
return 0;
}
The result is 2.16559e+33
My experience with RF devices is that the SNMP replies are either in decimal or hex format and represent power in mW. If you take your get response 0x76 D5 8B 3F, and convert hex to decimal, you get 1,993,706,303 mW. This translates to 1.9937 kW. For VSWR, this is an accurate and acceptable measurement if your forward power is 2+ MW.
I used FFMPEg codes in my app, where I need to get FLV packets for my program. For this I use avcodec_encode_video2(). My problem is that function creates AVPacket packet, which does not keep a full FLV format, only its body. But I need still its header. Usually another function (av_write_frame()) makes it. I cannot use av_write_frame() in my app, because it does not fit my requirement. So maybe anybody knows a function in ffmpeg library, which could add FLV header to the created packets by avcodec_encode_video2().
The FLV header by itself is relatively simple.
It can be modelized with the following code:
/* FLV file header */
#define FLV_SIGNATURE "FLV"
#define FLV_VERSION ((uint8)0x01)
#define FLV_FLAG_VIDEO ((uint8)0x01)
#define FLV_FLAG_AUDIO ((uint8)0x04)
typedef struct __flv_header {
uint8_t signature[3]; /* always "FLV" */
uint8_t version; /* should be 1 */
uint8_t flags;
uint32_t offset; /* always 9 */
} flv_header;
The flags field is a bitmask telling whether the file possesses video, audio, or both streams. For example, if your file has audio and video, its value will be 5.
Be careful that the offset field is encoded in big-endian, which on little-endian platforms is represented by the value 150994944.
If you do not wish to use such a structure, and have a way to directly write a buffer, you can create it like this:
uint_8 buffer[9] = {0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00, 0x09};
I would like to use MS function to send data.
I didnt find examples where they send other type of data other than const char * .
I tried to send a int, or other, but I failed.
WSASend() and send() both function only take a Char* parameters.
How should i proceed ?
Thanks
Its just a pointer to a buffer, this buffer may contains anything you want.
This char pointer is actually an address to a bytes array, this function requires a length parameter too.
An integer is a 2/4 (short/long) bytes value,
Then if you want to send an integer variable (for example) you have to pass its address, and its length.
WSASend and send are simple functions that send a memory block.
I assume you are talking about C, you have to understand that C's char variables are bytes - 8 bits block, char variables contain any value between 0 and 255.
A pointer to a char var is an address to a byte (which maybe the first cell of a bytes array).
I think thats what confuses you.
I hope you understand.
The const char* parameter indicates that the function is taking a pointer to bytes. Witch really seems to be the result of the original socket api designers being pedantic - C has a generic type to handle any kind of pointer without explicit casts: void*.
You could make a convenience wrapper for send like this - which would allow you to send any (contiguous) thing you can make a pointer to:
int MySend(SOCKET s, const void* buf, int len,int flags)
{
return send(s,(const char*)buf,len,flags);
}
Using void* in place of char* actually makes the api safer, as it can now detect when you do something stupid:
int x=0x1234;
send(s,(const char*)x,sizeof(x),0); // looks right, but is wrong.
mysend(s,x,sizeof(x),0); // this version correctly fails
mysend(s,&x,sizeof(x),0); // correct - pass a pointer to the buffer to send.
WSASend is a bit more tricky to make a convenience wapper for as you have to pass it an array of structs that contain the char*'s - but again its a case of defining an equivalent struct with const void*'s in place of the const char*'s and then casting the data structures to the WSA types in the convenience wrapper. Get it right once, and the rest of the program becomes much easier to determine correct as you don't need casts everywhere hiding potential bugs.