Oops, add missing files.
[monky] / src / ccurl_thread.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Please see COPYING for details
5  *
6  * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
7  *      (see AUTHORS)
8  * All rights reserved.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "conky.h"
25 #include "logging.h"
26 #include "ccurl_thread.h"
27
28 #ifdef DEBUG
29 #include <assert.h>
30 #endif /* DEBUG */
31
32 #include <curl/curl.h>
33 #include <curl/types.h>
34 #include <curl/easy.h>
35
36 typedef struct _ccurl_memory_t {
37         char *memory;
38         size_t size;
39 } ccurl_memory_t;
40
41 ccurl_location_t *ccurl_find_location(ccurl_location_t **locations_head, char *uri)
42 {
43         ccurl_location_t *tail = *locations_head;
44         ccurl_location_t *new = 0;
45         while (tail) {
46                 if (tail->uri &&
47                                 strcmp(tail->uri, uri) == EQUAL) {
48                         return tail;
49                 }
50                 tail = tail->next;
51         }
52         if (!tail) { /* new location!!!!!!! */
53                 new = malloc(sizeof(ccurl_location_t));
54                 memset(new, 0, sizeof(ccurl_location_t));
55                 new->uri = strndup(uri, text_buffer_size);
56                 tail = *locations_head;
57                 while (tail && tail->next) {
58                         tail = tail->next;
59                 }
60                 if (!tail) {
61                         /* omg the first one!!!!!!! */
62                         *locations_head = new;
63                 } else {
64                         tail->next = new;
65                 }
66         }
67         return new;
68 }
69
70 void ccurl_free_locations(ccurl_location_t **locations_head)
71 {
72         ccurl_location_t *tail = *locations_head;
73         ccurl_location_t *last = 0;
74
75         while (tail) {
76                 if (tail->uri) free(tail->uri);
77                 if (tail->result) free(tail->result);
78                 last = tail;
79                 tail = tail->next;
80                 free(last);
81         }
82         *locations_head = 0;
83 }
84
85 size_t ccurl_write_memory_callback(void *ptr, size_t size, size_t nmemb, void *data)
86 {
87         size_t realsize = size * nmemb;
88         ccurl_memory_t *mem = (ccurl_memory_t*)data;
89
90         mem->memory = (char *) realloc(mem->memory, mem->size + realsize + 1);
91         if (mem->memory) {
92                 memcpy(&(mem->memory[mem->size]), ptr, realsize);
93                 mem->size += realsize;
94                 mem->memory[mem->size] = 0;
95         }
96         return realsize;
97 }
98
99
100
101 void ccurl_fetch_data(ccurl_location_t *curloc)
102 {
103         CURL *curl = NULL;
104         CURLcode res;
105
106         // curl temps
107         ccurl_memory_t chunk;
108
109         chunk.memory = NULL;
110         chunk.size = 0;
111
112         curl = curl_easy_init();
113         if (curl) {
114                 curl_easy_setopt(curl, CURLOPT_URL, curloc->uri);
115                 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
116                 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ccurl_write_memory_callback);
117                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk);
118                 curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-curl/1.0");
119
120                 res = curl_easy_perform(curl);
121                 if (res == CURLE_OK && chunk.size) {
122                         timed_thread_lock(curloc->p_timed_thread);
123                         (*curloc->process_function)(curloc->result, chunk.memory);
124                         timed_thread_unlock(curloc->p_timed_thread);
125                         free(chunk.memory);
126                 } else {
127                         ERR("weather: no data from server");
128                 }
129
130                 curl_easy_cleanup(curl);
131         }
132
133         return;
134 }
135
136 void *ccurl_thread(void *) __attribute__((noreturn));
137
138 void ccurl_init_thread(ccurl_location_t *curloc, int interval)
139 {
140 #ifdef DEBUG
141         assert(curloc->result);
142 #endif /* DEBUG */
143         curloc->p_timed_thread =
144                 timed_thread_create(&ccurl_thread,
145                                 (void *)curloc, interval * 1000000);
146
147         if (!curloc->p_timed_thread) {
148                 ERR("curl thread: error creating timed thread");
149         }
150         timed_thread_register(curloc->p_timed_thread,
151                         &curloc->p_timed_thread);
152         if (timed_thread_run(curloc->p_timed_thread)) {
153                 ERR("curl thread: error running timed thread");
154         }
155 }
156
157 void *ccurl_thread(void *arg)
158 {
159         ccurl_location_t *curloc = (ccurl_location_t*)arg;
160
161         while (1) {
162                 ccurl_fetch_data(curloc);
163                 if (timed_thread_test(curloc->p_timed_thread, 0)) {
164                         timed_thread_exit(curloc->p_timed_thread);
165                 }
166         }
167         /* never reached */
168 }
169
170 static ccurl_location_t *ccurl_locations_head = 0;
171
172 void ccurl_free_info(void)
173 {
174         ccurl_free_locations(&ccurl_locations_head);
175 }
176
177 void ccurl_parse_data(void *result, const char *data)
178 {
179         strncpy(result, data, max_user_text);
180 }
181
182 void ccurl_process_info(char *p, int p_max_size, char *uri, int interval)
183 {
184         ccurl_location_t *curloc = ccurl_find_location(&ccurl_locations_head, uri);
185         if (!curloc->p_timed_thread) {
186                 curloc->result = malloc(max_user_text);
187                 memset(curloc->result, 0, max_user_text);
188                 curloc->process_function = &ccurl_parse_data;
189                 ccurl_init_thread(curloc, interval);
190                 if (!curloc->p_timed_thread) {
191                         ERR("error setting up weather thread");
192                 }
193         }
194
195         timed_thread_lock(curloc->p_timed_thread);
196         strncpy(p, curloc->result, p_max_size);
197         timed_thread_unlock(curloc->p_timed_thread);
198 }
199