I'm finding it very hard to get information on Bluetooth communication in C++. Specifically I want to avoid using any third party libraries and I simply want to connect to a device already paired with my computer.
The device has already had its passcode entered and is available in the 'Show Bluetooth Devices' under my devices and printers. I'm using Windows 7 and visual studio 2013 professional for development in C++.
I've got some example code (from here http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedotherprotocol4k.html) which displays information on my Bluetooth radio and then displays device information and it seems to work well. Although it's printing out every Bluetooth device already paired with the computer, not ones which are within range, but that may be me misinterpreting what the code is suppose to do.
I've been looking through the Bluetooth reference page (http://msdn.microsoft.com/en-us/library/windows/desktop/aa362930%28v=vs.85%29.aspx) and all the functions are just to do with setting the Bluetooth radio availability and other things like that; no sign of connecting to a found device at all.
I must be missing something, using wrong key words when Googling or something, because I've found nothing about connecting to a Bluetooth device!
If anyone has any suggestions, code, or links that would be great! I can connect to my device using the serial functionality (very easily) but I have to manually enter the COM port it's registered on, which isn't very user friendly. I want to scan and select, or enter a Bluetooth device name, and connect that way.
Cheers
EDIT:
BitBanks answer pointed me in the right direction. Only thing missing was a WSAStartup request before any socket requests:
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
If you have a bluetooth address from discovery or the paired-devices list, you can connect to it like this (error checking needs to be added):
#include <winsock2.h>
#include <ws2bth.h>
SOCKADDR_BTH sockAddr;
SOCKET btSocket;
int error;
btSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
memset (&sockAddr, 0, sizeof(sockAddr));
sockAddr.addressFamily = AF_BTH;
sockAddr.serviceClassId = RFCOMM_PROTOCOL_UUID;
sockAddr.port = BT_PORT_ANY;
sockAddr.btAddr = <your bluetooth address>
error = connect(btSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
Some devices advertise the SerialPortServiceClass_UUID instead of the RFCOMM_PROTOCOL_UUID. You also may need to retry the connection several times. Certain poorly implemented bluetooth devices (cough PowerA Moga cough) require multiple tries to connect.
This may not be the official way to do it, but I get the 6-byte BT address of the device I'm interested in from the paired list like this:
unsigned char *p;
ULONGLONG ullAddr;
p = (unsigned char *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr; // point to addr
memcpy(&ullAddr, &p[2], 8); // copy Bluetooth address of device we found
Related
I'm making a LAN multiplayer game using c++ and winsock, were I've created my own protocol for connecting two machines to eachother. The protocol involves broadcasting a message over the local LAN, which strangely isn't working on one of the two machines I'm using to test my code. The strange part is that it's as mentioned working on one machine, whereas not on the other. I've used wireshark to monitor outgoing packets, and the packets isn't being sent on the failing machine, even though that sendto() is returning the correct amount of bytes. The only difference between the machines is that one (the failing one) is using win10 and the other win8.
Is there any difference in the winsock library/networking layer between windows 10 and windows 8 that could cause this? Else, do you have any other ideas of what could cause the failure?
The code for sending a broadcast looks like this:
sockaddr_in send_addr;
send_addr.sin_family = AF_INET;
send_addr.sin_port = htons(PORT);
send_addr.sin_addr.s_addr = inet_addr("255.255.255.255");
int iResult = sendto(sock,
reinterpret_cast<char*>(&packet),
sizeof(Packet),
0,
(SOCKADDR *)&send_addr,
sizeof(send_addr));
if (iResult == SOCKET_ERROR)
{
printf("Failed to send broadcastmsg");
}
And the code to recieve it looks like this:
sockaddr_in sender_addr;
int sender_addrLen = sizeof(sender_addr);
Packet recvdPacket = {};
int iResult = recvfrom(sock,
reinterpret_cast<char*>(&recvdPacket),
sizeof(recvdPacket),
0,
(SOCKADDR*)&sender_addr,
&sender_addrLen);
if (iResult > 0)
{
return recvdPacket;
}
return Packet{};
You need to enable broadcast setting SO_BROADCAST before sending a broadcast message: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx ,
Why do we need SocketOptions.SO_BROADCAST to enable broadcast?
char broadcast = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast))
Also you should use directed broadcast (for example, 192.168.0.255) instead of Internet broadcast (255.255.255.255). I believe you don't need Internet broadcast.
Also, can you print the value returned by sendto? is iResult == sizeof(Packet)?
Last, which is the size of Packet? Is it a class? you are reinterpreting &packet as a char *. You must be sure there is no error there.
Could broadcast be blocked in the Win10 PC? I don't know if it's possible.
Consider using multicast.
Using Win8.1 and Visual Studio 2013, I’ve tested every example of Windows Registered I/O that I can find (about 5). All result in error 10045 on RioCreateRequestQueue() as shown below on one.
c:>rioServerTest.exe
InitialiseRio Start
InitialiseRio End
CreateCompletionQueue Start
CreateCompletionQueue End
CreateRequestQueue start
RIOCreateRequestQueue Error: 10045
Related code is :
void *pContext = 0;
printf("CreateRequestQueue start\n");
g_requestQueue = g_rio.RIOCreateRequestQueue(
g_socket, // Socket
(ULONG) 10, // MaxOutstandingReceive,
(ULONG) 1, // maxReceiveDataBuffers,
(ULONG) 10, // MaxOutstandingSend,
(ULONG) 1, // MaxSendDataBuffers
g_completionQueue, // ReceiveCQ
g_completionQueue, // SendCQ
pContext); // SocketContect
if (g_requestQueue == RIO_INVALID_RQ) {
printf_s("RIOCreateRequestQueue Error: %d\n", GetLastError());
exit(1);
}
printf("CreateRequestQueue End\n");
According to the literature that I have read, Registered I/O is intended to work with Windows 8 and later and Windows Server 2012 and later.
Can anyone explain to me via an example how to get this to work on Win8.1? TIA
10045 is WSAEOPNOTSUPP the description of which is "Operation not supported.
The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation is trying to accept a connection on a datagram socket."
So actually it's likely that the code we need to see is in fact where you create your socket.
Your socket creation code should look something like this:
socket = ::WSASocket(
AF_INET,
SOCK_DGRAM,
IPPROTO_UDP,
NULL,
0,
WSA_FLAG_REGISTERED_IO);
I have some example articles (including a whole suite of RIO, UDP server designs with complete source code) here, all of these run on all operating systems that RIO supports.
I am using libpcap to sniff traffic. I would like to do it on the currently active network device (e.g. one that has an assigned IP address, etc). What's the best way to do this? I'm assuming I would have to do the following:
pcap_findalldevs(&alldevs, errbuf)
to get all the network devices, then loop through and check which one is currently active.
Edit: The following function
(pcap_lookupnet(dev, &net, &mask, errbuf)
returns the network address and subnet mask for a network device. I ran some tests with the different ethernet adapters on my computer and it returns -1 when I call it on an adapter that is not connected to a network. Would this be the bulletproof way to get an active interface? Are there any edge cases it would miss?
the API pcap has for looking up interfaces conforming to some user defined rules is trivial. You could indeed use pcap_findalldevs() to interate over all suitable-to-use network devices or use pcap_lookupdev() to get the next network device that you can use with pcap. Defining what is the interface you want to use with your sniffer may be problematic (code wise) on systems with multiple network devices and you would want to define more explicit rules for choosing such an interface. Such rules are usually statically defined (like "the active interface with the default route installed"). However, you may have multiple default routes (think load balancing) and here you may either want to sniff on all of them or (for example) only on the ppp interface. So choosing the target interface I would say is a task to be resolved outside the sniffer rather than at runtime in the sniffer code.
For example:
If by "active interface" we understand the interface on which the default route is installed (i assume a linux system here):
ip route show 0.0.0.0/0 | awk ' { print $5 ; } ' | xargs ./sniffer
if you want to get the active interface which has the default route installed on from your sniffer code, you would rather use netlink(7) or proc(5) (/proc/net/route) than pcap's device lookup api but the complexity is high.
In conclusion, the interface lookup logic can be easily scripted into some wrapper program on any system and the result(s) passed as parameter(s) to your sniffer.
Why don't you capture on 'any' device (Pseudo-device that captures on all interfaces) ?
Any way, here is a little snippet that will help you find 'active' interfaces
#include <stdio.h>
#include <pcap.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static void
dump_addresses (pcap_addr_t *addresses)
{
pcap_addr_t *addr = addresses;
printf("(");
while (addr) {
struct sockaddr_in *ip = (struct sockaddr_in *)addr->addr;
struct sockaddr_in *nm = (struct sockaddr_in *)addr->netmask;
if (ip && nm)
printf("%s/%s ",
inet_ntoa(ip->sin_addr), inet_ntoa(nm->sin_addr));
addr = addr->next;
}
printf(")");
}
static void
devs_dump (pcap_if_t *devs)
{
pcap_if_t *dev = devs;
while (dev) {
printf("dev: %s - %s - ",
dev->name, dev->description);
dump_addresses(dev->addresses);
printf("\n");
dev = dev->next;
}
}
int
main(int argc, char *argv[])
{
int r;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *devs;
r = pcap_findalldevs (&devs, errbuf);
if (r) {
printf("Findalldevs: %d (%s)\n", r, errbuf);
return -1;
}
devs_dump(devs);
pcap_freealldevs (devs);
return 0;
}
I've been down this road several times before, and usually find myself falling back to adding a -i switch to allow the user to precisely identify the interface.
It makes your job simpler and avoids any edge conditions.
According to pcap_open_live (3):
DESCRIPTION
pcap_open_live() is used to obtain a packet capture handle to
look at packets on the network. device is a string that
specifies the network device to open; on Linux systems with
2.2 or later kernels, a device argument of "any" or NULL can
be used to capture packets from all interfaces.
But it seems it's deprecated now, you should use pcap_create(3)
How do I receive layer 2 packets in POSIXy C++? The packets only have src and dst MAC address, type/length, and custom formatted data. They're not TCP or UDP or IP or IGMP or ARP or whatever - they're a home-brewed format given unto me by the Hardware guys.
My socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) never returns from its recvfrom().
I can send fine, I just can't receive no matter what options I fling at the network stack.
(Platform is VxWorks, but I can translate POSIX or Linux or whatever...)
receive code (current incarnation):
int s;
if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) {
printf("socket create error.");
return -1;
}
struct ifreq _ifr;
strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0"));
ioctl(s, IP_SIOCGIFINDEX, &_ifr);
struct sockaddr_ll _sockAttrib;
memset(&_sockAttrib, 0, sizeof(_sockAttrib));
_sockAttrib.sll_len = sizeof(_sockAttrib);
_sockAttrib.sll_family = AF_PACKET;
_sockAttrib.sll_protocol = IFT_ETHER;
_sockAttrib.sll_ifindex = _ifr.ifr_ifindex;
_sockAttrib.sll_hatype = 0xFFFF;
_sockAttrib.sll_pkttype = PACKET_HOST;
_sockAttrib.sll_halen = 6;
_sockAttrib.sll_addr[0] = 0x00;
_sockAttrib.sll_addr[1] = 0x02;
_sockAttrib.sll_addr[2] = 0x03;
_sockAttrib.sll_addr[3] = 0x12;
_sockAttrib.sll_addr[4] = 0x34;
_sockAttrib.sll_addr[5] = 0x56;
int _sockAttribLen = sizeof(_sockAttrib);
char packet[64];
memset(packet, 0, sizeof(packet));
if (recvfrom(s, (char *)packet, sizeof(packet), 0,
(struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0)
{
printf("packet receive error.");
}
// code never reaches here
I think the way to do this is to write your own Network Service that binds to the MUX layer in the VxWorks network stack. This is reasonably well documented in the VxWorks Network Programmer's Guide and something I have done a number of times.
A custom Network Service can be configured to see all layer 2 packets received on a network interface using the MUX_PROTO_SNARF service type, which is how Wind River's own WDB protocol works, or packets with a specific protocol type.
It is also possible to add a socket interface to your custom Network Service by writing a custom socket back-end that sits between the Network Service and the socket API. This is not required if you are happy to do the application processing in the Network Service.
You haven't said which version of VxWorks you are using but I think the above holds for VxWorks 5.5.x and 6.x
Have you tried setting the socket protocol to htons(ETH_P_ALL) as prescribed in packet(7)? What you're doing doesn't have much to do with IP (although IPPROTO_RAW may be some wildcard value, dunno)
I think this is going to be a bit tougher problem to solve than you expect. Given that it's not IP at all (or apparently any other protocol anything will recognize), I don't think you'll be able to solve your problem(s) entirely with user-level code. On Linux, I think you'd need to write your own device agnostic interface driver (probably using NAPI). Getting it to work under VxWorks will almost certainly be non-trivial (more like a complete rewrite from the ground-up than what most people would think of as a port).
Have you tried confirming via Wireshark that a packet has actually been sent from the other end?
Also, for debugging, ask your hardware guys if they have a debug pin (you can attach to a logic analyzer) that they can assert when it receives a packet. Just to make sure that the hardware is getting the packets fine.
First you need to specify the protocol as ETH_P_ALL so that your interface gets all the packet. Set your socket to be on promiscuous mode. Then bind your RAW socket to an interface before you perform a receive.
I'm having the weirdest problem causing me headaches. Consider the following code:
// Create and bind socket
std::map<Connection, bool> clients;
unsigned short port=6222;
struct sockaddr_in local_address, from_address;
int result;
char buffer[10000];
SOCKET receive_socket;
local_address.sin_family = AF_INET;
local_address.sin_addr.s_addr = INADDR_ANY;
local_address.sin_port = htons(port);
receive_socket = socket(AF_INET,SOCK_DGRAM,0);
What's happening is receive_socket is not binding, I get SOCKET_ERROR. When I debug the program and check receive_socket, it appears to just be garbled crap. I put a breakpoint on the 'std::map' line. When I step into each line of the above code, the debug cursor jumps straight from the 'unsigned short port' line to the first 'local_address.sin' line, even though I am using step into (F11), it does not stop at struct, int, char or SOCKET lines, it jumps straight over them.
At this point I hover my mouse over local_address, from_address, result, buffer and receive_socket. They are all full of garbled crap. Is this because I have not defined these variables yet? I've also noticed that when I reach the bottom of the above code, local_address.sin_port is set to 19992, but it should be 6222?
Edit: here is my binding code which is failing because the if statement is true:
if(bind( receive_socket, (SOCKADDR*) &local_address, sizeof(local_address)) == SOCKET_ERROR)
{
closesocket(receive_socket);
return 1;
}
I figured out the answer! The problem was I was not calling WSAStartup anywhere in my program. The following code at the beginning fixed it:
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return 1;
}
I found this out by getting the error number from WSAGetLastError() and looking it up on msdn.
Try changing SOCK_DGRAM to SOCK_STREAM
According to MSDN,
SOCK_STREAM - A socket type that provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. This socket type uses the Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6).
SOCK_DGRAM - A socket type that supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. This socket type uses the User Datagram Protocol (UDP) for the Internet address family (AF_INET or AF_INET6).
And as far as the port goes...
local_address.sin_port is set to 19992, but it should be 6222?
htons converts a port number in host byte order to network byte order (see here)
local_address.sin_port = htons(port);
I found that rather weird. Also, why htons() the port? That makes no sense. Couldn't you just use getaddrinfo() or something like that, or does winsock require to manually fill in info?