1329
1329
data_transmitted(bytes_so_far, (int) soup_message.request_body.length);
1332
public void on_finished(Soup.Session session, Soup.Message msg) {
1333
assert(msg == soup_message);
1335
msg.wrote_body_data.disconnect(on_wrote_body_data);
1337
Spit.Publishing.PublishingError? error = null;
1338
switch (msg.status_code) {
1339
case Soup.KnownStatusCode.OK:
1340
case Soup.KnownStatusCode.CREATED: // HTTP code 201 (CREATED) signals that a new
1341
// resource was created in response to a PUT
1345
case EXPIRED_SESSION_STATUS_CODE:
1346
error = new Spit.Publishing.PublishingError.EXPIRED_SESSION(
1347
"OAuth Access Token has Expired. Logout user.", get_uri(), msg.status_code);
1350
case Soup.KnownStatusCode.CANT_RESOLVE:
1351
case Soup.KnownStatusCode.CANT_RESOLVE_PROXY:
1352
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1353
"Unable to resolve %s (error code %u)", get_uri(), msg.status_code);
1356
case Soup.KnownStatusCode.CANT_CONNECT:
1357
case Soup.KnownStatusCode.CANT_CONNECT_PROXY:
1358
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1359
"Unable to connect to %s (error code %u)", get_uri(), msg.status_code);
1363
// status codes below 100 are used by Soup, 100 and above are defined HTTP
1365
if (msg.status_code >= 100) {
1366
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1367
"Service %s returned HTTP status code %u %s", get_uri(),
1368
msg.status_code, msg.reason_phrase);
1370
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1371
"Failure communicating with %s (error code %u)", get_uri(),
1377
// All valid communication with Facebook involves body data in the response
1379
if (msg.response_body.data == null || msg.response_body.data.length == 0)
1380
error = new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
1381
"No response data from %s", get_uri());
1388
host_session.unmanage_message(this);
1392
1333
private class GraphQueryMessage : GraphMessageImpl {
1417
1358
public GraphUploadMessage(GraphSession host_session, string access_token,
1418
1359
string relative_uri, Spit.Publishing.Publishable publishable,
1419
bool suppress_titling) {
1360
bool suppress_titling, string? resource_privacy = null) {
1420
1361
base(host_session, Publishing.RESTSupport.HttpMethod.POST, relative_uri, access_token,
1421
1362
(publishable.get_media_type() == Spit.Publishing.Publisher.MediaType.VIDEO) ?
1422
1363
Endpoint.VIDEO : Endpoint.DEFAULT);
1365
// Video uploads require a privacy string at the per-resource level. Since they aren't
1366
// placed in albums, they can't inherit their privacy settings from their containing
1367
// album like photos do
1368
assert(publishable.get_media_type() != Spit.Publishing.Publisher.MediaType.VIDEO ||
1369
resource_privacy != null);
1424
1371
this.publishable = publishable;
1426
1373
// attempt to map the binary payload from disk into memory
1491
1441
private Soup.Session soup_session;
1492
1442
private string? access_token;
1493
private Gee.Set<GraphMessage> messages;
1443
private GraphMessage? current_message;
1495
1445
public GraphSession() {
1496
1446
this.soup_session = new Soup.SessionAsync();
1447
this.soup_session.request_unqueued.connect(on_request_unqueued);
1448
this.soup_session.timeout = 15;
1497
1449
this.access_token = null;
1498
this.messages = new Gee.HashSet<GraphMessage>();
1450
this.current_message = null;
1454
soup_session.request_unqueued.disconnect(on_request_unqueued);
1501
1457
private void manage_message(GraphMessage msg) {
1502
assert(!messages.contains(msg));
1458
assert(current_message == null);
1460
current_message = msg;
1507
1463
private void unmanage_message(GraphMessage msg) {
1508
assert(messages.contains(msg));
1464
assert(current_message != null);
1510
messages.remove(msg);
1466
current_message = null;
1469
private void on_request_unqueued(Soup.Message msg) {
1470
assert(current_message != null);
1471
GraphMessageImpl real_message = (GraphMessageImpl) current_message;
1472
assert(real_message.soup_message == msg);
1474
// these error types are always recoverable given the unique behavior of the Facebook
1475
// endpoint, so try again
1476
if (msg.status_code == Soup.KnownStatusCode.IO_ERROR ||
1477
msg.status_code == Soup.KnownStatusCode.MALFORMED ||
1478
msg.status_code == Soup.KnownStatusCode.TRY_AGAIN) {
1479
real_message.bytes_so_far = 0;
1480
soup_session.queue_message(msg, null);
1484
unmanage_message(real_message);
1485
msg.wrote_body_data.disconnect(real_message.on_wrote_body_data);
1487
Spit.Publishing.PublishingError? error = null;
1488
switch (msg.status_code) {
1489
case Soup.KnownStatusCode.OK:
1490
case Soup.KnownStatusCode.CREATED: // HTTP code 201 (CREATED) signals that a new
1491
// resource was created in response to a PUT
1495
case EXPIRED_SESSION_STATUS_CODE:
1496
error = new Spit.Publishing.PublishingError.EXPIRED_SESSION(
1497
"OAuth Access Token has Expired. Logout user.", real_message.get_uri(), msg.status_code);
1500
case Soup.KnownStatusCode.CANT_RESOLVE:
1501
case Soup.KnownStatusCode.CANT_RESOLVE_PROXY:
1502
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1503
"Unable to resolve %s (error code %u)", real_message.get_uri(), msg.status_code);
1506
case Soup.KnownStatusCode.CANT_CONNECT:
1507
case Soup.KnownStatusCode.CANT_CONNECT_PROXY:
1508
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1509
"Unable to connect to %s (error code %u)", real_message.get_uri(), msg.status_code);
1513
// status codes below 100 are used by Soup, 100 and above are defined HTTP
1515
if (msg.status_code >= 100) {
1516
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1517
"Service %s returned HTTP status code %u %s", real_message.get_uri(),
1518
msg.status_code, msg.reason_phrase);
1520
error = new Spit.Publishing.PublishingError.NO_ANSWER(
1521
"Failure communicating with %s (error code %u)", real_message.get_uri(),
1527
// All valid communication with Facebook involves body data in the response
1529
if (msg.response_body.data == null || msg.response_body.data.length == 0)
1530
error = new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
1531
"No response data from %s", real_message.get_uri());
1534
real_message.completed();
1536
real_message.failed(error);
1513
1539
public void authenticate(string access_token) {
1514
1540
this.access_token = access_token;
1589
1615
string resource_uri =
1590
1616
(publishable.get_media_type() == Spit.Publishing.Publisher.MediaType.PHOTO) ?
1591
1617
"/%s/photos".printf(publishing_params.get_target_album_id()) : "/me/videos";
1618
string? resource_privacy =
1619
(publishable.get_media_type() == Spit.Publishing.Publisher.MediaType.VIDEO) ?
1620
publishing_params.privacy_object : null;
1592
1621
GraphMessage upload_message = session.new_upload(resource_uri, publishable,
1593
publishing_params.strip_metadata);
1622
publishing_params.strip_metadata, resource_privacy);
1595
1624
upload_message.data_transmitted.connect(on_chunk_transmitted);
1596
1625
upload_message.completed.connect(on_message_completed);