4578dd46e79028fb37b88e5bcac10b4b2cdd3db3
[sim/o1-interface.git] / ntsimulator / ntsim-ng / utils / http_client.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "http_client.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include <curl/curl.h>
29
30 struct memory {
31     char *response;
32     size_t size;
33 };
34
35 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp);
36  
37 int http_request(const char *url, const char *username, const char* password, const char *method, const char *send_data, int *response_code, char **recv_data) {
38     assert(url);
39     assert(method);
40
41     const char *send_data_good = send_data;
42     if(!send_data_good) {
43         send_data_good = "";
44     }
45
46     CURL *curl = curl_easy_init();
47     if(curl == 0) {
48         log_error("could not initialize cURL\n");
49         return NTS_ERR_FAILED;
50     }
51
52     // set curl options
53     struct curl_slist *header = 0;
54     header = curl_slist_append(header, "Content-Type: application/json");
55     if(!header) {
56         log_error("curl_slist_append failed\n");
57         curl_easy_cleanup(curl);
58         return NTS_ERR_FAILED;
59     }
60
61     header = curl_slist_append(header, "Accept: application/json");
62     if(!header) {
63         log_error("curl_slist_append failed\n");
64         curl_easy_cleanup(curl);
65         return NTS_ERR_FAILED;
66     }
67
68     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
69     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);     //seconds timeout for a connection
70     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);            //seconds timeout for an operation
71     curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
72     curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
73
74     // disable SSL verifications
75     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
76     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
77     curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
78     curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
79
80     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
81     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
82     curl_easy_setopt(curl, CURLOPT_URL, url);
83
84     if((username) && (password)) {
85         char *credentials = 0;
86         asprintf(&credentials, "%s:%s", username, password);
87         if(credentials == 0) {
88             log_error("asprintf failed\n");
89             curl_slist_free_all(header);
90             curl_easy_cleanup(curl);
91             return NTS_ERR_FAILED;
92         }
93         curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
94         free(credentials);
95     }
96
97     struct memory response_data = {0};
98     if(recv_data) {
99         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
100         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
101     }
102     
103     log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"... ", method, url, send_data_good);
104     CURLcode res = curl_easy_perform(curl);
105     curl_slist_free_all(header);
106
107     if(res != CURLE_OK) {
108         log_add(2, "failed with error: %s\n", curl_easy_strerror(res));
109         curl_easy_cleanup(curl);
110         return NTS_ERR_FAILED;
111     }
112     else {
113         log_add(2, "success\n");
114     }
115
116     if(response_code) {
117         long http_rc;
118         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
119         *response_code = http_rc;
120     }
121
122     if(recv_data) {
123         *recv_data = response_data.response;
124     }
125
126     curl_easy_cleanup(curl);
127     return NTS_ERR_OK;
128 }
129
130 int http_socket_request(const char *url, const char *sock_fname, const char *method, const char *send_data, int *response_code, char **recv_data) {
131     assert(url);
132     assert(sock_fname);
133     assert(method);
134
135     const char *send_data_good = send_data;
136     if(!send_data_good) {
137         send_data_good = "";
138     }
139
140     CURL *curl = curl_easy_init();
141     if(curl == 0) {
142         log_error("could not initialize cURL\n");
143         return NTS_ERR_FAILED;
144     }
145
146     // set curl options
147     struct curl_slist *header = 0;
148     header = curl_slist_append(header, "Content-Type: application/json");
149     if(!header) {
150         log_error("curl_slist_append failed\n");
151         curl_easy_cleanup(curl);
152         return NTS_ERR_FAILED;
153     }
154
155     header = curl_slist_append(header, "Accept: application/json");
156     if(!header) {
157         log_error("curl_slist_append failed\n");
158         curl_easy_cleanup(curl);
159         return NTS_ERR_FAILED;
160     }
161
162     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
163     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);     //seconds timeout for a connection
164     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);            //seconds timeout for an operation
165     curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
166     curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
167
168     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
169     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
170     curl_easy_setopt(curl, CURLOPT_URL, url);
171     curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, sock_fname);
172
173     struct memory response_data = {0};
174     if(recv_data) {
175         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
176         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
177     }
178     
179     log_add_verbose(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good);
180     CURLcode res = curl_easy_perform(curl);
181     curl_slist_free_all(header);
182
183     if(res != CURLE_OK) {
184         log_add(2, "failed with error %s\n", curl_easy_strerror(res));
185         curl_easy_cleanup(curl);
186         return NTS_ERR_FAILED;
187     }
188     else {
189         log_add(2, "success\n");
190     }
191
192     if(response_code) {
193         long http_rc;
194         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
195         *response_code = http_rc;
196     }
197
198     if(recv_data) {
199         *recv_data = response_data.response;
200     }
201
202     curl_easy_cleanup(curl);
203     return NTS_ERR_OK;
204 }
205
206 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
207     size_t realsize = size * nmemb;
208     struct memory *mem = (struct memory *)userp;
209
210     char *ptr = realloc(mem->response, mem->size + realsize + 1);
211     if(ptr == NULL) {
212         log_error("realloc failed\n");
213         return 0;  /* out of memory! */
214     }
215
216     mem->response = ptr;
217     memcpy(&(mem->response[mem->size]), data, realsize);
218     mem->size += realsize;
219     mem->response[mem->size] = 0;
220
221     return realsize;
222 }