xref: /petsc/src/sys/webclient/globus.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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   PetscErrorCode ierr;
235dc0f0a4SBarry Smith 
245dc0f0a4SBarry Smith   PetscFunctionBegin;
255dc0f0a4SBarry Smith   ierr = PetscStrlen((const char*)data,&input_length);CHKERRQ(ierr);
265dc0f0a4SBarry Smith   output_length = 4 * ((input_length + 2) / 3);
27*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(output_length > len,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length not large enough");
285dc0f0a4SBarry Smith 
295dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
305dc0f0a4SBarry Smith      uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
315dc0f0a4SBarry Smith      uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
325dc0f0a4SBarry Smith      uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
335dc0f0a4SBarry Smith      uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
345dc0f0a4SBarry Smith 
355dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
365dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
375dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
385dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
395dc0f0a4SBarry Smith   }
405dc0f0a4SBarry Smith   encoded_data[j] = 0;
415dc0f0a4SBarry Smith   for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[output_length - 1 - i] = '=';
425dc0f0a4SBarry Smith   PetscFunctionReturn(0);
435dc0f0a4SBarry Smith }
445dc0f0a4SBarry Smith 
455dc0f0a4SBarry Smith PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data,unsigned char* decoded_data, size_t length)
465dc0f0a4SBarry Smith {
475dc0f0a4SBarry Smith   static char    decoding_table[257];
485dc0f0a4SBarry Smith   static int     decode_table_built = 0;
49c1f4622dSBarry Smith   size_t         i,j;
505dc0f0a4SBarry Smith   PetscErrorCode ierr;
515dc0f0a4SBarry Smith   size_t         input_length,output_length;
525dc0f0a4SBarry Smith 
535dc0f0a4SBarry Smith   PetscFunctionBegin;
545dc0f0a4SBarry Smith   if (!decode_table_built) {
555dc0f0a4SBarry Smith     for (i = 0; i < 64; i++) decoding_table[(unsigned char) encoding_table[i]] = i;
565dc0f0a4SBarry Smith     decode_table_built = 1;
575dc0f0a4SBarry Smith   }
585dc0f0a4SBarry Smith 
595dc0f0a4SBarry Smith   ierr = PetscStrlen((const char*)data,&input_length);CHKERRQ(ierr);
60*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(input_length % 4 != 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input length must be divisible by 4");
615dc0f0a4SBarry Smith 
625dc0f0a4SBarry Smith   output_length = input_length / 4 * 3;
635dc0f0a4SBarry Smith   if (data[input_length - 1] == '=') (output_length)--;
645dc0f0a4SBarry Smith   if (data[input_length - 2] == '=') (output_length)--;
65*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(output_length > length,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length too shore");
665dc0f0a4SBarry Smith 
675dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
685dc0f0a4SBarry Smith     uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
695dc0f0a4SBarry Smith     uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
705dc0f0a4SBarry Smith     uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
715dc0f0a4SBarry Smith     uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
725dc0f0a4SBarry Smith     uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
735dc0f0a4SBarry Smith 
745dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
755dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
765dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
775dc0f0a4SBarry Smith   }
785dc0f0a4SBarry Smith   decoded_data[j] = 0;
795dc0f0a4SBarry Smith   PetscFunctionReturn(0);
805dc0f0a4SBarry Smith }
815dc0f0a4SBarry Smith 
825dc0f0a4SBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
835dc0f0a4SBarry Smith #include <unistd.h>
845dc0f0a4SBarry Smith #endif
855dc0f0a4SBarry Smith 
865dc0f0a4SBarry Smith /*@C
875dc0f0a4SBarry Smith      PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests
885dc0f0a4SBarry Smith 
895dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
905dc0f0a4SBarry Smith 
915dc0f0a4SBarry Smith    Input Parameters:
925dc0f0a4SBarry Smith +  comm - the MPI communicator
935dc0f0a4SBarry Smith -  tokensize - size of the token array
945dc0f0a4SBarry Smith 
955dc0f0a4SBarry Smith    Output Parameters:
965dc0f0a4SBarry Smith .  access_token - can be used with PetscGlobusUpLoad() for 30 days
975dc0f0a4SBarry Smith 
9895452b02SPatrick Sanan    Notes:
9995452b02SPatrick Sanan     This call requires stdout and stdin access from process 0 on the MPI communicator
1005dc0f0a4SBarry Smith 
101c4762a1bSJed Brown    You can run src/sys/webclient/tutorials/globusobtainaccesstoken to get an access token
1025dc0f0a4SBarry Smith 
1032b26979fSBarry Smith    Level: intermediate
1042b26979fSBarry Smith 
1055dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload()
1065dc0f0a4SBarry Smith 
1075dc0f0a4SBarry Smith @*/
1085dc0f0a4SBarry Smith PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm,char access_token[],size_t tokensize)
1095dc0f0a4SBarry Smith {
1105dc0f0a4SBarry Smith   SSL_CTX        *ctx;
1115dc0f0a4SBarry Smith   SSL            *ssl;
1125dc0f0a4SBarry Smith   int            sock;
1135dc0f0a4SBarry Smith   PetscErrorCode ierr;
1145dc0f0a4SBarry Smith   char           buff[8*1024],*ptr,head[1024];
1155dc0f0a4SBarry Smith   PetscMPIInt    rank;
1165dc0f0a4SBarry Smith   size_t         len;
1175dc0f0a4SBarry Smith   PetscBool      found;
1185dc0f0a4SBarry Smith 
1195dc0f0a4SBarry Smith   PetscFunctionBegin;
120ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
121dd400576SPatrick Sanan   if (rank == 0) {
122*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!isatty(fileno(PETSC_STDOUT)),PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output");
1235dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"Enter globus username:");CHKERRQ(ierr);
1245dc0f0a4SBarry Smith     ptr  = fgets(buff, 1024, stdin);
125*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!ptr,PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
1265dc0f0a4SBarry Smith     ierr = PetscStrlen(buff,&len);CHKERRQ(ierr);
1275dc0f0a4SBarry Smith     buff[len-1] = ':'; /* remove carriage return at end of line */
1285dc0f0a4SBarry Smith 
1295dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"Enter globus password:");CHKERRQ(ierr);
1305dc0f0a4SBarry Smith     ptr  = fgets(buff+len, 1024-len, stdin);
131*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!ptr,PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
1325dc0f0a4SBarry Smith     ierr = PetscStrlen(buff,&len);CHKERRQ(ierr);
1335dc0f0a4SBarry Smith     buff[len-1] = '\0'; /* remove carriage return at end of line */
1345dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization: Basic ");CHKERRQ(ierr);
1355dc0f0a4SBarry Smith     ierr = base64_encode((const unsigned char*)buff,(unsigned char*)(head+21),sizeof(head)-21);CHKERRQ(ierr);
1365dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
1375dc0f0a4SBarry Smith 
1385dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
1395dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("nexus.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
1405dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("GET","nexus.api.globusonline.org/goauth/token?grant_type=client_credentials",head,"application/x-www-form-urlencoded",NULL,ssl,buff,sizeof(buff));CHKERRQ(ierr);
1415dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
1425dc0f0a4SBarry Smith     close(sock);
1435dc0f0a4SBarry Smith 
1445dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr);
145*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return access token");
1465dc0f0a4SBarry Smith 
1475dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"Here is your Globus access token, save it in a save place, in the future you can run PETSc\n");CHKERRQ(ierr);
1485dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"programs with the option -globus_access_token %s\n",access_token);CHKERRQ(ierr);
1495dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"to access Globus automatically\n");CHKERRQ(ierr);
1505dc0f0a4SBarry Smith   }
1515dc0f0a4SBarry Smith   PetscFunctionReturn(0);
1525dc0f0a4SBarry Smith }
1535dc0f0a4SBarry Smith 
1545dc0f0a4SBarry Smith /*@C
1555dc0f0a4SBarry Smith      PetscGlobusGetTransfers - Get a record of current transfers requested from Globus
1565dc0f0a4SBarry Smith 
1575dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
1585dc0f0a4SBarry Smith 
1595dc0f0a4SBarry Smith    Input Parameters:
1605dc0f0a4SBarry Smith +  comm - the MPI communicator
1615dc0f0a4SBarry Smith .  access_token - Globus access token, if NULL will check in options database for -globus_access_token XXX otherwise
1625dc0f0a4SBarry Smith                   will call PetscGlobusAuthorize().
1635dc0f0a4SBarry Smith -  buffsize - size of the buffer
1645dc0f0a4SBarry Smith 
1655dc0f0a4SBarry Smith    Output Parameters:
1665dc0f0a4SBarry Smith .  buff - location to put Globus information
1675dc0f0a4SBarry Smith 
1682b26979fSBarry Smith    Level: intermediate
1692b26979fSBarry Smith 
1705dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload(), PetscGlobusAuthorize()
1715dc0f0a4SBarry Smith 
1725dc0f0a4SBarry Smith @*/
1735dc0f0a4SBarry Smith PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm,const char access_token[],char buff[],size_t buffsize)
1745dc0f0a4SBarry Smith {
1755dc0f0a4SBarry Smith   SSL_CTX        *ctx;
1765dc0f0a4SBarry Smith   SSL            *ssl;
1775dc0f0a4SBarry Smith   int            sock;
1785dc0f0a4SBarry Smith   PetscErrorCode ierr;
1795dc0f0a4SBarry Smith   char           head[4096];
1805dc0f0a4SBarry Smith   PetscMPIInt    rank;
1815dc0f0a4SBarry Smith 
1825dc0f0a4SBarry Smith   PetscFunctionBegin;
183ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
184dd400576SPatrick Sanan   if (rank == 0) {
1855dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization : Globus-Goauthtoken ");CHKERRQ(ierr);
1865dc0f0a4SBarry Smith     if (access_token) {
1875dc0f0a4SBarry Smith       ierr = PetscStrcat(head,access_token);CHKERRQ(ierr);
1885dc0f0a4SBarry Smith     } else {
1895dc0f0a4SBarry Smith       PetscBool set;
1905dc0f0a4SBarry Smith       char      accesstoken[4096];
191c5929fdfSBarry Smith       ierr = PetscOptionsGetString(NULL,NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set);CHKERRQ(ierr);
192*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!set,PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
1935dc0f0a4SBarry Smith       ierr = PetscStrcat(head,accesstoken);CHKERRQ(ierr);
1945dc0f0a4SBarry Smith     }
1955dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
1965dc0f0a4SBarry Smith 
1975dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
1985dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
1995dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/tasksummary",head,"application/json",NULL,ssl,buff,buffsize);CHKERRQ(ierr);
2005dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
2015dc0f0a4SBarry Smith     close(sock);
2025dc0f0a4SBarry Smith   }
2035dc0f0a4SBarry Smith   PetscFunctionReturn(0);
2045dc0f0a4SBarry Smith }
2055dc0f0a4SBarry Smith 
2065dc0f0a4SBarry Smith /*@C
2075dc0f0a4SBarry Smith      PetscGlobusUpload - Loads a file to Globus
2085dc0f0a4SBarry Smith 
2095dc0f0a4SBarry Smith      Not collective, only the first process in the MPI_Comm uploads the file
2105dc0f0a4SBarry Smith 
2115dc0f0a4SBarry Smith   Input Parameters:
2125dc0f0a4SBarry Smith +   comm - MPI communicator
2135dc0f0a4SBarry Smith .   access_token - obtained with PetscGlobusAuthorize(), pass NULL to use -globus_access_token XXX from the PETSc database
2145dc0f0a4SBarry Smith -   filename - file to upload
2155dc0f0a4SBarry Smith 
2165dc0f0a4SBarry Smith   Options Database:
21710699b91SBarry Smith .  -globus_access_token XXX - the Globus token
2185dc0f0a4SBarry Smith 
2192b26979fSBarry Smith    Level: intermediate
2202b26979fSBarry Smith 
2215dc0f0a4SBarry Smith .seealso: PetscURLShorten(), PetscGoogleDriveAuthorize(), PetscGoogleDriveRefresh(), PetscGlobusAuthorize()
2225dc0f0a4SBarry Smith 
2235dc0f0a4SBarry Smith @*/
2245dc0f0a4SBarry Smith PetscErrorCode PetscGlobusUpload(MPI_Comm comm,const char access_token[],const char filename[])
2255dc0f0a4SBarry Smith {
2265dc0f0a4SBarry Smith   SSL_CTX        *ctx;
2275dc0f0a4SBarry Smith   SSL            *ssl;
2285dc0f0a4SBarry Smith   int            sock;
2295dc0f0a4SBarry Smith   PetscErrorCode ierr;
2305dc0f0a4SBarry Smith   char           head[4096],buff[8*1024],body[4096],submission_id[4096];
2315dc0f0a4SBarry Smith   PetscMPIInt    rank;
2325dc0f0a4SBarry Smith   PetscBool      flg,found;
2335dc0f0a4SBarry Smith 
2345dc0f0a4SBarry Smith   PetscFunctionBegin;
235ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
236dd400576SPatrick Sanan   if (rank == 0) {
2375dc0f0a4SBarry Smith     ierr = PetscTestFile(filename,'r',&flg);CHKERRQ(ierr);
238*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to find file: %s",filename);
2395dc0f0a4SBarry Smith 
2405dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization : Globus-Goauthtoken ");CHKERRQ(ierr);
2415dc0f0a4SBarry Smith     if (access_token) {
2425dc0f0a4SBarry Smith       ierr = PetscStrcat(head,access_token);CHKERRQ(ierr);
2435dc0f0a4SBarry Smith     } else {
2445dc0f0a4SBarry Smith       PetscBool set;
2455dc0f0a4SBarry Smith       char      accesstoken[4096];
246c5929fdfSBarry Smith       ierr = PetscOptionsGetString(NULL,NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set);CHKERRQ(ierr);
247*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!set,PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
2485dc0f0a4SBarry Smith       ierr = PetscStrcat(head,accesstoken);CHKERRQ(ierr);
2495dc0f0a4SBarry Smith     }
2505dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
2515dc0f0a4SBarry Smith 
2525dc0f0a4SBarry Smith     /* Get Globus submission id */
2535dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
2545dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
2555dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/submission_id",head,"application/json",NULL,ssl,buff,sizeof(buff));CHKERRQ(ierr);
2565dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
2575dc0f0a4SBarry Smith     close(sock);
2585dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"value",submission_id,sizeof(submission_id),&found);CHKERRQ(ierr);
259*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return submission id");
2605dc0f0a4SBarry Smith 
2615dc0f0a4SBarry Smith     /* build JSON body of transfer request */
2625dc0f0a4SBarry Smith     ierr = PetscStrcpy(body,"{");CHKERRQ(ierr);
2635dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"submission_id",submission_id,sizeof(body));CHKERRQ(ierr);                 ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2645dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"DATA_TYPE","transfer",sizeof(body));CHKERRQ(ierr);                        ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2655dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"sync_level","null",sizeof(body));CHKERRQ(ierr);                           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2665dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"source_endpoint","barryfsmith#MacBookPro",sizeof(body));CHKERRQ(ierr);    ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2675dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"label","PETSc transfer label",sizeof(body));CHKERRQ(ierr);                ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2685dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"length","1",sizeof(body));CHKERRQ(ierr);                                  ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2695dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"destination_endpoint","mcs#home",sizeof(body));CHKERRQ(ierr);             ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2705dc0f0a4SBarry Smith 
2715dc0f0a4SBarry Smith     ierr = PetscStrcat(body,"\"DATA\": [ {");CHKERRQ(ierr);
2725dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"source_path","/~/FEM_GPU.pdf",sizeof(body));CHKERRQ(ierr);                ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2735dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"destination_path","/~/FEM_GPU.pdf",sizeof(body));CHKERRQ(ierr);           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2745dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"verify_size","null",sizeof(body));CHKERRQ(ierr);                          ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2755dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"recursive","false",sizeof(body));CHKERRQ(ierr);                           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
2765dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"DATA_TYPE","transfer_item",sizeof(body));CHKERRQ(ierr);
2775dc0f0a4SBarry Smith     ierr = PetscStrcat(body,"} ] }");CHKERRQ(ierr);
2785dc0f0a4SBarry Smith 
2795dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
2805dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
2815dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("POST","transfer.api.globusonline.org/v0.10/transfer",head,"application/json",body,ssl,buff,sizeof(buff));CHKERRQ(ierr);
2825dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
2835dc0f0a4SBarry Smith     close(sock);
2845dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"code",submission_id,sizeof(submission_id),&found);CHKERRQ(ierr);
285*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return code on transfer");
2865dc0f0a4SBarry Smith     ierr = PetscStrcmp(submission_id,"Accepted",&found);CHKERRQ(ierr);
287*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not accept transfer");
2885dc0f0a4SBarry Smith   }
2895dc0f0a4SBarry Smith   PetscFunctionReturn(0);
2905dc0f0a4SBarry Smith }
2915dc0f0a4SBarry Smith 
292