What's meaning of range start=range end in http response - android

When I try to analyse CDN download, some logs looks like below:
GET http://1234.apk?track=mmmmmmm range:bytes-sent=[500-500], content-length:1500 ...
In my understanding, range:bytes-sent represents continue download after break and it should have different number in bytes-sent, the followings are reasonable:
bytes-sent=[500-600]
bytes-sent=[500-]
bytes-sent=[-500]
but what meaning of range start = range end like [500-500]? It seems no data should be downloaded but generates http response.
Thanks first~

The bytes mentioned in the range are also sent. Hence if the server wants to only send the 500th byte, the server would send [500-500] as the bytes range. Have a look at https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p5-range-26 which has an example of how the first and last byte are sent :
o The first and last bytes only (bytes 0 and 9999):
bytes=0-0,-1

Related

FIDO2 - Get Authenticator Info issue

I am developing Android authenticator.I am getting {-125,0,1,4} byte array from webauthn client after pairing. When I decoding this array
-125 (0x83) - MSG
1 (0x01) - length of the data
4 (0x04) - AuthenticatorGetInfo
I am not sure about 0 in this array. Please let me know is there any meaning for this 0.
For this request, I am sending response as CBOR data.
00a60182684649444f5f325f30665532465f563202816b686d61632d73656372657403506435323965353235383533343133663304a462726bf5627570f564706c6174f469636c69656e7450696ef505190400069f01ff
I am notifying above data by using Fido Status as follows.
for (byte[] frame : response.toFrames(mMTU)) {
getFidoStatus().setValue(frame);
mGattServer.notifyCharacteristicChanged(device, getFidoStatus(), true);
}
After that I am not getting any request/response from webauthn client. I am sending KEEPALIVE(0x82) command with value PROCESSING(0x01) for every kKeepAliveMillis(500ms). Is there any issue with my implementation?
Please help me to proceed this. Thanks in advance.
This speciciation fully explains for you
https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ble-framing-fragmentation
CMD is 0x83 (MSG)
Length of DATA is 2 bytes: HLEN byte and LLEN byte.
In your case, length of DATA is 0x0001 (= 1). The DATA is 0x04

Mi Band 2 past data

I'm writing my thesis on how to obtain data from different fitness bands.
At the moment I'm doing some research on the Mi Band 2 using bluetooth connection with my PC, unfortunately BLE is a new field for me.
By looking at projects like Gadgetbridge or miband2-python-test I try to understand the protocol. I get how the authentication works and how to extract data like battery or time information. However, I don't understand the protocol to obtain past data, like the minutely steps from two days ago until now.
I would be pleased if someone could help me by giving a tip or explaining the steps of the protocol. Thanks in advance!
That's my code for now, as far as I understood the protocol:
UUID_CHAR_ACTIVITY_DATA = "00000005-0000-3512-2118-0009af100700"
UUID_CHAR_FETCH = "00000004-0000-3512-2118-0009af100700"
CCCD_UUID = 0x2902
class MiBand2(Peripheral):
[...]
self.char_activity_data = self.getCharacteristics(uuid=UUID_CHAR_ACTIVITY_DATA)[0]
self.char_fetch = self.getCharacteristics(uuid=UUID_CHAR_FETCH)[0]
self.cccd_fetch = self.char_fetch.getDescriptors(forUUID=CCCD_UUID)[0]
def fetch_activity_data(self):
# \x01\x01 key?
# \xe2\x07 2018 year
# \x05 month
# \x03 year
# \x11 hour
# \x2f minute
# \x00\x08 timezone
value = b'\x01\x01\xe2\x07\x05\x03\x11\x2f\x00\x08'
self.cccd_fetch.write(b'\x01\x00', False)
self.char_fetch.write(value_from_wireshark, False)
for i in range(30):
self.waitForNotifications(1.0)
class AuthenticationDelegate(DefaultDelegate):
[...]
def handleNotification(self, hnd, data):
[...]
if hnd == self.device.char_fetch.getHandle():
if data[:3] == b'\x10\x01\x01':
self.device.char_activity_data.write(b'\x01\x00', False)
# After \x02 I receive \x10\x02\x01 instead of fitness data as I thought
self.device.char_fetch.write(b'\x02', False)
It is need to analyze btsnoop_hci.log
On every 30 minute the device send a notification value 0x0e from 00000010-0000-3512-2118-0009af100700. Then you must start to take your past data. Firstly you need to enable notification descriptors for UUID_CHAR_ACTIVITY_DATA and so called UUID_CHAR_FETCH. Then you need to get count of packages from your last successful getting of data. So you send a value 0x0101+datatime+tz to UUID_CHAR_FETCH. The device response to you with value of 0x100101+packages_count+1st_package_datetimetz if no gaps the 1st_package_datetimetz is that you send previously. Now you need to start transfer past data, just send one byte value 0x02 to UUID_CHAR_FETCH and device will send notifications from UUID_CHAR_ACTIVITY_DATA. Every activity data notification value has a queue number in first byte and maximum 4 packages of data in remain bytes. Every single package of past data consists of 4 bytes and has this format: activity_type,intensity,steps,heart_rate. The device stores data for every minute. So usualy on every 0x0e event you will get 30 packages in 8 notification message values by 4 packages most of time. After the last notification got the device will send notification of success 0x100201 from UUID_CHAR_FETCH. I don't know why but it need to be done the last 3-rd step: send a single byte 0x03 to UUID_CHAR_FETCH then get success response 0x100301. This actualy all what you need but Mi Fit does bouble check for a new data packages, then gets zero count and then does last 3-rd step. Now it need to set notification descriptors off with value 0x0000. After all this your success synchronize datatime will be grater for count of past data packets you got * 60 seconds.
If you have response packages count = 0 after 0x0101 command the device will obviously send to you nothing after command 0x02 and then send success 0x100201 :)
I don't know what for 0x0102+datatimetz is. It always response packages count = 0 in my btsnoop_hci.logs.
I think it is not necessary to synchronize by 0x0e event.
https://gist.github.com/Roxxor91/0d3ff17153270e447d01e7afd0c54e0f

Android nfcA.connect(), nfcA.transceive(), nfcA.setTimeout() and nfcA.getMaxTransceiveLength()

I have a a number of newbie NfcA questions. There seems to be little guidance on this in the docs and elsewhere on the web, so I hope no-one minds me stringing a few basic questions together here...
I am using nfcA.transceive() to write data to my NTAG213 tag like this:
byte[] result = nfcA.transceive(new byte[] {
(byte)0xA2, // WRITE
(byte)(pageNum & 0x0ff),
myData[0], myData[1], myData[2], myData[3]
});
1. The result array is a single byte of value 10. What does this mean and what other values should I look out for?
I am also using the same method to read data from my NTAG213 tags:
byte[] result = nfcA.transceive(new byte[] {
(byte)0x30, // READ
(byte)(pageNum & 0x0ff)
});
2. I expected this to return 4 bytes of user data (i.e., the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so? (I ask as I have seen code examples from reputable sources of both.)
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
1. The result array for a WRITE command is a single byte of value 10. What does this mean and what other values should I look out for?
The value 10 (Ah in hexadecimal or 1010b in binary representation) is an explicit ACK, an acknowledgement returned when a command that returns no data succeeds.
The possible values are actual data, ACK, passive ACK, or NACK. These are defined by the NFC Forum Digital Protocol specification and by the NFC Forum Type 2 Tag Operation specification.
If the command is expected to return actual data on success, the data is returned instead of an explicit ACK value.
ACK is defined as a 4-bit short frame (see NFC Forum Digital Protocol specification and ISO/IEC 14443-3 for further details) with the value 1010b (Ah).
A passive ACK is defined as the tag not sending a response at all within a certain timeout.
NACK is defined as a 4-bit short frame with the value 0x0xb (where x is either 0 or 1).
The NTAG213/215/216 product data sheet is a bit more specific on possible NACK values:
0000b (0h) indicates an invalid command argument.
0001b (1h) indicates a parity or CRC error.
0100b (4h) indicates an invalid authentication counter overflow.
0101b (5h) indicates an EEPROM write error.
In addition to the above, the NFC stack implementations on some devices do not properly propagate NACK responses to the app. Instead they either throw a TagLostException or return null. Similarly, you might(?) get a TagLostException indicating a passive ACK.
Thus, you would typically check the result of the transceive method for the following (unless you send a command that is expected to result in a passive ACK):
try {
response = nfca.transceive(command);
if (response == null) {
// either communication to the tag was lost or a NACK was received
} else if ((response.length == 1) && ((response[0] & 0x00A) != 0x00A)) {
// NACK response according to Digital Protocol/T2TOP
} else {
// success: response contains ACK or actual data
}
} catch (TagLostException e) {
// either communication to the tag was lost or a NACK was received
}
2. I expected the READ method to to return 4 bytes of user data (i.e. the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
The READ command is defined to return 4 blocks of data starting with the specified block number (in the NFC Forum Type 2 Tag Operation specification). Thus, if you send a READ command for block 4, you get the data of blocks 4, 5, 6, and 7.
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so?
If you receive the Tag handle directly from the NFC system service (through an NFC intent) the tag won't be connected. So unless you use the Tag handle before calling nfca.connect(), I don't see why you would want to call nfca.isConnected() before. However, calling that method before connecting has barely any performance overhead since calling isConnected() on a closed tag technology object will be handled by the famework API without calling into the NFC system service. Hence, it's not much more overhead than a simple if over a boolean member variable of the NfcA object.
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
I'm not sure about that one. However, the transceive timeout is typically reset on disconnecting the tag technology.
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
No, you can only write one block at a time. This is limited by the WRITE command of the NTAG213, which only supports one block as data input.
However, a transceive buffer size of 253 allows you to use the FAST_READ command to read multiple blocks (up to 62, so up to 45 for the NTAG213) at a time:
int firstBlockNum = 0;
int lastBlockNum = 42;
byte[] result = nfcA.transceive(new byte[] {
(byte)0x3A, // FAST_READ
(byte)(firstBlockNum & 0x0ff),
(byte)(lastBlockNum & 0x0ff),
});

Sending image via bluetooth is split into packages

I modified the sample Bluetooth Chat application with a feature of sending image. I ran into a problem I can't figure out. The sample app needs a string to send and receive data. I am suing Base64 to convert the bitmaps to byte then to string so I could send the text with the selected image. If I send a small image (e.g. a fully black image with 4kb size) it is sent and received and displayed in the listview. But when I send larger images, they are split into many packages. This means, instead of one image, I get numerous texts, and the size of array I use to populate the listview will be anyhing more than 1, depending on the number of packages, so my listview is populated with a lot of text.
As it turns out, it depends on the size of the image. I experimented with many images. In case of a photo, whose length (as a string) is 50096, I get 51 packages on the receiver side. In case of another image, whose lenght is 77896, I get 81 packages. So I decided to try with a really small image. I created a black image in Paint, and it was succesfully sent and received. I measured it's length, which was 280. Then I experimented with a white image with a little yellow, which had a lenght of 980. That was also successfully sent. Then I added some black to the image which resulted in 1554 in length. This time I received a couple of texts instead of the image.
So my conclusion is that the length of string is restricted when sending data via Bluetooth, which may be obvious to someone who is familiar with the technology.
What can I do about this? If I knew the max number of characters that I can send in one package, I could calculate the number of packages on the sender side and I could concatenate all the packages on the receiver size.
I show you two images on the receiver side to demonstrate this behavious. The first one is the correct function, the second one is the wrong function:
Your problem is in the receiver portion, as can be found in this function from the bluetooth chat source code:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
Specifically, note the byte[] buffer = new byte[1024];. You are limited to only 1K. If you want to do more, you need to increase the size of the buffer, or build a method to detect that files are exceeding this buffer size.
A few things of note, should you design a protocol to handle this.
You shouldn't need to send this in base 64, the stream accepts binary just fine.
Put a header that includes the file type, packet number, and total number of packets. If you want to be really fancy, include a checksum of some sort, to verify the packet is intact.
You should include a mechanism to re-transmit missing packets.
You might want to send out an initial header, explaining what is coming.

HttpURLConnection readLine() hanging on Sprint 4G network

I have a routine that uses a HttpURLConnection to upload a file via a multipart/form-data content type. The server does some processing on the uploaded file and returns a short response code. This works fine in all cases so far except with one user with an HTC Evo when on 4G. If the user switches to 3G then everything works fine. When on 4G the app will wait on the while ((line = reader.readLine()) != null) { until a socket connection timeout exception is thrown. I have the connection timeout set to 70 seconds. The server is in php here is the relevant snippet
//all ob_ related entries were added because I found some info indicating
//that some clients would not acknowledge the response without the content-length header
ob_end_clean();
header("Connection: close");
ob_start();
...
//the response is one of either
echo "BACKGROUND"; //this one works!
//or
echo $rv //$rv = "1336757671374T37171FR"
//or
echo "FailedQA";
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
ob_flush();
flush();
die();
?>
Note that the 'BACKGROUND' response works, and the rest cause the client to sit until the timeout exception. I have currently 2 notions on this, but I am not in a 4G area so I can only test this through the end user and I really want to limit the number of attempts. My first thought is that the 'BACKGROUND' is slightly longer than the 'FailedQA', and while the other one is longer it has a numeric start. So maybe adding white space to the response would help? The other aspect is response time. The 'BACKGROUND' message is normally sent faster than the other ones. But, I do have a counter example here so I am not sire. Example: the 'BACKGROUND' message normally goes out within 15 to 20 seconds. The other messages are normally 30-40 seconds. However, I have one example where the '1336757671374T37171FR' style response went out in 24 seconds and was not received and one where the 'BACKGROUND' message went out in 27 seconds and was received.
So to sum up: This only happens on Sprint 4G. I suspect it might either be content length or response time that is causing the issue, but in both cases I have a counter example to the contrary. Except with the length case the one that is the longer counter example has a numeric beginning, so there's that.
It seems to be the delay before a response that was causing the problem. I used this guide Easy Parallel Processing in PHP to set up a multi-tasking php configuration. This way I have a script that just counts and echos the elapsed seconds while the other one does the job processing. The problem is now resolved.

Categories

Resources