Coap server resources discovery - android

I am using the californium library for coap communication and it is being deployed on the Android platform. I have started coap server in one device and the client is on another device, both are in the same network.
Server code :
Creating a server with below resource
class HelloWorldResource extends CoapResource {
public HelloWorldResource() {
// set resource identifier
super("hello");
// set display name
getAttributes().setTitle("Hello-World Resource");
}
#Override
public void handleGET(CoapExchange exchange) {
// respond to the request
exchange.respond("Hello Android!");
}
}
Client code :
CoapClient coapClient = new CoapClient("coap://localhost/.well-known/core");
try {
Set<WebLink> webLinks = coapClient.discover();
System.out.println(webLinks.size());
} catch (ConnectorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
no output from the above code. I don't know the IP address and I want to communicate with the server. is this the right way or I am missing something?

A "discover" is a special coap request, to discover the resources of a known host.
To discover the host, a mutlicast request may be used, but must be supported by the server.
"localhost" is the address of the device itself. With that, the device will send the discover-request to itself.
I don't know the IP address and I want to communicate with the server.
If you dont't know the address, you might either use a "multicast" request first (requires also preparation on the server side, see MulticastServer Example. That example is more complex, than you will need. But demonstrates the principles as well). Or you need to lookup that address (android: settings -> Connections -> WLAN -> Settings-Icon : there you see your IP-address.
coapClient.discover()
Discovers a "known" server, not the local-network. Replace the localhost with "californium.eclipseprojects.io" and you will get:
</.well-known/core>
</large> Large resource
rt: [block]
sz: [1280]
</large-create> Large resource that can be created using POST method
rt: [block]
</large-post> Handle POST with two-way blockwise transfer
rt: [block]
</large-separate> Large resource
rt: [block]
sz: [1280]
</large-update> Large resource that can be updated using PUT method
rt: [block]
sz: [1280]
</link1> Link test resource
rt: [Type1, Type2]
if: [If1]
</link2> Link test resource
rt: [Type2, Type3]
if: [If2]
</link3> Link test resource
rt: [Type1, Type3]
if: [foo]
</location-query> Perform POST transaction with responses containing several Location-Query options (CON mode)
</multi-format> Resource that exists in different content formats (text/plain utf8 and application/xml)
ct: [0, 41, 50, 60]
</obs> Observable resource which changes every 5 seconds
rt: [observe]
obs: []
</obs-large> Observable resource which changes every 5 seconds
rt: [observe]
obs: []
</obs-non> Observable resource which changes every 5 seconds
rt: [observe]
obs: []
</obs-pumping> Observable resource which changes every 5 seconds
rt: [observe]
obs: []
</obs-pumping-non> Observable resource which changes every 5 seconds
rt: [observe]
obs: []
</obs-reset>
</path> Hierarchical link description entry
ct: [40]
</path/sub1> Hierarchical link description sub-resource
</path/sub2> Hierarchical link description sub-resource
</path/sub3> Hierarchical link description sub-resource
</query> Resource accepting query parameters
</seg1> Long path resource
</seg1/seg2> Long path resource
</seg1/seg2/seg3> Long path resource
</separate> Resource which cannot be served immediately and which cannot be acknowledged in a piggy-backed way
</shutdown>
</test> Default test resource
</validate> Resource which varies
ct: [0]
sz: [20]
All the received links are relative to the server you send the discover to.

Related

iccOpenLogicalChannel returns STATUS_NO_SUCH_ELEMENT on Javacard Applet

I have an applet (taken from this HelloSTK2 repo) I've compiled and installed on a SysmoISIM-SJA2 card and I've lightly modified it to respond to a SELECT APDU. The modification looks like this:
public void process(APDU arg0) throws ISOException {
showHello();
}
private void showHello() {
ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
proHdlr.initDisplayText((byte)0, DCS_8_BIT_DATA, welcomeMsg, (short)0,
(short)(welcomeMsg.length));
proHdlr.send();
return;
}
All I did was move the existing showHello() function to the function that handles APDUs. It's my understanding from the Javacard documentation that the process() function should run and then return a status word of 9000, or an error code if applicable.
To SELECT the file I have an Android application I've written that uses iccOpenLogicalChannel and takes the AID as an argument. Using GlobalPlatformPro I can see that the applet is installed properly on the UICC and that it is listed as SELECTABLE, however when I run my Android application I get a STATUS_NO_SUCH_ELEMENT response which according to the iccOpenLogicalChannelResponse source means the AID is not found on the UICC.
The code for the Android app is very simple and looks like this:
val inputView: EditText = findViewById<EditText>(R.id.AID_INPUT)
val input: String = inputView.text.toString()
val ch = mTelephonyManager.iccOpenLogicalChannel(input)
Toast.makeText(this, ch.toString(), Toast.LENGTH_LONG).show()
mTelephonyManager.iccCloseLogicalChannel(ch.channel)
and the output of listing the applets on the card looks like this (truncated):
AID: d07002ca44, State: 01, Privs: 00
Instance AID: d07002ca44900102
I've tried both d07002ca44 and d07002ca44900102 and get the same response for both AIDs.
My question then: what steps do I need to take to ensure this applet is able to be selected by my Android application?
Worth noting probably that my Android app does have carrier privileges and I'm able to send APDUs to other applications such as the USIM and ISIM applets.

gRPC Android Client losing connection "too many pings"

Android grpc client is receiving GOAWAY from server with "too many pings" error. Now I realise that this is probably a server side issue, but I think the issue is that the client channel settings do not match that of the servers.
I have a C# gRPC server with the following settings:
List<ChannelOption> channelOptions = new List<ChannelOption>();
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS",
1000));
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA", 0));
channelOptions.Add(new
ChannelOption("GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS", 1));
this.server = new Server(channelOptions) {
Services = { TerminalService.BindService(this) },
Ports = {new ServerPort("0.0.0.0", 5000,
ServerCredentials.Insecure)}
};
On Android I have the following channel setup:
private val channel = ManagedChannelBuilder.forAddress(name, port)
.usePlaintext()
.keepAliveTime(10, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true)
.build()
After a few min (however seems to be a random time). I get the goaway error. I noticed that if I stream data on the call then the error never happens. It is only when there is no data on the stream. This leads me to believe the issue is that the GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA needs to be set on the Android client aswell. Problem is for the life of me I cannot find where to set these channel settings on gRPC java. Can someone point out to me where I can set these channel settings? There are no examples where these have been set.
The channel options being specified are using the wrong names. Names like GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA are the C-defines for things like "grpc.http2.max_pings_without_data".
You can map from the C name to the key string by looking at grpc_types.h. You should prefer using one of the C# constants in ChannelOptions when it is available, but that doesn't seem to be an option in this case.
These options are not visible in the Java ManagedChannelBuilder API because they are server-specific settings. So instead they are visible on the ServerBuilder. See A8 client-side keepalive for reference to the Java keepalive API.

Obtaining data from my TP-Link router programmatically

I'm trying to design an app that can communicate with my router programmatically using the same endpoints as the web interface (there's a demo on TP-Link's website). My router is a TP-Link TD-W8980, if that matters.
The format appears to be very difficult to decipher. Here is a request which obtains the data for the status part of my app. This can obtain a valid response from the router but I'm not sure why!
I'm especially confused by the #0,0,0,0,0,0#0,0,0,0,0,0] part of the response. It's the only part I haven't managed to work out but I think I recall reading it's to do with the stack?!?
[SYS_MODE#0,0,0,0,0,0#0,0,0,0,0,0]0,1
mode
[LAN_HOST_CFG#1,0,0,0,0,0#0,0,0,0,0,0]1,1
DNSServers
[WAN_DSL_INTF_CFG#1,0,0,0,0,0#0,0,0,0,0,0]2,8
upstreamCurrRate
downstreamCurrRate
upstreamMaxRate
downstreamMaxRate
upstreamNoiseMargin
downstreamNoiseMargin
upstreamAttenuation
downstreamAttenuation
[IGD_DEV_INFO#0,0,0,0,0,0#0,0,0,0,0,0]3,3
softwareVersion
hardwareVersion
upTime
[LAN_IP_INTF#0,0,0,0,0,0#0,0,0,0,0,0]4,2
IPInterfaceIPAddress
X_TPLINK_MACAddress
[LAN_HOST_ENTRY#0,0,0,0,0,0#0,0,0,0,0,0]5,4
leaseTimeRemaining
MACAddress
hostName
IPAddress
[WAN_PPP_CONN#0,0,0,0,0,0#0,0,0,0,0,0]6,4
enable
connectionStatus
externalIPAddress
DNSServers
If it helps, the names in capitals (e.g. SYS_MODE) is the name of the section. The number after the ] is a counter stating the section number (sections can be in any order). The final number following the , is the number of parameters that follow in this section.
There are also request types for each section. In the example above, the URL is http://192.168.1.1/cgi?1&1&1&1&5&5&5. As you can see the two main request types are 1 and 5.
Here is an example response from the server. As you can see, some of the sections can be returned more than once, which makes the first number of the six zeros increment each time.
[0,0,0,0,0,0]0
mode=DSL
[1,0,0,0,0,0]1
DNSServers=x.x.x.x,x.x.x.x
[1,0,0,0,0,0]2
upstreamCurrRate=928
downstreamCurrRate=3072
upstreamMaxRate=1068
downstreamMaxRate=3104
upstreamNoiseMargin=60
downstreamNoiseMargin=57
upstreamAttenuation=295
downstreamAttenuation=546
[0,0,0,0,0,0]3
softwareVersion=0.6.0 1.3 v000e.0 Build 131012 Rel.51720n
hardwareVersion=TD-W8980 v1 00000000
upTime=x
[1,1,0,0,0,0]4
IPInterfaceIPAddress=192.168.1.1
X_TPLINK_MACAddress=xx:xx:xx:xx:xx:xx
[1,0,0,0,0,0]5
leaseTimeRemaining=-1
MACAddress=xx:xx:xx:xx:xx:xx
hostName=X
IPAddress=192.168.1.2
[2,0,0,0,0,0]5
leaseTimeRemaining=-1
MACAddress=xx:xx:xx:xx:xx:xx
hostName=X
IPAddress=192.168.1.4
[3,0,0,0,0,0]5
leaseTimeRemaining=-1
MACAddress=xx:xx:xx:xx:xx:xx
hostName=X
IPAddress=192.168.1.11
[4,0,0,0,0,0]5
leaseTimeRemaining=-1
MACAddress=xx:xx:xx:xx:xx:xx
hostName=X
IPAddress=192.168.1.5
[1,2,1,0,0,0]6
enable=1
connectionStatus=Connected
externalIPAddress=x.x.x.x
DNSServers=x.x.x.x,x.x.x.x
[2,1,1,0,0,0]6
enable=0
connectionStatus=Unconfigured
externalIPAddress=0.0.0.0
DNSServers=0.0.0.0,0.0.0.0
[3,1,1,0,0,0]6
enable=0
connectionStatus=Unconfigured
externalIPAddress=0.0.0.0
DNSServers=0.0.0.0,0.0.0.0
[error]0
I would appreciate any explanation of this format and if it appears anywhere else on the web. I've never seen such a system before!

Receiving hexadecimal values from socket instead of strings on SocketServer

I opened a socket between an Android app and a python server. The combination is that the Server listens, and android connects to the Server.
Here is the server code. The problematic part takes place in the definition of handle :
import SocketServer
from time import sleep
import sys
HOST = '192.168.56.1'
PORT = 2000
class SingleTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
try:
while(1):
sleep(0.03)
data = self.rfile.readline().strip()
print data
except KeyboardInterrupt:
sys.exit(0)
class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
server = SimpleServer((HOST, PORT), SingleTCPHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
sys.exit(0)
The connection is established normally, and the Android app sends the following data to the socket:
'0:0'
But the data is received on the Server as:
'\x000\x00:\x000\x00'
The variable that receives the data is:
data = self.rfile.readline().strip()
and printing gives the regular format:
In [2]: print data
0:0
I didn't manage to step into the print function with pdb to see what it does.
I'm looking for a way to convert the '\x000\x00:\x000\x00' to '0:0'.
Please advise on a way to convert the variable. You are welcome to comment/criticize the whole implementation. This is my first project in dealing with sockets so i don't know the pitfalls.
Update
This was the original Android code:
String podaci = "0:0";
public void Socketic() throws IOException {
Socket mojSocket = new Socket(urlServer, port);
DataOutputStream izlazdata = new DataOutputStream(
mojSocket.getOutputStream());
while (podaci != "end") {
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
izlazdata.writeChars(podaci);
izlazdata.flush();
}
izlazdata.close();
mojSocket.close();
};
And the problem was, as you suspected in:
izlazdata.writeChars(podaci);
writeChars uses the method writeChar. The API documentation for writeChar states:
Writes a char to the underlying output stream as a 2-byte value, high byte first...
The two bytes represent the 16bits which UTF-16 uses for encoding.
When we changed it to everything started working:
izlazdata.writeBytes(podaci);
Update
Based on the answers given, here is how the unwanted string is to be interpreted in terms of characters.
This solves my concrete problem, however, if someone would give a more generic solution to what happend here so that a larger lesson can be learned.
If not, i will accept Esailijas answer in a few days.
You need to show the code happening Android but it strongly seems like it's sending data in UTF-16BE. You should specify the encoding on the Android end. The characters are not hexadecimal literally, but because the NUL character is unprintable, python shows \x00 instead.
Another option is to decode it:
self.rfile.readline().decode("utf_16_be").strip()
note that the result of this is an unicode string.

Android URLConnection class cannot get content lenght using 3G internet connection

I've got the following piece of code:
URL url = new URL("http://myserver.com/getFile.php");
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
Everything works fine until I work with WiFi connection. If I try to run this code when there is only GPRS/3G connection available, conexion.getContentLength() returns -1.
Any idea why?
EDIT:
I've check the headers using getHeaderFields(). They are different if I use 3G network. Basically there is no Content-Length in this case. Any idea why server returns different headers? I'm not using any special script to provide the file, I only get the file that is placed at given location.
Entire header for the WiFi case:
{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Length=[628254], Content-Type=[text/plain; charset=UTF-8], Date=[Tue, 29 Nov 2011 11:22:50 GMT], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[Fri, 14 Oct 2011 09:52:52 GMT], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2.9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0]}
Entire header for the case when using 3G:
{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Type=[text/plain; charset=UTF-8], Date=[Tue, 29 Nov 2011 11:20:33 GMT], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[Fri, 14 Oct 2011 09:52:52 GMT], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2.9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0], Transfer-Encoding=[chunked], Warning=[214 warkaz-fe07 "Transformation applied"]}
Are you sure that the server provides the content length by sending the Content-Length header in the response?
From the headers it's clear that your provider has some kind of proxy in place that does a transformation, stripping the content-length in the process. The warning header clearly indicates this. You could try returning a different type of content type (you are now getting text/plain), maybe this particular proxy won't touch it. It's not a great solution of course, there are a lot things carriers may have to "optimize" their network in some way.
You could also try a HEAD request using a range header to get a ballpark of the content size. In that case you'd guess a few ranges, like 100k, 1000k etc to see if the server thinks that's an acceptable range. You could use that fake range for your progress. Again, this isn't a very good solution but if you really need the progress, it's something to try.
In the end it's best to just show the progress as unknown if there's no length known.
Since you are using
new URL("http://myserver.com/getFile.php");
I suppose you are using a personal server that you have set up, and when using WiFi your phone is in your local network and thereby can see your server, but when you are trying to connect via GPRs/3G you are trying to access your local server from the internet.
It is probably due to a limitation from your carrier. Try to avoid needing this value. (for example, by reading the inputStream until you cannot read it).

Categories

Resources