SDL 2 how to check for "no modifiers" (keyboard input) - sdl-2

This is my attempt:
const bool MOD_NONE{SDL_GetModState() == KMOD_NONE};
if(MOD_NONE) std::cout << "none" << std::endl;
However this does not work. Why?
If I print the integer value returned by SDL_GetModState(), without pressing any modifiers the value is 4096. Also why?

Looking at the SDL (2.0.5) source code, here is the SDL_Keymod structure:
typedef enum
{
KMOD_NONE = 0x0000,
KMOD_LSHIFT = 0x0001,
KMOD_RSHIFT = 0x0002,
KMOD_LCTRL = 0x0040,
KMOD_RCTRL = 0x0080,
KMOD_LALT = 0x0100,
KMOD_RALT = 0x0200,
KMOD_LGUI = 0x0400,
KMOD_RGUI = 0x0800,
KMOD_NUM = 0x1000,
KMOD_CAPS = 0x2000,
KMOD_MODE = 0x4000,
KMOD_RESERVED = 0x8000
} SDL_Keymod;
The value 4096 you get when calling SDL_GetModState corresponds to the "Num Lock" key (which doesn't have to be physically pressed to be active, just like the Caps Lock key).
What you likely want is to check for the Alt, Shift, Ctrl and Gui keys (the Gui key is the special OS-specific key, if I'm not mistaken).
const SDL_Keymod modkeys = KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI;
const bool MOD_NONE{(SDL_GetModState() & modkeys) == KMOD_NONE};
// or simply
const auto modkeys = KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI;
const bool MOD_NONE = !(SDL_GetModState() & modkeys);

Related

Error 65535 from CommDlgExtendedError after calling GetFileSaveName

So, I'm calling GetFileSaveName from some C code. The C code is called from PowerBuilder, but I really don't think that is relevant.
On just one user's computer currently (Windows 10, updates done), it returns 0, then CommDlgExtendedError return 65535 (CDERR_DIALOGFAILURE), which the docs say means "The dialog box could not be created. The common dialog box function's call to the DialogBox function failed. For example, this error occurs if the common dialog box call specifies an invalid window handle."
I know that the common dialogs aren't completely broken on her PC - I can pull up a File Open or Save dialog in Notepad, for instance.
I had a bug in my code giving the same error number in the past, where in the OPENFILENAME structure I passed in to GetOpenFileName I had set the hWndOwner variable to a handle to a window that no longer exists, but in this case it is being set to 0, so that's not the problem.
The same code is working for thousands of other users of our software! Any bright ideas what could be going on? Thanks.
OK, people have asked me to post my code initializing the OpenFileName structure. It's PowerScript (PowerBuilder's coding language) but should be pretty comprehensible).
OPENFILENAME iOFN
CONSTANT long CHARSIZE = 2
aul_flags = OFN_HIDEREADONLY + OFN_EXPLORER +
OFN_FILEMUSTEXIST+ OFN_NOCHANGEDIR + OFN_DONTADDTORECENT
RtlZeroMemory(iOFN, ll_sizeof)
// initialize structure
iOFN.lStructSize = ll_sizeof
iOFN.nFilterIndex = 1
iOFN.nMaxFile = MAX_LENGTH
iOFN.hWndOwner = il_hWnd
iOFN.Flags = aul_flags + OFN_ENABLESIZING /* needed when using hook procedure */
// allocate memory and copy title
ll_length = Len(as_title) * CHARSIZE
iOFN.lpstrTitle = LocalAlloc(LMEM_ZEROINIT, ll_length + 2)
RtlMoveMemory(iOFN.lpstrTitle, as_title, ll_length)
// allocate memory and copy filter
this.of_Parse(",", as_filter, ls_filter)
li_max = UpperBound(ls_filter) /* count of 1-based array elements */
For li_cnt = 1 To li_max
ll_length = this.of_StringToChar(Trim(ls_filter[li_cnt]), lc_filter)
Next
ll_length = UpperBound(lc_filter) * CHARSIZE
iOFN.lpstrFilter = LocalAlloc(LMEM_ZEROINIT, ll_length)
RtlMoveMemory(iOFN.lpstrFilter, lc_filter, ll_length)
// allocate memory and copy default extension (if given)
If as_extension <> "" Then
ll_length = Len(as_extension) * CHARSIZE
iOFN.lpstrDefExt = LocalAlloc(LMEM_ZEROINIT, ll_length)
RtlMoveMemory(iOFN.lpstrDefExt, as_extension, ll_length)
End If
// allocate memory and copy initialdir (if given)
If as_initdir <> "" Then
ll_length = Len(as_initdir) * CHARSIZE
iOFN.lpstrInitialDir = LocalAlloc(LMEM_ZEROINIT, ll_length)
RtlMoveMemory(iOFN.lpstrInitialDir, as_initdir, ll_length)
End If
// allocate memory for returned data
lc_pathname = Space(MAX_LENGTH)
iOFN.nMaxFile = MAX_LENGTH
iOFN.lpstrFile = LocalAlloc(LMEM_ZEROINIT, MAX_LENGTH)
If as_initialfile <> "" Then
ll_length = Len(as_initialfile) * CHARSIZE
RtlMoveMemory(iOFN.lpstrFile, as_initialfile, ll_length)
End If
// display dialog box
lb_return = GetOpenFileName(iOFN)
I recommend you to check if there is any problem with the OPENFILENAME parameter configuration. There are many parameters in OPENFILENAME that need to be configured before GetSaveFileName can be used. Maybe there is something wrong.
TCHAR szFilename[MAX_PATH] = TEXT("");
BOOL bResult = FALSE;
DWORD dwError = NOERROR;
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFilter = TEXT("All Files\0*.*\0\0");
ofn.lpstrFile = szFilename;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER |
OFN_ENABLEHOOK |
OFN_HIDEREADONLY |
OFN_NOCHANGEDIR |
OFN_PATHMUSTEXIST;
bResult = GetSaveFileName(&ofn);
if (bResult == FALSE)
{
dwError = CommDlgExtendedError();
return dwError;
}

enum value defined in hex grows and turns into negative value

I'm maintaining a project which contains following enum type definition. enum values are used in
a combobox.
Why this enum type is defined in hex like this, for performance improvement?
xxxxx920P3 is actually a negative value -2147483648 and xxxxx920P2 is positive, it causes the conditional code to fail.The next value will be twice bigger as the xxxxx920P3, so any alternative solution for this enum definition rule? thanks.
It is a QT c++ project. Can I define a enum type to ULONGLONG?
enum Version
{
xxxxx = 0x00000000,
xxxxx400 = 0x00000001,
xxxxx401 = 0x00000002,
xxxxx410 = 0x00000004,
xxxxx411 = 0x00000008,
xxxxx412 = 0x00000010,
xxxxx420 = 0x00000020,
xxxxx430 = 0x00000040,
xxxxx431 = 0x00000080,
xxxxx432 = 0x00000100,
xxxxx440 = 0x00000200,
xxxxx500 = 0x00000400,
xxxxx510 = 0x00000800,
xxxxx520 = 0x00001000,
xxxxx521 = 0x00002000,
xxxxx600 = 0x00004000,
xxxxx611 = 0x00008000,
xxxxx620 = 0x00010000,
xxxxx621 = 0x00020000,
xxxxx700 = 0x00040000,
xxxxx910 = 0x00080000,
xxxxx910P5 = 0x00100000,
xxxxx910P6 = 0x00200000,
xxxxx910P11 = 0x00400000,
xxxxx910P12 = 0x00800000,
xxxxx910P13 = 0x01000000,
xxxxx910P14 = 0x02000000,
xxxxx910P15 = 0x04000000,
xxxxx910P16 = 0x08000000,
xxxxx920 = 0x10000000,
xxxxx920P1 = 0x20000000,
xxxxx920P2 = 0x40000000,
xxxxx920P3 = 0x80000000,
};
Versions newVersions = (Version)mComboBox->itemData(inIndex).toUInt();
if ( newVersions < xxxxx500) //now newVersions is a negative value
{
}
else
{
}
In Standard C enumerators have type int and the value must be in range of int. The 0x80000000 is out of range for int, this is a constraint violation that requires a diagnostic.
So what is happening depends on your compiler. The compiler implements an extension of its own devising for enumerators out of range for int. Based on the evidence you posted, the compiler gives that enumerator a value of INT_MIN (a large negative number).
You will have to design your code to take this into account, e.g. have a specific branch of the verstion test for xxxxx920P3.
When an enumeration contains a bunch of one-bit flags it's usually so that they can be combined together, e.g. xxxxx600 | xxxxx700 | xxxxx432 giving the ability to have a single value that represents any sized set of elements.

CAN 1 RX works in loopback mode, but not in Normal mode

I am using a STM32F413RG based custom board and trying to run some CAN bus based applications on it.
I am trying to start with CAN 1 and wrote a bare metal code using CMSIS library to transmit and receive.
Here is the code for three functions - Init,Send and Receive.
void initCAN()
{
// enable clock
// note: because CAN2 is a "slave CAN" you have to enable CAN1 clock
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
// and reset CAN1, so request reset
CAN1->MCR |= CAN_MCR_RESET;
// wait for it to say it has gone to sleep
while ((CAN1->MSR & CAN_MSR_SLAK_Msk) == 1) {}
//CAN1
// enable port A clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
__DSB();
// CAN_RX = CAN1R on PA11, so set alt function
GPIOA->MODER &= ~GPIO_MODER_MODER11_Msk;
GPIOA->MODER |= GPIO_MODER_MODER11_1;
// CAN 1 is AF9 (AFSEL 9 = 0b1001 -> bit 3 & bit 0
GPIOA->AFR[1] |= (GPIO_AFRH_AFSEL11_3 | GPIO_AFRH_AFSEL11_0);
// CAN_TX = CAN1T on PA12
GPIOA->MODER &= ~GPIO_MODER_MODER12_Msk;
GPIOA->MODER |= GPIO_MODER_MODER12_1;
// open-drain
GPIOA->OTYPER |= GPIO_OTYPER_OT_11;
GPIOA->OTYPER |= GPIO_OTYPER_OT_12;
// CAN 1 is AF9 (AFSEL 9 = 0b1001 -> bit 3 & bit 0
GPIOA->AFR[1] |= (GPIO_AFRH_AFSEL12_3 | GPIO_AFRH_AFSEL12_0);
//bring it our from sleep by setting the sleep bit in MCR to 0
CAN1->MCR &= ~CAN_MCR_SLEEP_Msk;
//if sleep ACK(SLAK) not zero, wait i.e. exited from sleep
while ((CAN1->MSR & CAN_MSR_SLAK_Msk) != 0) {}
//put CAN 1 to Init mode
CAN1->MCR |= CAN_MCR_INRQ;
// wait for it to say it has gone there
while ((CAN1->MSR & CAN_MSR_INAK_Msk) != CAN_MSR_INAK_Msk) {}
uint32_t APB1Clock = SystemCoreClock/2000000; // in MHz
CAN1->BTR = 0x00050007U;
CAN1->FMR |= CAN_FMR_FINIT;
// and make sure the CANSB value is zero
CAN1->FMR &= ~(CAN_FMR_CAN2SB_Msk);
//Give 14 filter banks to CAN 1 and 2 each
CAN1->FMR |= (((uint32_t) 14) << CAN_FMR_CAN2SB_Pos) & CAN_FMR_CAN2SB_Msk;
// set all as 32 bit filter in identifier mask mode (zeros)
CAN1->FM1R = 0;
// use all as 32 bit filter with mask
CAN1->FS1R |= CAN_FS1R_FSC_Msk;
// assign FIFO0 to CAN1, and FIFO1 to CAN2 (well, all to FIFO0, except filter 14)
CAN1->FFA1R = CAN_FFA1R_FFA14;
// make sure it is deactivated (clear FACT in CAN_FAR)
CAN1->FA1R &= ~CAN_FA1R_FACT0;
CAN1 ->FA1R &= ~CAN_FA1R_FACT14;
// setup a filter that accepts everything (w/ extended id)
// Each filter bank i (i= 0 to 27 in dual CAN configuration and i= 0 to 13 in single CAN configuration)
//is composed of two 32-bit registers, CAN_FiR\[2:1\].
CAN1->sFilterRegister[0].FR1 = CAN_F0R1_FB2;
CAN1->sFilterRegister[0].FR2 = CAN_F0R1_FB2;
CAN1->sFilterRegister[14].FR1 = CAN_F0R1_FB2;
CAN1->sFilterRegister[14].FR2 = CAN_F0R1_FB2;
// now activate filter
CAN1->FA1R |= CAN_FA1R_FACT0;
CAN1->FA1R |= CAN_FA1R_FACT14;
// take out of init mode for filters
CAN1->FMR &= ~CAN_FMR_FINIT;
//loopback mode. need to do it while on init mode
// CAN1->BTR |= CAN_BTR_LBKM;
//bring CAN1 out from init mode.
CAN1->MCR &= ~CAN_MCR_INRQ;
while ((CAN1->MSR & CAN_MSR_INAK_Msk) != 0) {}
}
void sendCAN1( uint32_t pgn, uint8_t bytes[], uint8_t len)
{
// wait for the mailbox to be empty
while ((CAN1->TSR & CAN_TSR_TME0_Msk) == 0) {};
// put this in next empty mailbox
int boxnum = (CAN1->TSR & CAN_TSR_CODE_Msk) >> CAN_TSR_CODE_Pos;
CAN1->sTxMailBox[boxnum].TDTR &= ~CAN_TDT0R_DLC_Msk;
CAN1->sTxMailBox[0].TIR = ((pgn << CAN_TI0R_EXID_Pos) & CAN_TI0R_EXID_Msk) | CAN_TI0R_IDE;
// for standard (11-bit) ids, replace the above with:
// CAN1->sTxMailBox[boxnum].TIR = ((pgn << CAN_TI0R_STID_Pos) & CAN_TI0R_STID_Msk);
CAN1->sTxMailBox[boxnum].TDHR = ((bytes[7]<<CAN_TDH0R_DATA7_Pos) |
(bytes[6]<<CAN_TDH0R_DATA6_Pos) |
(bytes[5]<<CAN_TDH0R_DATA5_Pos) | bytes[4]);
CAN1->sTxMailBox[boxnum].TDLR = ((bytes[3]<<CAN_TDL0R_DATA3_Pos) |
(bytes[2]<<CAN_TDL0R_DATA2_Pos) |
(bytes[1]<<CAN_TDL0R_DATA1_Pos) | bytes[0]);
CAN1->sTxMailBox[boxnum].TDTR = (len << CAN_TDT0R_DLC_Pos) & CAN_TDT0R_DLC_Msk;
CAN1->sTxMailBox[boxnum].TIR |= CAN_TI0R_TXRQ;
}
uint8_t recCAN1()
{
uint8_t data[8];
uint32_t pgn;
uint8_t len;
uint8_t msgcount;
static uint8_t ret = 0;
// check for any msg in FIFO
// we only use FIFO 0 here
msgcount = CAN1->RF0R & CAN_RF0R_FMP0_Msk;
ret += msgcount;
// read them out one at a time
while (msgcount > 0)
{
pgn = CAN1->sFIFOMailBox[0].RIR >> 3;
len = CAN1->sFIFOMailBox[0].RDTR & 0xF;
// NOTE: case fall through is intentional and critical
switch (len)
{
case 8:
data[7] = (CAN1->sFIFOMailBox[0].RDHR >> 24) & 0xFF;
case 7:
data[6] = (CAN1->sFIFOMailBox[0].RDHR >> 16) & 0xFF;
case 6:
data[5] = (CAN1->sFIFOMailBox[0].RDHR >> 8) & 0xFF;
case 5:
data[4] = CAN1->sFIFOMailBox[0].RDHR & 0xFF;
case 4:
data[3] = (CAN1->sFIFOMailBox[0].RDLR >> 24) & 0xFF;
case 3:
data[2] = (CAN1->sFIFOMailBox[0].RDLR >> 16) & 0xFF;
case 2:
data[1] = (CAN1->sFIFOMailBox[0].RDLR >> 8) & 0xFF;
case 1:
data[0] = CAN1->sFIFOMailBox[0].RDLR & 0xFF;
// do nothing as data is empty
}
// process as they are read
// processCAN(pgn, data, len);
// release that mailbox
CAN1->RF0R |= CAN_RF0R_RFOM0;
// update the message count
msgcount = CAN1->RF0R & CAN_RF0R_FMP0_Msk;
}
return ret;
}
Sending a packet from CAN 1 is fine. When receiving, I cannot see any status changing on the Rx Registers. But, I can see an ACK being transmitted from the TX pin upon receiving a packet when scoping the signals.
The CAN 1 Error Status is completely empty (0x0).
However, when I try the same code with Loopback mode activated, I can see a message received on the registers and my code picks it up too.
Attaching screenshots of CAN 1 RF0R register when in loopback mode which indicates reception.
This scope (Channel 0 for RX and Channel 2 for TX) shows that its receiving a message on RX and it sends back an ACK on its TX under normal mode.
I have checked the termination too and its fine. (120 ohms added. Anyway, getting an ACK, so I am thinking that's not the problem).
I am out of ideas of where I might be going wrong.
No explicit error messages. However, the Rx message is not reflecting on any one of the registers under normal mode.
From the reference manual in CAN_FMR register : to use CAN1 only: stop the clock on CAN2 and/or set the CAN_MCR.INRQ on CAN2, I haven't seen instruction that does this explicitly in your code.
Also in the comments from your code it says that you are not filtering anything but you set CAN_F0R1_FB2 in sFilterRegister thus not everything will be accepted. The ID you are sending is one of those.

How can I force all events from one device to be handled by one window, while allowing all other events from all other devices to be handled normally?

I have an application that is used as a control system for a presentation, under Linux and using X11. I have a USB presentation remote that acts as a very miniature keyboard (four buttons: Page Up, Page Down, and two others) which can be used to advance and go back in the presentation. I would like to have my presentation application to receive all of the events from this remote regardless of where the mouse focus is. But I would also like to be able to receive the normal mouse and keyboard events if the current window focus is on the presentation application. Using XIGrabDevice() I was able to receive all events from the remote in the presentation application regardless of the current focus but I was not able to receive any events from the mouse or keyboard while the grab was active.
I ended up setting up a separate program to capture the remote's keys, then I relay those keys to my main program. I did it this way because the original program was using the older XInput extension, and I needed to use the newer XInput2 extension, and they do not exist well together. Here's some C++ code (it doesn't do any error checking, but this should be done in a real program):
// Open connection to X Server
Display *dpy = XOpenDisplay(NULL);
// Get opcode for XInput Extension; we'll need it for processing events
int xi_opcode = -1, event, error;
XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error);
// Allow user to select a device
int num_devices;
XIDeviceInfo *info = XIQueryDevice(dpy, XIAllDevices, &num_devices);
for (int i = 0; i < num_devices; ++i)
{
XIDeviceInfo *dev = &info[i];
std::cout << dev->deviceid << " " << dev->name << "\n";
}
XIFreeDeviceInfo(info);
std::cout << "Enter the device number: ";
std::string input;
std::cin >> input;
int deviceid = -1;
std::istringstream istr(input);
istr >> deviceid;
// Create an InputOnly window that is just used to grab events from this device
XSetWindowAttributes attrs;
long attrmask = 0;
memset(&attrs, 0, sizeof(attrs));
attrs.override_redirect = True; // Required to grab device
attrmask |= CWOverrideRedirect;
Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, InputOnly, CopyFromParent, attrmask, &attrs);
// Make window without decorations
PropMotifWmHints hints;
hints.flags = 2;
hints.decorations = 0;
Atom property = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);
XChangeProperty(dpy, win, property, property, 32, PropModeReplace, (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
// We are interested in key presses and hierarchy changes. We also need to get key releases or else we get an infinite stream of key presses.
XIEventMask evmasks[1];
unsigned char mask0[XIMaskLen(XI_LASTEVENT)];
memset(mask0, 0, sizeof(mask0));
XISetMask(mask0, XI_KeyPress);
XISetMask(mask0, XI_KeyRelease);
XISetMask(mask0, XI_HierarchyChanged);
evmasks[0].deviceid = XIAllDevices;
evmasks[0].mask_len = sizeof(mask0);
evmasks[0].mask = mask0;
XISelectEvents(dpy, win, evmasks, 1);
XMapWindow(dpy, win);
XFlush(dpy);
XEvent ev;
bool grab_success = false, grab_changed;
while (1)
{
grab_changed = false;
if (!grab_success)
{
XIEventMask masks[1];
unsigned char mask0[XIMaskLen(XI_LASTEVENT)];
memset(mask0, 0, sizeof(mask0));
XISetMask(mask0, XI_KeyPress);
masks[0].deviceid = deviceid;
masks[0].mask_len = sizeof(mask0);
masks[0].mask = mask0;
XIGrabDevice(dpy, deviceid, win, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, XIOwnerEvents, masks);
}
XNextEvent(dpy, &ev);
XGenericEventCookie *cookie = &ev.xcookie;
if (cookie->type == GenericEvent && cookie->extension == xi_opcode && XGetEventData(dpy, cookie))
{
if (cookie->evtype == XI_KeyPress)
{
XIDeviceEvent *de = (XIDeviceEvent*)cookie->data;
std::cout << "found XI_KeyPress event: keycode " << de->detail << "\n";
}
else if (cookie->evtype == XI_HierarchyChanged)
{
// Perhaps a device was unplugged. The client is expected to re-read the list of devices to find out what changed.
std::cout << "found XI_HierarchyChanged event.\n";
grab_changed = true;
}
XFreeEventData(dpy, cookie);
}
if (grab_changed)
{
XIUngrabDevice(dpy, deviceid, CurrentTime);
grab_success = false;
break;
}
}
I found the following links helpful:
Peter Hutterer's 6-part blog on XInput2: 1 2 3 4 5 6
This blog entry was useful to determine which class to cast the cookie->data pointer to, depending on the cookie->evtype: 7

Convert connect address with address familiy AF_SYSTEM to human readable string

Background
I'm writing some dtrace program which tracks application socket file descriptors. Aim is to provide logs which help me spot leak of file descriptors in some very complex OS X application.
Here is my other question with very helpful answer.
Problem
I want that my program is logging address to which file descriptor has been connected to. In examples there is a code which partial do what I need: soconnect_mac.d, here is link to github.
soconnect_mac.d works great when applied on Firefox, but it completely fails in case of my application. Quick investigation shown that soconnect_mac.d is able to interpret only AF_INET (value 2) family address and som library used by my application is using AF_SYSTEM (value 32) family address.
I can't find anything which could help me convert received address to something what is human readable.
So far I've got this:
#!/usr/sbin/dtrace -s
inline int af_inet = 2 ; /* AF_INET defined in Kernel/sys/socket.h */
inline int af_inet6 = 30; /* AF_INET6 defined in Kernel/sys/socket.h */
inline int af_system = 32; /* AF_SYSTEM defined in Kernel/sys/socket.h */
… // some stuff
syscall::connect:entry
/pid == $target && isOpened[pid, arg0] == 1/
{
/* assume this is sockaddr_in until we can examine family */
this->s = (struct sockaddr_in *)copyin(arg1, arg2);
this->f = this->s->sin_family;
self->fileDescriptor = arg0;
}
/* this section is copied with pride from "soconnect_mac.d" */
syscall::connect:entry
/this->f == af_inet/
{
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8;
/*
* Convert an IPv4 address into a dotted quad decimal string.
* Until the inet_ntoa() functions are available from DTrace, this is
* converted using the existing strjoin() and lltostr(). It's done in
* two parts to avoid exhausting DTrace registers in one line of code.
*/
this->a = (uint8_t *)&this->s->sin_addr;
this->addr1 = strjoin(lltostr(this->a[0] + 0ULL),
strjoin(".",
strjoin(lltostr(this->a[1] + 0ULL),
".")));
this->addr2 = strjoin(lltostr(this->a[2] + 0ULL),
strjoin(".",
lltostr(this->a[3] + 0ULL)));
self->address = strjoin(this->addr1, this->addr2);
}
/* this section is my */
syscall::connect:entry
/this->f == af_system/
{
/* TODO: Problem how to handle AF_SYSTEM address family */
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8; // this also doen't work as it should
self->address = "system family address needed here";
}
// a fallback
syscall::connect:entry
/this->f && this->f != af_inet && this->f != af_system/
{
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8;
self->address = strjoin("Can't handle family: ", lltostr(this->f));
}
syscall::connect:return
/self->fileDescriptor/
{
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
printf("%Y.%03d FD:%d Status:%s Address:%s Port:%d",
walltimestamp, walltimestamp % 1000000000 / 1000000,
self->fileDescriptor, this->errstr, self->address, self->port);
self->fileDescriptor = 0;
self->address = 0;
self->port = 0;
}
What is even more annoying my code has failed to read port number (I get 512 value instead one of this: 443, 8443, 5061).
IMO problem is first syscall::connect:entry where it is assumed that second argument can be treated as struct sockaddr_in. I'm guessing struct sockaddr_storage should be used in case of AF_SYSTEM address family, but I didn't found any documentation or source code which proves this in direct way.
My section with this->f == af_system condition properly catches events from application I'm investigating.

Resources