Hi I have try to read Stream from the server with this code
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, wchar_t &Key)
{
//TMemoryStream *TMS = new TMemoryStream;
TStringStream *TSS = new TStringStream;
AnsiString A,B;
TStream *TS;
INT64 Len;
try
{
if (Key == VK_RETURN)
{
Beep(0,0);
if(Edit1->Text == "mystream")
{
TCPClient1->IOHandler->WriteLn("mystream");
Len = StrToInt(TCPClient1->IOHandler->ReadLn());
TCPClient1->IOHandler->ReadStream(TS,Len,false);
TSS->CopyFrom(TS,0);
RichEdit1->Lines->Text = TSS->DataString;
Edit1->Clear();
}
else
{
TCPClient1->IOHandler->WriteLn(Edit1->Text);
A = TCPClient1->IOHandler->ReadLn();
RichEdit1->Lines->Add(A);
Edit1->Clear();
}
}
}
__finally
{
TSS->Free();
}
}
and every times client try to read stream from the server, compiler says.
First chance exception at $75D89617. Exception class EAccessViolation with message 'Access violation at address 500682B3 in module 'rtl140.bpl'. Read of address 00000018'. Process Project1.exe (6056)
How to handle this?
You are not instantiating your TStream object before calling ReadStream(). Your TS variable is completely uninitialized. ReadStream() does not create the TStream object for you, only writes to it, so you have to create the TStream yourself beforehand.
Given the code you have shown, you can replace the TStream completely by using the ReadString() method instead:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, wchar_t &Key)
{
if (Key == VK_RETURN)
{
Beep(0,0);
if (Edit1->Text == "mystream")
{
TCPClient1->IOHandler->WriteLn("mystream");
int Len = StrToInt(TCPClient1->IOHandler->ReadLn());
RichEdit1->Lines->Text = TCPClient1->IOHandler->ReadString(Len);
}
else
{
TCPClient1->IOHandler->WriteLn(Edit1->Text);
String A = TCPClient1->IOHandler->ReadLn();
RichEdit1->Lines->Add(A);
}
Edit1->Clear();
}
}
Related
Hello nano developers,
I'd like to realize the following proto:
message container {
enum MessageType {
TYPE_UNKNOWN = 0;
evt_resultStatus = 1;
}
required MessageType mt = 1;
optional bytes cmd_evt_transfer = 2;
}
message evt_resultStatus {
required int32 operationMode = 1;
}
...
The dots denote, there are more messages with (multiple) primitive containing datatypes to come. The enum will grow likewise, just wanted to keep it short.
The container gets generated as:
typedef struct _container {
container_MessageType mt;
pb_callback_t cmd_evt_transfer;
} container;
evt_resultStatus is:
typedef struct _evt_resultStatus {
int32_t operationMode;
} evt_resultStatus;
The field cmd_evt_transfer should act as a proxy of subsequent messages like evt_resultStatus holding primitive datatypes.
evt_resultStatus shall be encoded into bytes and be placed into the cmd_evt_transfer field.
Then the container shall get encoded and the encoding result will be used for subsequent transfers.
The background why to do so, is to shorten the proto definition and avoid the oneof thing. Unfortunately syntax version 3 is not fully supported, so we can not make use of any fields.
The first question is: will this approach be possible?
What I've got so far is the encoding including the callback which seems to behave fine. But on the other side, decoding somehow skips the callback. I've read issues here, that this happened also when using oneof and bytes fields.
Can someone please clarify on how to proceed with this?
Sample code so far I got:
bool encode_msg_test(pb_byte_t* buffer, int32_t sval, size_t* sz, char* err) {
evt_resultStatus rs = evt_resultStatus_init_zero;
rs.operationMode = sval;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/*encode container*/
container msg = container_init_zero;
msg.mt = container_MessageType_evt_resultStatus;
msg.cmd_evt_transfer.arg = &rs;
msg.cmd_evt_transfer.funcs.encode = encode_cb;
if(! pb_encode(&stream, container_fields, &msg)) {
const char* local_err = PB_GET_ERROR(&stream);
sprintf(err, "pb_encode error: %s", local_err);
return false;
}
*sz = stream.bytes_written;
return true;
}
bool encode_cb(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
evt_resultStatus* rs = (evt_resultStatus*)(*arg);
//with the below in place a stream full error rises
// if (! pb_encode_tag_for_field(stream, field)) {
// return false;
// }
if(! pb_encode(stream, evt_resultStatus_fields, rs)) {
return false;
}
return true;
}
//buffer holds previously encoded data
bool decode_msg_test(pb_byte_t* buffer, int32_t* sval, size_t msg_len, char* err) {
container msg = container_init_zero;
evt_resultStatus res = evt_resultStatus_init_zero;
msg.cmd_evt_transfer.arg = &res;
msg.cmd_evt_transfer.funcs.decode = decode_cb;
pb_istream_t stream = pb_istream_from_buffer(buffer, msg_len);
if(! pb_decode(&stream, container_fields, &msg)) {
const char* local_err = PB_GET_ERROR(&stream);
sprintf(err, "pb_encode error: %s", local_err);
return false;
}
*sval = res.operationMode;
return true;
}
bool decode_cb(pb_istream_t *istream, const pb_field_t *field, void **arg) {
evt_resultStatus * rs = (evt_resultStatus*)(*arg);
if(! pb_decode(istream, evt_resultStatus_fields, rs)) {
return false;
}
return true;
}
I feel, I don't have a proper understanding of the encoding / decoding process.
Is it correct to assume:
the first call of pb_encode (in encode_msg_test) takes care of the mt field
the second call of pb_encode (in encode_cb) handles the cmd_evt_transfer field
If I do:
bool encode_cb(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
evt_resultStatus* rs = (evt_resultStatus*)(*arg);
if (! pb_encode_tag_for_field(stream, field)) {
return false;
}
if(! pb_encode(stream, evt_resultStatus_fields, rs)) {
return false;
}
return true;
}
then I get a stream full error on the call of pb_encode.
Why is that?
Yes, the approach is reasonable. Nanopb callbacks do not care what the actual data read or written by the callback is.
As for why your decode callback is not working, you'll need to post the code you are using for decoding.
(As an aside, Any type does work in nanopb and is covered by this test case. But the type_url included in all Any messages makes them have a quite large overhead.)
I'm trying to create a function to get a username using a try and catch method in C++. Unfortunately this code doesn't work, and my application closes when it tries to run.
QString UserInfo::getFullUserName()
{
DBG_ENTERFUNC(getFullUserName);
QString result;
qDebug("trying to get the username");
try
{
struct passwd fullUserData=*getpwnam(getUserName().toLatin1());
result = fullUserData.pw_gecos;
// it is the first of the comma seperated records that contain the user name
result = result.split(",").first();
if (result.isEmpty())
{
result = getUserName();
}
}
catch (...)
{
qDebug("exception caught");
}
qDebug() << result;
#endif
DBG_EXITFUNC;
return result;
}
The problem occurs in this line of code as I have placed prints after it that are never reached.
struct passwd fullUserData=*getpwnam(getUserName().toLatin1());
Does anyone know what is the issue here?
*Edit--------
Here is my function getUserName()
QString UserInfo::GetUserName()
{
DBG_ENTERFUNC(GetUserName);
QString result;
foreach (QString environmentEntry, QProcess::systemEnvironment())
{
QString varName = environmentEntry.section('=',0,0);
QString varValue = environmentEntry.section('=',1,1);
if (varName == "USER" || varName == "USERNAME")
{
result = varValue;
}
}
DBG_EXITFUNC;
return result;
}
getpwnam() returns NULL when the username was not found. You are potentially dereferencing a NULL pointer.
*getpwnam(getUserName().toLatin1());
// ^ potential NULL pointer deref
Always check before deferencing a potentially invalid pointer:
struct passwd *fullUserData = getpwnam(getUserName().toLatin1());
// ^ note pointer
if (fullUserData != NULL) {
result = fullUserData->pw_gecos;
// ^^ fullUserData is a struct pointer
} else {
// throw Exception
}
If this is confusing to you, you might want to read up on C++ and pointers.
I'm using C# to call methods from an dll file to record video.
This is the Marshal methods file
http://pastebin.com/YrVvBfZ9
This is my CameraUtilities file
http://pastebin.com/0AZNtnhk
This is my camera file
http://pastebin.com/ZE3HD1zq
When I call StartRecord method (in camera file) to start Record video.
public void StartRecord()
{
if (this.ListCameras != null)
{
bool bRes = true;
try
{
int tmpError = -1;
m_tmpContext = new IntPtr();
m_handle = new GCHandle();
m_callBackChannels = new ulong[m_ListCameras.Length];
for (int i = 0; i < m_ListCameras.Length; i++)
{
m_callBackChannels[i] = 10;
cameraCurrentIndex = 0;
IntPtr channelHandle = T1800.T18_ChannelOpen(cameraCurrentIndex);
m_ListCameras[cameraCurrentIndex].ChannelHandle = channelHandle;
T1800.T18_CaptureIFrame(m_ListCameras[i].ChannelHandle);
m_ListCameras[i].BeginRecord();
if (AllowRecordVideo)
{
m_del = new T1800.STREAM_READ_CALLBACK(StreamReadCallBack);
m_tmpContext = m_ListCameras[i].ChannelHandle;
tmpError = T1800.T18_RegisterStreamReadCallback(m_del, ref m_tmpContext);
}
}
if (tmpError == -1) bRes = false;
}
catch (Exception ex)
{
Log.Logger.Error(ex);
bRes = false;
}
}
}
It throw an exception
- System.Runtime.InteropServices.MarshalDirectiveException: Invalid PInvoke calling convention.
Thiscall requires that the first parameter is present and can be enregistered.
at System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegateInternal(Delegate d)
at System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(Delegate d)
at TH.Parking.Wrapper.HBCamera.T1800.dll_T18_RegisterStreamReadCallback(STREAM_READ_CALLBACK STREAM_READ_CALLBACK, IntPtr& context)
at TH.Parking.Wrapper.HBCamera.CameraUtilities.StartRecord() in d:\TH.Parking\TH.Parking\Wrapper\HBCamera\CameraUtilities.cs:line 93
I can't find any reason for this error. Can somebody help me to fix this.
I think the callback you pass to create the STREAM_READ_CALLBACK object should be static. Otherwise, the thispointer is lost during the marshalling.
Instead of:
private int StreamReadCallBack(ulong channelHandle, IntPtr context)
{
...
}
try:
private static int StreamReadCallBack(ulong channelHandle, IntPtr context)
{
...
}
And you'll need to somehow put your instance of CameraUtility into the context parameter.
I've been trying to call an external function with the GetProcAddress function but everytime i call the function it crashes the console, ive been looking but in every post i get the same final solution but when i try it in my DLL it crashes the app.
Here's the code:
#include <Windows.h>
#include <vector>
#include "SDK\plugin.h"
typedef void (*logprintf_t)(char* format, ...);
logprintf_t logprintf;
// static void* m_AMXExports[44];
typedef bool (PLUGIN_CALL *ServerPluginLoad_t)(void **data);
typedef void (PLUGIN_CALL *ServerPluginUnload_t)();
typedef unsigned int (PLUGIN_CALL *ServerPluginSupports_t)();
typedef void (PLUGIN_CALL *ServerPluginProcessTick_t)();
typedef int (PLUGIN_CALL *ServerPluginAmxLoad_t)(AMX *amx);
typedef int (PLUGIN_CALL *ServerPluginAmxUnload_t)(AMX *amx);
struct Plugins
{
void* AppData[256];
SUPPORTS_FLAGS FlagSupport;
HMODULE Module;
ServerPluginLoad_t LOAD;
ServerPluginUnload_t UNLOAD;
ServerPluginSupports_t SUPPORTS;
ServerPluginProcessTick_t PROCESSTICK;
// AMX Plugin Interface
ServerPluginAmxLoad_t AMXLOAD;
ServerPluginAmxUnload_t AMXUNLOAD;
};
Plugins* ServerPlugins;
void **ppPluginData ;
extern void *pAMXFunctions;
//native LoadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
bool validfunc = false;
char *path;
amx_StrParam(amx, params[1], path);
logprintf("Loading plugin %s", path);
ServerPlugins = new Plugins();
ServerPlugins->Module = LoadLibraryA(path);
if (ServerPlugins->Module == NULL)
{
delete ServerPlugins;
logprintf("Failed loading plugin %s (Error: %d)", path, GetLastError());
return 0;
}
logprintf("NULL");
ServerPlugins->LOAD = (ServerPluginLoad_t)GetProcAddress(ServerPlugins->Module, "Load");
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
ServerPlugins->SUPPORTS = (ServerPluginSupports_t)GetProcAddress(ServerPlugins->Module, "Supports");
if (ServerPlugins->LOAD == NULL || ServerPlugins->SUPPORTS == NULL || ServerPlugins->UNLOAD == NULL)
{
logprintf(" Plugin doesnt conform to architecture");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 1");
ServerPlugins->FlagSupport = (SUPPORTS_FLAGS)ServerPlugins->SUPPORTS();
if ((ServerPlugins->FlagSupport & SUPPORTS_VERSION_MASK) > SUPPORTS_VERSION)
{
logprintf("Unsupported Version; unloading.");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 2");
if ((ServerPlugins->FlagSupport & SUPPORTS_AMX_NATIVES) > SUPPORTS_VERSION)
{
ServerPlugins->AMXLOAD = (ServerPluginAmxLoad_t)GetProcAddress(ServerPlugins->Module, "AmxLoad");
ServerPlugins->AMXUNLOAD = (ServerPluginAmxUnload_t)GetProcAddress(ServerPlugins->Module, "AmxUnload");
}
else
{
ServerPlugins->AMXLOAD = NULL;
ServerPlugins->AMXUNLOAD = NULL;
logprintf("Any Abstract Machine has been loaded");
}
logprintf("NULL 3");
if ((ServerPlugins->FlagSupport & SUPPORTS_PROCESS_TICK) != 0)
{
ServerPlugins->PROCESSTICK = (ServerPluginProcessTick_t)GetProcAddress(ServerPlugins->Module, "ProcessTick");
}
else
{
ServerPlugins->PROCESSTICK = NULL;
}
logprintf("NULL 4"); //debugging
ServerPlugins->AppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ServerPlugins->AppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ServerPlugins->AppData)) //i didnt put it as &ServerPlugins->AppData because it causes an error
{
logprintf("Initialized failed loading plugin %s", path);
FreeLibrary(ServerPlugins->Module);
logprintf("NULL 5");
delete ServerPlugins;
return false;
}
logprintf("Plugin %s loaded", path);
return true;
}
//native UnloadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
char *path;
amx_StrParam(amx, params[1], path);
ServerPlugins->Module = GetModuleHandle((LPCTSTR)path);
if (ServerPlugins->Module != NULL)
{
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
if (ServerPlugins->UNLOAD != NULL)
{
ServerPlugins->UNLOAD();
FreeLibrary(GetModuleHandleA(path));
logprintf("Library %s has been unloaded correctly", path);
return 1;
}
else
{
logprintf("Unloading library %s failed (Error: %d)", GetLastError());
return 0;
}
}
return 1;
}
PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData)
{
pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
return 1;
}
PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
}
PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}
AMX_NATIVE_INFO projectNatives[] =
{
{ "LoadLibrary", my_LoadLibrary },
{ "UnloadLibrary", my_UnloadLibrary }
};
PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx)
{
return amx_Register(amx, projectNatives, -1);
}
PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx)
{
return AMX_ERR_NONE;
}
You have a memory leak in convertCharArrayToLPCWSTR(). You are never freeing the wchar_t* that you allocate. The convertCharArrayToLPCWSTR() function itself is not needed, you can simply pass the char* path as-is to LoadLibraryA() instead:
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Module = LoadLibraryA(path);
You are not checking if ServerPlugins->UNLOAD is successfully loaded by GetProcAddress("Unload") or not.
You are using GetProcAddress("Load") for both ServerPlugins->LOAD and ServerPlugins->AMXLOAD, and GetProcAddress("Unload") for both ServerPlugins->UNLOAD and ServerPlugins->AMXUNLOAD. That is very fishy to me. Does the DLL really use the same exports for AMX and non-AMX entry points? If so, that is very bad design, considering that ServerPluginLoad_t has a very different signature than ServerPluginAmxLoad_t, and the same for ServerPlugin(Amx)Unload_t. That is a corrupted call stack waiting to happen. It would be much safer to have the DLL export separate AmxLoad() and AmxUnload() functions instead.
For that matter, the SUPPORTS_AMX_NATIVES and SUPPORTS_PROCESS_TICK flags are redundant, since GetProcAddress() would tell you if those exports are available or not.
As for the crash when calling ServerPlugins->LOAD, I do not see you initializing ppData with any data before passing it to Load(). Certainly not the PLUGIN_DATA_AMX_EXPORTS and PLUGIN_DATA_LOGPRINTF slots, at least:
ppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ppData))
So even if the call to Load() itself did not crash, the DLL would still likely crash at a later time when it tries to use its local pAMXFunctions and logprintf pointers that were assigned in Load().
For that matter, why are you passing things like that as a void* array instead of a struct? That would have been much safer, eg:
struct PluginInitData
{
void* pAMXFunctions;
logprintf_t logprintf;
...
};
typedef bool (__stdcall *ServerPluginLoad_t)(PluginInitData* data);
PluginInitData pInitData;
pInitData.pAMXFunctions = pAMXFunctions;
pInitData.logprintf = &logprintf;
...
if (!(ServerPlugins->LOAD)(&pInitData))
extern "C" bool __stdcall Load(PluginInitData* data)
{
pAMXFunctions = data->pAMXFunctions;
logprintf = data->logprintf;
...
return true;
}
Update: you have fixed most of the issues I mentioned, but now I see that your my_UnloadLibrary() function is implemented wrong. DO NOT call GetModuleHandle() or GetProcAddress() at all, use the existing Module and UNLOAD pointers that were initialized earlier in my_LoadLibrary().
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Path = path;
...
}
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
if (ServerPlugins)
{
if (ServerPlugins->UNLOAD != NULL)
ServerPlugins->UNLOAD();
if (ServerPlugins->Module != NULL)
{
FreeLibrary(ServerPlugins->Module);
ServerPlugins->Module = NULL;
}
logprintf("Library %s has been unloaded", ServerPlugins->Path);
delete ServerPlugins;
ServerPlugins = NULL;
}
return 1;
}
If you are still having problems with Load() crashing, then you are just going to have to use your compiler's debugger to find out what is actually happening at run-time. The code shown so far should not be crashing, so either you have a calling convention mismatch, or a data alignment mismatch, or corrupted memory, or something like that. We can't run you debugger for you.
I want to implement port-forwarding using intel-upnp.
I got XML data like:
Device found at location: http://192.168.10.1:49152/gatedesc.xml
service urn:schemas-upnp-org:service:WANIPConnection:1
controlurl /upnp/control/WANIPConn1
eventsuburl : /upnp/control/WANIPConn1
scpdurl : /gateconnSCPD.xml
And now, I want to make upnp-action. But, I don't know how to make it.
If you know some code snippet or helpful URL in C, please tell me.
char actionxml[250];
IXML_Document *action = NULL;
strcpy(actionxml, "<u:GetConnectionTypeInfo xmlns:u=\"urn:schemas-upnp- org:service:WANCommonInterfaceConfig:1\">");
action = ixmlParseBuffer(actionxml);
int ret = UpnpSendActionAsync( g_handle,
"http:192.168.10.1:49152/upnp/control/WANCommonIFC1",
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
NULL,
action,
upnp_callback,
NULL);
I know this is an old question, but it can be kept for reference. You can take a look at the sample code in the libupnp library here: https://github.com/mrjimenez/pupnp/blob/master/upnp/sample/common/tv_ctrlpt.c
The relevant code is in the function TvCtrlPointSendAction():
int TvCtrlPointSendAction(
int service,
int devnum,
const char *actionname,
const char **param_name,
char **param_val,
int param_count)
{
struct TvDeviceNode *devnode;
IXML_Document *actionNode = NULL;
int rc = TV_SUCCESS;
int param;
ithread_mutex_lock(&DeviceListMutex);
rc = TvCtrlPointGetDevice(devnum, &devnode);
if (TV_SUCCESS == rc) {
if (0 == param_count) {
actionNode =
UpnpMakeAction(actionname, TvServiceType[service],
0, NULL);
} else {
for (param = 0; param < param_count; param++) {
if (UpnpAddToAction
(&actionNode, actionname,
TvServiceType[service], param_name[param],
param_val[param]) != UPNP_E_SUCCESS) {
SampleUtil_Print
("ERROR: TvCtrlPointSendAction: Trying to add action param\n");
/*return -1; // TBD - BAD! leaves mutex locked */
}
}
}
rc = UpnpSendActionAsync(ctrlpt_handle,
devnode->device.
TvService[service].ControlURL,
TvServiceType[service], NULL,
actionNode,
TvCtrlPointCallbackEventHandler, NULL);
if (rc != UPNP_E_SUCCESS) {
SampleUtil_Print("Error in UpnpSendActionAsync -- %d\n",
rc);
rc = TV_ERROR;
}
}
ithread_mutex_unlock(&DeviceListMutex);
if (actionNode)
ixmlDocument_free(actionNode);
return rc;
}
The explanation is that you should create the action with UpnpMakeAction() if you have no parameters or UpnpAddToAction() if you have parameters to create your action, and then send it either synchronously or asynchronously.