gSOAP client example throws SOAP 1.1 fault SOAP-ENV:Client[no subcode] - soap-client

I download gsoap_2.8.83 and ran into following soap error when executing the example from the online document.
SOAP 1.1 fault SOAP-ENV:Client[no subcode]
"Error 200: HTTP 200 OK"
Detail: [no detail]
The Code is exactly this:
//#include "gsoapWinInet.h"
#include "soapcalcProxy.h"
#include "calc.nsmap"
#include "stdafx.h"
/* the Web service endpoint URL */
const char server[] = "http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";
int main(int argc, char **argv)
{
if (argc < 4)
{
fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
exit(1);
}
calcProxy calc(server);
//soap_register_plugin(calc.soap, wininet_plugin);
calc.soap->recv_timeout = 60;
double a, b, result;
a = strtod(argv[2], NULL);
b = strtod(argv[3], NULL);
int ret = 0;
switch (*argv[1])
{
case 'a':
std::cout << a << " + " << b;
ret = calc.add(a, b, result);
break;
case 's':
std::cout << a << " - " << b;
ret = calc.sub(a, b, result);
break;
case 'm':
std::cout << a << " * " << b;
calc.mul(a, b, result);
break;
case 'd':
std::cout << a << " / " << b;
calc.div(a, b, result);
break;
case 'p':
std::cout << a << " ^ " << b;
calc.pow(a, b, result);
break;
default:
fprintf(stderr, "Unknown command\n");
exit(1);
}
if (calc.soap->error)
calc.soap_stream_fault(std::cerr);
else
std::cout << " = " << result << std::endl;
calc.destroy(); /* clean up */
getchar();
return 0;
}
Full VS2015 project can also be fetched here.
Build and run with command line arguments:
main.exe add 1 2
Getting the error abovemetioned.
In order to debug the SOAP message, I added gsoap WinInet plugin (just uncommenting out those two lines in the code above), then the response turns to be good.
My question is why the code without wininet plugin is unsuccessful? Thanks.

Related

How to use a specific DNS server/nameserver for name resolve queries in C++ boost::asio?

I would like to bypass system configured nameserver and use my own nameserver (or list of them) configured in application. I can do in nslookup in windows. How can I do it in C++ preferably by using boost::asio? I would like to avoid using std::system("nslookup ...> output.txt") and reading the file.
I cannot see where I can specify nameserver to use for lookup in boost::asio.
#include <boost/asio.hpp>
#include <string>
#include <iostream>
using namespace boost;
int main()
{
asio::io_service io_service;
asio::ip::tcp::resolver resolver(io_service);//how to pass specific nameserver?
asio::ip::tcp::resolver::iterator itr = resolver.resolve("bbc.co.uk","");
asio::ip::tcp::resolver::iterator end;
for (int i = 1; itr != end; itr++, i++)
std::cout << "hostname #" << i << ": " << itr->host_name() << " " << itr->endpoint() << '\n';
return 0;
}
You can't. The DNS resvoling is handled by the sockets api and you can't specify the DNS servers.
You will have to directly use either a OS specific API to resolve names like DnsQueryEx in win32 or using a library like LDNS.
/*
* DNSResolver.h
*
* Created on: Jan 12, 2023
* Author: marian
*/
#ifndef DNSRESOLVER_H_
#define DNSRESOLVER_H_
#include <cstdint>
#include <cstddef>
#include <vector>
#include <string_view>
#include <string>
#include <ostream>
#include <iostream>
#include <thread>
#include <chrono>
#include <boost/asio.hpp>
namespace tools
{
template <typename Func>
std::string_view find_first_success(const std::string_view& str,const Func& func, size_t pos0=0, char delim=',')
{
size_t pos=0;
do
{
pos=str.find_first_of(delim,pos0);
std::string_view sv=str.substr(pos0,pos-pos0);
if (func(sv))
return sv;
pos0=pos+1;
} while (pos!=std::string_view::npos);
return {};
}
template<int unused=0>
uint16_t be2uint16(const uint8_t* hi)
{
uint16_t hi1=*(hi+1);
return (((uint16_t)*hi)<<8)|hi1;
}
template<int unused=0>
uint32_t be2uint32(const uint8_t* hi)
{
uint32_t v3=*(hi+3);
uint32_t v2=*(hi+2);
uint32_t v1=*(hi+1);
uint32_t v0=*hi;
return (v0<<24)|(v1<<16)|(v2<<8)|v3;
}
template<int unused=0>
void out_IP4(std::ostream& os,uint32_t IP4)
{
os << (IP4>>24) << '.' << ((IP4>>16)&0xFF) << '.' << ((IP4>>8)&0xFF) << '.' << (IP4&0xFF);
}
}
namespace DNS
{
const char *rcode_msg[]={"No error","Format error","Server failure","Name error","Not implemented","Refused"};
const char *opcode_msg[]={"Standard query","Inverse query","Status"};
const char *type_msg[]={"0","A","NS","MD","MF","CNAME","SOA","MB","MG","MR","NULL","WKS","PTR","HINFO","MINFO","MX","TX"};
/*
A 1 a host address
NS 2 an authoritative name server
MD 3 a mail destination (Obsolete - use MX)
MF 4 a mail forwarder (Obsolete - use MX)
CNAME 5 the canonical name for an alias
SOA 6 marks the start of a zone of authority
MB 7 a mailbox domain name (EXPERIMENTAL)
MG 8 a mail group member (EXPERIMENTAL)
MR 9 a mail rename domain name (EXPERIMENTAL)
NULL 10 a null RR (EXPERIMENTAL)
WKS 11 a well known service description
PTR 12 a domain name pointer
HINFO 13 host information
MINFO 14 mailbox or mail list information
MX 15 mail exchange
TXT 16 text strings
*/
template<int unused=0>
void disp_type(std::ostream&os,uint16_t type)
{
os << (int)type;
if (type<=16)
os << " " << type_msg[type];
}
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option; //somewhere in your headers to be used everywhere you need it
template<int unused=0>
class resolver
{
public:
resolver(const std::string_view& nameservers="127.0.0.53",boost::asio::chrono::milliseconds timeout=boost::asio::chrono::milliseconds{3000})
:nameservers_{nameservers},timeout_(timeout)
{}
std::vector<uint32_t> resolve(
const std::string_view& hostname,
std::string_view& nameserver_used,
std::vector<uint32_t>* pTTLs=nullptr)
{
std::vector<uint8_t> result;
result.resize(1024);
nameserver_used=resolve(hostname,result);
if (nameserver_used.empty())
return {};
std::string qname;
std::vector<uint32_t> IP4s;
int cnt=answer_A(result,qname,IP4s,pTTLs);
(void)cnt;
if (hostname!=qname)
return {};
return IP4s;
}
void resolve_ostream(
const std::string_view& hostname,
std::string_view& nameserver_used,
std::ostream& os)
{
std::vector<uint8_t> result;
result.resize(1024);
nameserver_used=resolve(hostname,result);
if (nameserver_used.empty())
return;
os << "nameserver:" << nameserver_used << std::endl;
disp_result(os,result);
}
private:
static void out_name(std::ostream&os,const std::vector<uint8_t>& result,uint16_t& pos)
{
uint8_t sz=result[pos++];
for (;sz;)
{
if (sz>=64)
{
if ((sz>>6)!=3)
throw "label size exceed 64 character and not pointer, see RFC 1035";
uint16_t offset=(((uint16_t)(sz&63))<<8)|result[pos++];
out_name(os,result,offset);//recursion, hope not too deep
return;
}
uint16_t epos=pos+sz;
while (pos<epos)
os << result[pos++];
sz=result[pos++];
if (sz)
os << ".";
}
}
static void disp_rr(std::ostream&os,const std::vector<uint8_t>& result,uint16_t& pos)
{
if (pos>=result.size())
return;
if (result[pos]==0)
return;
out_name(os,result,pos);
if (((size_t)pos+10)>=(size_t)result.size())
{
throw "wrong packet size1";
}
uint16_t rr_type=tools::be2uint16(&result[pos]);
os << " (" ;
os << "type:" ; disp_type(os,rr_type) ;
pos+=2;
os << " class:" << tools::be2uint16(&result[pos]) ;
pos+=2;
os << " TTL:" << tools::be2uint32(&result[pos]) << " secs) ";
pos+=4;
uint16_t len=tools::be2uint16(&result[pos]);
pos+=2;
if (pos+len>result.size())
throw "wrong packet size2";
if (rr_type==1)
{
if (len!=4)
{
throw "unknown data size";
}
os << (int)result[pos] << "." << (int)result[pos+1] << "." << (int)result[pos+2] << "." << (int)result[pos+3];
} else if (rr_type==2)
{
uint16_t pos2=pos;
out_name(os,result,pos2);
} else
{
throw "unimplement type";
}
pos+=len;
}
static void split_rr(const std::vector<uint8_t>& result,
uint16_t& pos,
std::string& name,
uint16_t& rr_type,
uint16_t& rr_class,
uint32_t& TTL,
uint32_t& IP4,
std::string* pname2=nullptr
)
{
if (pos>=result.size())
return;
if (result[pos]==0)
return;
std::stringstream ss;
out_name(ss,result,pos);
name=ss.str();
if (((size_t)pos+10)>=(size_t)result.size())
{
throw "wrong packet size1";
}
rr_type=tools::be2uint16(&result[pos]);
pos+=2;
rr_class=tools::be2uint16(&result[pos]) ;
pos+=2;
TTL=tools::be2uint32(&result[pos]);
pos+=4;
uint16_t len=tools::be2uint16(&result[pos]);
pos+=2;
if (pos+len>result.size())
throw "wrong packet size2";
if (rr_type==1)
{
if (len!=4)
{
throw "unknown data size";
}
IP4=tools::be2uint32(&result[pos]); //*(uint32_t*)&result[pos];
} else if (rr_type==2)
{
uint16_t pos2=pos;
std::stringstream ss;
out_name(ss,result,pos2);
if (pname2)
*pname2=ss.str();
} else
{
throw "unimplement type";
}
pos+=len;
}
static int check_A(const std::vector<uint8_t>& result)
{
if (result.size()<12)
return -1;
uint8_t response=(result[2]>>7);
if (response!=1)
return -2;
uint8_t rcode=result[3]&0xf;
if (rcode!=0)
return -3;
uint8_t opcode=(result[2]>>3)&0xF;
if (opcode!=0)
return -4;
return 0;
}
static int answer_A(const std::vector<uint8_t>& result,
std::string& q_name,
std::vector<uint32_t>& IP4s,
std::vector<uint32_t>* pTTLs=nullptr)
{
int ret=check_A(result);
if (ret<0)
return ret;
std::string name;
uint16_t q_type=0;
uint16_t q_class=0;
uint16_t rr_type=0;
uint16_t rr_class=0;
uint32_t TTL=0;
uint32_t IP4=0;
uint16_t qc=tools::be2uint16(&result[4]);
uint16_t pos=12;
for (int i=0;i<qc;i++)//qc =1 usually
{
std::stringstream ss;
out_name(ss,result,pos);
q_name=ss.str();
q_type=tools::be2uint16(&result[pos]);
pos+=2;
q_class=tools::be2uint16(&result[pos]);
pos+=2;
}
uint16_t ac=tools::be2uint16(&result[6]);
IP4s.resize(ac);
if (pTTLs)
pTTLs->resize(ac);
for (int i=0;i<ac;i++)
{
split_rr(result,pos,name,rr_type,rr_class,TTL,IP4);
if (name!=q_name)
break;
if (rr_type!=q_type)
break;
if (rr_class!=q_class)
break;
IP4s[i]=IP4;
if (pTTLs)
(*pTTLs)[i]=TTL;
}
return ac;
}
static void disp_result(std::ostream&os,const std::vector<uint8_t>& result)
{
if (result.size()<12)
return;
os << std::string((result[2]&0x80) ? "response" : "query") << std::endl;
os << "size=" << result.size() << " bytes" << std::endl;
uint8_t opcode=(result[2]>>3)&0xF;
os << "Opcode:" << (int)opcode;
if (opcode<=2)
os << " " << opcode_msg[opcode];
os << std::endl;
os << ((result[2]&1) ? "recursion asked" : "recursion NOT asked") << std::endl;
if (result[2]&2)
os << "response truncated" << std::endl;
if (result[2]&4)
os << "Authoritative answer" << std::endl;
os << ((result[3]&0x80) ? "recursion available" : "recursion NOT available") << std::endl;
uint8_t rcode=result[3]&0xf;
os << "rcode:" << (int)rcode;
if (rcode<=5)
os << " " << rcode_msg[rcode];
os << std::endl;
uint16_t qc=tools::be2uint16(&result[4]);
os << "Query Count:" << qc << std::endl;
uint16_t ac=tools::be2uint16(&result[6]);
os << "Answer Count:" << ac << std::endl;
uint16_t nc=tools::be2uint16(&result[8]);
os << "Authoritative Name Server Count:" << nc << std::endl;
uint16_t arc=tools::be2uint16(&result[10]);
os << "Additional resource records Count:" << arc << std::endl;
uint16_t pos=12;
os << "_____________" << std::endl;
os << "Query:" << std::endl;
for (int i=0;i<qc;i++)//qc =1 usually
{
out_name(os,result,pos);
os << " (";
os << "type:"; disp_type(os,tools::be2uint16(&result[pos]));
pos+=2;
os << " class:" << tools::be2uint16(&result[pos]) << " ) ";
pos+=2;
os << std::endl;
}
//answer
if (ac)
{
os << "_________________________" << std::endl;
os << "Answer:" << std::endl;
}
for (int i=0;i<ac;i++)
{
disp_rr(os,result,pos);
os << std::endl;
}
if (nc)
{
os << "_________________________" << std::endl;
os << "Authoritative nameservers:" << std::endl;
}
for (int i=0;i<nc;i++)
{
disp_rr(os,result,pos);
os << std::endl;
}
if (arc)
{
os << "_________________________" << std::endl;
os << "Additional resource records:" << std::endl;
}
for (int i=0;i<arc;i++)
{
disp_rr(os,result,pos);
os << std::endl;
}
}
size_t udp_request(const boost::asio::const_buffer& request,
const boost::asio::mutable_buffer& response,
const std::string_view& destination_ip,
const unsigned short port,
boost::system::error_code& ec)
{
using namespace boost;
asio::ip::udp::socket socket(io_context_);
auto remote = asio::ip::udp::endpoint(asio::ip::make_address(destination_ip), port);
socket.open(boost::asio::ip::udp::v4());
size_t sent=socket.send_to(request, remote);
if (request.size()!=sent)
return 0;
return receive_from(socket,response,timeout_,ec);
}
std::size_t receive_from(
boost::asio::ip::udp::socket& sock,
const boost::asio::mutable_buffer& buffer,
boost::asio::chrono::steady_clock::duration timeout,
boost::system::error_code& ec)
{
std::size_t length = 0;
sock.async_receive(boost::asio::buffer(buffer),
[&](const boost::system::error_code& ec1,std::size_t sz){
ec=ec1;
length=sz;
}
);
run(sock,timeout);
return length;
}
void run(boost::asio::ip::udp::socket& sock,boost::asio::chrono::steady_clock::duration timeout)
{
// Restart the io_context, as it may have been left in the "stopped" state
// by a previous operation.
io_context_.restart();
// Block until the asynchronous operation has completed, or timed out. If
// the pending asynchronous operation is a composed operation, the deadline
// applies to the entire operation, rather than individual operations on
// the socket.
io_context_.run_for(timeout);
// If the asynchronous operation completed successfully then the io_context
// would have been stopped due to running out of work. If it was not
// stopped, then the io_context::run_for call must have timed out.
if (!io_context_.stopped())
{
// Cancel the outstanding asynchronous operation.
sock.cancel();
// Run the io_context again until the operation completes.
io_context_.run();
}
}
static std::vector<uint8_t> make_dns_request(const std::string_view& hostname)
{
static uint16_t id=257;
id++;
std::vector<uint8_t> req;
uint16_t epos=12+1+hostname.size();
req.resize(epos+1+4);//plus null plus type (2 bytes) plus class (2 bytes)
*((uint16_t*)&req[0])=id;
req[2]=1;//recursive
req[3]=32;//??, linux has 32, but 0 works too
req[5]=1;//one query
req[epos]=0;//end of string
req[epos+2]=1;//type A - host address
req[epos+4]=1;//class INT
uint16_t cnt=0;
for(int i=hostname.size()-1;i>=0;i--)
{
req[13+i]=(hostname[i]=='.') ? cnt : hostname[i];
cnt=(hostname[i]=='.') ? 0 : cnt+1;
}
req[12]=cnt;
return req;
}
std::string_view resolve(const std::string_view& hostname,std::vector<uint8_t>& result)
{
auto myrequest=make_dns_request(hostname);
return tools::find_first_success(nameservers_,
[&](const std::string_view& nameserver)
{
size_t sz=0;
try
{
boost::system::error_code ec;
sz=udp_request(boost::asio::buffer(myrequest),
boost::asio::mutable_buffer(&result[0],result.size()),
nameserver,53,ec);
if (ec.value()!=boost::system::errc::success)
{
std::cerr << "skipping due to error code not a success : error code=" << ec.value() << " " << ec.message() << std::endl;
return false;
}
if (sz<35)//min packet , 12 header+3 name+4 type/class+ 16 (rr type 1)
{
std::cerr << "skipping because packet size < 35" << std::endl;
return false;
}
if ((myrequest[0]!=result[0])||(myrequest[1]!=result[1]))
{
std::cerr << "skipping because ID respond not matching ID request " << std::endl;
return false;
}
if (check_A(result)<0)
{
std::cerr << "skipping because packet check failed " << std::endl;
return false;
}
}
catch(std::exception& ex)
{
std::cerr << "Skipping because of exception:" << ex.what() << std::endl;
return false;
}
catch(...)
{
std::cerr << "Skipping because of unknown exception:" << std::endl;
return false;
}
result.resize(sz);
return true;
});
}
private:
boost::asio::io_context io_context_;
std::string nameservers_;
boost::asio::chrono::milliseconds timeout_;
};
}
#endif /* DNSRESOLVER_H_ */
/*
* main.cpp
*
* Created on: Jan 12, 2023
* Author: marian
*/
#include <iostream>
#include <vector>
#include "DNSResolver.h"
#define check_offset if (offset==argc) { print_error(); return 1;}
int main (int argc, char **argv) {
auto print_error=[&]()
{
std::cerr << "Usage: " << argv[0] << " [-v] [-t timeout_msecs] [--nottl] [--nons] <query> [csv_ip_nameserver_list] \n";
std::cerr << "Example: " << argv[0] << " bbc.co.uk 127.0.0.53,8.8.8.8" << std::endl;
std::cerr << "Example: " << argv[0] << " -v bbc.co.uk" << std::endl;
};
if (argc < 2) {
print_error();
return 1;
}
int offset=1;
bool verbose= (std::string(argv[offset])=="-v");
if (verbose)
offset++;
check_offset;
int millisecs=3000;
if (std::string(argv[offset])=="-t")
{
offset++;
check_offset;
millisecs=std::stoi(argv[offset++]);
}
check_offset;
bool ttl=true;
if (std::string(argv[offset])=="--nottl")
{
ttl=false;
offset++;
}
check_offset;
bool ns=true;
if (std::string(argv[offset])=="--nons")
{
ns=false;
offset++;
}
check_offset;
const char *dname=argv[offset];
const char *nameservers= (offset+1<argc) ? argv[offset+1] : "127.0.0.53,8.8.8.8";
if (ns)
std::cout << "nameservers:" << nameservers << std::endl;
DNS::resolver resolver{nameservers,boost::asio::chrono::milliseconds{millisecs}};
if (verbose)
{
std::string_view nameserver_used;
resolver.resolve_ostream(dname,nameserver_used,std::cout);
return 0;
}
std::vector<uint32_t> TTLs;
std::string_view nameserver_used;
std::vector<uint32_t> IP4s=resolver.resolve(dname,nameserver_used,&TTLs);
if (ns&&(!nameserver_used.empty()))
std::cout << "nameserver:" << nameserver_used << std::endl;
int n=IP4s.size();
if (!n)
{
std::cerr << "Error: No IPs found" << std::endl;
return 2;
}
for (int i=0;i<n;i++)
{
tools::out_IP4(std::cout,IP4s[i]);
if (ttl)
std::cout << " (TTL:" << TTLs[i] << " sec)" ;
std::cout << std::endl;
}
return 0;
}

Why does glReadPixels seem to return garbage?

I'm trying to draw offscreen with OpenGL. For this I use EGL to initialize a pbuffer surface, and then draw to it, reading the results back with glReadPixels. But the following program gives me garbage on different (Mesa-based Intel on Linux) GPUs. Namely, on Atom N550 I get zeros, while on Xeon E3-1200 v3 I have 70 00 07 44 instead of the expected 40 80 bf ff.
With LIBGL_ALWAYS_SOFTWARE=1 environment variable set, I get the expected results. Also, if I comment out the line with eglBindAPI, I get good result on Xeon, but still zeros on Atom.
Here's my program:
#include <EGL/egl.h>
#include <GL/gl.h>
#include <iostream>
#include <iomanip>
#include <cstring>
int eglPrintError(std::string const& context)
{
const GLint error=eglGetError();
std::cerr << context << ": error 0x" << std::hex << int(error) << "\n";
return 1;
}
bool checkError(std::string const& funcName)
{
const GLenum error=glGetError();
if(error!=GL_NO_ERROR)
{
std::cerr << funcName << ": error 0x" << std::hex << int(error) << "\n";
return true;
}
return false;
}
constexpr int fbW=1, fbH=1;
bool initGL()
{
if(!eglBindAPI(EGL_OPENGL_API)) return !eglPrintError("eglBindAPI");
const EGLDisplay dpy=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(!dpy) return !eglPrintError("eglGetDisplay");
if(!eglInitialize(dpy,nullptr,nullptr)) return !eglPrintError("eglInitialize");
static const EGLint cfgAttribs[]={EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE};
EGLConfig cfg;
EGLint cfgCount;
if(!eglChooseConfig(dpy,cfgAttribs,&cfg,1,&cfgCount))
return !eglPrintError("eglChooseConfig");
if(cfgCount==0)
{
std::cerr << "Failed to get any usable EGL configs\n";
return false;
}
const EGLContext context=eglCreateContext(dpy,cfg,EGL_NO_CONTEXT,NULL);
if(!context) return !eglPrintError("eglCreateContext");
const EGLint surfaceAttribs[]={EGL_WIDTH, fbW, EGL_HEIGHT, fbH, EGL_NONE};
const EGLSurface surface=eglCreatePbufferSurface(dpy,cfg,surfaceAttribs);
if(!surface) return eglPrintError("eglCreatePbufferSurface");
if(!eglMakeCurrent(dpy,surface,surface,context))
return !eglPrintError("eglMakeCurrent");
return true;
}
int main(int argc, char** argv)
{
if(!initGL()) return 1;
glViewport(0,0,fbW,fbH);
glClearColor(0.25,0.5,0.75,1.);
glClear(GL_COLOR_BUFFER_BIT);
glFinish();
unsigned char data[4*fbW*fbH];
std::memset(data,0xb7,sizeof data); // to see unchanged values
glReadPixels(0,0,fbW,fbH,GL_RGBA,GL_UNSIGNED_BYTE,data);
if(checkError("glReadPixels")) return 1;
std::cout << "Data read: " << std::hex << std::setfill('0');
for(auto datum : data)
std::cout << std::setw(2) << +datum << " ";
std::cout << "\n";
return 0;
}
My question is, is there anything wrong in the above code which could lead to such behavior, or are my drivers just simply buggy?

winsock : bluetooth client-server not connecting

I have written a small bluetooth server and client progrem using winsock
I am not able to figure out why the client is not getting connected to the server. Both are running in different pcs and
both are paired through bluetooth.
The server code is
void server()
{
SOCKET server_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM), new_socket;
if (server_socket == INVALID_SOCKET)
{
cout << "socket creation failed...Error code : " << WSAGetLastError() << endl;
Sleep(2000);
return;
}
cout << "socket created" << endl;
SOCKADDR_BTH sa, sa2;
int channel = 0, len=sizeof(sa2);
memset(&sa, 0, sizeof(SOCKADDR_BTH));
sa.addressFamily = AF_BTH;
sa.port = channel & 0xff;
//bind
if (bind(server_socket, (SOCKADDR *)&sa, sizeof(sa)))
{
cout << "Binding failed...Error code : " << WSAGetLastError() << endl;
closesocket(server_socket);
Sleep(2000);
return;
}
cout << "binding done" << endl;
cout << "\nWaiting for client" << endl;
listen(server_socket, 3);
new_socket = accept(server_socket, (sockaddr *)&sa2, &len);
cout<<"connection accepted";
}
The client code is
void client()
{
SOCKET client_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
int channel = 0;
BTH_ADDR bt_addr;
char* server_address = "34:02:86:26:c1:62";
if (client_socket == INVALID_SOCKET)
{
cout << "socket creation failed...Error code : " << WSAGetLastError() << endl;
Sleep(2000);
return;
}
cout << "socket created" << endl;
if (str2ba(server_address, &bt_addr) == 1)
{
cout << "address conversion error..." << endl;
Sleep(2000);
return;
}
SOCKADDR_BTH sa;
sa.addressFamily = AF_BTH;
sa.port = channel & 0xff;
sa.btAddr = bt_addr;
cout << "\nconnecting..." << endl;
if (connect(client_socket, (sockaddr *)&sa, sizeof(sockaddr)))
{
cout << "Error in connecting...Error code : " << WSAGetLastError() << endl;
closesocket(client_socket);
Sleep(2000);
return;
}
cout << "\nConnected" << endl;
Sleep(2000);
}
int str2ba(char *str_bt_addr, BTH_ADDR *bt_addr)//for converting string to bluetooth address
{
unsigned int addr[6];
if (sscanf_s(str_bt_addr, "%02x:%02x:%02x:%02x:%02x:%02x",
&addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6)
{
return 1;
}
*bt_addr = 0;
BTH_ADDR tmpaddr;
int i;
for (i = 0;i < 6;++i)
{
tmpaddr = (BTH_ADDR)(addr[i] & 0xff);
*bt_addr = ((*bt_addr) << 8) + tmpaddr;
}
return 0;
}
Why are these not getting connected? What am I missing?
Please help me.
Thanks in advance for any help.
In my short Bluetooth experience, the problem is normally somewhere in the SOCKADDR_BTH declarations.
I hard coded the MAC Address of each Endpoint: "38:2D:E8:B9:FA:EB" in Hex
RemoteEndPoint.btAddr = BTH_ADDR(0x382DE8B9FAEB);
Also make sure your Ports are the same on each Endpoint, I used:
RemoteEndPoint.port = 0;
and
LocalEndpoint.port = 0;
I have some code here: C++ WinSock Bluetooth Connection - AT Command - Error Received where I have an issue also.
Bluetooth is not as easy as some may think, thus the lack of answers received by the OP's

ncurses nodelay for responsive arrow key feedback

I am trying to write integers to a file using ncurses and the keyboard arrows. I use nodelay so that I can write a 4 to the file while nothing is being pressed. ESC exits the program. The problem is that all I can ever write to the files is 4. ESC seems to work fine, so the switch is working. If I take out the nodelay the program works but 4 cannot ever be writen.
Thanks
#include <ncurses.h>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
ofstream outFile;
char outputFilename[80];
sprintf(outputFilename, "files/file.%s",argv[1]);
outFile.open(outputFilename, ios::out);
int ch;
initscr();
nodelay(stdscr,TRUE);
raw();
keypad(stdscr, TRUE);
noecho();
refresh();
while(1){
ch = getch();
switch(ch)
{
case KEY_UP:
outFile << 0 << endl;
break;
case KEY_DOWN:
outFile << 1 << endl;
break;
case KEY_RIGHT:
outFile << 2 << endl;
break;
case KEY_LEFT:
outFile << 3 << endl;
break;
case ERR:
outFile << 4 << endl;
break;
case 27:
outFile.close();
endwin();
return 0;
break;
default:
break;
}
refresh();
}
}
I was able to fix this issue by checking to see if the last value of ch was ERR before writing 4 to the file. Not sure I understand completely... maybe a timing issue. New program:
#include <ncurses.h>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
ofstream outFile;
char outputFilename[80];
sprintf(outputFilename, "interactive/taker.%s",argv[1]);
outFile.open(outputFilename, ios::out);
int ch;
int ch_prev=0;
initscr();
nodelay(stdscr,TRUE);
raw();
keypad(stdscr, TRUE);
noecho();
while(1){
ch = getch();
switch(ch)
{
case KEY_UP:
outFile << 0 << endl;
break;
case KEY_DOWN:
outFile << 1 << endl;
break;
case KEY_RIGHT:
outFile << 2 << endl;
break;
case KEY_LEFT:
outFile << 3 << endl;
break;
case ERR:
if (ch_prev != ERR)
outFile << 4 << endl;
break;
case 27:
outFile.close();
endwin();
return 0;
break;
default:
break;
}
ch_prev=ch;
refresh();
}
}
Without the check, you will overlook the lines which are not 4's, since almost all of the return values are ERR's. Also - the program will be using a lot of CPU (doing nothing). You would get better results if you used timeout with a fairly short value (10-50 milliseconds) rather than nodelay.

EBADF while recv after epoll_wait

i've got a following problem: i have a epoll code which receives connections:
while (1) {
int nfds = epoll_wait(epollfd, events, 4096, -1);
if (nfds == -1) {
if (errno == EINTR)
continue;
perror("epoll_wait");
exit(EXIT_FAILURE);
}
for (int i = 0; i < nfds; i++) {
if (events[i].data.fd == server_sock) {
client_sock = accept(server_sock,
(struct sockaddr *)&client_name,
(socklen_t *)(&client_name_len));
if (client_sock == -1) //server overloaded
continue;
ev.events = EPOLLIN | EPOLLERR;
#ifdef CORE_NONBLOCKING_SOCKETS
Arch::set_nonblocking(client_sock);
ev.events |= EPOLLET; //input data and connection closing
#endif
#ifdef EPOLLRDHUP
ev.events |= EPOLLRDHUP ;//
#else
//for old libraries
ev.events |= EPOLLHUP;//
#endif
ev.data.fd = client_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, client_sock, &ev) == -1) {
perror("epoll_ctl: client_socket");
exit(EXIT_FAILURE);
}
accept_request(client_sock);
} else {
#ifdef EPOLLRDHUP
if (events[i].events & EPOLLRDHUP) {
std::cout << "EPOLLRDHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}
#else
if (events[i].events & EPOLLHUP) {
std::cout << "EPOLLHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}
#endif
if (events[i].events & EPOLLIN) {
std::cout << "debug EPOLLIN on " << events[i].data.fd << std::endl;
accept_request(events[i].data.fd);
}
if (events[i].events & EPOLLERR) {
std::cout << "debug EPOLLERR on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}
}
}
when i received input connection i trying to read all buff data:
void get_all_buf(int sock, std::string & inStr) {
int n = 1;
int total = 0;
char c;
char temp[1024*1024];
bzero(temp, sizeof(temp));
do {
#ifdef CORE_NONBLOCKING_SOCKETS
timespec time_to_wait;
time_to_wait.tv_nsec = 10000000;
time_to_wait.tv_sec = 0;
timespec tm;
time_t begin = time(NULL);
do {
#endif
n = recv(sock, &temp[total], sizeof(temp), 0);
#ifdef CORE_NONBLOCKING_SOCKETS
nanosleep(&time_to_wait, &tm);
time_t end = time(NULL);
if ((end - begin) > MAX_CLIENT_TIME) {
inStr = std::string();
return;
}
} while (n < 0 && errno == EAGAIN); //nonblocking sockets in edge-triggered mode
#endif
if (n > 0) {
total += n;
} else if (n == 0) {
//TODO: error handling
//debug
std::cout << "possibly no one byte was received" << std::endl;
break;
} else if (n < 0) {
//TODO: error handling
//debug
std::cout << "error while receiving data" << std::endl;
if (errno == EBADF) {
std::cout << "recv returns with EBADF: " << strerror(errno) << std::endl;
} else if (errno == EFAULT) {
std::cout << "recv returns with EFAULT: " << strerror(errno) << std::endl;
} else if (errno == EINTR) {
std::cout << "recv returns with EINTR: " << strerror(errno) << std::endl;
} else if (errno == EINVAL) {
std::cout << "recv returns with EINVAL: " << strerror(errno) << std::endl;
}
//end debug
break;
}
} while (!strstr(temp, "</packet>"));
inStr = temp;
};
within accept_request function. but sometime i get following in my debug output:
packet type='connect'
size of vector<Driver> in getDriversWithMoney is 1
epoll_wait detected activity of 164 counter i = 0 nfds = 1
EPOLLRDHUP on 164
disconnectDriver (fd = 164)
driver 1 disconnected
debug EPOLLIN on 164
error while receiving data
recv returns with EBADF: Invalid file descriptor
which means that someone was connected first than disconnected and when he's trying to connect again recv returns EBADF. what i did wrong? please help me.
P.S. on EPOLLRDHUP i just close file descriptor. epoll man says it's ok, because epoll removes closed fd from epoll_wait queue by itself.
When the remote host closes the socket, epoll() reports both a HUP and an EPOLLIN for the file descriptor.
You check for EPOLLRDHUP first, and close the socket; then you check for EPOLLIN, find that too, and try to call recv(). Since the socket has been closed, the file descriptor is no longer valid, and you get EBADF (the closed socket is removed from the epoll set, so subsequent epoll_wait() calls won't return it; but for the epoll_wait() that has already returned it's too late - the EPOLLIN is already waiting in your events[i].
You need to stop checking for events after you call disconnectDriver() (if it closed the file descriptor):
if (events[i].events & EPOLLRDHUP) {
std::cout << "EPOLLRDHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
continue;
}

Resources