Jump to content

You're browsing the 2004-2023 VATSIM Forums archive. All content is preserved in a read-only fashion.
For the latest forum posts, please visit https://forum.vatsim.net.

Need to find something? Use the Google search below.

Best way to asynchronously call a webpage and weird bugs


Pierre Ferran
 Share

Recommended Posts

Pierre Ferran
Posted
Posted

Hello everyone,

 

I'm making a plugin that [Mod - Happy Thoughts]ign squawk code based on the response from a webpage, what would be the best way to call that webpage asynchronously ?

The way i'm currently doing this is making a std thread that I detach, but i'm no expert in thread management/c++ so i'm asking for your help.

 

Here is the code I tried:

 

[...]
else if (FunctionId == TAG_FUNC_SQUAWKFORCEMODEA) {

	thread m_getSqThread = std::thread(&CCAUTRA::CautraHTTPThreadedGetSq, this, FlightPlanSelectASEL());
	m_getSqThread.detach();
}
[...]
void CCAUTRA::CautraHTTPThreadedGetSq(EuroScopePlugIn::CFlightPlan fp) {

string url = "http://195.154.85.30/vCAUTRA/cautra.php";

CInternetSession session;
CHttpFile *pHttpFile = NULL;
CString response = NULL;

do {
	try
	{
		pHttpFile = (CHttpFile *)session.OpenURL(url.c_str(), 1, INTERNET_FLAG_DONT_CACHE);
	}
	catch (...)
	{
		DisplayUserMessage("vCAUTRA", "WARNING", "Impossible de se connecter au serveur, mode hors-ligne activé.", true, true, true, true, true);
		offline_mode = true;
		break;
	}

	if (pHttpFile == NULL) {
		DisplayUserMessage("vCAUTRA", "WARNING", "Impossible de se connecter au serveur, mode hors-ligne activé.", true, true, true, true, true);
		offline_mode = true;
		break;
	}
	else
	{
		CString line;
		for (long j = 0; pHttpFile->ReadString(line); j++) {
			response += line;
		}
	}
	pHttpFile->Close();
} while (IsSquawkInUse(atoi(response)) &&!offline_mode);

if (!offline_mode)
	fp.GetController[Mod - Happy Thoughts]ignedData().SetSquawk(response);	

}

 

EDIT: Pink screen bug fixed

 

I never had a problem before drawing the trails, so I think the bug comes from drawing the symbol, using the position of the aircraft. I have to specify that I use Professional Radar, and the issue seems to appear when an uncorrelated aircraft spawns. That bug occurs using EuroScope 3.2, and EuroScope 3.2 with the beta patch.

 

Another issue that I have using EuroScope 3.2, and EuroScope 3.2 with the beta patch, is that even if I have turned off the simulated traffic, it actually sometimes appear randomly, and some aircraft are showing up in my sector inbound list that are very far from my sector, eg: controlling LFPG_APP, i'll see an Aircraft that is in Greece flying from LGAV and OMDB, so yea, no way its going near my sector. I think I might have solved the problem by overriding the vatsim status URL with a blank box, but i'm not sure yet. That is using again professional mode S.

 

Thank you for your help

Link to comment
Share on other sites

Pierre Ferran
Posted
Posted

I fixed the pink screen problem, it was just the mfc library being dumb (dc.Rectangle()).

Link to comment
Share on other sites

  • 2 weeks later...
Merik Nanish 1184142
Posted
Posted

Pierre,

 

This thread happens to be very timely and beneficial for me, as I am also working on a plugin where I need to asynchronously fetch some information from a URL and use that to modify certain aspects of the flight plan.

 

I understand you may not want to share the full code publicly. Can I please ask you to kindly send it to me by email? You can find my email on this page: http://nyartcc.org/roster/staff

 

Thanks!

 

Merik

NYARTCC Facility Engineer and Instructor

 

255qao8.png

Link to comment
Share on other sites

Pierre Ferran
Posted
Posted

Sent you an e-mail

Link to comment
Share on other sites

Gergely Csernak
Posted
Posted

I have no experience with std::thread as I always use the MFC version.

But be sure that EuroScope plug-in functions are not thread safe at all. So it would be a much wiser to propagate the squawk to the main thread and [Mod - Happy Thoughts]ign it to the plane there. Even it works fine at the moment.

Gergely.

EuroScope developer

Link to comment
Share on other sites

Sam White 1214219
Posted
Posted
If you decide to use this method I would be happy to share some of my source code from an MFC application for the communication with the web server if it helps?

 

Hi Sam,

 

If you don't mind, I would be very interested in the c++/mfc code, i've posted this thread a few weeks ago, and so far no replies: viewtopic.php?f=71&t=65956

 

That would be very nice of you.

 

Regards

Hello Pierre,

 

To communicate with a web-server I use libcurl which makes the communication process a lot easier. To set it up with MSVS follow the tutorial here:

http://quantcorner.wordpress.com/2012/04/08/using-libcurl-with-visual-c-2010/

 

Please be aware that the following code is lifted from another file I have created and may have some errors where I have accidentally deleted needed lines of code! If you get any errors that may be down to this please say, and I will look into it for you! In the same respect some of the includes libraries may not actually be needed and may be needed for other code I have written. Please also note that not all of this code is my own and the vast majority is from the example source code here:

http://curl.haxx.se/libcurl/c/getinmemory.html

and here:

http://curl.haxx.se/libcurl/c/http-post.html

 

Here is the source code, I have tried to annotate it with comments in key places:

// Generic post and response

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>	//not sure if needed
#include <sstream>		//not sure if needed

struct MemoryStruct {
 char *memory;
 size_t size;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
 size_t realsize = size * nmemb;
 struct MemoryStruct *mem = (struct MemoryStruct *)userp;

 mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
 if(mem->memory == NULL) {
printf("not enough memory (realloc returned NULL)\n");	// out of memory!

   return 0;
 }

 memcpy(&(mem->memory[mem->size]), contents, realsize);
 mem->size += realsize;
 mem->memory[mem->size] = 0;

 return realsize;
}

void SendData()
{
CURL *curl_handle;
CURLcode res;
struct MemoryStruct chunk;
chunk.memory = (char*)malloc(1);  // will be grown as needed by the realloc above
chunk.size = 0;    //no data at this point
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();	//init curl
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://example.com/data.php");	//URL to send data to
std::string param1("data1=");	//Name of first field in the POST form
std::string param2("&data2=");	//Name of second field in the POST form
CString data1("datatosend1");	//Data to send to first field in the POST form
CString data2("datatosend2");	//Data to send to second field in the POST form
param1.append(data1);
param2.append(data2);
param1.append(param2);
const char* parameters;
parameters=param1.c_str();	//combines the data to send to the webpage into a single variable which can be used by CURLOPT_POSTFIELDS
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, parameters);	//add data to be sent
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, 1);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);	//all data sent to this function 
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);	//p[Mod - Happy Thoughts] buffer to writeback func
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");	//useragent
res = curl_easy_perform(curl_handle);	//perform request
if(res != CURLE_OK)	//error check
{
	fprintf(stderr, "curl_easy_perform() failed: %s\n",
	curl_easy_strerror(res));
}
else 
{
	//At this stage the data retrieved from the webpage is in chunk.memory
	//The code below might be useful for copying data out of chunk.memory and into more usable variables
	//It presumes the data is returned in the format: "<string>,<int>,<int>" where each value is separated by ',' as a delimiter
	CString int1temp;
	CString int2temp;
	CString fullcpy;
	CString string;	//the string
	int int1(0);	//first integer
	int int2(0);	//second integer
	char result[254];	//buffer to copy data to
	strcpy(result, chunk.memory);	//copies chunk.memory into result
	char *p = std::strtok (result,",");	//delimiter is ','
	string=p;	//the string is stored here
	p = std::strtok(NULL,",");
	int1temp=p;
	int1=atoi(int1temp);	//first integer is stored here
	p = std::strtok(NULL,",");
	int2temp=p;
	int2=atoi(int2temp);	//second integer is stored here
}
curl_easy_cleanup(curl_handle);	//clean up curl
if(chunk.memory)
	free(chunk.memory);
curl_global_cleanup();	//clean up libcurl


}

The PHP script it interacts with has a basic structure like this:

<?php
if (!isset($_POST['data1']))
{
echo '
<form method="post" action="' . $_SERVER["PHP_SELF"] . '">
<input type="text" name="data1">
<input type="text" name="data2">
<input type="hidden" name="Sent" value="1">
<input type="submit" value="Submit Data">
</form>';
}
else
{
//Do something with the sent data and then give a result to be returned to the application using either 'echo' or 'die'
//e.g.
echo "Sam White,100,90";	//the result that the application will return
}
?>

There is no 'proper' HTML in this like starting with then e.c.t. as otherwise that will also be sent back to the client.

 

I hope this helps you!

Sam

VATSIM UK S2 Rated (Essex RTS)

Sam%20White.jpg

Link to comment
Share on other sites

Pierre Ferran
Posted
Posted

Thank you very much for your code, i'll try it and keep you up to date

Link to comment
Share on other sites

 Share