15dc0f0a4SBarry Smith #include <petscwebclient.h> 21c7e414eSJacob Faibussowitsch PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wdeprecated-declarations") 35dc0f0a4SBarry Smith 45dc0f0a4SBarry Smith /* 55dc0f0a4SBarry Smith Encodes and decodes from MIME Base64 65dc0f0a4SBarry Smith */ 79371c9d4SSatish Balay static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 89371c9d4SSatish Balay 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; 95dc0f0a4SBarry Smith 10d71ae5a4SJacob Faibussowitsch static PetscErrorCode base64_encode(const unsigned char *data, unsigned char *encoded_data, size_t len) 11d71ae5a4SJacob Faibussowitsch { 12f5b927afSBarry Smith static size_t mod_table[] = {0, 2, 1}; 13f5b927afSBarry Smith size_t i, j; 145dc0f0a4SBarry Smith size_t input_length, output_length; 155dc0f0a4SBarry Smith 165dc0f0a4SBarry Smith PetscFunctionBegin; 179566063dSJacob Faibussowitsch PetscCall(PetscStrlen((const char *)data, &input_length)); 185dc0f0a4SBarry Smith output_length = 4 * ((input_length + 2) / 3); 1908401ef6SPierre Jolivet PetscCheck(output_length <= len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Output length not large enough"); 205dc0f0a4SBarry Smith 215dc0f0a4SBarry Smith for (i = 0, j = 0; i < input_length;) { 225dc0f0a4SBarry Smith uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; 235dc0f0a4SBarry Smith uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; 245dc0f0a4SBarry Smith uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; 255dc0f0a4SBarry Smith uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; 265dc0f0a4SBarry Smith 275dc0f0a4SBarry Smith encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; 285dc0f0a4SBarry Smith encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; 295dc0f0a4SBarry Smith encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; 305dc0f0a4SBarry Smith encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; 315dc0f0a4SBarry Smith } 325dc0f0a4SBarry Smith encoded_data[j] = 0; 335dc0f0a4SBarry Smith for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[output_length - 1 - i] = '='; 343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 355dc0f0a4SBarry Smith } 365dc0f0a4SBarry Smith 37d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data, unsigned char *decoded_data, size_t length) 38d71ae5a4SJacob Faibussowitsch { 395dc0f0a4SBarry Smith static char decoding_table[257]; 405dc0f0a4SBarry Smith static int decode_table_built = 0; 41c1f4622dSBarry Smith size_t i, j; 425dc0f0a4SBarry Smith size_t input_length, output_length; 435dc0f0a4SBarry Smith 445dc0f0a4SBarry Smith PetscFunctionBegin; 455dc0f0a4SBarry Smith if (!decode_table_built) { 465dc0f0a4SBarry Smith for (i = 0; i < 64; i++) decoding_table[(unsigned char)encoding_table[i]] = i; 475dc0f0a4SBarry Smith decode_table_built = 1; 485dc0f0a4SBarry Smith } 495dc0f0a4SBarry Smith 509566063dSJacob Faibussowitsch PetscCall(PetscStrlen((const char *)data, &input_length)); 5108401ef6SPierre Jolivet PetscCheck(input_length % 4 == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input length must be divisible by 4"); 525dc0f0a4SBarry Smith 535dc0f0a4SBarry Smith output_length = input_length / 4 * 3; 545dc0f0a4SBarry Smith if (data[input_length - 1] == '=') (output_length)--; 555dc0f0a4SBarry Smith if (data[input_length - 2] == '=') (output_length)--; 5608401ef6SPierre Jolivet PetscCheck(output_length <= length, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Output length too shore"); 575dc0f0a4SBarry Smith 585dc0f0a4SBarry Smith for (i = 0, j = 0; i < input_length;) { 595dc0f0a4SBarry Smith uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 605dc0f0a4SBarry Smith uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 615dc0f0a4SBarry Smith uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 625dc0f0a4SBarry Smith uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 635dc0f0a4SBarry Smith uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); 645dc0f0a4SBarry Smith 655dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; 665dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; 675dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; 685dc0f0a4SBarry Smith } 695dc0f0a4SBarry Smith decoded_data[j] = 0; 703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 715dc0f0a4SBarry Smith } 725dc0f0a4SBarry Smith 735dc0f0a4SBarry Smith #if defined(PETSC_HAVE_UNISTD_H) 745dc0f0a4SBarry Smith #include <unistd.h> 755dc0f0a4SBarry Smith #endif 765dc0f0a4SBarry Smith 775dc0f0a4SBarry Smith /*@C 785dc0f0a4SBarry Smith PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests 795dc0f0a4SBarry Smith 80*20f4b53cSBarry Smith Not Collective, only the first process in `MPI_Comm` does anything 815dc0f0a4SBarry Smith 825dc0f0a4SBarry Smith Input Parameters: 835dc0f0a4SBarry Smith + comm - the MPI communicator 845dc0f0a4SBarry Smith - tokensize - size of the token array 855dc0f0a4SBarry Smith 865dc0f0a4SBarry Smith Output Parameters: 87811af0c4SBarry Smith . access_token - can be used with `PetscGlobusUpLoad()` for 30 days 885dc0f0a4SBarry Smith 89*20f4b53cSBarry Smith Level: intermediate 90*20f4b53cSBarry Smith 9195452b02SPatrick Sanan Notes: 92*20f4b53cSBarry Smith This call requires `stdout` and `stdin` access from process 0 on the MPI communicator 935dc0f0a4SBarry Smith 94c4762a1bSJed Brown You can run src/sys/webclient/tutorials/globusobtainaccesstoken to get an access token 955dc0f0a4SBarry Smith 96db781477SPatrick Sanan .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()` 975dc0f0a4SBarry Smith @*/ 98d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm, char access_token[], size_t tokensize) 99d71ae5a4SJacob Faibussowitsch { 1005dc0f0a4SBarry Smith SSL_CTX *ctx; 1015dc0f0a4SBarry Smith SSL *ssl; 1025dc0f0a4SBarry Smith int sock; 1035dc0f0a4SBarry Smith char buff[8 * 1024], *ptr, head[1024]; 1045dc0f0a4SBarry Smith PetscMPIInt rank; 1055dc0f0a4SBarry Smith size_t len; 1065dc0f0a4SBarry Smith PetscBool found; 1075dc0f0a4SBarry Smith 1085dc0f0a4SBarry Smith PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 110dd400576SPatrick Sanan if (rank == 0) { 111cc73adaaSBarry Smith PetscCheck(isatty(fileno(PETSC_STDOUT)), PETSC_COMM_SELF, PETSC_ERR_USER, "Requires users input/output"); 1129566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Enter globus username:")); 1135dc0f0a4SBarry Smith ptr = fgets(buff, 1024, stdin); 11428b400f6SJacob Faibussowitsch PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 1159566063dSJacob Faibussowitsch PetscCall(PetscStrlen(buff, &len)); 1165dc0f0a4SBarry Smith buff[len - 1] = ':'; /* remove carriage return at end of line */ 1175dc0f0a4SBarry Smith 1189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Enter globus password:")); 1195dc0f0a4SBarry Smith ptr = fgets(buff + len, 1024 - len, stdin); 12028b400f6SJacob Faibussowitsch PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 1219566063dSJacob Faibussowitsch PetscCall(PetscStrlen(buff, &len)); 1225dc0f0a4SBarry Smith buff[len - 1] = '\0'; /* remove carriage return at end of line */ 123c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(head, "Authorization: Basic ", sizeof(head))); 1249566063dSJacob Faibussowitsch PetscCall(base64_encode((const unsigned char *)buff, (unsigned char *)(head + 21), sizeof(head) - 21)); 125c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "\r\n", sizeof(head))); 1265dc0f0a4SBarry Smith 1279566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 1289566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("nexus.api.globusonline.org", 443, ctx, &sock, &ssl)); 1299566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("GET", "nexus.api.globusonline.org/goauth/token?grant_type=client_credentials", head, "application/x-www-form-urlencoded", NULL, ssl, buff, sizeof(buff))); 1309566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 1315dc0f0a4SBarry Smith close(sock); 1325dc0f0a4SBarry Smith 1339566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found)); 13428b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return access token"); 1355dc0f0a4SBarry Smith 1369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Here is your Globus access token, save it in a save place, in the future you can run PETSc\n")); 1379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -globus_access_token %s\n", access_token)); 1389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Globus automatically\n")); 1395dc0f0a4SBarry Smith } 1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1415dc0f0a4SBarry Smith } 1425dc0f0a4SBarry Smith 1435dc0f0a4SBarry Smith /*@C 1445dc0f0a4SBarry Smith PetscGlobusGetTransfers - Get a record of current transfers requested from Globus 1455dc0f0a4SBarry Smith 146*20f4b53cSBarry Smith Not Collective, only the first process in `MPI_Comm` does anything 1475dc0f0a4SBarry Smith 1485dc0f0a4SBarry Smith Input Parameters: 1495dc0f0a4SBarry Smith + comm - the MPI communicator 150*20f4b53cSBarry Smith . access_token - Globus access token, if `NULL` will check in options database for -globus_access_token XXX otherwise 151811af0c4SBarry Smith will call `PetscGlobusAuthorize()`. 1525dc0f0a4SBarry Smith - buffsize - size of the buffer 1535dc0f0a4SBarry Smith 1545dc0f0a4SBarry Smith Output Parameters: 1555dc0f0a4SBarry Smith . buff - location to put Globus information 1565dc0f0a4SBarry Smith 1572b26979fSBarry Smith Level: intermediate 1582b26979fSBarry Smith 159db781477SPatrick Sanan .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()`, `PetscGlobusAuthorize()` 1605dc0f0a4SBarry Smith @*/ 161d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm, const char access_token[], char buff[], size_t buffsize) 162d71ae5a4SJacob Faibussowitsch { 1635dc0f0a4SBarry Smith SSL_CTX *ctx; 1645dc0f0a4SBarry Smith SSL *ssl; 1655dc0f0a4SBarry Smith int sock; 1665dc0f0a4SBarry Smith char head[4096]; 1675dc0f0a4SBarry Smith PetscMPIInt rank; 1685dc0f0a4SBarry Smith 1695dc0f0a4SBarry Smith PetscFunctionBegin; 1709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 171dd400576SPatrick Sanan if (rank == 0) { 172c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(head, "Authorization : Globus-Goauthtoken ", sizeof(head))); 1735dc0f0a4SBarry Smith if (access_token) { 174c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, access_token, sizeof(head))); 1755dc0f0a4SBarry Smith } else { 1765dc0f0a4SBarry Smith PetscBool set; 1775dc0f0a4SBarry Smith char accesstoken[4096]; 1789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set)); 17928b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_USER, "Pass in Globus accesstoken or use -globus_access_token XXX"); 180c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, accesstoken, sizeof(head))); 1815dc0f0a4SBarry Smith } 182c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "\r\n", sizeof(head))); 1835dc0f0a4SBarry Smith 1849566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 1859566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 1869566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/tasksummary", head, "application/json", NULL, ssl, buff, buffsize)); 1879566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 1885dc0f0a4SBarry Smith close(sock); 1895dc0f0a4SBarry Smith } 1903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1915dc0f0a4SBarry Smith } 1925dc0f0a4SBarry Smith 1935dc0f0a4SBarry Smith /*@C 1945dc0f0a4SBarry Smith PetscGlobusUpload - Loads a file to Globus 1955dc0f0a4SBarry Smith 196*20f4b53cSBarry Smith Not Collective, only the first process in the `MPI_Comm` uploads the file 1975dc0f0a4SBarry Smith 1985dc0f0a4SBarry Smith Input Parameters: 1995dc0f0a4SBarry Smith + comm - MPI communicator 200*20f4b53cSBarry Smith . access_token - obtained with `PetscGlobusAuthorize()`, pass `NULL` to use `-globus_access_token XXX` from the PETSc database 2015dc0f0a4SBarry Smith - filename - file to upload 2025dc0f0a4SBarry Smith 203811af0c4SBarry Smith Options Database Key: 20410699b91SBarry Smith . -globus_access_token XXX - the Globus token 2055dc0f0a4SBarry Smith 2062b26979fSBarry Smith Level: intermediate 2072b26979fSBarry Smith 208db781477SPatrick Sanan .seealso: `PetscURLShorten()`, `PetscGoogleDriveAuthorize()`, `PetscGoogleDriveRefresh()`, `PetscGlobusAuthorize()` 2095dc0f0a4SBarry Smith @*/ 210d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGlobusUpload(MPI_Comm comm, const char access_token[], const char filename[]) 211d71ae5a4SJacob Faibussowitsch { 2125dc0f0a4SBarry Smith SSL_CTX *ctx; 2135dc0f0a4SBarry Smith SSL *ssl; 2145dc0f0a4SBarry Smith int sock; 2155dc0f0a4SBarry Smith char head[4096], buff[8 * 1024], body[4096], submission_id[4096]; 2165dc0f0a4SBarry Smith PetscMPIInt rank; 2175dc0f0a4SBarry Smith PetscBool flg, found; 2185dc0f0a4SBarry Smith 2195dc0f0a4SBarry Smith PetscFunctionBegin; 2209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 221dd400576SPatrick Sanan if (rank == 0) { 2229566063dSJacob Faibussowitsch PetscCall(PetscTestFile(filename, 'r', &flg)); 22328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to find file: %s", filename); 2245dc0f0a4SBarry Smith 225c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(head, "Authorization : Globus-Goauthtoken ", sizeof(head))); 2265dc0f0a4SBarry Smith if (access_token) { 227c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, access_token, sizeof(head))); 2285dc0f0a4SBarry Smith } else { 2295dc0f0a4SBarry Smith PetscBool set; 2305dc0f0a4SBarry Smith char accesstoken[4096]; 2319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set)); 23228b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_USER, "Pass in Globus accesstoken or use -globus_access_token XXX"); 233c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, accesstoken, sizeof(head))); 2345dc0f0a4SBarry Smith } 235c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "\r\n", sizeof(head))); 2365dc0f0a4SBarry Smith 2375dc0f0a4SBarry Smith /* Get Globus submission id */ 2389566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 2399566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 2409566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/submission_id", head, "application/json", NULL, ssl, buff, sizeof(buff))); 2419566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 2425dc0f0a4SBarry Smith close(sock); 2439566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "value", submission_id, sizeof(submission_id), &found)); 24428b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return submission id"); 2455dc0f0a4SBarry Smith 2465dc0f0a4SBarry Smith /* build JSON body of transfer request */ 247c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, "{", sizeof(body))); 2489371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "submission_id", submission_id, sizeof(body))); 249c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2509371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "DATA_TYPE", "transfer", sizeof(body))); 251c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2529371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "sync_level", "null", sizeof(body))); 253c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2549371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "source_endpoint", "barryfsmith#MacBookPro", sizeof(body))); 255c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2569371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "label", "PETSc transfer label", sizeof(body))); 257c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2589371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "length", "1", sizeof(body))); 259c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2609371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "destination_endpoint", "mcs#home", sizeof(body))); 261c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2625dc0f0a4SBarry Smith 263c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "\"DATA\": [ {", sizeof(body))); 2649371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "source_path", "/~/FEM_GPU.pdf", sizeof(body))); 265c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2669371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "destination_path", "/~/FEM_GPU.pdf", sizeof(body))); 267c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2689371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "verify_size", "null", sizeof(body))); 269c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2709371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "recursive", "false", sizeof(body))); 271c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", sizeof(body))); 2729566063dSJacob Faibussowitsch PetscCall(PetscPushJSONValue(body, "DATA_TYPE", "transfer_item", sizeof(body))); 273c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "} ] }", sizeof(body))); 2745dc0f0a4SBarry Smith 2759566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 2769566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 2779566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "transfer.api.globusonline.org/v0.10/transfer", head, "application/json", body, ssl, buff, sizeof(buff))); 2789566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 2795dc0f0a4SBarry Smith close(sock); 2809566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "code", submission_id, sizeof(submission_id), &found)); 28128b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return code on transfer"); 2829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(submission_id, "Accepted", &found)); 28328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not accept transfer"); 2845dc0f0a4SBarry Smith } 2853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2865dc0f0a4SBarry Smith } 287