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 */
7*66976f2fSJacob Faibussowitsch static const 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
base64_encode(const unsigned char * data,unsigned char * encoded_data,size_t len)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
base64_decode(const unsigned char * data,unsigned char * decoded_data,size_t length)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
8020f4b53cSBarry 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
862fe279fdSBarry Smith Output Parameter:
87811af0c4SBarry Smith . access_token - can be used with `PetscGlobusUpLoad()` for 30 days
885dc0f0a4SBarry Smith
8920f4b53cSBarry Smith Level: intermediate
9020f4b53cSBarry Smith
9195452b02SPatrick Sanan Notes:
9220f4b53cSBarry 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
96c30dda00SJacob Faibussowitsch .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscGlobusUpload()`
975dc0f0a4SBarry Smith @*/
PetscGlobusAuthorize(MPI_Comm comm,char access_token[],size_t tokensize)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
14620f4b53cSBarry Smith Not Collective, only the first process in `MPI_Comm` does anything
1475dc0f0a4SBarry Smith
1485dc0f0a4SBarry Smith Input Parameters:
1495dc0f0a4SBarry Smith + comm - the MPI communicator
15020f4b53cSBarry 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
1542fe279fdSBarry Smith Output Parameter:
1555dc0f0a4SBarry Smith . buff - location to put Globus information
1565dc0f0a4SBarry Smith
1572b26979fSBarry Smith Level: intermediate
1582b26979fSBarry Smith
159c30dda00SJacob Faibussowitsch .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscGlobusUpload()`, `PetscGlobusAuthorize()`
1605dc0f0a4SBarry Smith @*/
PetscGlobusGetTransfers(MPI_Comm comm,const char access_token[],char buff[],size_t buffsize)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
19620f4b53cSBarry 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
20020f4b53cSBarry 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
208c30dda00SJacob Faibussowitsch .seealso: `PetscGoogleDriveAuthorize()`, `PetscGoogleDriveRefresh()`, `PetscGlobusAuthorize()`
2095dc0f0a4SBarry Smith @*/
PetscGlobusUpload(MPI_Comm comm,const char access_token[],const char filename[])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