Project

General

Profile

Statistics
| Branch: | Revision:

root / mainbox / query.c @ ea46eeca

History | View | Annotate | Download (7.05 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
  int len;
27

    
28
  server = server_name;
29

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

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

    
40
  return 0;
41
}
42

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

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

    
52
  to_read = nmemb;
53

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

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

    
62
  return to_read;
63
}
64

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

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

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

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

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

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

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

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

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

    
111
  curl_easy_cleanup(handle);
112
  return result;
113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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