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;
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 writing an open source framework to use BLE Mini module with Android and iOS mobile devices using Unity engine.
This framework should allow to establish a connection between the mobile device and the BLE Mini module, and to send/receive data using it. The framework can be theoretically adapted to work with any BLE module.
The idea is to make the existing BLE Mini frameworks (available for iOS and Android) work in Unity engine, hence I am writing native plugins for iOS and Android that will allow Unity apps use the native frameworks.
The iOS plugin is working as expected, while I am having problems writing the Android plugin.
Everything works as expected except the fact that I cannot send data to my characteristic. If I send the data the BLE Mini module does not receive it.
The code controlling the BLE Mini data reception is correct because it works when iOS sends the data. So I am pretty sure the problem is in the Android plugin.
The Android plugin is composed by Android native code that can be found here:
https://github.com/giomurru/ble-framework/tree/master/AndroidPlugin/src/com/gmurru/bleframework
and by Unity c# code that can call the public java methods: https://github.com/giomurru/ble-framework/blob/master/Unity/Assets/BLE/BLEController.cs
The code contained in RBLGattAttributes.java and RBLService.java is correct because it is the framework provided by RedBearLab and I tested it and it works correctly with native Android apps.
The code in which I need help and that probably contains the bug is the one in BleFramework.java
The BleFramework class contains a series of functions that can be called by the Unity engine. The functions are called following this order:
Call the get static method BleFramework.getInstance() to get a singleton instance of the class BleFramework. This method returns one and only one instance of the BleFramework class.
After I have the instance of the class I can call the BleFramework methods using this instance (which is always the same instance).
The methods are called following this order:
1) Call the function _InitBLEFramework from Unity. The function should initialize the BLE framework. When the initialization is finished the Android plugin answer to Unity with a OnBleDidInitialize "Success" message.
2) If Unity receives the OnBleDidInitialize "Success" message, I can call the function _ScanForPeripherals from Unity. The function scans for available BLE modules peripherals. When the available peripherals are found the plugin answer to Unity with a OnBleDidCompletePeripheralScan "Success" message.
3) If Unity receives the OnBleDidCompletePeripheralScan "Success" message, I can call the function _GetListOfDevices to get the list of found devices.
4) Once I have the list of BLE module devices I found, I can try to connect to one of them using the function _ConnectPeripheralAtIndex(int peripheralIndex). When the _mGattUpdateReceiver receives RBLService.ACTION_GATT_SERVICES_DISCOVERED I can say the connection is established and I can let Unity know I am ready to send/receive data by sending a OnBleDidConnect "Success" message.
Up to here the plugin works as expected, and the connection is established.
The problem is when I try to send data in step 5.
5) When Unity receives the OnBleDidConnect "Success" message it is ready to send data through the established connection. Hence I try to send the data by using _SendData function in the plugin. Unfortunately it does not work.
This is the code:
public void _SendData(byte[] data)
{
Log.d(TAG,"_SendData: ");
BluetoothGattCharacteristic characteristic = _map.get(RBLService.UUID_BLE_SHIELD_TX);
Log.d(TAG, "Set data in the _characteristicTx");
byte[] tx = hexStringToByteArray("fefefe");
characteristic.setValue(tx);
Log.d(TAG, "Write _characteristicTx in the _mBluetoothLeService: " + tx[0] + " " + tx[1] + " " + tx[2]);
if (_mBluetoothLeService==null)
{
Log.d(TAG, "_mBluetoothLeService is null");
}
_mBluetoothLeService.writeCharacteristic(characteristic);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Just for the purpose of testing I ignored byte[] data parameter and I try to send byte[] tx data that I create inside the _SendData function using hexStringToByteArray function (that I found in this StackOverflow post: Convert a string representation of a hex dump to a byte array using Java?)
I also tried to create the tx data as:
byte tx[] = new byte[] { (byte) 0xfe, (byte) 0xfe, (byte) 0xfe };
or to send the data directly like this:
public void _SendData(byte[] data)
{
Log.d(TAG,"_SendData: ");
BluetoothGattCharacteristic characteristic = _map.get(RBLService.UUID_BLE_SHIELD_TX);
Log.d(TAG, "Set data in the _characteristicTx");
characteristic.setValue(data);
Log.d(TAG, "Write _characteristicTx in the _mBluetoothLeService: " + data[0] + " " + data[1] + " " + data[2]);
if (_mBluetoothLeService==null)
{
Log.d(TAG, "_mBluetoothLeService is null");
}
_mBluetoothLeService.writeCharacteristic(characteristic);
}
In all the cases I failed to send the data.
I really can't understand why this is happening. The code I am using to search ble devices, establish connection, send receive data is very similar to the Android native samples available in ReadBearLab github page: https://github.com/RedBearLab/Android/tree/master/Examples
The only difference is that I am not extending Activity.
I tried to make BleFramework class an extension of Activity but it didn't work. The problem I had was that while BleFramework activity was running I was not able to send messages back to Unity using the UnityPlayer.UnitySendMessage function.
I answer my own question just for reference if anybody is interested in the solution I found.
I fixed the bug by updating the code to the latest Android APIs. Please check out the commits from June 15th 2019 to June 22nd 2019 in the repository if you are interested in the modifications. In particular the commit named "Android tx/rx works"
https://github.com/giomurru/ble-framework
I'm trying to generate keypairs in a React Native project. The key pair generation tool relies on the crypto module's random byte generation, which produces a buffer of a specified lengths with random byte values.
In order to use the crypto module within React Native, it has to be browserified, and the browserified random number generator looks like this:
https://github.com/crypto-browserify/randombytes/blob/master/browser.js
Here's the key component:
var crypto = global.crypto || global.msCrypto
if (crypto && crypto.getRandomValues) {
module.exports = randomBytes
} else {
module.exports = oldBrowser
}
Indeed, when debugging the application with Chrome, everything works fine, but when running it on iOS's JavaScriptCore engine, the oldBrowser method gets called instead, throwing the following error:
secure random number generation not supported by this browser
use chrome, FireFox or Internet Explorer 11
Thus I'm trying to find a replacement for the random bytes generation. One module I found is this one:
https://www.npmjs.com/package/react-native-randombytes
It uses the device's native libraries to generate a random number, and exposes it to React Native through their Obj-C/JS interface. It should be noted that this method only works on iOS, and the library's author doesn't have an Android solution yet, but that's an issue for another time.
This method works, in that it can generate random bytes, but it has one major drawback. React only supports asynchronous interfacing between Objective-C and JavaScript, which means that this method returns its results asynchronously. The original randomBytes method is synchronous, and pretty much every SDK out there that relies on it uses it synchronously. So if we were to go with the async version, all the SDKs would have to be rewritten for it, including all dependencies that rely on methods that used to be synchronous and now would no longer be.
Thus I'm trying to find a way to make the asynchronous native random number generator work synchronously. There are several node packages that do that, the most prominent one of them being deasync, but deasync relies on some core Node modules that cannot be browserified, so the synchronous version doesn't work.
Alternatively, I've tried wrapping it in a method that would set a semaphore, call the async generator, and wait in a while loop for the semaphore's value to change. That attempt failed because the while loop was blocking the callback from ever executing. Here's an approximation of my attempts, where the call to the async method has been replaced with a setTimeout, and the random number to be returned is a four, as determined by a fair dice roll.
function testSynchronicity() {
var isDone = false;
setTimeout(function() {
isDone = true;
}, 1000); // set isDone to true after a second
while (!isDone) {
// do nothing
}
return 4;
};
As this wasn't working, I figured I would try a completely different random number generator entirely, without the native-code-relying react-native-randombytes module and went with this one for JavaScript:
https://github.com/skeeto/rng-js
It worked fine within Node itself, but after browserifying it and trying to run the first example within React Native, it threw an error saying that the main object was not a constructor. Here's what the example looks like:
var RNG = require('./rng_react'); // rng_react is rng-js browserified
var rng = new RNG();
var randomValue = rng.random(0, 255, false);
So at this point, I'm at a bit of a loss, and would appreciate any help. Thanks!
EDIT: If all else fails, there's this, but I think it would pretty much beat the purpose of the question. https://github.com/bitpay/bitcore-lib/blob/master/lib/crypto/random.js#L37
I have found an answer that usually works. However, it is imperfect, because it works only if the randomBytes method is not required during app launch.
My solution does involve using the react-native-randombytes library. It relies on iOS's built-in CSPRNG to generate a random buffer, and then returns it asynchronously. In order to support synchronous responses, I expanded the moduel's randomBytes to not throw an error when no callback method is provided, but rather to use Stanford's JavaScript Crypto Library to generate random "words," as they're called, convert those to a buffer and then trim it accordingly:
var sjcl = require('sjcl');
var sjclRandom = new sjcl.prng(10);
var RNRandomBytes = require('react-native').NativeModules.RNRandomBytes;
module.exports.randomBytes = function(length, cb) {
if (!cb) {
var size = length;
var wordCount = Math.ceil(size * 0.25);
var randomBytes = sjclRandom.randomWords(wordCount, 10);
var hexString = sjcl.codec.hex.fromBits(randomBytes);
hexString = hexString.substr(0, size * 2);
return new Buffer(hexString, 'hex');
}
RNRandomBytes.randomBytes(length, function(err, base64String) {
if (err) {
cb(err);
} else {
cb(null, new Buffer(base64String, 'base64'));
}
});
};
The crux is, in order for the SJCL library to have sufficient entropy, it needs to have been seeded properly. So, on startup, we use the asynchronous CSPRNG functionality to seed the SJCL random number generator:
module.exports.randomBytes(4096, function(err, buffer) {
var hexString = buffer.toString('hex');
// we need to convert the hex string to bytes, or else SJCL assumes low entropy
var stanfordSeed = sjcl.codec.hex.toBits(hexString);
sjclRandom.addEntropy(stanfordSeed, 10, 'csprng');
});
Thus, we have a synchronous randomBytes method within React Native, provided we have had the opportunity to call it asynchronously at least once before we need its synchronous functionality.
Your solution does answer the question but seems a bit complex. In particular, why not use only SJCL?
In my case I've ended up using react-native-securerandom, which is just a thin wrapper over Android and iOS native calls. Then I've done this to initialise SJCL's RNG:
const { generateSecureRandom } = require('react-native-securerandom');
const sjcl = require('lib/vendor/sjcl');
const randomBytes = await generateSecureRandom(1024/8);
let temp = [];
for (let n in randomBytes) {
if (!randomBytes.hasOwnProperty(n)) continue;
temp.push(randomBytes[n].toString(16));
}
const hexSeed = sjcl.codec.hex.toBits(temp.join(''));
sjcl.random.addEntropy(hexSeed, 1024, 'generateSecureRandom');
`DT_MACHINE_START(MSM8974_DT, "Qualcomm MSM 8974 (Flattened Device Tree)")
.map_io = msm8974_map_io,
.init_irq = msm_dt_init_irq,
.init_machine = msm8974_init,
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm8974_dt_match,
.reserve = msm_8974_reserve,
.init_very_early = msm8974_init_very_early,
.restart = msm_restart,
.smp = &msm8974_smp_ops,
MACHINE_END`
This DT_MACHINE_START macro is there in one of board files for a Qualcomm chipset 8974.
My question is that how the control comes to this MACHINE START as ".init_machine" is getting called.
The Linux kernel creates an ARRAY using section magic and linker scripts and the boot loader must pass the key MSM8974_DT to Linux. Linux init code looks up the machine structure and calls these function pointers at appropriate times during initialization. See arch/arm/kernel/setup.c for the call location.
See similar: SO MACHINE_START macro. The current arch.h has definitions and vmlinux.lds.S has the linker section .init.arch.info.
How is control handed to the MACHINE START's ".init_machine"?
This call is from customize_machine in the current Linux source.
static int __init customize_machine(void)
{
/*
* customizes platform devices, or adds new ones
* On DT based machines, we fall back to populating the
* machine from the device tree, if no callback is provided,
* otherwise we would always need an init_machine callback.
*/
of_iommu_init();
if (machine_desc->init_machine)
machine_desc->init_machine(); /** HERE - calls your routine **/
#ifdef CONFIG_OF
else
of_platform_populate(NULL, of_default_bus_match_table,
NULL, NULL);
#endif
return 0;
}
The structure pointer machine_desc is matched earlier in the init code as above.
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.