I've searched all over google and can't find a solution to this problem:
I'm trying to do some basic socket programming (client/server apps) on my Android device and I'm not having any luck starting the Server app. In my native code, I call bind(...) and I see from the log that it returns -1. When I check errno, the value is 97 (EAFNOSUPPORT), which indicates "Address family not supported by protocol." When I checked the values for sin_family, it was AF_INET, which is IPv4. Is this not supported by the Android NDK? If not, what else could be the cause of this error?
Socket is initialized as:
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
listenAddr is a sockaddr_in struct that's initialized with:
sin_family = AF_INET;
sin_port = htons(9099);
sin_addr.s_addr = INADDR_NONE;
Call to bind:
bindResult = bind(sock, (sockaddr *)listenAddr, sizeof(listenAddr))
Bind result returns -1. Subsequent call to errno returns 97.
Use INADDR_ANY (or a specific interface's address) rather than INADDR_NONE.
INADDR_NONE is an unsigned constant with the same bit pattern as the signed value -1, returned as an indication of error from certain calls.
Related
I wrote a netfilter hook function for incoming packets in linux kernel. Is there a way to get the receiving socket information from the hook function. The code is
register() {
hk.hook = hookfunction;
hk.hooknum = NF_INET_PRE_ROUTING;
hk.pf = PF_INET;
hk.priority = NF_IP_PRI_LAST;
}
static unsigned int hookfunction (void *priv,struct sk_buff,const struct nf_hook_state *state) {
if (skb->sk) {
printk("%d", skb->sk->sk_mark);
}
}
Lets assume I have a udp socket open at port 15000 and a udp packet arrives at port 15000. In the above written hook function how can I access the struct sock of the udp socket opened at port 15000. With the above code, the control doesnot pass the if(skb->sk) condition as if skb->sk is null. Can you please suggest me a way to get the struct sock of the socket or should I have to put the hook in some other position like NF_INET_LOCAL_IN,. I am also confused about the difference between NF_INET_XX_XX and NF_IP_XX_XX.
The kernel uses __inet_lookup_skb() internally to get sk from skb, which calls skb_steal_sock() first to check if skb->sk is NULL, if that is the case, it then calls __inet_lookup() to lookup sk.
However you might need to tweak the kernel a little bit because __inet_lookup_skb symbol is not exported and can't be called directly.
Some references from kernel source:
1 2 3
Regarding NF_INET_XX if you are talking about NF_IP_PRE_ROUTING and NF_INET_PRE_ROUTING I believe NF_IP_PRE_ROUTING is obsolete in recent kernel, as far as I know 4.4 has replaced it with NF_INET_PRE_ROUTING.
Hope that helps.
I am using the AsyncSocket source code from libjingle to connect to a server. I am using the same source code in an iPhone App and the connection is fine, but on the Android phone, I get access denied error when creating a socket.
This is the function that fails at s_ = ::socket(family, type, 0).
// Creates the underlying OS socket (same as the "socket" function).
virtual bool Create(int family, int type) {
Close();
s_ = ::socket(family, type, 0);
udp_ = (SOCK_DGRAM == type);
UpdateLastError();
if (udp_)
enabled_events_ = DE_READ | DE_WRITE;
return s_ != INVALID_SOCKET;
}
The family value is 2 and type is 1. S_ gets a return value of -1 with errno of 13. I looked up Linux error code and it's access denied. Do you know if there is any special setting in Android that I need to set? Any help would be appreciated.
Permissions?
Specifically : <uses-permission android:name="android.permission.INTERNET" />
I'm currently setting up a UDP-based networking library in C++.
The way i intend to use them is to have two instances of the same application running.
One on Windows and one on Android.
The Android instance is supposed to send out a broadcast message which is received on Windows.
Then a unicast socket is opened on both ends and communication is started.
Right now, however, I'm testing with simple broadcasts in both directions.
According to what i've found in order to receive messages from a socket the bind() function must be called with the local IP address (in the form "192.168.x.x") and the port number to listen on.
On windows i'm able to find this local IP address using the following code:
char* UDPSocketPC::getLocalAddress()
{
hostent *thisHost = gethostbyname ( "" );
char buf [100];
_itoa_s ( **thisHost->h_addr_list, buf, 10 );
return inet_ntoa ( *reinterpret_cast<struct in_addr * >(*thisHost->h_addr_list) );
//returns an ip address in the form of "192.168.0.3"
}
On Android however, the gethostbyname function doesn't exist and neither does the hostent class.
What i'm using instead right now are things like INADDR_ANY (0.0.0.0), INADDR_BROADCAST (255.255.255.255) and INADDR_LOOPBACK(127.0.0.1). Neither of these addresses receive the broadcasts i'm sending.
All other things appear to be set up correctly.
On Windows i'm receiving broadcasts sent from Windows as well as from Android.
On Android i'm receiving neither.
The main difficulty with this question is that the vast majority of documentation online is either targeted at Unix sockets or at WinSock sockets, so it's quite difficult to find a good example of this for the NDK.
Thanks in advance for any help.
EDIT:
I've made some progress, and it looks like the problem I was having was actually related to my attempts to make the recvfrom () function non-blocking
Here is my implementation of the select() function on Windows:
fd_set sockets = fd_set ( );
sockets.fd_array [0] = socketPTR;
sockets.fd_count = 1;
fd_set empty = fd_set ( );
const timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( 0, &sockets, &empty, &empty, &timeout ) > 0;
And here's how i did it on Android:
fd_set sockets = fd_set ( );
FD_ZERO ( &sockets );
FD_SET ( socketPTR, &sockets );
fd_set empty = fd_set ( );
FD_ZERO ( &empty );
timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( 0, &sockets, &empty, &empty, &timeout ) > 0;
The Windows implementation does pretty much exactly what i would expect it to, it returns false when no data is available for reading, and true when there is at least one message in the queue.
However on Android it seems to always return false.
By temporarily removing the call from Android i am able to send and receive messages from both platforms on both platforms.
But now the call is blocking on Android (which isn't ideal since i want to have the thread doing other things while no data is available).
I will look for more information regarding the select() function on Android in order to get it actually working.
You are not supplying a value to the first parameter of select(). That parameter is ignored on Windows, but it is NOT ignored on other platforms. Per the documentation:
nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
So, in your example, you need to set the parameter to socketPTR+1.
Also, do not provide empty fd_set structs for unused parameters. Use NULL instead:
Each of the three file descriptor sets may be specified as NULL if no file descriptors are to be watched for the corresponding class of events.
Also, always use FD_ZERO() and FD_SET(), even on Windows. This helps to promote code portability across platforms that use different layouts for fd_set.
Try this code instead:
fd_set sockets;
FD_ZERO( &sockets );
FD_SET( socketPTR, &sockets );
timeval timeout = { timeoutSec, timeoutMicroSec };
return select ( socketPTR+1, &sockets, NULL, NULL, &timeout ) > 0;
I am working with custom devices and I am struggling to manage the Bluetooth LE correctly.
My only concern is not getting 0 (BluetoothGatt.GATT_SUCCESS) when I read the status value along with value 2 on newState variable (what means BluetoothProfile.STATE_DISCONNECTED) at method onConnectionStateChange. Instead, I get an 8, what can't be tracked in the BluetoothGatt nor BluetoothProfile classes.
All connection works fine, I read and write values perfectly.
(1) Is this supposed to be like that? Why do I read an eight?
I have seen many status values at my onConnectionStateChange method: 8, 19, 133 etc.
(2) Where can I check this values?
Thanks in advance
EDIT: There are many values in the api.h file, we were looking in the wrong place.
8: 0x08 = GATT CONN TIMEOUT
19: 0x13 = GATT CONN TERMINATE PEER USER
133: 0x85 = GATT_ERROR
The int error codes need to be converted to HEX and mapped to the values in the following file:
https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.1_r13/stack/include/gatt_api.h
In the cases you mentioned:
8 = GATT_INSUF_AUTHORIZATION
19 = GATT_RSP_WRITE
133 = GATT_ERROR
Answer is no.
I wasn't getting BluetoothGatt.GATT_SUCCESS because the connection was closed by the other end. If gatt.disconnect() is executed I read status = BluetoothGatt.GATT_SUCCESS.
I want to implement socket function in the Android frameworks/native/service/surfaceFlinger for sending screen information.
So, I made my source code about networking by using socket(), and inserted into the Android framework source tree.
However, it couldn't create socket descriptor.
It always returned -1 and errno is 13
So I added permission code like this:
// framework/frameworks/native/services/surfaceflinger/mynetwork.cpp
if (PermissionCache::checkCallingPermission("android.permission.INTERNET") < 0)
...
fd = socket(AF_INET, SOCK_DGRAM, 0);
But still doesn't work.
Any body know about this issue?
and know soution?
Thank you.