I would like to enable EXTI interrupts in order to have information on whether the port has changed its state.
As you can see below, I've configured 2 pins, GPIOA5 and GPIOB3. Both have been configured with pullup resistors, so they should change state when they are connected to the ground.
The problem is that everything works for GPIOA5 but doesn't work for GPIOB3. The isr for GPIO5 is being called, but for GPIOB isn't.
I commented part of code regarding UART configuration as it's not relevant in this case - uart works fine, so I can see messages going out from MCU.
What could be a problem here?
I'm using STM32f411CEU6 and libopencm3.
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/cm3/systick.h>
volatile bool sensor_isr_process { false };
volatile bool sensor_isr_process2 { false };
extern "C" {
void exti3_isr()
{
sensor_isr_process2 = true;
exti_reset_request(EXTI3);
}
void exti9_5_isr()
{
sensor_isr_process = true;
exti_reset_request(EXTI5);
}
}
void configure_exti(uint32_t nvicirq, uint32_t exti, uint32_t gpioport)
{
nvic_enable_irq(nvicirq);
exti_select_source(exti, gpioport);
exti_set_trigger(exti, EXTI_TRIGGER_FALLING);
exti_enable_request(exti);
}
int main()
{
//Setup Clock
auto clock = rcc_clock_scale{};
clock.pllm = 8;
clock.plln = 100; //336;
clock.pllp = 2; //4;
clock.pllq = 4; //7;
clock.pllr = 2; //0;
clock.pll_source = RCC_CFGR_PLLSRC_HSI_CLK;
clock.hpre = RCC_CFGR_HPRE_DIV_NONE; //?
clock.ppre1 = RCC_CFGR_PPRE_DIV_2; // ?
clock.ppre2 = RCC_CFGR_PPRE_DIV_NONE; // ?
clock.voltage_scale = PWR_SCALE1; //?
clock.flash_config = FLASH_ACR_DCEN | FLASH_ACR_ICEN |
FLASH_ACR_LATENCY_2WS;
clock.ahb_frequency = 100000000;
clock.apb1_frequency = 50000000;
clock.apb2_frequency = 100000000;
rcc_clock_setup_pll(&clock);
//Enable GPIO
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOB);
//Setup GPIO
gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO5);
gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO3);
configure_exti(NVIC_EXTI9_5_IRQ, EXTI5, GPIOA);
configure_exti(NVIC_EXTI3_IRQ, EXTI3, GPIOB);
while(1)
{
if (sensor_isr_process) {
// trace(1, "Sensor 1\r\n"); //sends message by uart
sensor_isr_process = false;
}
else if (sensor_isr_process2) {
// trace(1, "Sensor 2\r\n"); //send message by uart
sensor_isr_process2 = false;
}
}
}
I'm not familiar with libopencm3, but normally EXTI mappings are configured in SYSCFG_EXTICR registers and in order to access them, SYSCFG clock needs to be enabled.
If you inspect its source file, you can see that exti_select_source() function doesn't enable SYSCFG clock itself. So probably you need to do it yourself by calling the relevant function:
rcc_periph_clock_enable(RCC_SYSCFG);
This application is created
1) Console Application
2) InjectedDLL - DLL Project for inject into the process
1) the console application i have taken notepad.exe process id and inject my DLL into the notepad.
2) I have Created one exported method in the injected dll.
3) Now after injecting dll into notepad , i require the proc address of that exported method.
I have writted code here to get it but it's is not calling that methods and crash it.
I am attaching sample code this here. for run it only need to give full path of the dll.
const WCHAR INJECTED_DLL_FULL_PATH[] = L"FULL PATH OF DLL";
Only change this path, everything else will work.
I am unable to get the proc address of the injected dll.
anyone can help me on that.
/
Console Application code
/ DLLInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <stdlib.h>
#include "RemoteOperation.h"
#include <stdio.h>
#include <tchar.h>
#include <tlhelp32.h>
BOOL InjectDLL();
void EjectDLL();
HANDLE m_hRemoteThread;
HANDLE m_hProcess;
void* m_pLibRemoteAddress;
DWORD m_dwhLibModule;
BOOL m_bIsDLLInjected;
DWORD m_dwProcessID;
HWND m_hCaptureWnd;
const WCHAR INJECTED_DLL[] = L"InjectedDLL.dll";
const WCHAR INJECTED_DLL_FULL_PATH[] = L"FULL PATH OF DLL";
DWORD GetProcessIdEx(LPCWSTR szExeName);
typedef void (WINAPI *test)();
test _test = NULL;
int main()
{
InjectDLL();
HMODULE hDLLModule = GetRemoteModuleHandle(m_hProcess, INJECTED_DLL);
_test = (test)GetRemoteProcAddress(m_hProcess, hDLLModule, "test");
_test();
EjectDLL();
return 0;
}
DWORD GetProcessIdEx(LPCWSTR szExeName)
{
DWORD dwRet = 0;
DWORD dwCount = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(hSnapshot, &pe);
while (bRet)
{
OutputDebugString(pe.szExeFile);
OutputDebugString(L"\n");
if (!wcscmp(szExeName, pe.szExeFile))
{
dwCount++;
dwRet = pe.th32ProcessID;
break;
}
bRet = Process32Next(hSnapshot, &pe);
}
if (dwCount > 1)
dwRet = 0xFFFFFFFF;
CloseHandle(hSnapshot);
}
return dwRet;
}
BOOL InjectDLL()
{
m_hRemoteThread = NULL;
m_hProcess = NULL;
m_pLibRemoteAddress = NULL;
m_dwhLibModule = 0;
char chardllPath[MAX_PATH] = "\0";
wcstombs(chardllPath, INJECTED_DLL_FULL_PATH, MAX_PATH);
int Length = strlen(chardllPath);
HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");
LPVOID LoadLibraryPoniter = (LPVOID)GetProcAddress(hKernel32, "LoadLibraryA");
m_dwProcessID = GetProcessIdEx(L"notepad.exe");
m_hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, m_dwProcessID);
// 1. Allocate memory in the remote process for szLibPath
// 2. Write szLibPath to the allocated memory
m_pLibRemoteAddress = 0;
m_pLibRemoteAddress = ::VirtualAllocEx(m_hProcess, NULL, Length, MEM_COMMIT, PAGE_READWRITE);
if (m_pLibRemoteAddress == NULL)
{
CloseHandle(m_hProcess);
m_hProcess = NULL;
return false;
}
::WriteProcessMemory(m_hProcess, m_pLibRemoteAddress, (void*)chardllPath, Length, NULL);
// Load "dll" into the remote process
// (via CreateRemoteThread & LoadLibrary)
m_hRemoteThread = ::CreateRemoteThread(m_hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryPoniter, (LPVOID)m_pLibRemoteAddress, 0, NULL);
m_bIsDLLInjected = true;
::WaitForSingleObject(m_hRemoteThread, INFINITE);
// Get handle of loaded module
m_dwhLibModule = 0;
::GetExitCodeThread(m_hRemoteThread, &m_dwhLibModule);
::CloseHandle(m_hRemoteThread);
m_hRemoteThread = NULL;
::VirtualFreeEx(m_hProcess, m_pLibRemoteAddress, Length, MEM_RELEASE);
m_pLibRemoteAddress = NULL;
return true;
}
void EjectDLL()
{
if (m_hProcess && m_bIsDLLInjected)
{
HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");
LPVOID LoadFreeLibraryPoniter = (LPVOID)GetProcAddress(hKernel32, "FreeLibrary");
HMODULE hDLLModule = GetRemoteModuleHandle(m_hProcess, INJECTED_DLL);
if (hDLLModule)
{
HANDLE hThread = ::CreateRemoteThread(m_hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadFreeLibraryPoniter, (void*)hDLLModule, 0, NULL);
::WaitForSingleObject(hThread, INFINITE);
// Clean up
::CloseHandle(hThread);
}
}
if (m_hProcess)
{
CloseHandle(m_hProcess);
}
m_hProcess = NULL;
}
Remoteoperation.h
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <commctrl.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#ifndef REM_OPS_H
#define REM_OPS_H
HMODULE WINAPI GetRemoteModuleHandle(HANDLE hProcess, LPCWSTR lpModuleName);
FARPROC WINAPI GetRemoteProcAddress(HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName, UINT Ordinal = 0, BOOL UseOrdinal = FALSE);
BOOL RemoteLibraryFunction(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn);
#endif //REM_OPS_H
// RemoteOperation.cpp
#include "stdafx.h"
/* RempteOps.cpp */
#include "stdafx.h" // SDKDDKVer.h, windows.h, stdlib.h, malloc.h, memory.h, tchar.h
#include "RemoteOperation.h" // Function prototypes
#include <string>
#include <windows.h>
#include <psapi.h>
using std::string;
//-----------------------------------------------------------------------------
HMODULE WINAPI GetRemoteModuleHandle(HANDLE hProcess, LPCWSTR lpModuleName)
{
HMODULE* ModuleArray = NULL;
DWORD ModuleArraySize = 200;
DWORD NumModules = 0;
WCHAR lpModuleNameCopy[MAX_PATH] = { 0 };
WCHAR ModuleNameBuffer[MAX_PATH] = { 0 };
/* Make sure we didn't get a NULL pointer for the module name */
if (lpModuleName == NULL)
goto GRMH_FAIL_JMP;
/* Convert lpModuleName to all lowercase so the comparison isn't case sensitive */
for (size_t i = 0; lpModuleName[i] != '\0'; ++i)
{
if (lpModuleName[i] >= 'A' && lpModuleName[i] <= 'Z')
lpModuleNameCopy[i] = lpModuleName[i] + 0x20; // 0x20 is the difference between uppercase and lowercase
else
lpModuleNameCopy[i] = lpModuleName[i];
lpModuleNameCopy[i + 1] = '\0';
}
/* Allocate memory to hold the module handles */
ModuleArray = new HMODULE[ModuleArraySize];
/* Check if the allocation failed */
if (ModuleArray == NULL)
goto GRMH_FAIL_JMP;
/* Get handles to all the modules in the target process */
if (!::EnumProcessModulesEx(hProcess, ModuleArray,
ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL))
goto GRMH_FAIL_JMP;
/* We want the number of modules not the number of bytes */
NumModules /= sizeof(HMODULE);
/* Did we allocate enough memory for all the module handles? */
if (NumModules > ModuleArraySize)
{
delete[] ModuleArray; // Deallocate so we can try again
ModuleArray = NULL; // Set it to NULL se we can be sure if the next try fails
ModuleArray = new HMODULE[NumModules]; // Allocate the right amount of memory
/* Check if the allocation failed */
if (ModuleArray == NULL)
goto GRMH_FAIL_JMP;
ModuleArraySize = NumModules; // Update the size of the array
/* Get handles to all the modules in the target process */
if (!::EnumProcessModulesEx(hProcess, ModuleArray,
ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL))
goto GRMH_FAIL_JMP;
/* We want the number of modules not the number of bytes */
NumModules /= sizeof(HMODULE);
}
/* Iterate through all the modules and see if the names match the one we are looking for */
for (DWORD i = 0; i <= NumModules; ++i)
{
/* Get the module's name */
::GetModuleBaseName(hProcess, ModuleArray[i],
ModuleNameBuffer, sizeof(ModuleNameBuffer));
/* Convert ModuleNameBuffer to all lowercase so the comparison isn't case sensitive */
for (size_t j = 0; ModuleNameBuffer[j] != '\0'; ++j)
{
if (ModuleNameBuffer[j] >= 'A' && ModuleNameBuffer[j] <= 'Z')
ModuleNameBuffer[j] += 0x20; // 0x20 is the difference between uppercase and lowercase
}
/* Does the name match? */
if (wcsstr(ModuleNameBuffer, lpModuleNameCopy) != NULL)
{
/* Make a temporary variable to hold return value*/
HMODULE TempReturn = ModuleArray[i];
/* Give back that memory */
delete[] ModuleArray;
/* Success */
return TempReturn;
}
/* Wrong module let's try the next... */
}
/* Uh Oh... */
GRMH_FAIL_JMP:
/* If we got to the point where we allocated memory we need to give it back */
if (ModuleArray != NULL)
delete[] ModuleArray;
/* Failure... */
return NULL;
}
//-----------------------------------------------------------------------------
FARPROC WINAPI GetRemoteProcAddress(HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName, UINT Ordinal, BOOL UseOrdinal)
{
BOOL Is64Bit = FALSE;
MODULEINFO RemoteModuleInfo = { 0 };
UINT_PTR RemoteModuleBaseVA = 0;
IMAGE_DOS_HEADER DosHeader = { 0 };
DWORD Signature = 0;
IMAGE_FILE_HEADER FileHeader = { 0 };
IMAGE_OPTIONAL_HEADER64 OptHeader64 = { 0 };
IMAGE_OPTIONAL_HEADER32 OptHeader32 = { 0 };
IMAGE_DATA_DIRECTORY ExportDirectory = { 0 };
IMAGE_EXPORT_DIRECTORY ExportTable = { 0 };
UINT_PTR ExportFunctionTableVA = 0;
UINT_PTR ExportNameTableVA = 0;
UINT_PTR ExportOrdinalTableVA = 0;
DWORD* ExportFunctionTable = NULL;
DWORD* ExportNameTable = NULL;
WORD* ExportOrdinalTable = NULL;
/* Temporary variables not used until much later but easier
/* to define here than in all the the places they are used */
CHAR TempChar;
BOOL Done = FALSE;
/* Check to make sure we didn't get a NULL pointer for the name unless we are searching by ordinal */
if (lpProcName == NULL && !UseOrdinal)
goto GRPA_FAIL_JMP;
/* Get the base address of the remote module along with some other info we don't need */
if (!::GetModuleInformation(hProcess, hModule, &RemoteModuleInfo, sizeof(RemoteModuleInfo)))
goto GRPA_FAIL_JMP;
RemoteModuleBaseVA = (UINT_PTR)RemoteModuleInfo.lpBaseOfDll;
/* Read the DOS header and check it's magic number */
if (!::ReadProcessMemory(hProcess, (LPCVOID)RemoteModuleBaseVA, &DosHeader,
sizeof(DosHeader), NULL) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
goto GRPA_FAIL_JMP;
/* Read and check the NT signature */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew),
&Signature, sizeof(Signature), NULL) || Signature != IMAGE_NT_SIGNATURE)
goto GRPA_FAIL_JMP;
/* Read the main header */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature)),
&FileHeader, sizeof(FileHeader), NULL))
goto GRPA_FAIL_JMP;
/* Which type of optional header is the right size? */
if (FileHeader.SizeOfOptionalHeader == sizeof(OptHeader64))
Is64Bit = TRUE;
else if (FileHeader.SizeOfOptionalHeader == sizeof(OptHeader32))
Is64Bit = FALSE;
else
goto GRPA_FAIL_JMP;
if (Is64Bit)
{
/* Read the optional header and check it's magic number */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)),
&OptHeader64, FileHeader.SizeOfOptionalHeader, NULL)
|| OptHeader64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
goto GRPA_FAIL_JMP;
}
else
{
/* Read the optional header and check it's magic number */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)),
&OptHeader32, FileHeader.SizeOfOptionalHeader, NULL)
|| OptHeader32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
goto GRPA_FAIL_JMP;
}
/* Make sure the remote module has an export directory and if it does save it's relative address and size */
if (Is64Bit && OptHeader64.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1)
{
ExportDirectory.VirtualAddress = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress;
ExportDirectory.Size = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size;
}
else if (OptHeader32.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1)
{
ExportDirectory.VirtualAddress = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress;
ExportDirectory.Size = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size;
}
else
goto GRPA_FAIL_JMP;
/* Read the main export table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportDirectory.VirtualAddress),
&ExportTable, sizeof(ExportTable), NULL))
goto GRPA_FAIL_JMP;
/* Save the absolute address of the tables so we don't need to keep adding the base address */
ExportFunctionTableVA = RemoteModuleBaseVA + ExportTable.AddressOfFunctions;
ExportNameTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNames;
ExportOrdinalTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNameOrdinals;
/* Allocate memory for our copy of the tables */
ExportFunctionTable = new DWORD[ExportTable.NumberOfFunctions];
ExportNameTable = new DWORD[ExportTable.NumberOfNames];
ExportOrdinalTable = new WORD[ExportTable.NumberOfNames];
/* Check if the allocation failed */
if (ExportFunctionTable == NULL || ExportNameTable == NULL || ExportOrdinalTable == NULL)
goto GRPA_FAIL_JMP;
/* Get a copy of the function table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportFunctionTableVA,
ExportFunctionTable, ExportTable.NumberOfFunctions * sizeof(DWORD), NULL))
goto GRPA_FAIL_JMP;
/* Get a copy of the name table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportNameTableVA,
ExportNameTable, ExportTable.NumberOfNames * sizeof(DWORD), NULL))
goto GRPA_FAIL_JMP;
/* Get a copy of the ordinal table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportOrdinalTableVA,
ExportOrdinalTable, ExportTable.NumberOfNames * sizeof(WORD), NULL))
goto GRPA_FAIL_JMP;
/* If we are searching for an ordinal we do that now */
if (UseOrdinal)
{
/* NOTE:
/* Microsoft's PE/COFF specification does NOT say we need to subtract the ordinal base
/* from our ordinal but it seems to always give the wrong function if we don't */
/* Make sure the ordinal is valid */
if (Ordinal < ExportTable.Base || (Ordinal - ExportTable.Base) >= ExportTable.NumberOfFunctions)
goto GRPA_FAIL_JMP;
UINT FunctionTableIndex = Ordinal - ExportTable.Base;
/* Check if the function is forwarded and if so get the real address*/
if (ExportFunctionTable[FunctionTableIndex] >= ExportDirectory.VirtualAddress &&
ExportFunctionTable[FunctionTableIndex] <= ExportDirectory.VirtualAddress + ExportDirectory.Size)
{
Done = FALSE;
string TempForwardString;
TempForwardString.clear(); // Empty the string so we can fill it with a new name
/* Get the forwarder string one character at a time because we don't know how long it is */
for (UINT_PTR i = 0; !Done; ++i)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex] + i),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempForwardString.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Find the dot that seperates the module name and the function name/ordinal */
size_t Dot = TempForwardString.find('.');
if (Dot == string::npos)
goto GRPA_FAIL_JMP;
/* Temporary variables that hold parts of the forwarder string */
string RealModuleName, RealFunctionId;
RealModuleName = TempForwardString.substr(0, Dot - 1);
RealFunctionId = TempForwardString.substr(Dot + 1, string::npos);
WCHAR newModuleName[MAX_PATH] = L"\0";
swprintf_s(newModuleName, L"%s", RealModuleName.c_str());
HMODULE RealModule = GetRemoteModuleHandle(hProcess, newModuleName);
FARPROC TempReturn;// Make a temporary variable to hold return value
/* Figure out if the function was exported by name or by ordinal */
if (RealFunctionId.at(0) == '#') // Exported by ordinal
{
UINT RealOrdinal = 0;
RealFunctionId.erase(0, 1); // Remove '#' from string
/* My version of atoi() because I was too lazy to use the real one... */
for (size_t i = 0; i < RealFunctionId.size(); ++i)
{
if (RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9')
{
RealOrdinal *= 10;
RealOrdinal += RealFunctionId[i] - '0';
}
else
break;
}
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE);
}
else // Exported by name
{
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE);
}
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
else // Not Forwarded
{
/* Make a temporary variable to hold return value*/
FARPROC TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex]);
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
}
/* Iterate through all the names and see if they match the one we are looking for */
for (DWORD i = 0; i < ExportTable.NumberOfNames; ++i) {
string TempFunctionName;
Done = FALSE;// Reset for next name
TempFunctionName.clear(); // Empty the string so we can fill it with a new name
/* Get the function name one character at a time because we don't know how long it is */
for (UINT_PTR j = 0; !Done; ++j)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportNameTable[i] + j),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempFunctionName.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Does the name match? */
if (TempFunctionName.find(lpProcName) != string::npos)
{
/* NOTE:
/* Microsoft's PE/COFF specification says we need to subtract the ordinal base
/*from the value in the ordinal table but that seems to always give the wrong function */
/* Check if the function is forwarded and if so get the real address*/
if (ExportFunctionTable[ExportOrdinalTable[i]] >= ExportDirectory.VirtualAddress &&
ExportFunctionTable[ExportOrdinalTable[i]] <= ExportDirectory.VirtualAddress + ExportDirectory.Size)
{
Done = FALSE;
string TempForwardString;
TempForwardString.clear(); // Empty the string so we can fill it with a new name
/* Get the forwarder string one character at a time because we don't know how long it is */
for (UINT_PTR j = 0; !Done; ++j)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[i] + j),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempForwardString.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Find the dot that seperates the module name and the function name/ordinal */
size_t Dot = TempForwardString.find('.');
if (Dot == string::npos)
goto GRPA_FAIL_JMP;
/* Temporary variables that hold parts of the forwarder string */
string RealModuleName, RealFunctionId;
RealModuleName = TempForwardString.substr(0, Dot);
RealFunctionId = TempForwardString.substr(Dot + 1, string::npos);
WCHAR newModuleName[MAX_PATH] = L"\0";
swprintf_s(newModuleName, L"%s", RealModuleName.c_str());
HMODULE RealModule = GetRemoteModuleHandle(hProcess, newModuleName);
FARPROC TempReturn;// Make a temporary variable to hold return value
/* Figure out if the function was exported by name or by ordinal */
if (RealFunctionId.at(0) == '#') // Exported by ordinal
{
UINT RealOrdinal = 0;
RealFunctionId.erase(0, 1); // Remove '#' from string
/* My version of atoi() because I was to lazy to use the real one... */
for (size_t i = 0; i < RealFunctionId.size(); ++i)
{
if (RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9')
{
RealOrdinal *= 10;
RealOrdinal += RealFunctionId[i] - '0';
}
else
break;
}
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE);
}
else // Exported by name
{
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE);
}
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
else // Not Forwarded
{
/* Make a temporary variable to hold return value*/
FARPROC TempReturn;
/* NOTE:
/* Microsoft's PE/COFF specification says we need to subtract the ordinal base
/*from the value in the ordinal table but that seems to always give the wrong function */
//TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i] - ExportTable.Base]);
/* So we do it this way instead */
TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i]]);
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
}
/* Wrong function let's try the next... */
}
/* Uh Oh... */
GRPA_FAIL_JMP:
/* If we got to the point where we allocated memory we need to give it back */
if (ExportFunctionTable != NULL)
delete[] ExportFunctionTable;
if (ExportNameTable != NULL)
delete[] ExportNameTable;
if (ExportOrdinalTable != NULL)
delete[] ExportOrdinalTable;
/* Falure... */
return NULL;
}
BOOL RemoteLibraryFunction(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn)
{
LPVOID lpRemoteParams = NULL;
LPVOID lpFunctionAddress = GetProcAddress(GetModuleHandleA(lpModuleName), lpProcName);
if (!lpFunctionAddress) lpFunctionAddress = GetProcAddress(LoadLibraryA(lpModuleName), lpProcName);
if (!lpFunctionAddress) goto ErrorHandler;
if (lpParameters)
{
lpRemoteParams = VirtualAllocEx(hProcess, NULL, dwParamSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!lpRemoteParams) goto ErrorHandler;
SIZE_T dwBytesWritten = 0;
BOOL result = WriteProcessMemory(hProcess, lpRemoteParams, lpParameters, dwParamSize, &dwBytesWritten);
if (!result || dwBytesWritten < 1) goto ErrorHandler;
}
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpFunctionAddress, lpRemoteParams, NULL, NULL);
if (!hThread) goto ErrorHandler;
DWORD dwOut = 0;
while (GetExitCodeThread(hThread, &dwOut)) {
if (dwOut != STILL_ACTIVE) {
*ppReturn = (PVOID)dwOut;
break;
}
}
return TRUE;
ErrorHandler:
if (lpRemoteParams)
VirtualFreeEx(hProcess, lpRemoteParams, dwParamSize, MEM_RELEASE);
return FALSE;
}
Injectdl DLL Expoerted methods
#define EXPORT __declspec (dllexport)
EXPORT void test();
EXPORT void test()
{
::MessageBox(NULL, L"test", L"", MB_OK);
}
DLL Main cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
::MessageBox(NULL, L"DLL Injected", L"", MB_OK);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
def file
LIBRARY InjectedDLL
EXPORTS
test #1
That is a lot of code to debug. What you're having a problem with is writing an external version of GetProcAddress which walks the export table. Instead of taking the time to debug your code I will supply a code which I know works. It is not my own code but I have used it before, the original author is iPower.
#define ReCa reinterpret_cast
uintptr_t GetProcAddressEx(HANDLE hProcess, DWORD pid, const char* module, const char* function)
{
if (!module || !function || !pid || !hProcess)
return 0;
uintptr_t moduleBase = GetModuleBaseEx(module, pid); //toolhelp32snapshot method
if (!moduleBase)
return 0;
IMAGE_DOS_HEADER Image_Dos_Header = { 0 };
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase), &Image_Dos_Header, sizeof(IMAGE_DOS_HEADER), nullptr))
return 0;
if (Image_Dos_Header.e_magic != IMAGE_DOS_SIGNATURE)
return 0;
IMAGE_NT_HEADERS Image_Nt_Headers = { 0 };
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + Image_Dos_Header.e_lfanew), &Image_Nt_Headers, sizeof(IMAGE_NT_HEADERS), nullptr))
return 0;
if (Image_Nt_Headers.Signature != IMAGE_NT_SIGNATURE)
return 0;
IMAGE_EXPORT_DIRECTORY Image_Export_Directory = { 0 };
uintptr_t img_exp_dir_rva = 0;
if (!(img_exp_dir_rva = Image_Nt_Headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress))
return 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + img_exp_dir_rva), &Image_Export_Directory, sizeof(IMAGE_EXPORT_DIRECTORY), nullptr))
return 0;
uintptr_t EAT = moduleBase + Image_Export_Directory.AddressOfFunctions;
uintptr_t ENT = moduleBase + Image_Export_Directory.AddressOfNames;
uintptr_t EOT = moduleBase + Image_Export_Directory.AddressOfNameOrdinals;
WORD ordinal = 0;
SIZE_T len_buf = strlen(function) + 1;
char* temp_buf = new char[len_buf];
for (size_t i = 0; i < Image_Export_Directory.NumberOfNames; i++)
{
uintptr_t tempRvaString = 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(ENT + (i * sizeof(uintptr_t))), &tempRvaString, sizeof(uintptr_t), nullptr))
return 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + tempRvaString), temp_buf, len_buf, nullptr))
return 0;
if (!lstrcmpi(function, temp_buf))
{
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(EOT + (i * sizeof(WORD))), &ordinal, sizeof(WORD), nullptr))
return 0;
uintptr_t temp_rva_func = 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(EAT + (ordinal * sizeof(uintptr_t))), &temp_rva_func, sizeof(uintptr_t), nullptr))
return 0;
delete[] temp_buf;
return moduleBase + temp_rva_func;
}
}
delete[] temp_buf;
return 0;
}
Am using HAL library but the reception interrupt only fires once.
I've tried debugging it but i still cant figure out where to start from.
Am not sure which status flag that is set so that i could re-enable it or disable it to make it run another round. The datasheet is a bit sheety coz STM isn't providing a detailed copy. Am using an STM32F303K8.
uint8_t rcvd, count = 0, reception_complete = FALSE;
char buffer[100];
int main(void)
{
HAL_Init();
SystemClockConfig();
UART2_Init();
__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);
while(1){
if(reception_complete == FALSE) {
HAL_UART_Receive_IT(&huart2, &rcvd, 1);
}
else {
ReturnProcessedString();
reception_complete = FALSE;
}
}
return 0;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2)
{
if(rcvd == '\r'){
reception_complete = TRUE;
buffer[count++] = '\r';
count = 0;
}else {
buffer[count++] = rcvd;
}
}
}
I had the same problem with you and had many tests in five days, but the results were not good. But I solved this problem with the help of someone I learned through someone' blog. So I want yout to share the solution.
My problem was that I used printf in interrupt route and callback. This is wrong behaviour. Also, the debugger only works once. Therefore, the results received should be verified by the trasmit command. I used TX with UART3 and RX with UART6. If there was a lot of RX data, there was a problem with sending TX as it is, so I had to print the 100th data. I confirmed that 3000Bytes are working without any problem. If you want my test code, send me the following email address. nicehans72#gmail.com. I'll let you go.
main.c
volatile uint8_t rxd[10];
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART7_Init();
MX_UART8_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart6, (uint8_t *)rxd, 1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
int a=0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
a++;
if(UartHandle->Instance == USART6)
{
if (a%100==0)
HAL_UART_Transmit(&huart3, (uint8_t *)rxd, 1, 0xFFFF);
HAL_UART_Receive_IT(&huart6, (uint8_t *)rxd, 1);
}
}
static void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
static void MX_USART6_UART_Init(void)
{
/* USER CODE BEGIN USART6_Init 0 */
/* USER CODE END USART6_Init 0 */
/* USER CODE BEGIN USART6_Init 1 */
/* USER CODE END USART6_Init 1 */
huart6.Instance = USART6;
huart6.Init.BaudRate = 9600;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
huart6.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart6.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart6) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART6_Init 2 */
/* USER CODE END USART6_Init 2 */
}
stm32f7xx_it.c
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
void USART6_IRQHandler(void)
{
/* USER CODE BEGIN USART6_IRQn 0 */
/* USER CODE END USART6_IRQn 0 */
//
HAL_UART_IRQHandler(&huart6);
/* USER CODE BEGIN USART6_IRQn 1 */
/* USER CODE END USART6_IRQn 1 */
}
I am using stm32f0 MCU.
I have a simple UART echo code in which every byte received will be transmitted out. I tested that it works. Here it is;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit(&huart1, &Rx_data[0], 1, tx_timeout);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
I do not feel comfortable with the code even though it works. Firstly, tx_timeout is 0 and most code examples are non-zero. I do not know the side effect. Secondly, HAL_UART_Transmit() is a blocking call and it is not advisable to use blocking calls inside an interrupt. So, I decided to use an interrupt for uart transmission HAL_UART_Transmit_IT()instead of a blocking call. Here is the modified code;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
However, it does not work as expected. My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with this code that uses HAL_UART_Transmit_IT()?
First:
As has been described in answers to your previous question null timeout just exclude wait for flag state. If you open HAL_UART_Transmit code - you will see that when you send 1 byte without timeout no any blocking state will!
Second:
It's not true method to send/receive one byte from a huge HAL's functions and their callbacks. I guess: next your question will "how i must implement parse there?". And I hope you will not insert you parse function in IRQ callback!
So generally you need buffers. And it is good idea to use cyclic buffer.
mxconstants.h:
/* USER CODE BEGIN Private defines */
/* Buffer's length must be select according to real messages frequency */
#define RXBUF_LEN 128 // must be power of 2
#define TXBUF_LEN 128 // must be power of 2
#define RXBUF_MSK (RXBUF_LEN-1)
#define TXBUF_MSK (TXBUF_LEN-1)
/* USER CODE END Private defines */
main.c:
uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
/* xx_i - counter of input bytes (tx - pushed for transmit, rx - received)
xx_o - counter of output bytes (tx - transmitted, rx - parsed)
xx_e - counter of echoed bytes */
volatile uint16_t rx_i = 0, tx_o = 0;
uint16_t rx_o = 0, rx_e = 0, tx_i = 0;
volatile uint8_t tx_busy = 0;
void transmit(uint8_t byte)
{
tx_buf[TXBUF_MSK & tx_i] = byte;
tx_i++;
tx_busy = 1;
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);
}
void main(void)
{
/* Initialization code */
/* ... */
/* Enable usart 1 receive IRQ */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
for (;;) {
/* Main cycle */
while (rx_i != rx_e) {
/* echo here */
transmit(rx_buf[RXBUF_MSK & rx_e]);
rx_e++;
}
while (rx_i != rx_o) {
/* parse here */
/* ... */
rx_o++;
}
/* Power save
while (tx_busy);
HAL_UART_DeInit(&huart1);
*/
}
}
stm32f0xx_it.c:
extern uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
extern volatile uint16_t rx_i, tx_o;
extern uint16_t rx_o, rx_e, tx_i;
extern volatile uint8_t tx_busy;
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if((__HAL_UART_GET_IT(&huart1, UART_IT_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET))
{
rx_buf[rx_i & RXBUF_MSK] = (uint8_t)(huart1.Instance->RDR & 0x00FF);
rx_i++;
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&huart1, UART_RXDATA_FLUSH_REQUEST);
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TXE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TXE) != RESET))
{
if (tx_i == tx_o) {
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
} else {
huart1.Instance->TDR = (uint8_t)(tx_buf[TXBUF_MSK & tx_o] & (uint8_t)0xFF);
tx_o++;
}
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TC) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TC) != RESET))
{
tx_busy = 0;
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
}
/* And never call default handler */
return;
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
And third!!!
And about this:
Why HAL_UART_Transmit_IT not help/work?
Because it's too slow! And if you try to count HAL_BUSY results:
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint32_t hal_busy_counter = 0;
if (huart->Instance == USART1) //current UART
{
if (HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1) == HAL_BUSY) {
hal_busy_counter++;
}
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
When you pause MCU in debugger after data exchange - you will be suprised: it will be equal to count of missed chars.
I would like to search Sat>IP servers on the network. Sat>IP servers advertise their presence to other Sat>IP servers and clients.
I must not continuosly send M-SEARCH messages but that instead it listens to server NOTIFY messages.
After initalizing network settings of my device, I'm sending M-SEARCH message and getting response if there is already any active Sat>IP server.
However, I couldn't get any response, If I opens Sat>IP server after sending M-SEARCH message.
Here's my code.
void SatIP::InitDiscoverThread()
{
if(INVALID_THREAD_CHK == DiscoverThreadChk)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
printf("InitDiscoverThread pthread_create\n");
DiscoverThreadChk = PTH_RET_CHK(pthread_create(&DiscoverThreadID, &attr, DiscoverThreadFunc, this));
if(DiscoverThreadChk != 0)
{
ASSERT(0);
}
}
}
void SatIP::FinalizeDiscoverThread()
{
if(INVALID_THREAD_CHK != DiscoverThreadChk)
{
printf("FinalizeDiscoverThread pthread_cancel\n");
pthread_cancel(DiscoverThreadID);
DiscoverThreadChk = INVALID_THREAD_CHK;
close(discoverSocket);
}
}
void *SatIP::DiscoverThreadFunc(void* arg)
{
SatIP* satip = (SatIP *)arg;
satip->ListenSSDPResponse();
pthread_exit(NULL);
}
bool SatIP::SendMSearchMessage()
{
vSatIPServers.clear();
FinalizeDiscoverThread();
const char *searchSatIPDevice = "M-SEARCH * HTTP/1.1\r\n" \
"HOST: 239.255.255.250:1900\r\n" \
"MAN: \"ssdp:discover\"\r\n" \
"MX: 2\r\n" \
"ST: urn:ses-com:device:SatIPServer:1\r\n\r\n";
struct sockaddr_in upnpControl, broadcast_addr;
discoverSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (discoverSocket == INVALID_SOCKET)
{
printf("socked failed INVALID_SOCKET\n");
return false;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(discoverSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)) == SOCKET_ERROR)
{
printf("setsockopt timeout failed\n");
close(discoverSocket);
return false;
}
socklen_t ttl = 2;
if(setsockopt(discoverSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == SOCKET_ERROR)
{
printf("setsockopt TTL failed\n");
close(discoverSocket);
return false;
}
if(setsockopt(discoverSocket, SOL_SOCKET, SO_BROADCAST, searchSatIPDevice, sizeof(searchSatIPDevice)) == SOCKET_ERROR)
{
printf("setsockopt broadcast failed\n");
close(discoverSocket);
return false;
}
upnpControl.sin_family = AF_INET;
upnpControl.sin_port = htons(0);
upnpControl.sin_addr.s_addr = INADDR_ANY;
if (bind(discoverSocket, (sockaddr*)&upnpControl, sizeof(upnpControl)) == SOCKET_ERROR)
{
printf("bind failed\n");
close(discoverSocket);
return false;
}
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
for(int i = 0; i < 3; i++)
{
if(sendto(discoverSocket, searchSatIPDevice, strlen(searchSatIPDevice), 0, (sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) == SOCKET_ERROR)
{
//printf("sendto failed\n");
close(discoverSocket);
return false;
}
else
{
usleep(10*100);
}
}
InitDiscoverThread();
return true;
}
void SatIP::ListenSSDPResponse()
{
while(1)
{
char buf[512];
memset(buf, 0, 512);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
int bcLen = sizeof(broadcast_addr);
//bool bRet = false;
while (recvfrom(discoverSocket, buf, 512, 0, (struct sockaddr*)&broadcast_addr, (socklen_t*)&bcLen) > 0)
{
printf("buf:%s\n",buf);
SATIP_SERVER_DESCRIPTION stServerDesc;
ostringstream ss;
if(strstr(buf, "device:SatIPServer"))
{
int i = 0;
char *deviceIp = strstr(buf, "LOCATION:") + 9; // get xml location including server description
while(deviceIp[i] == ' ') i++; // remove spaces from string
while(!isspace(deviceIp[i]))
{
ss << deviceIp[i];
++i;
}
stServerDesc.location = ss.str().c_str();
printf("location:%s\n",stServerDesc.location.c_str());
ss.str(""); // clear ss
i=0; // clear counter
deviceIp = strstr(buf, "http://") + 7; // get ip address
while(deviceIp[i] != ':')
{
ss << deviceIp[i];
++i;
}
stServerDesc.ipAddr = ss.str().c_str();
printf("ipAddr:%s\n", stServerDesc.ipAddr.c_str());
DownloadDeviceDescription(&stServerDesc);
stServerDesc.macAddr = GetMACAddressviaIP(stServerDesc.ipAddr);
printf("macAddr:%s\n", stServerDesc.macAddr.c_str());
if(IsServerProperToAdd(&stServerDesc))
vSatIPServers.push_back(stServerDesc);
printf("\n");
//bRet = true;
}
memset(buf, 0, 512);
}
}
}
How can I fix this issue? Any help would be appreciated.
Listening SSDP notify message is not related to sending M-SEARCH message. Devices like Sat>IP send NOTIFY message to 239.255.255.250 periodically even if you don't send M-SEARCH message. So, you should join a multicast group and receives from the group.
You can use the listener program in the following link by changing HELLO_PORT as 1900 and HELLO_GROUP as "239.255.255.250".
http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html
/*
* listener.c -- joins a multicast group and echoes all data it receives from
* the group to its stdout...
*
* Antony Courtney, 25/11/94
* Modified by: Frédéric Bastien (25/03/04)
* to compile without warning and work correctly
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define HELLO_PORT 1900
#define HELLO_GROUP "239.255.255.250"
#define MSGBUFSIZE 256
main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd, nbytes,addrlen;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1) {
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
(struct sockaddr *) &addr,&addrlen)) < 0) {
perror("recvfrom");
exit(1);
}
puts(msgbuf);
}
}