Project

General

Profile

Statistics
| Branch: | Revision:

root / mainbox / query.c @ e247ef4d

History | View | Annotate | Download (7.04 KB)

1
#include "query.h"
2
#include "cache.h"
3
#include "event.h"
4
#include "util.h"
5
#include "log.h"
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <string.h>
9
#include <curl/curl.h>
10

    
11
/* Outputs the response to /add_card_event to debug.html */
12
//#define DEBUG_EVENT_RESPONSE
13

    
14
/* Size of buffer written to by write_buffer(). We are only reading integers
15
 * back from the server, so we don't need much of the response and anything
16
 * else can be ignored */
17
#define WRITE_BUFFER_SIZE 30
18

    
19
static const char *server;
20
static char *tooltron_password;
21
static char buffer[WRITE_BUFFER_SIZE];
22
static int buffer_idx;
23

    
24
int query_init(const char *server_name) {
25
  CURLcode error_code;
26

    
27
  server = server_name;
28

    
29
  error_code = curl_global_init(CURL_GLOBAL_SSL);
30
  if (error_code) {
31
    log_print("ERROR: curl_global_init: %s\n", curl_easy_strerror(error_code));
32
    return error_code;
33
  }
34

    
35
  tooltron_password = read_file("tooltron_password");
36
  if (tooltron_password == NULL)
37
    return 1;
38

    
39
  return 0;
40
}
41

    
42
void query_cleanup() {
43
  curl_global_cleanup();
44
  if (tooltron_password)
45
    free(tooltron_password);
46
}
47

    
48
static size_t write_buffer(void *buf_in, size_t size, size_t nmemb, void *userp) {
49
  size_t to_read;
50

    
51
  to_read = nmemb;
52

    
53
  if (buffer_idx + to_read*size > WRITE_BUFFER_SIZE)
54
    to_read = (WRITE_BUFFER_SIZE - buffer_idx)/size;
55

    
56
  if (to_read > 0) {
57
    memcpy(buffer+buffer_idx, buf_in, to_read*size);
58
    buffer_idx += to_read*size;
59
  }
60

    
61
  return to_read;
62
}
63

    
64
static size_t write_ignore(void *buffer, size_t size, size_t nmemb,
65
    void *userp) {
66
  return nmemb;
67
}
68

    
69
/*
70
 * do_q_user_perm
71
 *
72
 * Makes an HTTP request to the CRM server to see what tools user_id has access
73
 * to. Returns a bitmask, and returns 0 if there was a problem.
74
 */
75
unsigned int do_q_user_perm(unsigned int user_id) {
76
  CURL* handle;
77
  CURLcode error_code;
78
  char url[1024];
79
  int result = 0;
80
  long response = 0;
81

    
82
  handle = curl_easy_init();
83
  if (handle == NULL)
84
    return 0;
85

    
86
  sprintf(url, "http://%s/crm/roboauth/%08x/", server, user_id);
87
  error_code = curl_easy_setopt(handle, CURLOPT_URL, url);
88
  if (error_code) goto error;
89

    
90
  buffer_idx = 0;
91
  error_code = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_buffer);
92
  if (error_code) goto error;
93

    
94
  error_code = curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL);
95
  if (error_code) goto error;
96

    
97
  error_code = curl_easy_perform(handle);
98
  if (error_code) goto error;
99

    
100
  error_code = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response);
101
  if (error_code) goto error;
102
  if (response >= 400)
103
    log_print("ERROR: response %ld from %s", response, url);
104
  else if (response > 200)
105
    log_print("WARNING: response %ld from %s", response, url);
106

    
107
  result = atoi(buffer);
108
  cache_update(user_id, result);
109

    
110
  curl_easy_cleanup(handle);
111
  return result;
112

    
113
error:
114
  log_print("ERROR: curl: %s", curl_easy_strerror(error_code));
115
  log_print("ERROR:       when authenticating user %08x", user_id);
116
  curl_easy_cleanup(handle);
117
  return 0;
118
}
119

    
120
void do_refresh(unsigned int key) {
121
  do_q_user_perm(key);
122
}
123

    
124
/*
125
 * query_refresh_cache
126
 *
127
 * Queries the CRM server to update every user permission entry in the cache.
128
 */
129
void query_refresh_cache() {
130
  cache_foreach(do_refresh);
131
}
132

    
133
/*
134
 * query_user_permission
135
 *
136
 * Checks whether user_id has permission for tool_id. First checks the cache,
137
 * then if that fails, calls do_q_user_perm to make an HTTP request to the CRM
138
 * server.
139
 */
140
int query_user_permission(int tool_id, unsigned int user_id) {
141
  unsigned int result;
142

    
143
  if (cache_lookup(user_id, &result))
144
    log_print("Serving permissions for %08x from cache", user_id);
145
  else {
146
    log_print("Requesting permissions for %08x from server", user_id);
147
    result = do_q_user_perm(user_id);
148
  }
149

    
150
  return (result >> tool_id) & 1;
151
}
152

    
153
/*
154
 * query_add_event
155
 *
156
 * Makes an HTTPS POST request to add an event to the CRM server, including
157
 * user, tool, start time, and stop time. Reads the password from password.txt.
158
 * Returns 0 if successful, or 1 if there was an error and the caller should
159
 * try the same event again later.
160
 *
161
 * Times are represented as strftime's "%F %T", which is like "YYYY-MM-DD
162
 * HH:MM:SS" with 24-hour time
163
 */
164
int query_add_event(struct event_t *event) {
165
  CURL* handle;
166
  CURLcode error_code;
167
  struct curl_httppost *formpost = NULL, *lastptr = NULL;
168
  char buf[1024];
169
  struct tm *timeinfo;
170
  long response = 0;
171

    
172
#ifdef DEBUG_EVENT_RESPONSE
173
  FILE *fdebug;
174
  fdebug = fopen("debug.html", "w");
175
#endif
176

    
177
  handle = curl_easy_init();
178
  if (handle == NULL)
179
    return 1;
180

    
181
  curl_formadd(&formpost, &lastptr,
182
      CURLFORM_COPYNAME, "username",
183
      CURLFORM_COPYCONTENTS, "tooltron",
184
      CURLFORM_END);
185

    
186
  curl_formadd(&formpost, &lastptr,
187
      CURLFORM_COPYNAME, "password",
188
      CURLFORM_COPYCONTENTS, tooltron_password,
189
      CURLFORM_END);
190

    
191
  timeinfo = localtime(&event->tstart);
192
  strftime(buf, sizeof(buf), "%F %T", timeinfo);
193
  curl_formadd(&formpost, &lastptr,
194
      CURLFORM_COPYNAME, "tstart",
195
      CURLFORM_COPYCONTENTS, buf,
196
      CURLFORM_END);
197

    
198
  timeinfo = localtime(&event->tend);
199
  strftime(buf, sizeof(buf), "%F %T", timeinfo);
200
  curl_formadd(&formpost, &lastptr,
201
      CURLFORM_COPYNAME, "tend",
202
      CURLFORM_COPYCONTENTS, buf,
203
      CURLFORM_END);
204

    
205
  sprintf(buf, "%08x", event->user);
206
  curl_formadd(&formpost, &lastptr,
207
      CURLFORM_COPYNAME, "user_id",
208
      CURLFORM_COPYCONTENTS, buf,
209
      CURLFORM_END);
210

    
211
  sprintf(buf, "%d", event->tool_id);
212
  curl_formadd(&formpost, &lastptr,
213
      CURLFORM_COPYNAME, "machine_id",
214
      CURLFORM_COPYCONTENTS, buf,
215
      CURLFORM_END);
216

    
217
  curl_formadd(&formpost, &lastptr,
218
      CURLFORM_COPYNAME, "succ",
219
      CURLFORM_COPYCONTENTS, event->succ? "1" : "0",
220
      CURLFORM_END);
221

    
222
  sprintf(buf, "https://%s/crm/add_card_event/", server);
223
  //sprintf(buf, "http://%s/crm/add_card_event/", server);
224
  error_code = curl_easy_setopt(handle, CURLOPT_URL, buf);
225
  if (error_code) goto error;
226

    
227
  /* TODO disabling host and peer verification should theoretically be removed
228
   * eventually */
229
  error_code = curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);
230
  if (error_code) goto error;
231

    
232
  error_code = curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);
233
  if (error_code) goto error;
234

    
235
#ifdef DEBUG_EVENT_RESPONSE
236
  error_code = curl_easy_setopt(handle, CURLOPT_WRITEDATA, fdebug);
237
#else
238
  error_code = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_ignore);
239
#endif
240
  if (error_code) goto error;
241

    
242
  error_code = curl_easy_setopt(handle, CURLOPT_HTTPPOST, formpost);
243
  if (error_code) goto error;
244

    
245
  error_code = curl_easy_perform(handle);
246
  if (error_code) goto error;
247

    
248
  error_code = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response);
249
  if (error_code) goto error;
250
  if (response >= 400)
251
    log_print("ERROR: response %ld from %s", response, buf);
252
  else if (response > 200)
253
    log_print("WARNING: response %ld from %s", response, buf);
254

    
255
  curl_easy_cleanup(handle);
256
  curl_formfree(formpost);
257
#ifdef DEBUG_EVENT_RESPONSE
258
  fclose(fdebug);
259
#endif
260
  return response >= 300;
261

    
262
error:
263
  log_print("ERROR: curl: %s", curl_easy_strerror(error_code));
264
  curl_easy_cleanup(handle);
265
  curl_formfree(formpost);
266
#ifdef DEBUG_EVENT_RESPONSE
267
  fclose(fdebug);
268
#endif
269
  return 1;
270
}