Default DNS server in monotouch - ios

I'm wondering how do I get default DNS server in monotouch?
this code works perfectly in simulator, but gives 0 records on device.
NetworkInterface.GetAllNetworkInterfaces();
foreach (IPAddress ipAddr in ipProps.DnsAddresses)
Console.WriteLine(ipAddr);
from the other hand, this code works on both simulator and device:
IPHostEntry he = Dns.GetHostEntry(domain);
dns = he.HostName.ToString();
having all this, I assume DNS server address is stored somewhere. I mean it is accessible. How to get its IP?

This will get the IP Address in MonoTouch:-
public string GetIPAddress()
{
string address = "Not Connected";
try
{
#if SIM
address = IPAddress.FileStyleUriParser("127.0.0.1");
#else
string str = Dns.GetHostName() + ".local";
IPHostEntry hostEntry = Dns.GetHostEntry(str);
address = (
from addr in hostEntry.AddressList
where addr.AddressFamily == AddressFamily.InterNetwork
select addr.ToString()
).FirstOrDefault();
#endif
}
catch (Exception ex)
{
// Add error handling....
}
return address;
}
Note the difference between using the simulator and device.

I do not believe such an API exists on iOS (but I would be happy to be proven wrong). Other projects, that needs this information, relies on hacks like using well known, static address to DNS servers) to overcome this.
Now the reason code like this:
var all = NetworkInterface.GetAllNetworkInterfaces ();
foreach (NetworkInterface ni in all) {
var props = ni.GetIPProperties ();
foreach (var dns in props.DnsAddresses) {
Console.WriteLine (dns);
}
}
works on the simulator is because it's a simulator and not an emulator. IOW the host (Mac) computer allows far more things than a real iOS device will allow.
More precisely props will be an instance of System.Net.NetworkInformation.MacOsIPInterfaceProperties, which inherits from UnixIPInterfaceProperties, and ends up reading the /etc/resolv.conf file (which iOS disallow your application from reading).
The second case, calling Dns.GetHostEntry, goes down into the Mono runtime but end up calling gethostname which does not require the caller to know the DNS server address.

Related

How to get device IP in Dart/Flutter

I am currently writing an app where the user needs to know the IP address of their phone/tablet. Where would I find this information?
I only want to know what the local IP address is, such as, 192.168.x.xxx and NOT the public IP address of the router.
So far, I can only seem to find InternetAddress.anyIPv4 and InternetAddress.loopbackIPv4. The loopback address is not what I want as it is 127.0.0.1.
I guess you mean the local IP of the currently connected Wifi network, right?
EDITED
In this answer, I used to suggest using the NetworkInterface in 'dart:io', however NetworkInterface.list is not supported in all Android devices (as pointed out by Mahesh). The wifi package provides that, but later this was incorporated to the flutter's connectivity plugin. In Oct/2020 the methods for that were moved from the connectivity to the wifi_info_flutter plugin, and in 2021 that package was discontinued in favor of network_info_plus.
So just go for network_info_plus and call await NetworkInfo().getWifiIP().
By the way, you may also want to check if Wifi is available using the connectivity_plus plugin in flutter/plugins. Here's an example of how to check if wifi is available.
This provides the IP addresses of all interfaces
import 'dart:io';
...
Future printIps() async {
for (var interface in await NetworkInterface.list()) {
print('== Interface: ${interface.name} ==');
for (var addr in interface.addresses) {
print(
'${addr.address} ${addr.host} ${addr.isLoopback} ${addr.rawAddress} ${addr.type.name}');
}
}
}
See also
https://api.dartlang.org/stable/2.0.0/dart-io/NetworkInterface-class.html
I was searching for getting IP address in flutter for both the iOS and android platforms.
As answered by Feu and Günter Zöchbauer following works on only iOS platform
NetworkInterface.list(....);
this listing of network interfaces is not supported for android platform.
After too long search and struggling with possible solutions, for getting IP also on android device, I came across a flutter package called wifi, with this package we can get device IP address on both iOS and android platforms.
Simple sample function to get device IP address
Future<InternetAddress> get selfIP async {
String ip = await Wifi.ip;
return InternetAddress(ip);
}
I have tested this on android using wifi and also from mobile network.
And also tested on iOS device.
Though from name it looks only for wifi network, but it has also given me correct IP address on mobile data network [tested on 4G network].
#finally_this_works : I have almost given up searching for getting IP address on android and was thinking of implementing platform channel to fetch IP natively from java code for android platform [as interface list was working for iOS]. This wifi package saved the day and lots of headache.
It seems that Dart doesn't have a solution to get your own ip address. Searching for a solution I came across the rest api https://ipify.org to get my public address. Hope it helps.
Here is another way.
Future<InternetAddress> _retrieveIPAddress() async {
InternetAddress result;
int code = Random().nextInt(255);
var dgSocket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
dgSocket.readEventsEnabled = true;
dgSocket.broadcastEnabled = true;
Future<InternetAddress> ret =
dgSocket.timeout(Duration(milliseconds: 100), onTimeout: (sink) {
sink.close();
}).expand<InternetAddress>((event) {
if (event == RawSocketEvent.read) {
Datagram dg = dgSocket.receive();
if (dg != null && dg.data.length == 1 && dg.data[0] == code) {
dgSocket.close();
return [dg.address];
}
}
return [];
}).firstWhere((InternetAddress a) => a != null);
dgSocket.send([code], InternetAddress("255.255.255.255"), dgSocket.port);
return ret;
}
here, you can use this package https://pub.dev/packages/dart_ipify available on pub.dev,
import 'package:dart_ipify/dart_ipify.dart';
void main() async {
final ipv4 = await Ipify.ipv4();
print(ipv4); // 98.207.254.136
final ipv6 = await Ipify.ipv64();
print(ipv6); // 98.207.254.136 or 2a00:1450:400f:80d::200e
final ipv4json = await Ipify.ipv64(format: Format.JSON);
print(ipv4json); //{"ip":"98.207.254.136"} or {"ip":"2a00:1450:400f:80d::200e"}
// The response type can be text, json or jsonp
}
To get device connected network/WiFi IP you can use network_info_plus package.
For android add the following permissions ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION in the AndroidManifest.xml file
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
IOS permissions are a little more complicated so please read what is requested in the library.
Add package to pubspec.yaml
dependencies:
network_info_plus: ^1.0.2
Than you can get the current IP by executing
String? wifiIP = await NetworkInfo().getWifiIP();
In my recent app I have a requirement to get user's Ip address and then I found this packgage useful. https://pub.dev/packages/get_ip
Here is How I use it.
_onLoginButtonPressed() async {
String ipAddress = await GetIp.ipAddress;
print(ipAddress); //192.168.232.2
}
You can use the wifi package for getting the local IP Address (for eg. 192.168.x.x). (as The NetworkInterface.list (from dart:io) is no longer supporting Android from 7.0 and above).
Use the wifi package :
import 'package:wifi/wifi.dart';
You can retrieve the IP Address like this:
Future<String> getIp() async {
String ip = await Wifi.ip;
return ip;
}
You can display it on a Text widget using FutureBuilder:
FutureBuilder<String>(
future: getIp(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
if (snapshot.hasError)
return Center(child: Text('Error: ${snapshot.error}'));
else
return Center(child: Text('IP Address is : ${snapshot.data}')); //IP Address
}
},
);
Have you tried the device_info package?
There is an example on querying device information in https://pub.dartlang.org/packages/device_info#-example-tab-
You can use the network_info_plus plugin to get various info about the wifi connection
Eg:
import 'package:network_info_plus/network_info_plus.dart';
final NetworkInfo _networkInfo = NetworkInfo();
wifiIPv4Addr = await _networkInfo.getWifiIP();
For further refernce you can refer to the examples given under the official page
You can use the following package: https://pub.dev/packages/network_info_plus
And here is the page giving more detail about how to use the package https://plus.fluttercommunity.dev/docs/network_info_plus/usage/#using-network-info-plus
Essentially...if you have the package installed, you would use something like
import 'package:network_info_plus/network_info_plus.dart';
final info = NetworkInfo();
var wifiIP = await info.getWifiIP();
This package comes with some additional methods that could prove quite useful ;)
NOTE: This package is not supported on flutter web.
The flutter network_info_plus package provides access to Wifi information such as Wifi IP and name, but the problem is that it doesn't work when the phone HotSpot is on and the phone gets its IP from its own HotSpot.
The code below works for any condition and returns local IP whether it comes from phone HotSpot or another router:
import 'package:flutter/services.dart';
MethodChannel _channel = const MethodChannel('get_ip');
String ip = await _channel.invokeMethod('getIpAdress');
Node that in case you got No implementation found for method error, you should add get_ip package.
I hope it helps.
If we want to find the public facing IP address of a browser we can use dart_ipify The example in the documentation worked perfectly for me.
Import the package:
import 'package:dart_ipify/dart_ipify.dart';
Add this code to _incrementCounter():
final ipv4 = await Ipify.ipv4();
print(ipv4);

How can I set the Tor IP to a GeoLocation?

I'm building a bot therefore I want to use Tor. More, I want to set my Ip to chosen Geoloaction or Country. Is this possible?
Heres my Tor initializing code
public static void setUp() throws Exception {
//driver = new HtmlUnitDriver();
//driver = new FirefoxDriver();
String torPath = "/Applications/TorBrowser.app/Contents/MacOS/firefox";
String profilePath = "/Applications/TorBrowser.app/TorBrowser/Data/Browser/profile.default/";
FirefoxProfile profile = new FirefoxProfile(new File(profilePath));
FirefoxBinary binary = new FirefoxBinary(new File(torPath));
driver = new FirefoxDriver(binary, profile);
baseUrl = "https://qa2all.wordpress.com";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
All you have to do is edit the torrc config file used by the Browser Bundle (usually located at Browser/TorBrowser/Data/Tor) and add a config value like so:
ExitNodes {US}
Where US is the country code of the IP you want to use. You can specify multiples by comma separating them. Note: Country codes must be enclosed by {} in order to work. See the ExcludeNodes documentation for details on what's accepted.

NSNetService Resolve ipv6 that can not make an http request on it

Recently, i was facing a problem while resolving NSNetService.
I was published an NSNetService with type _http._tcp., to be just like an http server.
Other wise, on another device, i was start searching for this service, and it will find it.
After finding it, i was apply resolveWithTimeout on it.
While resolving, sometimes i was get only ipv6, that i can't make an HTTPRequest using NSURLConnection sendAsynchronousRequest: queue: completionHandler: on it.
How can i apply and HTTPRequest on url contains ipv6 ?
How can i deal with that problem ?
It looks like you're building a string like http://{IP}:{port}/ based on the information provided in NSNetService. And it works fine for an IPv4 address, the resulting string is like http://192.168.1.8:8080/.
However, IPv6 addresses use colons as a separator (instead of periods), so the same code generates a string like http://fe80::e31:db5a:0089:98ba:8080/, and the resulting address is incorrect. First, you need to wrap the address in square brackets: http://[fe80::e31:db5a:0089:98ba]:8080/. Second, fe80::/64 (as in the example) addresses are link-local and can be assigned to each IPv6-supporting interface, so you need to also provide the interface to use, e.g. http://[fe80::e31:db5a:0089:98ba%25en0]:8080/ where %25 is an encoded percent symbol and en0 is the interface name to use.
To sum up, you need to build different strings for IPv4 and IPv6 addresses. Speaking of which, there are Apple's recommendations:
As a rule, you should not resolve a service to an IP address and port number unless you are doing something very unusual.
– Connecting to a Bonjour Service by IP Address
Try to use this URL string if possible: http://{hostname}:{port}/, you won't need those extra IP address manipulations.
So this is what I end up using... it correctly translates address into URL including the interface:
NSString * result = nil;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int err;
err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
if (err == 0) {
struct sockaddr_storage *sockaddr = (struct sockaddr_storage *)address.bytes;
if (sockaddr->ss_family == AF_INET6) {
result = [NSString stringWithFormat:#"[%s]:%s", host, service];
} else if (sockaddr->ss_family == AF_INET) {
result = [NSString stringWithFormat:#"%s:%s", host, service];
}
}

Is there a better way to "lock" a Port as a semaphore in Dart than this example?

Is it possible in Dart to “lock” a Port other than by starting a server on that Port. In other words I guess, the Port is acting as a semaphore. Alternatively is there another way to achieve the same result?
I posted a question asking for a solution to this problem, and Fox32 suggested starting a server on a specific Port, and in that way determine if another instance of the program is already running. I need to determine the first instance to start actual processing rather than whether actually just running, and that solution works.
While that solution works well, it appears to me that there should be a more tailored solution. Example code is below:
/*
* Attempt to connect to specific port to determine if first process.
*/
async.Future<bool> fTestIfFirstInstance() {
async.Completer<bool> oCompleter = new async.Completer<bool>();
const String S_HOST = "127.0.0.1"; // ie: localhost
const int I_PORT = 8087;
HttpServer.bind(S_HOST, I_PORT).then((oHtServer) {
ogHtServer = oHtServer; // copy to global
oCompleter.complete(true); // this is the first process
return;
}).catchError((oError) {
oCompleter.complete(false); // this is NOT the first process
return;
});
return oCompleter.future;
}
This is often done by using a file, e.g. '/tmp/my_program.lock' or '~/.my_program.lock' depending on global or per-user lock.
I dart in would be as simple as:
bool isRunning() {
return new File(lockPath).existsSync();
}
Starting:
void createLock() {
if (isRunning()) throw "Lock file '$lockPath' exists, program may be running";
new File(lockPath).createSync();
}
And when closing the program:
void deleteLock() {
new File(lockPath).deleteSync();
}
Something to remember is that while the HttpServer will be closed when the program closes, the file won't be deleted. This can be worked around by writing the programs PID to the lock file when creating the file, and check if the PID is alive in isRunning. If it's not alive, delete the file and return false.
I'm unsure whether this (RawServerSocket) is any "better" than the HttpServer solution, however perhaps it makes more sense.
I think that a means to simply "lock" the Port and unlock the Port would be worthwhile. It provides a good means of using a semaphore IMHO.
/*
* Attempt to connect to specific port to determine if first process.
*/
async.Future<bool> fTestIfFirstInstance() {
async.Completer<bool> oCompleter = new async.Completer<bool>();
RawServerSocket.bind("127.0.0.1", 8087).then((oSocket) {
ogSocket = oSocket; // assign to global
oCompleter.complete(true);
}).catchError((oError) {
oCompleter.complete(false);
});
return oCompleter.future;
}

How to properly build HTTP connection suffix

I have written code to get a location name using Google Maps reverse geocoding, for example:
http://maps.google.com/maps/geo?json&ll=9.6,73.7
How can I add an appropriate HTTP connection suffix to the above URL?
I have tried the following function:
private static String getConnectionStringForGoogleMap(){
String connectionString="";
if(WLANInfo.getWLANState()==WLANInfo.WLAN_STATE_CONNECTED){
connectionString="&interface=wifi";
}
else if((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS){
connectionString = "&deviceside=false";
}
else if((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT)==CoverageInfo.COVERAGE_DIRECT){
String carrierUid=getCarrierBIBSUid();
if(carrierUid == null) {
connectionString = "&deviceside=true";
}
else{
connectionString = "&deviceside=false&connectionUID="+carrierUid + "&ConnectionType=mds-public";
}
}
else if(CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE)
{
}
return connectionString;
}
When I run the application in the simulator, I create the URL like this:
http://maps.google.com/maps/geo?json&ll=9.6,73.7+getConnectionStringForGoogleMap();
But I get a tunnel exception and am not sure what to do next.
This URL also leads to an exception:
http://maps.google.com/maps/geo?json&ll=9.6,73.7&deviceside=false&ConnectionType=mds-public
As does:
http://maps.google.com/maps/geo?json&ll=9.6,73.7;deviceside=false;ConnectionType=mds-public
I am confused about what to do to get this to work.
You definitely want semi-colons (;) and not ampersands (&). Are you tring to run this on the simulator? If so, do you have the MDS simulator running? That is required in order to use devicside=false on the simulator.
Try using Versatile Monkey's networking helper class to find the best path for your HTTP connection and avoid those tunnel exceptions. And form the URL with the correct syntax.
There is a very good posting about this on the BlackBerry Java development forum, complete with sample HTTP connection code.
Try using following
It worked for me
http://maps.google.com/maps/geo?json&ll=9.6,73.7&;deviceside=false;ConnectionType=mds-public
If you are targeting OS5 and above you can use ConnectionFactory. This takes a lot of the hard work out of establishing the correct connection type.

Resources