I have successfully opened a connection using a RGenericAgent. I knwo would like to know how I can get the IP address that has been assigned to my phone. Any clues ?
This is the recurring question. The final answer is of course, listing them all using the following code:
Code:
// - assumes socket is already Open // - allocate from heap, because this is large structure TSoInetInterfaceInfo *inf = new TSoInetInterfaceInfo; if (inf == NULL) return KErrNoMemory; TPckg<TSoInetInterfaceInfo> opt(*inf); TInt err = socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl); if (err == KErrNone) { while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, inf) == KErrNone) { if (inf().iAddress.IsUnspecified()) { // Interface inf().iName has no address } else { // interface inf().iName has address inf().iAddress } } } delete inf;
Now, the question is which one do you use? When no interfaces are up, you only see the loopback addresses ("::" and 127.0.0.1).
Other addresses are only defined when one or more interface is up.
An interface can have multiple addresses.
If your application is such that it actually connects to something, connecting does not need the knowledge of own address. After connect has been succesfull, you can find the correct address from the connected socket.
If you are doing server application, you don't need to know your address either. Just use unspecified address. Of course, your server will not see anything from outside until some interface is up.
I have been using this code successfully on UIQ v2.x devices but it looks like it is not working on S60 v2 FP2 and S60 v2 FP3 (neither emulator nor devices).
I would be interested in the equivalent for these platforms....
Eric Bustarret
NewLC Founder & CEO / Professional Symbian OS Consultant
My mistake.... Reading the SDL give me the answer: TInetAddr::Output requires a buffer with at least 39 characters or fills the result with '*'. And that what I got....
Eric Bustarret
NewLC Founder & CEO / Professional Symbian OS Consultant
Has anyone tried the above with a UDP socket? I'm using the following: TInetAddr bound_ip; iSocket.LocalName(bound_ip); But on UDP at least, this works only after at least one packet has been sent...
Previously I've been using RHostResolver to retrieve the address for the name "" (empty string), but this stopped working on Symbian 8.0 phones, and is anyway problematic if the phones has more than one IP address (when connecting through more than one APN I think).
The answer why it works over TCP sooner than over UDP (i.e. without having to send a packet) is that you have to create a connection before sending any packets. And establishing a connection always results in the allocation of an IP address for your phone.
I recall that it was tricky to get the local IP address of the phone when using TCP, but not due to the complexity of the API method (it was something like RSocket::LocalAddress), but the timing. When RGenericAgent returned saying that "okay, connection is up", I still had to wait for a while until it was really up. Figuring out that "while" was tricky, when - as far as I remember, at least - it turned out that we had to wait for a special state change in the connection (used NitMan for monitoring) and after that we could get that piece of information in a jiffy.
Multiple IP addresses of a phone? Duhh, that I have never heard of. Is it in connection with multiple PDPs? Even then I can't imagine that a phone is having more than one IP address.
// Get the IAP id of the underlying interface of this RConnection //TUint32 iapId = 0; //User::LeaveIfError(conn.GetIntSetting(_L("IAP\\Id"), iapId));
// Get IP information from the socket TSoInetInterfaceInfo ifInfo; TPckg<TSoInetInterfaceInfo> ifInfoPkg(ifInfo); TSoInetIfQuery ifQuery; TPckg<TSoInetIfQuery> ifQueryPkg(ifQuery); // To find out which interfaces are using our current IAP, we must // enumerate and go through all of them and make a query by name for each. User::LeaveIfError(sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
ifQuery.iName = ifInfo.iName; TInt err = sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifQueryPkg); if( err == KErrNone && ifQuery.iZone[1] == g_iapId) { // IAP ID is index 1 of iZone // We have found an interface using the IAP we are interested in. //if( ifinfo.iAddress.Address() >0 ) if (!ifInfo.iAddress.IsUnspecified() && !ifInfo.iAddress.IsLoopback() && !ifInfo.iAddress.IsLinkLocal()) {
// found a IPv4 address aAddr = ifInfo.iAddress; aAddr.ConvertToV4(); aAddr.Output(aIP);
if (!ifInfo.iAddress.IsUnspecified() && !ifInfo.iAddress.IsLoopback() && !ifInfo.iAddress.IsLinkLocal())
This works in most cases, but sometimes you want to know a link-local address, i.e. a number of self-configured devices with no DHCP server present (not an unlikely scenario).
Ok, once you have gone through all that trouble, someone might find it useful to know following little information tidbits:
Code:
ifQuery.iZone[0]
is the interface index, which might come handy with multicast join/leave operations.
Code:
ifQuery.iZone[15]
is the network id (usually).
Code:
aAddr.ConvertToV4()
Loose this. There is no reason for it (all it does, is that if address happens to be IPv6, it gets lost). Don't cripple your applications unnecessarily for IPv6.
If you want to avoid IPv6 addresses, the test "addr.Address() > 0" is a pretty good filter. Address() returns 0 for IPv6 (but, of course it also returns 0 for "0.0.0.0" or if family is not KAfInet).
I have an application for a socket server. I use the following to find out what the local IP adddress is (to later make a call to bind to this same address).
On an emulator (S60_3rd_FP1_3), the above does not work. It goes twice through the loop, but the IAP-IDs and addresses it finds are always equal to 0. Why is this?
On the mobile phone it returns an IP address of the form 169.x.x.x, which normally means that the adddress is non-valid (however, from another phone or the emulator I can actually connect to the socket using this IP address).
On the other hand, the following code *does* find the local IP address on the emulator:
// Get info about local IP address RHostResolver hostResolver; hostResolver.Open(iSocketServ, KAfInet, KProtocolInetTcp, iConnection);
// - assumes socket is already Open
// - allocate from heap, because this is large structure
TSoInetInterfaceInfo *inf = new TSoInetInterfaceInfo;
if (inf == NULL)
return KErrNoMemory;
TPckg<TSoInetInterfaceInfo> opt(*inf);
TInt err = socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
if (err == KErrNone)
{
while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, inf) ==
KErrNone)
{
if (inf().iAddress.IsUnspecified())
{
// Interface inf().iName has no address
}
else
{
// interface inf().iName has address inf().iAddress
}
}
}
delete inf;
Now, the question is which one do you use? When no interfaces are up, you only see the loopback addresses ("::" and 127.0.0.1).
Other addresses are only defined when one or more interface is up.
An interface can have multiple addresses.
If your application is such that it actually connects to something, connecting does not need the knowledge of own address. After connect has been succesfull, you can find the correct address from the connected socket.
If you are doing server application, you don't need to know your address either. Just use unspecified address. Of course, your server will not see anything from outside until some interface is up.
replace all of "inf()." with "inf->", and the GetOpt parameter should be "opt", not "inf".
Forum posts: 2133
I would be interested in the equivalent for these platforms....
Eric Bustarret
NewLC Founder & CEO / Professional Symbian OS Consultant
Forum posts: 100
It works on all Symbian OS releases, at least it should.
Forum posts: 2133
Eric Bustarret
NewLC Founder & CEO / Professional Symbian OS Consultant
Forum posts: 50
goready
Forum posts: 5
I'm using the following:
TInetAddr bound_ip;
iSocket.LocalName(bound_ip);
But on UDP at least, this works only after at least one packet has been sent...
Previously I've been using RHostResolver to retrieve the address for the name "" (empty string), but this stopped working on Symbian 8.0 phones, and is anyway problematic if the phones has more than one IP address (when connecting through more than one APN I think).
Forum posts: 723
I recall that it was tricky to get the local IP address of the phone when using TCP, but not due to the complexity of the API method (it was something like RSocket::LocalAddress), but the timing. When RGenericAgent returned saying that "okay, connection is up", I still had to wait for a while until it was really up. Figuring out that "while" was tricky, when - as far as I remember, at least - it turned out that we had to wait for a special state change in the connection (used NitMan for monitoring) and after that we could get that piece of information in a jiffy.
Multiple IP addresses of a phone? Duhh, that I have never heard of. Is it in connection with multiple PDPs? Even then I can't imagine that a phone is having more than one IP address.
tOtE
Gabor Torok
Software architect, Agil Eight (http://www.agileight.com/)
Blog: http://mobile-thoughts.blogspot.com/
Forum posts: 5
I remember that at least since 2nd Edition the phone is a multi homed device.
You can have more then one connection active at the same time.
You can be connected to multiple Access Points, which with its own IP address.
So you don't have an IP address to the phone, but an IP address for each active interface on the phone.
Forum posts: 127
TInetAddr aAddr;
RSocket sock;
TBuf8<20> aIP8;
TBuf<20> aIP;
User::LeaveIfError(sock.Open(socketServ, KAfInet, KSockStream, KProtocolInetTcp));
// Get the IAP id of the underlying interface of this RConnection
//TUint32 iapId = 0;
//User::LeaveIfError(conn.GetIntSetting(_L("IAP\\Id"), iapId));
// Get IP information from the socket
TSoInetInterfaceInfo ifInfo;
TPckg<TSoInetInterfaceInfo> ifInfoPkg(ifInfo);
TSoInetIfQuery ifQuery;
TPckg<TSoInetIfQuery> ifQueryPkg(ifQuery);
// To find out which interfaces are using our current IAP, we must
// enumerate and go through all of them and make a query by name for each.
User::LeaveIfError(sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
while(sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifInfoPkg) == KErrNone) {
ifQuery.iName = ifInfo.iName;
TInt err = sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifQueryPkg);
if( err == KErrNone && ifQuery.iZone[1] == g_iapId)
{ // IAP ID is index 1 of iZone
// We have found an interface using the IAP we are interested in.
//if( ifinfo.iAddress.Address() >0 )
if (!ifInfo.iAddress.IsUnspecified() && !ifInfo.iAddress.IsLoopback() && !ifInfo.iAddress.IsLinkLocal())
{
// found a IPv4 address
aAddr = ifInfo.iAddress;
aAddr.ConvertToV4();
aAddr.Output(aIP);
aIP8.Copy(aIP);
strncpy(out,(char*)aIP8.Ptr(),aIP8.Length());
sock.Close();
return err; // stop & return KErrNone
}
}
else if( err !=KErrNone ) {
sock.Close();
return err; // return with error
}
} // while
sock.Close();
return KErrNotFound; // return with KErrNotFound
Regards,
Mateen Maldar
Mateen Maldar
Forum posts: 132
This works in most cases, but sometimes you want to know a link-local address, i.e. a number of self-configured devices with no DHCP server present (not an unlikely scenario).
Forum posts: 100
is the interface index, which might come handy with multicast join/leave operations.
is the network id (usually).
Loose this. There is no reason for it (all it does, is that if address happens to be IPv6, it gets lost). Don't cripple your applications unnecessarily for IPv6.
If you want to avoid IPv6 addresses, the test "addr.Address() > 0" is a pretty good filter. Address() returns 0 for IPv6 (but, of course it also returns 0 for "0.0.0.0" or if family is not KAfInet).
Forum posts: 24
I have an application for a socket server. I use the following to find out what the local IP adddress is (to later make a call to bind to this same address).
RSocket sock;
sock.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp);
iConnection.Open(iSocketServ));
iConnection.GetIntSetting(_L("IAP\\Id"), iapId));
TSoInetInterfaceInfo ifinfo;
TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
TSoInetIfQuery ifquery;
TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
while(sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
ifquery.iName = ifinfo.iName;
sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
if(ifquery.iZone[1] == iapId) {
if(ifinfo.iAddress.Address() > 0) {
aAddr = ifinfo.iAddress;
sock.Close();
return KErrNone;
}
}
}
sock.Close();
On an emulator (S60_3rd_FP1_3), the above does not work. It goes twice through the loop, but the IAP-IDs and addresses it finds are always equal to 0. Why is this?
On the mobile phone it returns an IP address of the form 169.x.x.x, which normally means that the adddress is non-valid (however, from another phone or the emulator I can actually connect to the socket using this IP address).
On the other hand, the following code *does* find the local IP address on the emulator:
// Get info about local IP address
RHostResolver hostResolver;
hostResolver.Open(iSocketServ, KAfInet, KProtocolInetTcp, iConnection);
TBuf<255> hostName;
hostResolver.GetHostName(hostName);
TNameEntry nameEntry;
hostResolver.GetByName(hostName, nameEntry);
TNameRecord nameRec = nameEntry();
TSockAddr sockAddr = nameRec.iAddr;
GetInetAddressL(sockAddr, aInetAddr);
Now, both on the emulator as on the mobile phone, I get an IP address of the form 192.x.x.x
I would like to know why one code works and the other doesn´t, since I have found both types of code on the internet presented as valid solutions.