15dc0f0a4SBarry Smith #include <petscwebclient.h> 2bb04b57dSBarry Smith #pragma clang diagnostic ignored "-Wdeprecated-declarations" 345e40e47SBarry Smith #pragma gcc diagnostic ignored "-Wdeprecated-declarations" 45dc0f0a4SBarry Smith 55dc0f0a4SBarry Smith /* 65dc0f0a4SBarry Smith Encodes and decodes from MIME Base64 75dc0f0a4SBarry Smith */ 89371c9d4SSatish 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', 99371c9d4SSatish 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', '+', '/'}; 105dc0f0a4SBarry Smith 119371c9d4SSatish Balay static PetscErrorCode base64_encode(const unsigned char *data, unsigned char *encoded_data, size_t len) { 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] = '='; 345dc0f0a4SBarry Smith PetscFunctionReturn(0); 355dc0f0a4SBarry Smith } 365dc0f0a4SBarry Smith 379371c9d4SSatish Balay PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data, unsigned char *decoded_data, size_t length) { 385dc0f0a4SBarry Smith static char decoding_table[257]; 395dc0f0a4SBarry Smith static int decode_table_built = 0; 40c1f4622dSBarry Smith size_t i, j; 415dc0f0a4SBarry Smith size_t input_length, output_length; 425dc0f0a4SBarry Smith 435dc0f0a4SBarry Smith PetscFunctionBegin; 445dc0f0a4SBarry Smith if (!decode_table_built) { 455dc0f0a4SBarry Smith for (i = 0; i < 64; i++) decoding_table[(unsigned char)encoding_table[i]] = i; 465dc0f0a4SBarry Smith decode_table_built = 1; 475dc0f0a4SBarry Smith } 485dc0f0a4SBarry Smith 499566063dSJacob Faibussowitsch PetscCall(PetscStrlen((const char *)data, &input_length)); 5008401ef6SPierre Jolivet PetscCheck(input_length % 4 == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input length must be divisible by 4"); 515dc0f0a4SBarry Smith 525dc0f0a4SBarry Smith output_length = input_length / 4 * 3; 535dc0f0a4SBarry Smith if (data[input_length - 1] == '=') (output_length)--; 545dc0f0a4SBarry Smith if (data[input_length - 2] == '=') (output_length)--; 5508401ef6SPierre Jolivet PetscCheck(output_length <= length, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Output length too shore"); 565dc0f0a4SBarry Smith 575dc0f0a4SBarry Smith for (i = 0, j = 0; i < input_length;) { 585dc0f0a4SBarry Smith uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 595dc0f0a4SBarry Smith uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 605dc0f0a4SBarry Smith uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 615dc0f0a4SBarry Smith uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; 625dc0f0a4SBarry Smith uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); 635dc0f0a4SBarry Smith 645dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; 655dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; 665dc0f0a4SBarry Smith if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; 675dc0f0a4SBarry Smith } 685dc0f0a4SBarry Smith decoded_data[j] = 0; 695dc0f0a4SBarry Smith PetscFunctionReturn(0); 705dc0f0a4SBarry Smith } 715dc0f0a4SBarry Smith 725dc0f0a4SBarry Smith #if defined(PETSC_HAVE_UNISTD_H) 735dc0f0a4SBarry Smith #include <unistd.h> 745dc0f0a4SBarry Smith #endif 755dc0f0a4SBarry Smith 765dc0f0a4SBarry Smith /*@C 775dc0f0a4SBarry Smith PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests 785dc0f0a4SBarry Smith 79*811af0c4SBarry Smith Not collective, only the first process in `MPI_Comm` does anything 805dc0f0a4SBarry Smith 815dc0f0a4SBarry Smith Input Parameters: 825dc0f0a4SBarry Smith + comm - the MPI communicator 835dc0f0a4SBarry Smith - tokensize - size of the token array 845dc0f0a4SBarry Smith 855dc0f0a4SBarry Smith Output Parameters: 86*811af0c4SBarry Smith . access_token - can be used with `PetscGlobusUpLoad()` for 30 days 875dc0f0a4SBarry Smith 8895452b02SPatrick Sanan Notes: 8995452b02SPatrick Sanan This call requires stdout and stdin access from process 0 on the MPI communicator 905dc0f0a4SBarry Smith 91c4762a1bSJed Brown You can run src/sys/webclient/tutorials/globusobtainaccesstoken to get an access token 925dc0f0a4SBarry Smith 932b26979fSBarry Smith Level: intermediate 942b26979fSBarry Smith 95db781477SPatrick Sanan .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()` 965dc0f0a4SBarry Smith @*/ 979371c9d4SSatish Balay PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm, char access_token[], size_t tokensize) { 985dc0f0a4SBarry Smith SSL_CTX *ctx; 995dc0f0a4SBarry Smith SSL *ssl; 1005dc0f0a4SBarry Smith int sock; 1015dc0f0a4SBarry Smith char buff[8 * 1024], *ptr, head[1024]; 1025dc0f0a4SBarry Smith PetscMPIInt rank; 1035dc0f0a4SBarry Smith size_t len; 1045dc0f0a4SBarry Smith PetscBool found; 1055dc0f0a4SBarry Smith 1065dc0f0a4SBarry Smith PetscFunctionBegin; 1079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 108dd400576SPatrick Sanan if (rank == 0) { 109cc73adaaSBarry Smith PetscCheck(isatty(fileno(PETSC_STDOUT)), PETSC_COMM_SELF, PETSC_ERR_USER, "Requires users input/output"); 1109566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Enter globus username:")); 1115dc0f0a4SBarry Smith ptr = fgets(buff, 1024, stdin); 11228b400f6SJacob Faibussowitsch PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 1139566063dSJacob Faibussowitsch PetscCall(PetscStrlen(buff, &len)); 1145dc0f0a4SBarry Smith buff[len - 1] = ':'; /* remove carriage return at end of line */ 1155dc0f0a4SBarry Smith 1169566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Enter globus password:")); 1175dc0f0a4SBarry Smith ptr = fgets(buff + len, 1024 - len, stdin); 11828b400f6SJacob Faibussowitsch PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 1199566063dSJacob Faibussowitsch PetscCall(PetscStrlen(buff, &len)); 1205dc0f0a4SBarry Smith buff[len - 1] = '\0'; /* remove carriage return at end of line */ 1219566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(head, "Authorization: Basic ")); 1229566063dSJacob Faibussowitsch PetscCall(base64_encode((const unsigned char *)buff, (unsigned char *)(head + 21), sizeof(head) - 21)); 1239566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, "\r\n")); 1245dc0f0a4SBarry Smith 1259566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 1269566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("nexus.api.globusonline.org", 443, ctx, &sock, &ssl)); 1279566063dSJacob 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))); 1289566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 1295dc0f0a4SBarry Smith close(sock); 1305dc0f0a4SBarry Smith 1319566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found)); 13228b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return access token"); 1335dc0f0a4SBarry Smith 1349566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Here is your Globus access token, save it in a save place, in the future you can run PETSc\n")); 1359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -globus_access_token %s\n", access_token)); 1369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Globus automatically\n")); 1375dc0f0a4SBarry Smith } 1385dc0f0a4SBarry Smith PetscFunctionReturn(0); 1395dc0f0a4SBarry Smith } 1405dc0f0a4SBarry Smith 1415dc0f0a4SBarry Smith /*@C 1425dc0f0a4SBarry Smith PetscGlobusGetTransfers - Get a record of current transfers requested from Globus 1435dc0f0a4SBarry Smith 144*811af0c4SBarry Smith Not collective, only the first process in `MPI_Comm` does anything 1455dc0f0a4SBarry Smith 1465dc0f0a4SBarry Smith Input Parameters: 1475dc0f0a4SBarry Smith + comm - the MPI communicator 1485dc0f0a4SBarry Smith . access_token - Globus access token, if NULL will check in options database for -globus_access_token XXX otherwise 149*811af0c4SBarry Smith will call `PetscGlobusAuthorize()`. 1505dc0f0a4SBarry Smith - buffsize - size of the buffer 1515dc0f0a4SBarry Smith 1525dc0f0a4SBarry Smith Output Parameters: 1535dc0f0a4SBarry Smith . buff - location to put Globus information 1545dc0f0a4SBarry Smith 1552b26979fSBarry Smith Level: intermediate 1562b26979fSBarry Smith 157db781477SPatrick Sanan .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()`, `PetscGlobusAuthorize()` 1585dc0f0a4SBarry Smith @*/ 1599371c9d4SSatish Balay PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm, const char access_token[], char buff[], size_t buffsize) { 1605dc0f0a4SBarry Smith SSL_CTX *ctx; 1615dc0f0a4SBarry Smith SSL *ssl; 1625dc0f0a4SBarry Smith int sock; 1635dc0f0a4SBarry Smith char head[4096]; 1645dc0f0a4SBarry Smith PetscMPIInt rank; 1655dc0f0a4SBarry Smith 1665dc0f0a4SBarry Smith PetscFunctionBegin; 1679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 168dd400576SPatrick Sanan if (rank == 0) { 1699566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(head, "Authorization : Globus-Goauthtoken ")); 1705dc0f0a4SBarry Smith if (access_token) { 1719566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, access_token)); 1725dc0f0a4SBarry Smith } else { 1735dc0f0a4SBarry Smith PetscBool set; 1745dc0f0a4SBarry Smith char accesstoken[4096]; 1759566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set)); 17628b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_USER, "Pass in Globus accesstoken or use -globus_access_token XXX"); 1779566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, accesstoken)); 1785dc0f0a4SBarry Smith } 1799566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, "\r\n")); 1805dc0f0a4SBarry Smith 1819566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 1829566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 1839566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/tasksummary", head, "application/json", NULL, ssl, buff, buffsize)); 1849566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 1855dc0f0a4SBarry Smith close(sock); 1865dc0f0a4SBarry Smith } 1875dc0f0a4SBarry Smith PetscFunctionReturn(0); 1885dc0f0a4SBarry Smith } 1895dc0f0a4SBarry Smith 1905dc0f0a4SBarry Smith /*@C 1915dc0f0a4SBarry Smith PetscGlobusUpload - Loads a file to Globus 1925dc0f0a4SBarry Smith 193*811af0c4SBarry Smith Not collective, only the first process in the `MPI_Comm` uploads the file 1945dc0f0a4SBarry Smith 1955dc0f0a4SBarry Smith Input Parameters: 1965dc0f0a4SBarry Smith + comm - MPI communicator 197*811af0c4SBarry Smith . access_token - obtained with `PetscGlobusAuthorize()`, pass NULL to use -globus_access_token XXX from the PETSc database 1985dc0f0a4SBarry Smith - filename - file to upload 1995dc0f0a4SBarry Smith 200*811af0c4SBarry Smith Options Database Key: 20110699b91SBarry Smith . -globus_access_token XXX - the Globus token 2025dc0f0a4SBarry Smith 2032b26979fSBarry Smith Level: intermediate 2042b26979fSBarry Smith 205db781477SPatrick Sanan .seealso: `PetscURLShorten()`, `PetscGoogleDriveAuthorize()`, `PetscGoogleDriveRefresh()`, `PetscGlobusAuthorize()` 2065dc0f0a4SBarry Smith @*/ 2079371c9d4SSatish Balay PetscErrorCode PetscGlobusUpload(MPI_Comm comm, const char access_token[], const char filename[]) { 2085dc0f0a4SBarry Smith SSL_CTX *ctx; 2095dc0f0a4SBarry Smith SSL *ssl; 2105dc0f0a4SBarry Smith int sock; 2115dc0f0a4SBarry Smith char head[4096], buff[8 * 1024], body[4096], submission_id[4096]; 2125dc0f0a4SBarry Smith PetscMPIInt rank; 2135dc0f0a4SBarry Smith PetscBool flg, found; 2145dc0f0a4SBarry Smith 2155dc0f0a4SBarry Smith PetscFunctionBegin; 2169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 217dd400576SPatrick Sanan if (rank == 0) { 2189566063dSJacob Faibussowitsch PetscCall(PetscTestFile(filename, 'r', &flg)); 21928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to find file: %s", filename); 2205dc0f0a4SBarry Smith 2219566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(head, "Authorization : Globus-Goauthtoken ")); 2225dc0f0a4SBarry Smith if (access_token) { 2239566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, access_token)); 2245dc0f0a4SBarry Smith } else { 2255dc0f0a4SBarry Smith PetscBool set; 2265dc0f0a4SBarry Smith char accesstoken[4096]; 2279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set)); 22828b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_USER, "Pass in Globus accesstoken or use -globus_access_token XXX"); 2299566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, accesstoken)); 2305dc0f0a4SBarry Smith } 2319566063dSJacob Faibussowitsch PetscCall(PetscStrcat(head, "\r\n")); 2325dc0f0a4SBarry Smith 2335dc0f0a4SBarry Smith /* Get Globus submission id */ 2349566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 2359566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 2369566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/submission_id", head, "application/json", NULL, ssl, buff, sizeof(buff))); 2379566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 2385dc0f0a4SBarry Smith close(sock); 2399566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "value", submission_id, sizeof(submission_id), &found)); 24028b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return submission id"); 2415dc0f0a4SBarry Smith 2425dc0f0a4SBarry Smith /* build JSON body of transfer request */ 2439566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(body, "{")); 2449371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "submission_id", submission_id, sizeof(body))); 2459371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2469371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "DATA_TYPE", "transfer", sizeof(body))); 2479371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2489371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "sync_level", "null", sizeof(body))); 2499371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2509371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "source_endpoint", "barryfsmith#MacBookPro", sizeof(body))); 2519371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2529371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "label", "PETSc transfer label", sizeof(body))); 2539371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2549371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "length", "1", sizeof(body))); 2559371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2569371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "destination_endpoint", "mcs#home", sizeof(body))); 2579371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2585dc0f0a4SBarry Smith 2599566063dSJacob Faibussowitsch PetscCall(PetscStrcat(body, "\"DATA\": [ {")); 2609371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "source_path", "/~/FEM_GPU.pdf", sizeof(body))); 2619371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2629371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "destination_path", "/~/FEM_GPU.pdf", sizeof(body))); 2639371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2649371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "verify_size", "null", sizeof(body))); 2659371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2669371c9d4SSatish Balay PetscCall(PetscPushJSONValue(body, "recursive", "false", sizeof(body))); 2679371c9d4SSatish Balay PetscCall(PetscStrcat(body, ",")); 2689566063dSJacob Faibussowitsch PetscCall(PetscPushJSONValue(body, "DATA_TYPE", "transfer_item", sizeof(body))); 2699566063dSJacob Faibussowitsch PetscCall(PetscStrcat(body, "} ] }")); 2705dc0f0a4SBarry Smith 2719566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 2729566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl)); 2739566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "transfer.api.globusonline.org/v0.10/transfer", head, "application/json", body, ssl, buff, sizeof(buff))); 2749566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 2755dc0f0a4SBarry Smith close(sock); 2769566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "code", submission_id, sizeof(submission_id), &found)); 27728b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not return code on transfer"); 2789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(submission_id, "Accepted", &found)); 27928b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Globus did not accept transfer"); 2805dc0f0a4SBarry Smith } 2815dc0f0a4SBarry Smith PetscFunctionReturn(0); 2825dc0f0a4SBarry Smith } 283