245223f8425d2746927b1a5957dbbd2fadc0e9d1
[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");
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");
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");
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");
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_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", 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_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res));
109         curl_easy_cleanup(curl);
110         return NTS_ERR_FAILED;
111     }
112
113     if(response_code) {
114         long http_rc;
115         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
116         *response_code = http_rc;
117     }
118
119     if(recv_data) {
120         *recv_data = response_data.response;
121     }
122
123     curl_easy_cleanup(curl);
124     return NTS_ERR_OK;
125 }
126
127 int http_socket_request(const char *url, const char *sock_fname, const char *method, const char *send_data, int *response_code, char **recv_data) {
128     assert(url);
129     assert(sock_fname);
130     assert(method);
131
132     const char *send_data_good = send_data;
133     if(!send_data_good) {
134         send_data_good = "";
135     }
136
137     CURL *curl = curl_easy_init();
138     if(curl == 0) {
139         log_error("could not initialize cURL");
140         return NTS_ERR_FAILED;
141     }
142
143     // set curl options
144     struct curl_slist *header = 0;
145     header = curl_slist_append(header, "Content-Type: application/json");
146     if(!header) {
147         log_error("curl_slist_append failed");
148         curl_easy_cleanup(curl);
149         return NTS_ERR_FAILED;
150     }
151
152     header = curl_slist_append(header, "Accept: application/json");
153     if(!header) {
154         log_error("curl_slist_append failed");
155         curl_easy_cleanup(curl);
156         return NTS_ERR_FAILED;
157     }
158
159     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
160     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);     //seconds timeout for a connection
161     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L);            //seconds timeout for an operation
162     curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
163     curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
164
165     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
166     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_data_good);
167     curl_easy_setopt(curl, CURLOPT_URL, url);
168     curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, sock_fname);
169
170     struct memory response_data = {0};
171     if(recv_data) {
172         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
173         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response_data);
174     }
175     
176     log_message(2, "%s-ing cURL to url=\"%s\" with body=\"%s\"\n", method, url, send_data_good);
177     CURLcode res = curl_easy_perform(curl);
178     curl_slist_free_all(header);
179
180     if(res != CURLE_OK) {
181         log_message(2, "--> could not send cURL to url=%s, with error: %s\n", url, curl_easy_strerror(res));
182         curl_easy_cleanup(curl);
183         return NTS_ERR_FAILED;
184     }
185
186     if(response_code) {
187         long http_rc;
188         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
189         *response_code = http_rc;
190     }
191
192     if(recv_data) {
193         *recv_data = response_data.response;
194     }
195
196     curl_easy_cleanup(curl);
197     return NTS_ERR_OK;
198 }
199
200 static size_t curl_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
201     size_t realsize = size * nmemb;
202     struct memory *mem = (struct memory *)userp;
203
204     char *ptr = realloc(mem->response, mem->size + realsize + 1);
205     if(ptr == NULL) {
206         log_error("realloc failed");
207         return 0;  /* out of memory! */
208     }
209
210     mem->response = ptr;
211     memcpy(&(mem->response[mem->size]), data, realsize);
212     mem->size += realsize;
213     mem->response[mem->size] = 0;
214
215     return realsize;
216 }