Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppleTV3,1 'POST Photo' protocol Not Working anymore #157

Closed
loretoparisi opened this issue May 22, 2015 · 14 comments
Closed

AppleTV3,1 'POST Photo' protocol Not Working anymore #157

loretoparisi opened this issue May 22, 2015 · 14 comments
Assignees
Labels

Comments

@loretoparisi
Copy link

It seems that on AppleTV3,1 devices:

{
deviceid = "xxxxx";
features = "0x5A7FFFF7,0xE";
flags = 0x44;
model = "AppleTV3,1";
pi = "43f884bc-eb56-459d-a307-9cce844f86bf";
pk = 8b197524a8f78819b8e64b8d8cd4a70faec1b49317e517fb81f624628a313a39;
srcvers = "220.68";
vv = 2;
}

The 'Photo' protocol is not working anymore.
Media Control for "Video" and "Audio" works.

I's easy to test it. Just use the "Connect SDK Sampler" app against a AppleTV3,1 device and send a photo then.
The app will log an error:

2015-05-22 17:10:38.286 ConnectSDKSampler[8926:824787] display photo failure: A generic error occured

I get the same error using the old AirPlayKit ( r0th/AirplayKit#4 ), so it seems to be a Async Socket error from the AppleTV side to me.

The 'photo' protocol works fine with AirPlay compatible devices like "AirServer" ( http://www.airserver.com/ ).

Also, the "photo" protocol, works fine on AppleTV3,1 with Erica Sadun's AirFlick utility ( rica Sadun's AirFlick ). This seems very weird, since I assume this app is not updated from a while.

I add here that sending a photo image on Apple TV is sending a socket message like

NSData *imageData = haRetinaDisplay ? UIImageJPEGRepresentation(image, _imageQuality) : UIImagePNGRepresentation(image);
        NSUInteger length = [imageData length];
        NSString *message = [[NSString alloc] initWithFormat:@"PUT /photo HTTP/1.1\r\n"
                             "Content-Length: %@\r\n"
                             "Host: musiXmatch\r\n"
                             "User-Agent: MediaControl/1.0\r\n\r\n", @(length)];
        NSMutableData *messageData = [[NSMutableData alloc] initWithData:[message dataUsingEncoding:NSUTF8StringEncoding]];
        [messageData appendData:imageData];

with the image is of mime type jpeg or png.

Regarding ConnectSDK, the classes involved are AirPlayServiceHTTP.m and AirPlayServer.m

The image is sent by class method:

- (void) displayImageWithMediaInfo:(MediaInfo *)mediaInfo success:(MediaPlayerSuccessBlock)success failure:(FailureBlock)failure

The error that is trapped is a ConnectError and it has a status code of type ConnectStatusCode
that is not in the enum, so then you get here

default:
            if (details)
                errorMessage = [NSString stringWithFormat:@"A generic error occured: %@", details];
            else
                errorMessage = [NSString stringWithFormat:@"A generic error occured"];

in class method

+ (NSError *) generateErrorWithCode:(ConnectStatusCode)code andDetails:(id)details

This error is raised by AirPlayServiceHTTP.m in method:

- (int) sendCommand:(ServiceCommand *)command withPayload:(id)payload toURL:(NSURL *)URL

due to a HTTP response code not 200:

CTASIHTTPRequest *strongRequest = weakRequest;

        if (strongRequest.responseStatusCode == 200)
        {
//....OK
} else
        {
            if (command.callbackError)
                dispatch_on_main(^{ command.callbackError([ConnectError generateErrorWithCode:strongRequest.responseStatusCode andDetails:nil]); });
        }

where the HTTP Response status was 404 / Not Found.

Here are more debugging info about this request to AirServer

(lldb) po strongRequest.responseStatusCode
404
(lldb) po strongRequest.responseHeaders
{
    "Content-Length" = 0;
    Server = "AirTunes/220.68";
}
(lldb) po strongRequest.responseStatusMessage
HTTP/1.1 404 Not Found
@loretoparisi
Copy link
Author

Adding more info about AppleTV3,1 here:

macbookproloreto:TherePlay-master admin$ curl --verbose "http://192.168.2.112:7000/server-info"
* Hostname was NOT found in DNS cache
*   Trying 192.168.2.112...
* Connected to 192.168.2.112 (192.168.2.112) port 7000 (#0)
> GET /server-info HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 192.168.2.112:7000
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Fri, 22 May 2015 15:50:58 GMT
< Content-Length: 581
< Content-Type: text/x-apple-plist+xml
< 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>deviceid</key>
    <string>9C:20:7B:E6:70:18</string>
    <key>features</key>
    <integer>61647880183</integer>
    <key>macAddress</key>
    <string>xxxxxx</string>
    <key>model</key>
    <string>AppleTV3,1</string>
    <key>osBuildVersion</key>
    <string>12F69</string>
    <key>protovers</key>
    <string>1.0</string>
    <key>srcvers</key>
    <string>220.68</string>
    <key>vv</key>
    <integer>2</integer>
</dict>
</plist>
* Connection #0 to host 192.168.2.112 left intact

@loretoparisi
Copy link
Author

If I try to send the image using cURL, I can see a Black Screen on the TV, and that is what I get from AppleTV3,1

macbookproloreto:TherePlay-master admin$ curl --verbose -X PUT "http://192.168.2.112:7000/photo" --header "User-Agent: MediaControl/1.0" --header "X-Apple-Session-ID: 1bd6ceeb-fffd-456c-a09c-996053a7a08c" --header "X-Apple-AssetKey: F92F9B91-954E-4D63-BB9A-EEC771ADE6E8" --header "Content-Type: image/jpeg" --data-binary "@/Users/admin/Desktop/SPACE.JPG"
* Hostname was NOT found in DNS cache
*   Trying 192.168.2.112...
* Connected to 192.168.2.112 (192.168.2.112) port 7000 (#0)
> PUT /photo HTTP/1.1
> Host: 192.168.2.112:7000
> Accept: */*
> User-Agent: MediaControl/1.0
> X-Apple-Session-ID: 1bd6ceeb-fffd-456c-a09c-996053a7a08c
> X-Apple-AssetKey: F92F9B91-954E-4D63-BB9A-EEC771ADE6E8
> Content-Type: image/jpeg
> Content-Length: 61079
> Expect: 100-continue
> 
* Done waiting for 100-continue
< HTTP/1.1 200 OK
< Date: Fri, 22 May 2015 16:17:47 GMT
< Content-Length: 0
< 
* Connection #0 to host 192.168.2.112 left intact

Look at the cURL request:

curl --verbose -X PUT "http://192.168.2.112:7000/photo" \
 --header "User-Agent: MediaControl/1.0" \
--header "X-Apple-Session-ID: 1bd6ceeb-fffd-456c-a09c-996053a7a08c" \
--header "X-Apple-AssetKey: F92F9B91-954E-4D63-BB9A-EEC771ADE6E8" \
--header "Content-Type: image/jpeg" \
--data-binary "@/Users/admin/Desktop/SPACE.JPG"

The Content-Length header should not be necessary, anyways, nothing better happens with:

--header 'Content-Length: 61079'

@loretoparisi
Copy link
Author

I found out that Open Airplay PHP library works fine: https://github.com/jamesdlow/open-airplay

php airplay.php -h 192.168.2.112:7000 -p /Users/admin/Desktop/SPACE.JPG

but the Shell example has the same issue that mine ( openairplay/open-airplay#8 )

curl -D test.txt -X PUT --data-binary @$filename -H 'Connection: keep-alive' -H 'User-Agent: MediaControl/1.0' -H 'X-Apple-Transition: None' -H 'Content-Type:' -H 'Accept:' -H 'Host:' -H 'Expect:' http://192.168.2.112:7000/photo

The result is a black screen /disconnect.

For some reason the PHP library works fine: https://github.com/jamesdlow/open-airplay/blob/master/PHP/airplay.php

@eunikolsky
Copy link

@loretoparisi, thanks for investigation and comments! We'll try to reproduce and fix it.

@loretoparisi
Copy link
Author

Any news on this issue?

@eunikolsky eunikolsky self-assigned this Jun 2, 2015
@eunikolsky
Copy link

I'm testing this on AppleTV3,2 (A1469), OS 6.0.2 (6646.81.1). Works fine. I'll try to upgrade the OS if possible.

@eunikolsky
Copy link

I can reproduce it now on OS 7.2 (7512). @loretoparisi, do you have any ideas of what could be broken?

@eunikolsky eunikolsky added the bug label Jun 2, 2015
@eunikolsky
Copy link

OK, the problem is that ConnectSDK uses the POST method and open-airplay uses PUT, which is correct. I'll need to check it on Apple TV 2 too.

@eunikolsky eunikolsky modified the milestone: v 1.6 Jun 2, 2015
eunikolsky pushed a commit to eunikolsky/Connect-SDK-iOS-Core that referenced this issue Jun 3, 2015
eunikolsky pushed a commit to eunikolsky/Connect-SDK-iOS that referenced this issue Jun 3, 2015
eunikolsky pushed a commit that referenced this issue Jun 3, 2015
eunikolsky pushed a commit to ConnectSDK/Connect-SDK-iOS-Lite that referenced this issue Jun 3, 2015
@eunikolsky
Copy link

Fixed in e05bfb5 and ConnectSDK/Connect-SDK-iOS-Lite@5916ff3. Merged into dev.

@loretoparisi, thanks for the bug report.

@eunikolsky
Copy link

@loretoparisi, please confirm the fix.

@loretoparisi
Copy link
Author

thank you @eunikolsky going to check it out!

@loretoparisi
Copy link
Author

So I have tried the Sampler App with the dev branch.
I get this error:

2015-06-07 19:47:26.297 ConnectSDKSampler[8680:874431] display photo failure: A generic error occured: STATUS CODE 404 MESSAGE:HTTP/1.1 404 Not Found
HEADERS:{
"Content-Length" = 0;
Server = "AirTunes/220.68";
}

The 404 error was not related to the image url that it works: http://ec2-54-201-108-205.us-west-2.compute.amazonaws.com/samples/media/photo.jpg, so I assume it is the protocol as you stated.

In fact it was the POST method instead of PUT in the AirPlayServiceHTTP.m method

- (void) displayImageWithMediaInfo:(MediaInfo *)mediaInfo success:(MediaPlayerSuccessBlock)success failure:(FailureBlock)failure
{
    _assetId = [[CTGuid randomGuid] stringValue];

    NSString *commandPathComponent = @"photo";
    NSURL *commandURL = [self.service.serviceDescription.commandURL URLByAppendingPathComponent:commandPathComponent];

    ServiceCommand *command = [ServiceCommand commandWithDelegate:self target:commandURL payload:nil];
    command.HTTPMethod = @"POST"; // Here with PUT it works :)

Have you merged that file as well?

That said,
I was not able to make it working anyways through the cURL shell command and PUT HTTP method, but if this could be something different or related to that issue I cannot say.

curl --request PUT --data-binary @"/Users/admin/Desktop/SPACE.JPG" -H 'Content-Type: image/jpeg' -H 'Connection: Keep-Alive' -H 'Content-Length:61079' -H 'X-Apple-AssetKey: 3933d7e9-b340-4a9a-a2cb-e11b4294cefd61079' -H 'X-Apple-Session-ID: b4fa3c4b-749f-4520-9795-84e978fbe95b' http://10.0.1.2:7000/photo

@eunikolsky
Copy link

@loretoparisi, have you updated the core submodule? The current dev branch points to commit ConnectSDK/Connect-SDK-iOS-Core@3385d16, where this is fixed.

@loretoparisi
Copy link
Author

Yes, that was. I think we can close this issue.
Even if I'm not sure of the related issues, but those ones are related to other projects.
Keep going the good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants