xref: /petsc/src/sys/webclient/globus.c (revision 5dc0f0a4f1e5fadabb4a56402c5d08263bae98d2)
1*5dc0f0a4SBarry Smith #include <stdint.h>
2*5dc0f0a4SBarry Smith #include <stdlib.h>
3*5dc0f0a4SBarry Smith #include <petscwebclient.h>
4*5dc0f0a4SBarry Smith 
5*5dc0f0a4SBarry Smith /*
6*5dc0f0a4SBarry Smith     Encodes and decodes from MIME Base64
7*5dc0f0a4SBarry Smith */
8*5dc0f0a4SBarry Smith static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
9*5dc0f0a4SBarry Smith                                 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
10*5dc0f0a4SBarry Smith                                 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
11*5dc0f0a4SBarry Smith                                 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
12*5dc0f0a4SBarry Smith                                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
13*5dc0f0a4SBarry Smith                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
14*5dc0f0a4SBarry Smith                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
15*5dc0f0a4SBarry Smith                                 '4', '5', '6', '7', '8', '9', '+', '/'};
16*5dc0f0a4SBarry Smith 
17*5dc0f0a4SBarry Smith static PetscErrorCode base64_encode(const unsigned char *data,unsigned char *encoded_data,size_t len)
18*5dc0f0a4SBarry Smith {
19*5dc0f0a4SBarry Smith   static int     mod_table[] = {0, 2, 1};
20*5dc0f0a4SBarry Smith   int            i,j;
21*5dc0f0a4SBarry Smith   size_t         input_length,output_length;
22*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
23*5dc0f0a4SBarry Smith 
24*5dc0f0a4SBarry Smith   PetscFunctionBegin;
25*5dc0f0a4SBarry Smith   ierr = PetscStrlen((const char*)data,&input_length);CHKERRQ(ierr);
26*5dc0f0a4SBarry Smith   output_length = 4 * ((input_length + 2) / 3);
27*5dc0f0a4SBarry Smith   if (output_length > len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length not large enough");
28*5dc0f0a4SBarry Smith 
29*5dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
30*5dc0f0a4SBarry Smith      uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
31*5dc0f0a4SBarry Smith      uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
32*5dc0f0a4SBarry Smith      uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
33*5dc0f0a4SBarry Smith      uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
34*5dc0f0a4SBarry Smith 
35*5dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
36*5dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
37*5dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
38*5dc0f0a4SBarry Smith      encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
39*5dc0f0a4SBarry Smith   }
40*5dc0f0a4SBarry Smith   encoded_data[j] = 0;
41*5dc0f0a4SBarry Smith   for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[output_length - 1 - i] = '=';
42*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
43*5dc0f0a4SBarry Smith }
44*5dc0f0a4SBarry Smith 
45*5dc0f0a4SBarry Smith PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data,unsigned char* decoded_data, size_t length)
46*5dc0f0a4SBarry Smith {
47*5dc0f0a4SBarry Smith   static char    decoding_table[257];
48*5dc0f0a4SBarry Smith   static int     decode_table_built = 0;
49*5dc0f0a4SBarry Smith   int            i,j;
50*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
51*5dc0f0a4SBarry Smith   size_t         input_length,output_length;
52*5dc0f0a4SBarry Smith 
53*5dc0f0a4SBarry Smith   PetscFunctionBegin;
54*5dc0f0a4SBarry Smith   if (!decode_table_built) {
55*5dc0f0a4SBarry Smith     for (i = 0; i < 64; i++) decoding_table[(unsigned char) encoding_table[i]] = i;
56*5dc0f0a4SBarry Smith     decode_table_built = 1;
57*5dc0f0a4SBarry Smith   }
58*5dc0f0a4SBarry Smith 
59*5dc0f0a4SBarry Smith   ierr = PetscStrlen((const char*)data,&input_length);CHKERRQ(ierr);
60*5dc0f0a4SBarry Smith   if (input_length % 4 != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input length must be divisible by 4");
61*5dc0f0a4SBarry Smith 
62*5dc0f0a4SBarry Smith   output_length = input_length / 4 * 3;
63*5dc0f0a4SBarry Smith   if (data[input_length - 1] == '=') (output_length)--;
64*5dc0f0a4SBarry Smith   if (data[input_length - 2] == '=') (output_length)--;
65*5dc0f0a4SBarry Smith   if (output_length > length) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Output length too shore");
66*5dc0f0a4SBarry Smith 
67*5dc0f0a4SBarry Smith   for (i = 0, j = 0; i < input_length;) {
68*5dc0f0a4SBarry Smith     uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
69*5dc0f0a4SBarry Smith     uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
70*5dc0f0a4SBarry Smith     uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
71*5dc0f0a4SBarry Smith     uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
72*5dc0f0a4SBarry Smith     uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
73*5dc0f0a4SBarry Smith 
74*5dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
75*5dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
76*5dc0f0a4SBarry Smith     if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
77*5dc0f0a4SBarry Smith   }
78*5dc0f0a4SBarry Smith   decoded_data[j] = 0;
79*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
80*5dc0f0a4SBarry Smith }
81*5dc0f0a4SBarry Smith 
82*5dc0f0a4SBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
83*5dc0f0a4SBarry Smith #include <unistd.h>
84*5dc0f0a4SBarry Smith #endif
85*5dc0f0a4SBarry Smith 
86*5dc0f0a4SBarry Smith #undef __FUNCT__
87*5dc0f0a4SBarry Smith #define __FUNCT__ "PetscGlobusAuthorize"
88*5dc0f0a4SBarry Smith /*@C
89*5dc0f0a4SBarry Smith      PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests
90*5dc0f0a4SBarry Smith 
91*5dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
92*5dc0f0a4SBarry Smith 
93*5dc0f0a4SBarry Smith    Input Parameters:
94*5dc0f0a4SBarry Smith +  comm - the MPI communicator
95*5dc0f0a4SBarry Smith -  tokensize - size of the token array
96*5dc0f0a4SBarry Smith 
97*5dc0f0a4SBarry Smith    Output Parameters:
98*5dc0f0a4SBarry Smith .  access_token - can be used with PetscGlobusUpLoad() for 30 days
99*5dc0f0a4SBarry Smith 
100*5dc0f0a4SBarry Smith    Notes: This call requires stdout and stdin access from process 0 on the MPI communicator
101*5dc0f0a4SBarry Smith 
102*5dc0f0a4SBarry Smith    You can run src/sys/webclient/examples/tutorials/globusobtainaccesstoken to get an access token
103*5dc0f0a4SBarry Smith 
104*5dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload()
105*5dc0f0a4SBarry Smith 
106*5dc0f0a4SBarry Smith @*/
107*5dc0f0a4SBarry Smith PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm,char access_token[],size_t tokensize)
108*5dc0f0a4SBarry Smith {
109*5dc0f0a4SBarry Smith   SSL_CTX        *ctx;
110*5dc0f0a4SBarry Smith   SSL            *ssl;
111*5dc0f0a4SBarry Smith   int            sock;
112*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
113*5dc0f0a4SBarry Smith   char           buff[8*1024],*ptr,head[1024];
114*5dc0f0a4SBarry Smith   PetscMPIInt    rank;
115*5dc0f0a4SBarry Smith   size_t         len;
116*5dc0f0a4SBarry Smith   PetscBool      found;
117*5dc0f0a4SBarry Smith 
118*5dc0f0a4SBarry Smith   PetscFunctionBegin;
119*5dc0f0a4SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
120*5dc0f0a4SBarry Smith   if (!rank) {
121*5dc0f0a4SBarry Smith     if (!isatty(fileno(PETSC_STDOUT))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output");
122*5dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"Enter globus username:");CHKERRQ(ierr);
123*5dc0f0a4SBarry Smith     ptr  = fgets(buff, 1024, stdin);
124*5dc0f0a4SBarry Smith     if (!ptr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
125*5dc0f0a4SBarry Smith     ierr = PetscStrlen(buff,&len);CHKERRQ(ierr);
126*5dc0f0a4SBarry Smith     buff[len-1] = ':'; /* remove carriage return at end of line */
127*5dc0f0a4SBarry Smith 
128*5dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"Enter globus password:");CHKERRQ(ierr);
129*5dc0f0a4SBarry Smith     ptr  = fgets(buff+len, 1024-len, stdin);
130*5dc0f0a4SBarry Smith     if (!ptr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno);
131*5dc0f0a4SBarry Smith     ierr = PetscStrlen(buff,&len);CHKERRQ(ierr);
132*5dc0f0a4SBarry Smith     buff[len-1] = '\0'; /* remove carriage return at end of line */
133*5dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization: Basic ");CHKERRQ(ierr);
134*5dc0f0a4SBarry Smith     ierr = base64_encode((const unsigned char*)buff,(unsigned char*)(head+21),sizeof(head)-21);CHKERRQ(ierr);
135*5dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
136*5dc0f0a4SBarry Smith 
137*5dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
138*5dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("nexus.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
139*5dc0f0a4SBarry 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);
140*5dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
141*5dc0f0a4SBarry Smith     close(sock);
142*5dc0f0a4SBarry Smith 
143*5dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr);
144*5dc0f0a4SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return access token");
145*5dc0f0a4SBarry Smith 
146*5dc0f0a4SBarry 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);
147*5dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"programs with the option -globus_access_token %s\n",access_token);CHKERRQ(ierr);
148*5dc0f0a4SBarry Smith     ierr = PetscPrintf(comm,"to access Globus automatically\n");CHKERRQ(ierr);
149*5dc0f0a4SBarry Smith   }
150*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
151*5dc0f0a4SBarry Smith }
152*5dc0f0a4SBarry Smith 
153*5dc0f0a4SBarry Smith 
154*5dc0f0a4SBarry Smith #undef __FUNCT__
155*5dc0f0a4SBarry Smith #define __FUNCT__ "PetscGlobusGetTransfers"
156*5dc0f0a4SBarry Smith /*@C
157*5dc0f0a4SBarry Smith      PetscGlobusGetTransfers - Get a record of current transfers requested from Globus
158*5dc0f0a4SBarry Smith 
159*5dc0f0a4SBarry Smith    Not collective, only the first process in MPI_Comm does anything
160*5dc0f0a4SBarry Smith 
161*5dc0f0a4SBarry Smith    Input Parameters:
162*5dc0f0a4SBarry Smith +  comm - the MPI communicator
163*5dc0f0a4SBarry Smith .  access_token - Globus access token, if NULL will check in options database for -globus_access_token XXX otherwise
164*5dc0f0a4SBarry Smith                   will call PetscGlobusAuthorize().
165*5dc0f0a4SBarry Smith -  buffsize - size of the buffer
166*5dc0f0a4SBarry Smith 
167*5dc0f0a4SBarry Smith    Output Parameters:
168*5dc0f0a4SBarry Smith .  buff - location to put Globus information
169*5dc0f0a4SBarry Smith 
170*5dc0f0a4SBarry Smith .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten(), PetscGlobusUpload(), PetscGlobusAuthorize()
171*5dc0f0a4SBarry Smith 
172*5dc0f0a4SBarry Smith @*/
173*5dc0f0a4SBarry Smith PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm,const char access_token[],char buff[],size_t buffsize)
174*5dc0f0a4SBarry Smith {
175*5dc0f0a4SBarry Smith   SSL_CTX        *ctx;
176*5dc0f0a4SBarry Smith   SSL            *ssl;
177*5dc0f0a4SBarry Smith   int            sock;
178*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
179*5dc0f0a4SBarry Smith   char           head[4096];
180*5dc0f0a4SBarry Smith   PetscMPIInt    rank;
181*5dc0f0a4SBarry Smith 
182*5dc0f0a4SBarry Smith   PetscFunctionBegin;
183*5dc0f0a4SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
184*5dc0f0a4SBarry Smith   if (!rank) {
185*5dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization : Globus-Goauthtoken ");CHKERRQ(ierr);
186*5dc0f0a4SBarry Smith     if (access_token) {
187*5dc0f0a4SBarry Smith       ierr = PetscStrcat(head,access_token);CHKERRQ(ierr);
188*5dc0f0a4SBarry Smith     } else {
189*5dc0f0a4SBarry Smith       PetscBool set;
190*5dc0f0a4SBarry Smith       char      accesstoken[4096];
191*5dc0f0a4SBarry Smith       ierr = PetscOptionsGetString(NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set);CHKERRQ(ierr);
192*5dc0f0a4SBarry Smith       if (!set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
193*5dc0f0a4SBarry Smith       ierr = PetscStrcat(head,accesstoken);CHKERRQ(ierr);
194*5dc0f0a4SBarry Smith     }
195*5dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
196*5dc0f0a4SBarry Smith 
197*5dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
198*5dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
199*5dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/tasksummary",head,"application/json",NULL,ssl,buff,buffsize);CHKERRQ(ierr);
200*5dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
201*5dc0f0a4SBarry Smith     close(sock);
202*5dc0f0a4SBarry Smith   }
203*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
204*5dc0f0a4SBarry Smith }
205*5dc0f0a4SBarry Smith 
206*5dc0f0a4SBarry Smith #undef __FUNCT__
207*5dc0f0a4SBarry Smith #define __FUNCT__ "PetscGlobusUpload"
208*5dc0f0a4SBarry Smith /*@C
209*5dc0f0a4SBarry Smith      PetscGlobusUpload - Loads a file to Globus
210*5dc0f0a4SBarry Smith 
211*5dc0f0a4SBarry Smith      Not collective, only the first process in the MPI_Comm uploads the file
212*5dc0f0a4SBarry Smith 
213*5dc0f0a4SBarry Smith   Input Parameters:
214*5dc0f0a4SBarry Smith +   comm - MPI communicator
215*5dc0f0a4SBarry Smith .   access_token - obtained with PetscGlobusAuthorize(), pass NULL to use -globus_access_token XXX from the PETSc database
216*5dc0f0a4SBarry Smith -   filename - file to upload
217*5dc0f0a4SBarry Smith 
218*5dc0f0a4SBarry Smith   Options Database:
219*5dc0f0a4SBarry Smith .  -globus_access_token   XXX
220*5dc0f0a4SBarry Smith 
221*5dc0f0a4SBarry Smith .seealso: PetscURLShorten(), PetscGoogleDriveAuthorize(), PetscGoogleDriveRefresh(), PetscGlobusAuthorize()
222*5dc0f0a4SBarry Smith 
223*5dc0f0a4SBarry Smith @*/
224*5dc0f0a4SBarry Smith PetscErrorCode PetscGlobusUpload(MPI_Comm comm,const char access_token[],const char filename[])
225*5dc0f0a4SBarry Smith {
226*5dc0f0a4SBarry Smith   SSL_CTX        *ctx;
227*5dc0f0a4SBarry Smith   SSL            *ssl;
228*5dc0f0a4SBarry Smith   int            sock;
229*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
230*5dc0f0a4SBarry Smith   char           head[4096],buff[8*1024],body[4096],submission_id[4096];
231*5dc0f0a4SBarry Smith   PetscMPIInt    rank;
232*5dc0f0a4SBarry Smith   PetscBool      flg,found;
233*5dc0f0a4SBarry Smith 
234*5dc0f0a4SBarry Smith   PetscFunctionBegin;
235*5dc0f0a4SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
236*5dc0f0a4SBarry Smith   if (!rank) {
237*5dc0f0a4SBarry Smith     ierr = PetscTestFile(filename,'r',&flg);CHKERRQ(ierr);
238*5dc0f0a4SBarry Smith     if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to find file: %s",filename);
239*5dc0f0a4SBarry Smith 
240*5dc0f0a4SBarry Smith     ierr = PetscStrcpy(head,"Authorization : Globus-Goauthtoken ");CHKERRQ(ierr);
241*5dc0f0a4SBarry Smith     if (access_token) {
242*5dc0f0a4SBarry Smith       ierr = PetscStrcat(head,access_token);CHKERRQ(ierr);
243*5dc0f0a4SBarry Smith     } else {
244*5dc0f0a4SBarry Smith       PetscBool set;
245*5dc0f0a4SBarry Smith       char      accesstoken[4096];
246*5dc0f0a4SBarry Smith       ierr = PetscOptionsGetString(NULL,"-globus_access_token",accesstoken,sizeof(accesstoken),&set);CHKERRQ(ierr);
247*5dc0f0a4SBarry Smith       if (!set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Pass in Globus accesstoken or use -globus_access_token XXX");
248*5dc0f0a4SBarry Smith       ierr = PetscStrcat(head,accesstoken);CHKERRQ(ierr);
249*5dc0f0a4SBarry Smith     }
250*5dc0f0a4SBarry Smith     ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr);
251*5dc0f0a4SBarry Smith 
252*5dc0f0a4SBarry Smith     /* Get Globus submission id */
253*5dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
254*5dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
255*5dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("GET","transfer.api.globusonline.org/v0.10/submission_id",head,"application/json",NULL,ssl,buff,sizeof(buff));CHKERRQ(ierr);
256*5dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
257*5dc0f0a4SBarry Smith     close(sock);
258*5dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"value",submission_id,sizeof(submission_id),&found);CHKERRQ(ierr);
259*5dc0f0a4SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return submission id");
260*5dc0f0a4SBarry Smith 
261*5dc0f0a4SBarry Smith     /* build JSON body of transfer request */
262*5dc0f0a4SBarry Smith     ierr = PetscStrcpy(body,"{");CHKERRQ(ierr);
263*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"submission_id",submission_id,sizeof(body));CHKERRQ(ierr);                 ierr = PetscStrcat(body,",");CHKERRQ(ierr);
264*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"DATA_TYPE","transfer",sizeof(body));CHKERRQ(ierr);                        ierr = PetscStrcat(body,",");CHKERRQ(ierr);
265*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"sync_level","null",sizeof(body));CHKERRQ(ierr);                           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
266*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"source_endpoint","barryfsmith#MacBookPro",sizeof(body));CHKERRQ(ierr);    ierr = PetscStrcat(body,",");CHKERRQ(ierr);
267*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"label","PETSc transfer label",sizeof(body));CHKERRQ(ierr);                ierr = PetscStrcat(body,",");CHKERRQ(ierr);
268*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"length","1",sizeof(body));CHKERRQ(ierr);                                  ierr = PetscStrcat(body,",");CHKERRQ(ierr);
269*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"destination_endpoint","mcs#home",sizeof(body));CHKERRQ(ierr);             ierr = PetscStrcat(body,",");CHKERRQ(ierr);
270*5dc0f0a4SBarry Smith 
271*5dc0f0a4SBarry Smith     ierr = PetscStrcat(body,"\"DATA\": [ {");CHKERRQ(ierr);
272*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"source_path","/~/FEM_GPU.pdf",sizeof(body));CHKERRQ(ierr);                ierr = PetscStrcat(body,",");CHKERRQ(ierr);
273*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"destination_path","/~/FEM_GPU.pdf",sizeof(body));CHKERRQ(ierr);           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
274*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"verify_size","null",sizeof(body));CHKERRQ(ierr);                          ierr = PetscStrcat(body,",");CHKERRQ(ierr);
275*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"recursive","false",sizeof(body));CHKERRQ(ierr);                           ierr = PetscStrcat(body,",");CHKERRQ(ierr);
276*5dc0f0a4SBarry Smith     ierr = PetscPushJSONValue(body,"DATA_TYPE","transfer_item",sizeof(body));CHKERRQ(ierr);
277*5dc0f0a4SBarry Smith     ierr = PetscStrcat(body,"} ] }");CHKERRQ(ierr);
278*5dc0f0a4SBarry Smith 
279*5dc0f0a4SBarry Smith     ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr);
280*5dc0f0a4SBarry Smith     ierr = PetscHTTPSConnect("transfer.api.globusonline.org",443,ctx,&sock,&ssl);CHKERRQ(ierr);
281*5dc0f0a4SBarry Smith     ierr = PetscHTTPSRequest("POST","transfer.api.globusonline.org/v0.10/transfer",head,"application/json",body,ssl,buff,sizeof(buff));CHKERRQ(ierr);
282*5dc0f0a4SBarry Smith     ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr);
283*5dc0f0a4SBarry Smith     close(sock);
284*5dc0f0a4SBarry Smith     ierr   = PetscPullJSONValue(buff,"code",submission_id,sizeof(submission_id),&found);CHKERRQ(ierr);
285*5dc0f0a4SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not return code on transfer");
286*5dc0f0a4SBarry Smith     ierr = PetscStrcmp(submission_id,"Accepted",&found);CHKERRQ(ierr);
287*5dc0f0a4SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Globus did not accept transfer");
288*5dc0f0a4SBarry Smith   }
289*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
290*5dc0f0a4SBarry Smith }
291*5dc0f0a4SBarry Smith 
292*5dc0f0a4SBarry Smith 
293