Recieving text data from remote android bluetooth to Windows xp PC - android

I want to recieve text data from remote android bluetooth. I had written simple winApi server, but it doesnt respond to remote android sending. The connection was fine and did responds( paired) using control panel manager with my bluetooth. When sending and recieving over control panel manager was working fine. But This time, I want to test using some c++ winapi. Here's my code so far. It was adapted from somewhere codeproject site :)
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <tchar.h>
#include <WinSock2.h>
#include <ws2bth.h>
#include <BluetoothAPIs.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested = 0x202;
WSADATA m_data;
if (0 == WSAStartup(wVersionRequested, &m_data))
{
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
const DWORD lastError = GetLastError();
if (s == INVALID_SOCKET)
{
ostringstream stream;
stream << lastError;
string data= stream.str();
printf("Failed to get bluetooth socket! %s\n", data.c_str());
return 1;
}
WSAPROTOCOL_INFO protocolInfo;
int protocolInfoSize = sizeof(protocolInfo);
if (0 != getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO,
(char*)&protocolInfo, &protocolInfoSize))
{
return 1;
}
SOCKADDR_BTH address;
address.addressFamily = AF_BTH;
address.btAddr = 0;
address.serviceClassId = GUID_NULL;
address.port = BT_PORT_ANY;
sockaddr *pAddr = (sockaddr*)&address;
if (0 != bind(s, pAddr, sizeof(SOCKADDR_BTH)))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str() );
}
else
{
printf("\nBinding Successful....\n");
int length = sizeof(SOCKADDR_BTH) ;
getsockname(s,(sockaddr*)&address,&length);
wprintf (L"Local Bluetooth device is %04x%08x \nServer channel = %d\n",
GET_NAP(address.btAddr), GET_SAP(address.btAddr), address.port);
}
int size = sizeof(SOCKADDR_BTH);
if (0 != getsockname(s, pAddr, &size))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
if (0 != listen(s, 10))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
WSAQUERYSET service;
memset(&service, 0, sizeof(service));
service.dwSize = sizeof(service);
// service.lpszServiceInstanceName = reinterpret_cast<LPWSTR>(_T("Accelerometer Data..."));
//service.lpszServiceInstanceName = ;
// service.lpszComment = reinterpret_cast<LPWSTR>(_T("Pushing data to PC"));
GUID serviceID = OBEXFileTransferServiceClass_UUID;
service.lpServiceClassId = &serviceID;
service.dwNumberOfCsAddrs = 1;
service.dwNameSpace = NS_BTH;
CSADDR_INFO csAddr;
memset(&csAddr, 0, sizeof(csAddr));
csAddr.LocalAddr.iSockaddrLength = sizeof(SOCKADDR_BTH);
csAddr.LocalAddr.lpSockaddr = pAddr;
csAddr.iSocketType = SOCK_STREAM;
csAddr.iProtocol = BTHPROTO_RFCOMM;
service.lpcsaBuffer = &csAddr;
if (0 != WSASetService(&service, RNRSERVICE_REGISTER, 0))
{
printf("Service registration failed....");
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%d\n", data.c_str());
}
else
{
printf("\nService registration Successful....\n");
}
HANDLE hRadio ;
BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&btfrp, &hRadio);
if ((hFind != NULL)&& (hRadio !=NULL))
{
if (BluetoothEnableDiscovery(hRadio,TRUE)){
printf("BluetoothEnableDiscovery() is working!\n");
}
if (BluetoothEnableIncomingConnections(hRadio,TRUE)){
printf("BluetoothEnableIncomingConnections() is working!\n");
}
if (BluetoothIsConnectable(hRadio)){
printf("BluetoothIsConnectable() is working!\n");
}
}
printf("\nBefore accept.........");
SOCKADDR_BTH sab2;
int ilen = sizeof(sab2);
SOCKET s2 = accept (s,(sockaddr*)&sab2, &ilen);
if (s2 == INVALID_SOCKET)
{
wprintf (L"Socket bind, error %d\n", WSAGetLastError ());
}
wprintf (L"\nConnection came from %04x%08x to channel %d\n",
GET_NAP(sab2.btAddr), GET_SAP(sab2.btAddr), sab2.port);
wprintf (L"\nAfter Accept\n");
char buffer[1024] = {0};
memset(buffer, 0, sizeof(buffer));
int r = recv(s2,(char*)buffer, sizeof(buffer), 0);
printf("%s\n",buffer);
closesocket(s2);
if (0 != WSASetService(&service, RNRSERVICE_DELETE, 0))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
closesocket(s);
WSACleanup();
return 0;
}
}
I use microsoft BT device btw..

Just to be sure: you said you're on WinXP... OK, but WinXP SP3 with Microsoft BT stack and appropriate dongle? or another XP version and another BT stack (like Widcomm or BlueSoleil...)?
In the later case, BT Socket API won't work...
Otherwise, not much to say about the code, except a missing BluetoothFindRadioClose...

Related

How to connect android application to local domun

I am using esp32 to bring up a tcp server. In order not to access this server by ip, I use mDNS on the esp32 side. I can successfully contact the tcp server from the PC at esp32.local. Now I want to do the same from android application. I wrote a little c ++ code which I run on android.
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
hello ="socket creation failed...";
return env->NewStringUTF(hello.c_str());
}
else
hello="Socket successfully created..\n";
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
std::string url = "esp32.local";
servaddr.sin_addr.s_addr = inet_addr(url.c_str());
servaddr.sin_port = htons(1234);
struct hostent *result;
result = gethostbyname(url.c_str());
// destAddr.sin_addr.s_addr = ((in_addr*)hosten->h_addr_list[0])->s_addr;
if (!result)
{
hello ="gethostbyname...";
return env->NewStringUTF(hello.c_str());
}
// puts(result->h_name);
memmove(&(servaddr.sin_addr.s_addr), result->h_addr, result->h_length);
// connect the client socket to server socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
hello="connection with the server failed..";
return env->NewStringUTF(hello.c_str());
}
else
printf("connected to the server..\n");
// function for chat
char buff = 0xA;
write(sockfd, &buff, sizeof(buff));
// close the socket
close(sockfd);
When trying to connect from android application, I get an error in function gethostbyname. . What do I need to do to access the .local domain?
std::string url = "esp32.local";
servaddr.sin_addr.s_addr = inet_addr(url.c_str());
inet_addr() does not support parsing hostnames like "sp32.local", only IP addresses. You need to use gethostbyname() or better getaddrinfo() instead.
struct hostent *result;
result = gethostbyname(url.c_str());
...
memmove(&(servaddr.sin_addr.s_addr), result->h_addr, result->h_length);
You are not copying the result of gethostbyname() into the sin_addr.s_addr correctly. Your commented-out code was doing it correctly:
servaddr.sin_addr.s_addr = ((in_addr*)(hosten->h_addr_list[0]))->s_addr;
Which can be simplified to:
servaddr.sin_addr = *(in_addr*)(hosten->h_addr_list[0]);
Or just:
servaddr.sin_addr = *(in_addr*)(hosten->h_addr);
But, getaddrinfo() would be easier to use than populating a sockaddr_in manually. And it supports IPv6, whereas gethostbyname() only supports IPv4:
std::string url = "esp32.local";
int sockfd = -1;
addrinfo hints = {};
addrinfo *result;
hints.ai_family = AF_INET; // AF_UNSPEC
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// assign IP, PORT
int res = getaddrinfo(url.c_str(), "1234", &hints, &result);
if (res != 0) {
return env->NewStringUTF("getaddrinfo failed...");
}
for(addrinfo *addr = result; addr; addr = addr->ai_next) {
// socket create and varification
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sockfd == -1) {
continue;
}
// connect the client socket to server socket
if (connect(sockfd, addr->ai_addr, addr->ai_addrlen) != 0) {
close(sockfd);
sockfd = -1;
continue;
}
break;
}
if (sockfd == -1) {
freeaddrinfo(result);
return env->NewStringUTF("socket creation/connect failed...");
}
freeaddrinfo(result);
printf("Connected to the server..\n");
// function for chat
char buff = 0xA;
write(sockfd, &buff, sizeof(buff));
// close the socket
close(sockfd);

Android Linux kernel communicate with user space

I'm following this article to implement android linux kernel communicate with user space.
I use insmod kernel to insert my kernel to Android avd goldfish kernel, then I use cat /proc/kmsg to observe the kernel message, but I find the program doesn't execute as intended. Here is my code:
void hello_nl_recv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %sn", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr *)skb->data;
printk(KERN_INFO "Netlink received msg payload:%sn", (char *)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out)
{
printk(KERN_ERR "Failed to allocate new skbn");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0)
printk(KERN_INFO "Error while sending bak to usern");
}
int init_module()
{
printk("Entering: %sn", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
printk("%s",nl_sk);
// nl_sk = netlink_kernel_create(NETLINK_USER, input);
//if (!nl_sk)
//{
// printk(KERN_ALERT "Error creating socket.n");
// return -10;
//}
return 0;
}
I find when the program exec
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
The kernel returns -1 or other integer, and it can't execute the function "hello_ne_recv_msg". I use android avd, the kernel is goldfish 2.6. Please help me, thanks.
Here is my code (tested on sony z2 kernel).
Note: your code may still fail if seandroid (selinux) is enforced.
Beware of code copy pasting. Check it!
Don't ignore compilation warnings.
Kernel module:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
static struct sock* nl_sk;
#define NETLINK_USER 31
void hello_nl_recv_msg(struct sk_buff* skb)
{
struct nlmsghdr* nlh;
int pid;
struct sk_buff* skb_out;
int msg_size;
char* msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n", (char*)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out) {
printk(KERN_ERR "Failed to allocate new skbn\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0) {
printk(KERN_INFO "Error while sending back to user\n");
}
}
int __init init_netlink_test(void)
{
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
if (!nl_sk) {
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
void __exit exit_netlink_test(void)
{
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(init_netlink_test);
module_exit(exit_netlink_test);
userspace test app:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr* nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
/* interested in group 1<<0 */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr*)malloc(
NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello");
iov.iov_base = (void*)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void*)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd, &msg, 0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf(" Received message payload: %s\n",
NLMSG_DATA(nlh));
close(sock_fd);
}

C++ Server Send message to Android Client using TCP

Problem
I am trying to send a packet from C++ Server to my Android client but the android client is never receiving the packet. I have tried different things on android both the readline and read buffer but these never return anything. Also I am calling the Method to receive packet from the main activity page.
C++ Code
int numBytes; // the number of bytes sent
// Sends the message to the connected host
try
{
string sendMsg = "This is a test \r\n";
if (numBytes = send(socketId, sendMsg.c_str(), sendMsg.size(), 0) == -1)
{
int errorCode = 0;
string errorMsg = "error calling send():\n";
detectErrorSend(&errorCode,errorMsg);
CExceptionEx socketSendException(errorCode,errorMsg);
throw socketSendException;
}
}
catch(CExceptionEx& excp)
{
excp.response();
exit(1);
}
return numBytes;
Android Code
public void RecievePacket()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(mSock.getInputStream()));
String test = br.readLine();
/* BufferedInputStream input = new BufferedInputStream(mSock.getInputStream());
byte[] buffer = new byte[10]; // 10 bytes buffer
int bytesRead = 0;
while( (bytesRead=input.read(buffer)) !=-1 ) { // read up to 10 bytes
String str = new String(buffer,0,bytesRead); // convert bytes to String using default encoding
//System.out.println("Data received: " + str);
}
*/
}
catch (Exception ex)
{
}
}
Note
The commented code block is the the other way I tried to receive the message, also please note that I am able to send packets from Android to C++.
Edit
The send() is sending 0 bytes but i am able to receive packets from android so there must be a connection.
There must be something wrong that's not part of the code you've given us. I wrote my own minimal example running on my own computer using your code, and everything worked as expected. Check if this runs correctly on your computer (run the C++, then the Java). Also check if there's anything I do in my C++ code that you're missing.
socket.cpp: (I'm more of a C programmer, so I just used C++ for the code you provided).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
void connection(int sock)
{
// Pretty much your C++ code verbatim.
std::string sendMsg = "This is a test \r\n";
int amt = send(sock, sendMsg.c_str(), sendMsg.size(), 0);
printf("Send %d bytes.\n", amt);
close(sock);
}
int main(int argc, char *argv[])
{
int sock, csock;
struct sockaddr_in sin;
char *host = "127.0.0.1";
unsigned short port = 1234;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if (inet_pton(AF_INET, host, &sin.sin_addr) != 1) {
perror("inet_pton");
exit(EXIT_FAILURE);
}
if (bind(sock, (struct sockaddr*) &sin, sizeof(sin)) != 0) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(sock, SOMAXCONN) != 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((csock = accept(sock, NULL, NULL)) == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
connection(csock);
close(sock);
return EXIT_SUCCESS;
}
SockTest.java:
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class SockTest {
public static void main(String[] args) {
try {
Socket sock = new Socket("127.0.0.1", 1234);
// Your Java Code Verbatim:
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String test = br.readLine();
System.out.println(test);
sock.close();
} catch (Exception ex) {}
}
}
Output for the C++:
$ ./socket
Send 17 bytes.
Output for the Java:
$ java SockTest
This is a test
shouldn't it be
if (numBytes = send(socketId, sendMsg.c_str(), (sendMsg.size() + 1), 0) == -1) ...
Note that +1

Linux Kernel Module unix domain sockets

I'm trying to share data between kernel and user space. The ultimate goal is to port it to Android, so I'm using unix domain sockets. (I don't know if this is the best option).
I have a kernel module acting as socket client and a c program acting as socket server. And vice-versa, a kernel module acting as socket server and a c program acting as socket client.
Programs are very simple. Servers just send a string to clients and they print it.
I run server_user.c and then I try to insert client_module.ko using insmod. I get the following error:
Kernel panic - not syncing: stack - protector: Kernel stack is corrupted in: ffffffffa0005157
drm-kms-helper: panic occurred, switching back to text console
What's wrong?
Module Server
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <net/sock.h>
#define SOCK_PATH "/tmp/usocket"
#define LISTEN 10
struct socket *sock = NULL;
struct socket *newsock = NULL;
static int __init server_module_init( void ) {
int retval;
char* string = "hello_world";
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr));
// listen
retval = sock->ops->listen(sock, LISTEN);
//accept
retval = sock->ops->accept(sock, newsock, 0);
//sendmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iov->iov_base = string;
msg.msg_iov->iov_len = strlen(string)+1;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_sendmsg(newsock, &msg, strlen(string)+1);
set_fs(oldfs);
return 0;
}
static void __exit server_module_exit( void ) {
printk(KERN_INFO "Exit usocket.");
}
module_init( server_module_init );
module_exit( server_module_exit );
MODULE_LICENSE("GPL");
Module Client
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/un.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/socket.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
struct socket *sock = NULL;
static int __init client_module_init( void ) {
int retval;
char str[MAX];
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
printk(KERN_INFO "Start client module.\n");
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
// connect
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr), 0);
// recvmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_iov->iov_base= str;
msg.msg_iov->iov_len= strlen(str)+1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_recvmsg(sock, &msg, strlen(str)+1, 0);
set_fs(oldfs);
// print str
printk(KERN_INFO "client module: %s.\n",str);
// release socket
sock_release(sock);
return 0;
}
static void __exit client_module_exit( void )
{
printk(KERN_INFO "Exit client module.\n");
}
module_init( client_module_init );
module_exit( client_module_exit );
MODULE_LICENSE("GPL");
User Server
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
int send_msg_to_client(int socketfd, char* data) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = strlen(data)+1;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = sendmsg(socketfd, &msg, 0);
printf("after send - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("sendmsg");
return 0;
}
return s;
}
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: $ %s <string>\n",argv[0]);
return 0;
}
int s, s2, len, slen;
socklen_t t;
struct sockaddr_un local, remote;
char* data = argv[1];
printf("print data: %s\n",data);
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
memset(&local, 0, sizeof(local));
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
slen = send_msg_to_client(s2, data);
if(slen < 0)
perror("send");
close(s2);
return 0;
}
User Client
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
int recv_msg_from_server(int socketfd, char data[MAX]) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = MAX;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = recvmsg(socketfd, &msg, 0);
printf("after recv - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("recvmsg");
}
return s;
}
int main(void)
{
int s, len, slen;
struct sockaddr_un remote;
char data[MAX];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
memset(&remote, 0, sizeof(remote));
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
slen = recv_msg_from_server(s, data);
if (slen < 0) {
perror("recvmsg");
}
//printf("print data received > %s\n", data);
close(s);
return 0;
}
I have just faced a similar issue (with UNIX datagrams though), and I believe there is a bug in the unix_mkname() function which is part of the kernel: this function makes sure the sun_path field of the given sockaddr_un structure is always null terminated by adding a NUL character after the end of that field. Since this is the last field, it will corrupt the area (stack or heap) where that structure has been allocated.
The best solution is to patch that function in the kernel source code, so that it only sets to NUL the last character of the sun_path field. Meanwhile, you can make your code work by decreasing by 1 byte the size you give for the sockaddr_un structure:
Module Server
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr) - 1);
Module Client
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr) - 1, 0);
As I am using UNIX datagrams, I cannot really tell if it fixes the issue for bind() and connect(), but a least, it fixes it for sock_sendmsg().
#shu-suzuki: thanks for the leads.
After 5 years I came back here...
I again stucked with this problem and found that I did the same thing 5 years ago.
The cause is as in Tey's answer and the solution is OK (sutbract 1 from the length) but here's another solution.
What you can do is to use struct sockaddr_storage as struct sockaddr_un. As far as I read the kernel code this is what they use to handle bind system call from user space.
sockeaddr_storage is larger than sockaddr_un so kernel code can write beyond the sizeof(sockaddr_un).
The code should be like
struct sockaddr_storage addrStorage;
struct sockaddr_un* addr;
memset(&addrStorage, 0, sizeof(addrStorage));
addr = (struct sockaddr_un*)&addrStorage;
addr->sun_family = AF_UNIX;
strcpy(addr->sun_path, "/my/sock/name");
kernel_bind(listenSock, (struct sockaddr*)addr, sizeof(*addr));
This looks working for me.

Android Opensles resampling PCM with FFmpeg

I'm trying to play an audio stream with ffmpeg and opensles in android. And the problem seems to be when passing the decoded and resampled frames from ffmpeg to opensles as the sound I can hear sounds robotic and has scratching.
The decoded frames from ffmpeg:
PCM
48000 Hz
S16p
Opensles needs in this case:
PCM
48000 Hz
S16
Opensles setup:
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 255};
SLDataFormat_PCM format_pcm = { SL_DATAFORMAT_PCM, 2 , SL_SAMPLINGRATE_48, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
This is the pseudocode for resampling and enqueueing to opensles:
#define OPENSLES_BUFLEN 10
#define MAX_AUDIO_FRAME_SIZE 192000
DECLARE_ALIGNED(16,uint8_t,audio_buffer)[MAX_AUDIO_FRAME_SIZE * OPENSLES_BUFLEN];
int decode_audio(AVCodecContext * ctx, SwrContext *swr_context, AVPacket *packet, AVFrame * frame){
int got_frame_ptr;
int len = avcodec_decode_audio4(ctx, frame, &got_frame_ptr, packet);
if(!got_frame_ptr)
return -ERROR;
int original_data_size = av_samples_get_buffer_size(NULL, ctx->channels,
frame->nb_samples, ctx->sample_fmt, 1);
uint8_t *audio_buf;
int data_size;
if (swr_context != NULL) {
uint8_t *out[] = { audio_buffer };
int sample_per_buffer_divider = 2* av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);;
int len2 = swr_convert(swr_context, out,
sizeof(audio_buffer) / sample_per_buffer_divider,
frame->extended_data, frame->nb_samples);
if (len2 < 0) {
return -ERROR;
}
if (len2 == sizeof(audio_buffer) / sample_per_buffer_divider) {
swr_init(swr_context);
}
audio_buf = audio_buffer;
data_size = len2 * sample_per_buffer_divider;
}
else {
audio_buf = frame->data[0];
data_size = original_data_size;
}
(*opengSLESData->bqPlayerBufferQueue)->Enqueue(opengSLESData->bqPlayerBufferQueue, audio_buf, data_size)
}
I would appreciate any help, thanks.
example may help
#include "stdafx.h"
#include <iostream>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
//#include "swscale.h"
#include "libswresample/swresample.h"
};
FILE *fin, *fout;
int ffmpeg_audio_decode( const char * inFile, const char * outFile)
{
// Initialize FFmpeg
av_register_all();
AVFrame* frame = avcodec_alloc_frame();
if (!frame)
{
std::cout << "Error allocating the frame" << std::endl;
return 1;
}
// you can change the file name "01 Push Me to the Floor.wav" to whatever the file is you're reading, like "myFile.ogg" or
// "someFile.webm" and this should still work
AVFormatContext* formatContext = NULL;
//if (avformat_open_input(&formatContext, "01 Push Me to the Floor.wav", NULL, NULL) != 0)
if (avformat_open_input(&formatContext, inFile, NULL, NULL) != 0)
{
av_free(frame);
std::cout << "Error opening the file" << std::endl;
return 1;
}
if (avformat_find_stream_info(formatContext, NULL) < 0)
{
av_free(frame);
av_close_input_file(formatContext);
std::cout << "Error finding the stream info" << std::endl;
return 1;
}
AVStream* audioStream = NULL;
// Find the audio stream (some container files can have multiple streams in them)
for (unsigned int i = 0; i < formatContext->nb_streams; ++i)
{
if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStream = formatContext->streams[i];
break;
}
}
if (audioStream == NULL)
{
av_free(frame);
av_close_input_file(formatContext);
std::cout << "Could not find any audio stream in the file" << std::endl;
return 1;
}
AVCodecContext* codecContext = audioStream->codec;
codecContext->codec = avcodec_find_decoder(codecContext->codec_id);
if (codecContext->codec == NULL)
{
av_free(frame);
av_close_input_file(formatContext);
std::cout << "Couldn't find a proper decoder" << std::endl;
return 1;
}
else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0)
{
av_free(frame);
av_close_input_file(formatContext);
std::cout << "Couldn't open the context with the decoder" << std::endl;
return 1;
}
std::cout << "This stream has " << codecContext->channels << " channels and a sample rate of " << codecContext->sample_rate << "Hz" << std::endl;
std::cout << "The data is in the format " << av_get_sample_fmt_name(codecContext->sample_fmt) << std::endl;
//codecContext->sample_fmt = AV_SAMPLE_FMT_S16;
int64_t outChannelLayout = AV_CH_LAYOUT_MONO; //AV_CH_LAYOUT_STEREO;
AVSampleFormat outSampleFormat = AV_SAMPLE_FMT_S16; // Packed audio, non-planar (this is the most common format, and probably what you want; also, WAV needs it)
int outSampleRate = 8000;//44100;
// Note that AVCodecContext::channel_layout may or may not be set by libavcodec. Because of this,
// we won't use it, and will instead try to guess the layout from the number of channels.
SwrContext* swrContext = swr_alloc_set_opts(NULL,
outChannelLayout,
outSampleFormat,
outSampleRate,
av_get_default_channel_layout(codecContext->channels),
codecContext->sample_fmt,
codecContext->sample_rate,
0,
NULL);
if (swrContext == NULL)
{
av_free(frame);
avcodec_close(codecContext);
avformat_close_input(&formatContext);
std::cout << "Couldn't create the SwrContext" << std::endl;
return 1;
}
if (swr_init(swrContext) != 0)
{
av_free(frame);
avcodec_close(codecContext);
avformat_close_input(&formatContext);
swr_free(&swrContext);
std::cout << "Couldn't initialize the SwrContext" << std::endl;
return 1;
}
fout = fopen(outFile, "wb+");
AVPacket packet;
av_init_packet(&packet);
// Read the packets in a loop
while (av_read_frame(formatContext, &packet) == 0)
{
if (packet.stream_index == audioStream->index)
{
AVPacket decodingPacket = packet;
while (decodingPacket.size > 0)
{
// Try to decode the packet into a frame
int frameFinished = 0;
int result = avcodec_decode_audio4(
codecContext,
frame,
&frameFinished,
&decodingPacket);
if (result < 0 || frameFinished == 0)
{
break;
}
unsigned char buffer[100000] = {NULL};
unsigned char* pointers[SWR_CH_MAX] = {NULL};
pointers[0] = &buffer[0];
int numSamplesOut = swr_convert(
swrContext,
pointers,
outSampleRate,
(const unsigned char**)frame->extended_data,
frame->nb_samples);
fwrite(
(short *)buffer,
sizeof(short),
(size_t)numSamplesOut,
fout);
decodingPacket.size -= result;
decodingPacket.data += result;
}
}
// You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory
av_free_packet(&packet);
}
// Some codecs will cause frames to be buffered up in the decoding process. If the CODEC_CAP_DELAY flag
// is set, there can be buffered up frames that need to be flushed, so we'll do that
if (codecContext->codec->capabilities & CODEC_CAP_DELAY)
{
av_init_packet(&packet);
// Decode all the remaining frames in the buffer, until the end is reached
int frameFinished = 0;
while (avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet) >= 0 && frameFinished)
{
}
}
// Clean up!
av_free(frame);
avcodec_close(codecContext);
av_close_input_file(formatContext);
fclose(fout);
}

Categories

Resources