Connecting to WCF web service using gSOAP - c++

I am writing a simple cmd client to try to consume the WCF web service i developed in order to test how to connect to the Web service using unmanaged C++.
I have been following this tutorial http://www.blinnov.com/en/2008/01/22/wcf-service-unmanaged-client/ step by step but still not managed to consume the service successfully.
#include "BasicHttpBinding_USCOREIService1.nsmap"
#include "soapBasicHttpBinding_USCOREIService1Proxy.h"
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char **argv)
{
BasicHttpBinding_USCOREIService1Proxy myProxy;
static const char* const endPoint = "http://localhost:50181/Service1.svc";
myProxy.soap_endpoint = endPoint;
_ns1__GetData param;
_ns1__GetDataResponse response;
param.fileName = &std::string("house.ifc");
if ( myProxy.GetData(&param, &response) == SOAP_OK) {
cout << "Hello" << endl; //Succeeded
}
else {
myProxy.soap_stream_fault(std::cerr);
}
return 0;
}
it always gives me
Error 415 fault: SOAP-ENV:Server[no subcode]
"HTTP Error"
Detail: HTTP/1.1 415 Unsupported Media Type
I have been trying all the day to get it done but still nothing new. :(

This is because gSOAP client and WCF service do not play nicely with SOAP 1.2.
It will work if you use soapcpp2 with the "-1" switch to force SOAP 1.1.
I've tested it with gSOAP 2.8.4 on Ubuntu and it works.

If your client will be installed in windows machine , the best way is to use a C++\CLI bridge that connect your client and the managed generated proxy, this is the only solution that works for all kind of wcf bindings (HTTP,TCP,MSMQ,...).
If you choose another librairy be sure that it can works perfectly only for HTTP binding.

Related

Minimal working example of QWebEngine with client certificates?

I am trying to get client certificates working with the Qt web engine (version 5.15), but I can't seem to get it done!
I have a local server set up to use SSL, to expect client certificates and check them against a locally created root CA certificate. The client on the other hand, has a client certificate, signed by this local root CA.
This is as far as I can whittle it down ... which might be too far, causing the problems!
#include <QApplication>
#include <QtWebEngine>
#include <QWebEngineProfile>
#include <QWebEngineView>
class MyWebPage : public QWebEnginePage
{
public:
MyWebPage(QObject * Parent) :
QWebEnginePage{Parent}
{
QObject::connect(this, &QWebEnginePage::selectClientCertificate, this, &MyWebPage::SelectClientCertificate);
}
protected:
auto certificateError(QWebEngineCertificateError const & CertificateError) -> bool override
{
return true;
}
auto SelectClientCertificate(QWebEngineClientCertificateSelection ClientCertificateSelection) -> void
{
ClientCertificateSelection.select(ClientCertificateSelection.certificates().front());
}
};
auto main(int argc, char *argv[]) -> int
{
QtWebEngine::initialize();
auto Application = QApplication{argc, argv};
auto WebView = QWebEngineView{};
WebView.resize(1024, 750);
WebView.show();
auto ClientCertificateFile = QFile{"client.pem"};
ClientCertificateFile.open(QIODevice::ReadOnly);
auto ClientCertificate = QSslCertificate{&ClientCertificateFile};
ClientCertificateFile.close();
auto PrivateKeyFile = QFile{"client.key"};
PrivateKeyFile.open(QIODevice::ReadOnly);
auto PrivateKey = QSslKey{&PrivateKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey};
PrivateKeyFile.close();
auto WebPage = MyWebPage{&WebView};
WebPage.profile()->clientCertificateStore()->add(ClientCertificate, PrivateKey);
WebPage.setUrl(QUrl{"https://localhost/"});
WebView.setPage(&WebPage);
return Application.exec();
}
What I get is an error message in the browser window with "ERR_SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS" - so apparently browser and server don't know how to talk to each other.
I've tried curl and it works fine with either
curl --tlsv1.2 --tls-max 1.2 --insecure https://localhost/ --cert client.certificate.pem --key client.private_key.key
or
curl --tlsv1.3 --tls-max 1.3 --insecure https://localhost/ --cert client.certificate.pem --key client.private_key.key
I've tried deactivating client certificates on the server side and it works fine.
Are there any problems with my example? Did I miss some initialization steps or something?
Maybe my example WOULD be working - if only the client and server knew how to talk to each other, so that, consequently, the error really is in the cipher suites?! Is there any way I can check the exchanged and possible algorithms? Ultimately, I find that very unlikely, as we're talking about a Chrome backend on the client side talking to an Apache server, both of which are hugely popular ...
Any hints?
Thank you for any help you can offer and best regards!

Using libhttpserver to build https server

I am trying to compile the below piece of code to run a basic https server and i am encountering an error which i am not able to resolve. The class hello_world_resource is responsible for the server startup and the return statement gives the response that the server should give when it is accessed.
the url for the server is defined by function 'register_resource'
the url for the github documentation of the library - https://github.com/etr/libhttpserver
I've tried downloading ssl and curl multiple times and searched the google too but i am still not able to find the cause for this problem.
abcd.key and xyz.crt are the self-signed certificates that i generated following this procedure online -
https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-in-ubuntu-16-04
#include <httpserver.hpp>
using namespace httpserver;
class hello_world_resource : public http_resource
{
public:
const std::shared_ptr<http_response> render(const http_request&)
{
return std::shared_ptr<http_response>(new
string_response("Hello, World!"));
}
};
int main()
{
webserver ws = create_webserver(8080)
.use_ssl()
.https_mem_key("/path/to/abcd.key")
.https_mem_cert("/path/to/xyz.crt");
hello_world_resource hwr;
ws.register_resource("/hello", &hwr);
ws.start(true);
return 0;
}
The error being thrown is :
terminate called after throwing an instance of 'std::invalid_argument'
what(): BD
A
(G BBJ
Aborted
the code should run and a server should be available at - https://localhost:8080/hello

grpc Google login failure

I'am trying to create a application using the cloud speech api of google.
I cloned all the repositories and created a really simple client app in C++.
#include <grpc++/grpc++.h>
#include "google/cloud/speech/v1/cloud_speech.grpc.pb.h"
namespace gs=google::cloud::speech::v1;
using gs::Speech;
using gs::RecognizeResponse;
using gs::RecognizeRequest;
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
int main(int argc, char** argv) {
try{
auto channel_creds = grpc::GoogleDefaultCredentials();
auto channel = grpc::CreateChannel("speech.googleapis.com:443", channel_creds);
auto stub = Speech::NewStub(channel);
RecognizeResponse res;
RecognizeRequest req;
ClientContext ctx;
auto status = stub->Recognize(&ctx, req, &res);
if(status.ok())
{
std::cout << "ok" << std::endl;
} else {
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
}
}catch(const std::exception& e)
{
std::cout<<e.what()<<std::endl;
}
std::cin.get();
}
This compiles fine, but when executed results in the following error message:
16: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
I have created a Service account and placed it's json key file next to the env variable "GOOGLE_APPLICATION_CREDENTIALS" to the correct file and I'm quite sure it is read (because if I remove it, it just crashes).
I also have enabled the speech API online.
I'm out of ideas since no matter what I do I can't get it to work.
Am I missing something ?
After some more trying and reading some more example code I finally found the reason myself.
I had to use a different URL. Changing "speech.googleapis.com:443" to "speech.googleapis.com" results in a different error, but connection and login work.
Setting up all parameters for this function correctly and supplying actual audio data returns usable results. I did not expect the port to make a difference, considering both URLs are in many example programs and grpc uses http2 (which in turn uses port 443).
Important piece: Make sure you don't include a port for use with google services.

C++ socket connection through proxy

hello guys I ask my question,
I have this code that download a web page
#include <iostream>
#include <urlmon.h>
#include <string>
#pragma comment(lib,"urlmon.lib")
using namespace std;
int main()
{
string indirizzo;
IStream * is;
char buffer[256];
cout<<"Insert adress of the web page: ";
cin>>indirizzo;
if(URLOpenBlockingStream(NULL,indirizzo.c_str(),&is,0,NULL)!=S_OK)
{
cerr<<"ERROR DOWNLOAD.";
}
else
{
cout<<"download OK"<<endl;
system("Pause");
ULONG readBytes;
while(is->Read(buffer,sizeof(buffer),&readBytes)==S_OK)
{
cout.write(buffer,readBytes);
}
is->Release();
}
system("cls");
system("Pause");
return 0;
}
You can do this by connecting the socket via a proxy before the http request? I would like to do everything through proxy
API that you use seems to be InternetExplorer derived. It seems that you cannot use proxy's (other than system-wide) using only this API. If that's fine with you, just set your ControlPanel proxy to desired settings and you are good to go. Browsers other than IE might even get configured so they use they own proxy settings, so you can limit the effects of system-wide settings if you need it only for your program.
If you need it stricly only for your app, or otherwise hidden/secured (users might be able to see/change IE settings) you might try to use WinINet to download your files, but that's not what you are asking. WinINet version will be lengthier and more troublesome I expect. See the MSDN WinINet documentation, specifically InternetSetOption.
EDIT:
I see that you will probably be able to use it to set IE settings both globally and on per-process basis. See How to programmatically query and set proxy settings under Internet Explorer, and documentation for INTERNET_OPTION_PER_CONNECTION_OPTION option.
To do it system-wide just use NULL as hInternet in InternetSetOption. To do it just for your own process, use InternetOpen before any other networking code, and use returned handle - it seems it should also affect dynamically loaded IE engine.

how to add proxy support to boost::asio?

In my desktop application I added access to various internet resources using boost::asio. All i do is sending http requests (i.e to map tile servers) and read the results.
My code is based on the asio sync_client sample.
Now i get reports from customers who are unable to use these functions as they are running a proxy in their company. In a web browser they can enter the address of their proxy and everything is fine. Our application is unable to download data.
How can i add such support to my application?
I found the answer myself. It's quite simple:
http://www.jmarshall.com/easy/http/#proxies
gives quite a brief and clear description how http proxies work.
All i had to do is add the following code to the asio sync_client sample sample :
std::string myProxyServer = ...;
int myProxyPort = ...;
void doDownLoad(const std::string &in_server, const std::string &in_path, std::ostream &outstream)
{
std::string server = in_server;
std::string path = in_path;
char serice_port[255];
strcpy(serice_port, "http");
if(! myProxyServer.empty())
{
path = "http://" + in_server + in_path;
server = myProxyServer;
if(myProxyPort != 0)
sprintf(serice_port, "%d", myProxyPort);
}
tcp::resolver resolver(io_service);
tcp::resolver::query query(server, serice_port);
...
It seems that sample is merely a show-off of what Boost ASIO can be used for but is likely not intended to be used as-is. You should probably use a complete library that handles not only HTTP proxies, but also HTTP redirects, compression, and so on.
HTTP is a complex thing: without doing so, chances are high that you will get news from another client soon with another problem.
I found cppnetlib which looks promising and is based on Boost ASIO not sure it handles proxies though.
There is also libcurl but I don't know if it can easily be integrated with Boost ASIO.