xref: /petsc/src/sys/webclient/globus.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
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 */
85dc0f0a4SBarry Smith static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
95dc0f0a4SBarry Smith                                 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
105dc0f0a4SBarry Smith                                 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
115dc0f0a4SBarry Smith                                 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
125dc0f0a4SBarry Smith                                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
135dc0f0a4SBarry Smith                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
145dc0f0a4SBarry Smith                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
155dc0f0a4SBarry Smith                                 '4', '5', '6', '7', '8', '9', '+', '/'};
165dc0f0a4SBarry Smith 
175dc0f0a4SBarry Smith static PetscErrorCode base64_encode(const unsigned char *data,unsigned char *encoded_data,size_t len)
185dc0f0a4SBarry Smith {
19f5b927afSBarry Smith   static size_t  mod_table[] = {0, 2, 1};
20f5b927afSBarry Smith   size_t         i,j;
215dc0f0a4SBarry Smith   size_t         input_length,output_length;
225dc0f0a4SBarry Smith 
235dc0f0a4SBarry Smith   PetscFunctionBegin;
249566063dSJacob Faibussowitsch   PetscCall(PetscStrlen((const char*)data,&input_length));
255dc0f0a4SBarry Smith   output_length = 4 * ((input_length + 2) / 3);
26*08401ef6SPierre Jolivet   PetscCheck(output_length <= len,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length not large enough");
275dc0f0a4SBarry Smith 
285dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
295dc0f0a4SBarry Smith      uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
305dc0f0a4SBarry Smith      uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
315dc0f0a4SBarry Smith      uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
325dc0f0a4SBarry Smith      uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
335dc0f0a4SBarry Smith 
345dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
355dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
365dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
375dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
385dc0f0a4SBarry Smith   }
395dc0f0a4SBarry Smith   encoded_data[j] = 0;
405dc0f0a4SBarry Smith   for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[output_length - 1 - i] = '=';
415dc0f0a4SBarry Smith   PetscFunctionReturn(0);
425dc0f0a4SBarry Smith }
435dc0f0a4SBarry Smith 
445dc0f0a4SBarry Smith PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data,unsigned char* decoded_data, size_t length)
455dc0f0a4SBarry Smith {
465dc0f0a4SBarry Smith   static char    decoding_table[257];
475dc0f0a4SBarry Smith   static int     decode_table_built = 0;
48c1f4622dSBarry Smith   size_t         i,j;
495dc0f0a4SBarry Smith   size_t         input_length,output_length;
505dc0f0a4SBarry Smith 
515dc0f0a4SBarry Smith   PetscFunctionBegin;
525dc0f0a4SBarry Smith   if (!decode_table_built) {
535dc0f0a4SBarry Smith     for (i = 0; i < 64; i++) decoding_table[(unsigned char) encoding_table[i]] = i;
545dc0f0a4SBarry Smith     decode_table_built = 1;
555dc0f0a4SBarry Smith   }
565dc0f0a4SBarry Smith 
579566063dSJacob Faibussowitsch   PetscCall(PetscStrlen((const char*)data,&input_length));
58*08401ef6SPierre Jolivet   PetscCheck(input_length % 4 == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input length must be divisible by 4");
595dc0f0a4SBarry Smith 
605dc0f0a4SBarry Smith   output_length = input_length / 4 * 3;
615dc0f0a4SBarry Smith   if (data[input_length - 1] == '=') (output_length)--;
625dc0f0a4SBarry Smith   if (data[input_length - 2] == '=') (output_length)--;
63*08401ef6SPierre Jolivet   PetscCheck(output_length <= length,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length too shore");
645dc0f0a4SBarry Smith 
655dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
665dc0f0a4SBarry Smith     uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
675dc0f0a4SBarry Smith     uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
685dc0f0a4SBarry Smith     uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
695dc0f0a4SBarry Smith     uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
705dc0f0a4SBarry Smith     uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
715dc0f0a4SBarry Smith 
725dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
735dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
745dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
755dc0f0a4SBarry Smith   }
765dc0f0a4SBarry Smith   decoded_data[j] = 0;
775dc0f0a4SBarry Smith   PetscFunctionReturn(0);
785dc0f0a4SBarry Smith }
795dc0f0a4SBarry Smith 
805dc0f0a4SBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
815dc0f0a4SBarry Smith #include <unistd.h>
825dc0f0a4SBarry Smith #endif
835dc0f0a4SBarry Smith 
845dc0f0a4SBarry Smith /*@C
855dc0f0a4SBarry Smith      PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests
865dc0f0a4SBarry Smith 
875dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
885dc0f0a4SBarry Smith 
895dc0f0a4SBarry Smith    Input Parameters:
905dc0f0a4SBarry Smith +  comm - the MPI communicator
915dc0f0a4SBarry Smith -  tokensize - size of the token array
925dc0f0a4SBarry Smith 
935dc0f0a4SBarry Smith    Output Parameters:
945dc0f0a4SBarry Smith .  access_token - can be used with PetscGlobusUpLoad() for 30 days
955dc0f0a4SBarry Smith 
9695452b02SPatrick Sanan    Notes:
9795452b02SPatrick Sanan     This call requires stdout and stdin access from process 0 on the MPI communicator
985dc0f0a4SBarry Smith 
99c4762a1bSJed Brown    You can run src/sys/webclient/tutorials/globusobtainaccesstoken to get an access token
1005dc0f0a4SBarry Smith 
1012b26979fSBarry Smith    Level: intermediate
1022b26979fSBarry Smith 
1035dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload()
1045dc0f0a4SBarry Smith 
1055dc0f0a4SBarry Smith @*/
1065dc0f0a4SBarry Smith PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm,char access_token[],size_t tokensize)
1075dc0f0a4SBarry Smith {
1085dc0f0a4SBarry Smith   SSL_CTX        *ctx;
1095dc0f0a4SBarry Smith   SSL            *ssl;
1105dc0f0a4SBarry Smith   int            sock;
1115dc0f0a4SBarry Smith   char           buff[8*1024],*ptr,head[1024];
1125dc0f0a4SBarry Smith   PetscMPIInt    rank;
1135dc0f0a4SBarry Smith   size_t         len;
1145dc0f0a4SBarry Smith   PetscBool      found;
1155dc0f0a4SBarry Smith 
1165dc0f0a4SBarry Smith   PetscFunctionBegin;
1179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
118dd400576SPatrick Sanan   if (rank == 0) {
1192c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!isatty(fileno(PETSC_STDOUT)),PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output");
1209566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Enter globus username:"));
1215dc0f0a4SBarry Smith     ptr  = fgets(buff, 1024, stdin);
12228b400f6SJacob Faibussowitsch     PetscCheck(ptr,PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
1239566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(buff,&len));
1245dc0f0a4SBarry Smith     buff[len-1] = ':'; /* remove carriage return at end of line */
1255dc0f0a4SBarry Smith 
1269566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Enter globus password:"));
1275dc0f0a4SBarry Smith     ptr  = fgets(buff+len, 1024-len, stdin);
12828b400f6SJacob Faibussowitsch     PetscCheck(ptr,PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
1299566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(buff,&len));
1305dc0f0a4SBarry Smith     buff[len-1] = '\0'; /* remove carriage return at end of line */
1319566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(head,"Authorization: Basic "));
1329566063dSJacob Faibussowitsch     PetscCall(base64_encode((const unsigned char*)buff,(unsigned char*)(head+21),sizeof(head)-21));
1339566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(head,"\r\n"));
1345dc0f0a4SBarry Smith 
1359566063dSJacob Faibussowitsch     PetscCall(PetscSSLInitializeContext(&ctx));
1369566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSConnect("nexus.api.globusonline.org",443,ctx,&sock,&ssl));
1379566063dSJacob 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)));
1389566063dSJacob Faibussowitsch     PetscCall(PetscSSLDestroyContext(ctx));
1395dc0f0a4SBarry Smith     close(sock);
1405dc0f0a4SBarry Smith 
1419566063dSJacob Faibussowitsch     PetscCall(PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found));
14228b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return access token");
1435dc0f0a4SBarry Smith 
1449566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Here is your Globus access token, save it in a save place, in the future you can run PETSc\n"));
1459566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"programs with the option -globus_access_token %s\n",access_token));
1469566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"to access Globus automatically\n"));
1475dc0f0a4SBarry Smith   }
1485dc0f0a4SBarry Smith   PetscFunctionReturn(0);
1495dc0f0a4SBarry Smith }
1505dc0f0a4SBarry Smith 
1515dc0f0a4SBarry Smith /*@C
1525dc0f0a4SBarry Smith      PetscGlobusGetTransfers - Get a record of current transfers requested from Globus
1535dc0f0a4SBarry Smith 
1545dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
1555dc0f0a4SBarry Smith 
1565dc0f0a4SBarry Smith    Input Parameters:
1575dc0f0a4SBarry Smith +  comm - the MPI communicator
1585dc0f0a4SBarry Smith .  access_token - Globus access token, if NULL will check in options database for -globus_access_token XXX otherwise
1595dc0f0a4SBarry Smith                   will call PetscGlobusAuthorize().
1605dc0f0a4SBarry Smith -  buffsize - size of the buffer
1615dc0f0a4SBarry Smith 
1625dc0f0a4SBarry Smith    Output Parameters:
1635dc0f0a4SBarry Smith .  buff - location to put Globus information
1645dc0f0a4SBarry Smith 
1652b26979fSBarry Smith    Level: intermediate
1662b26979fSBarry Smith 
1675dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload(), PetscGlobusAuthorize()
1685dc0f0a4SBarry Smith 
1695dc0f0a4SBarry Smith @*/
1705dc0f0a4SBarry Smith PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm,const char access_token[],char buff[],size_t buffsize)
1715dc0f0a4SBarry Smith {
1725dc0f0a4SBarry Smith   SSL_CTX        *ctx;
1735dc0f0a4SBarry Smith   SSL            *ssl;
1745dc0f0a4SBarry Smith   int            sock;
1755dc0f0a4SBarry Smith   char           head[4096];
1765dc0f0a4SBarry Smith   PetscMPIInt    rank;
1775dc0f0a4SBarry Smith 
1785dc0f0a4SBarry Smith   PetscFunctionBegin;
1799566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
180dd400576SPatrick Sanan   if (rank == 0) {
1819566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(head,"Authorization : Globus-Goauthtoken "));
1825dc0f0a4SBarry Smith     if (access_token) {
1839566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(head,access_token));
1845dc0f0a4SBarry Smith     } else {
1855dc0f0a4SBarry Smith       PetscBool set;
1865dc0f0a4SBarry Smith       char      accesstoken[4096];
1879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetString(NULL,NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set));
18828b400f6SJacob Faibussowitsch       PetscCheck(set,PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
1899566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(head,accesstoken));
1905dc0f0a4SBarry Smith     }
1919566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(head,"\r\n"));
1925dc0f0a4SBarry Smith 
1939566063dSJacob Faibussowitsch     PetscCall(PetscSSLInitializeContext(&ctx));
1949566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl));
1959566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/tasksummary",head,"application/json",NULL,ssl,buff,buffsize));
1969566063dSJacob Faibussowitsch     PetscCall(PetscSSLDestroyContext(ctx));
1975dc0f0a4SBarry Smith     close(sock);
1985dc0f0a4SBarry Smith   }
1995dc0f0a4SBarry Smith   PetscFunctionReturn(0);
2005dc0f0a4SBarry Smith }
2015dc0f0a4SBarry Smith 
2025dc0f0a4SBarry Smith /*@C
2035dc0f0a4SBarry Smith      PetscGlobusUpload - Loads a file to Globus
2045dc0f0a4SBarry Smith 
2055dc0f0a4SBarry Smith      Not collective, only the first process in the MPI_Comm uploads the file
2065dc0f0a4SBarry Smith 
2075dc0f0a4SBarry Smith   Input Parameters:
2085dc0f0a4SBarry Smith +   comm - MPI communicator
2095dc0f0a4SBarry Smith .   access_token - obtained with PetscGlobusAuthorize(), pass NULL to use -globus_access_token XXX from the PETSc database
2105dc0f0a4SBarry Smith -   filename - file to upload
2115dc0f0a4SBarry Smith 
2125dc0f0a4SBarry Smith   Options Database:
21310699b91SBarry Smith .  -globus_access_token XXX - the Globus token
2145dc0f0a4SBarry Smith 
2152b26979fSBarry Smith    Level: intermediate
2162b26979fSBarry Smith 
2175dc0f0a4SBarry Smith .seealso: PetscURLShorten(), PetscGoogleDriveAuthorize(), PetscGoogleDriveRefresh(), PetscGlobusAuthorize()
2185dc0f0a4SBarry Smith 
2195dc0f0a4SBarry Smith @*/
2205dc0f0a4SBarry Smith PetscErrorCode PetscGlobusUpload(MPI_Comm comm,const char access_token[],const char filename[])
2215dc0f0a4SBarry Smith {
2225dc0f0a4SBarry Smith   SSL_CTX        *ctx;
2235dc0f0a4SBarry Smith   SSL            *ssl;
2245dc0f0a4SBarry Smith   int            sock;
2255dc0f0a4SBarry Smith   char           head[4096],buff[8*1024],body[4096],submission_id[4096];
2265dc0f0a4SBarry Smith   PetscMPIInt    rank;
2275dc0f0a4SBarry Smith   PetscBool      flg,found;
2285dc0f0a4SBarry Smith 
2295dc0f0a4SBarry Smith   PetscFunctionBegin;
2309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
231dd400576SPatrick Sanan   if (rank == 0) {
2329566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(filename,'r',&flg));
23328b400f6SJacob Faibussowitsch     PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to find file: %s",filename);
2345dc0f0a4SBarry Smith 
2359566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(head,"Authorization : Globus-Goauthtoken "));
2365dc0f0a4SBarry Smith     if (access_token) {
2379566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(head,access_token));
2385dc0f0a4SBarry Smith     } else {
2395dc0f0a4SBarry Smith       PetscBool set;
2405dc0f0a4SBarry Smith       char      accesstoken[4096];
2419566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetString(NULL,NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set));
24228b400f6SJacob Faibussowitsch       PetscCheck(set,PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
2439566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(head,accesstoken));
2445dc0f0a4SBarry Smith     }
2459566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(head,"\r\n"));
2465dc0f0a4SBarry Smith 
2475dc0f0a4SBarry Smith     /* Get Globus submission id */
2489566063dSJacob Faibussowitsch     PetscCall(PetscSSLInitializeContext(&ctx));
2499566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl));
2509566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/submission_id",head,"application/json",NULL,ssl,buff,sizeof(buff)));
2519566063dSJacob Faibussowitsch     PetscCall(PetscSSLDestroyContext(ctx));
2525dc0f0a4SBarry Smith     close(sock);
2539566063dSJacob Faibussowitsch     PetscCall(PetscPullJSONValue(buff,"value",submission_id,sizeof(submission_id),&found));
25428b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return submission id");
2555dc0f0a4SBarry Smith 
2565dc0f0a4SBarry Smith     /* build JSON body of transfer request */
2579566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(body,"{"));
2589566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"submission_id",submission_id,sizeof(body)));                 PetscCall(PetscStrcat(body,","));
2599566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"DATA_TYPE","transfer",sizeof(body)));                        PetscCall(PetscStrcat(body,","));
2609566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"sync_level","null",sizeof(body)));                           PetscCall(PetscStrcat(body,","));
2619566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"source_endpoint","barryfsmith#MacBookPro",sizeof(body)));    PetscCall(PetscStrcat(body,","));
2629566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"label","PETSc transfer label",sizeof(body)));                PetscCall(PetscStrcat(body,","));
2639566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"length","1",sizeof(body)));                                  PetscCall(PetscStrcat(body,","));
2649566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"destination_endpoint","mcs#home",sizeof(body)));             PetscCall(PetscStrcat(body,","));
2655dc0f0a4SBarry Smith 
2669566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(body,"\"DATA\": [ {"));
2679566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"source_path","/~/FEM_GPU.pdf",sizeof(body)));                PetscCall(PetscStrcat(body,","));
2689566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"destination_path","/~/FEM_GPU.pdf",sizeof(body)));           PetscCall(PetscStrcat(body,","));
2699566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"verify_size","null",sizeof(body)));                          PetscCall(PetscStrcat(body,","));
2709566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"recursive","false",sizeof(body)));                           PetscCall(PetscStrcat(body,","));
2719566063dSJacob Faibussowitsch     PetscCall(PetscPushJSONValue(body,"DATA_TYPE","transfer_item",sizeof(body)));
2729566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(body,"} ] }"));
2735dc0f0a4SBarry Smith 
2749566063dSJacob Faibussowitsch     PetscCall(PetscSSLInitializeContext(&ctx));
2759566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl));
2769566063dSJacob Faibussowitsch     PetscCall(PetscHTTPSRequest("POST","transfer.api.globusonline.org/v0.10/transfer",head,"application/json",body,ssl,buff,sizeof(buff)));
2779566063dSJacob Faibussowitsch     PetscCall(PetscSSLDestroyContext(ctx));
2785dc0f0a4SBarry Smith     close(sock);
2799566063dSJacob Faibussowitsch     PetscCall(PetscPullJSONValue(buff,"code",submission_id,sizeof(submission_id),&found));
28028b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return code on transfer");
2819566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(submission_id,"Accepted",&found));
28228b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not accept transfer");
2835dc0f0a4SBarry Smith   }
2845dc0f0a4SBarry Smith   PetscFunctionReturn(0);
2855dc0f0a4SBarry Smith }
286