当前位置:   article > 正文

HTTP客户端(libcurl) & HTTP服务端(libevent)_libcurl http服务端

libcurl http服务端
  1. #include <ctype.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <stdint.h>
  7. #include <stdbool.h>
  8. #include <libgen.h>
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <signal.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <jansson.h>
  15. #include <curl/curl.h>
  16. #include "log.h"
  17. #ifndef likely
  18. #define likely(x) __builtin_expect(!!(x), 1)
  19. #endif
  20. #ifndef unlikely
  21. #define unlikely(x) __builtin_expect(!!(x), 0)
  22. #endif
  23. typedef struct data_t
  24. {
  25. unsigned char *value;
  26. unsigned int length;
  27. }data_t;
  28. static volatile sig_atomic_t isterm = 0; // 结束信号
  29. static volatile sig_atomic_t isalarm = 0; // 时钟信号
  30. // 中断后的信号处理函数
  31. static void signals_handler(int sig, siginfo_t *si, void *context)
  32. {
  33. static siginfo_t empty_siginfo;
  34. if(!si) si = &empty_siginfo;
  35. switch(sig)
  36. {
  37. case SIGINT: case SIGTERM:
  38. isterm = sig;
  39. break;
  40. case SIGPIPE:
  41. break;
  42. case SIGALRM:
  43. isalarm = sig;
  44. break;
  45. default:
  46. break;
  47. }
  48. }
  49. // 注册信号中断
  50. static void signals_register()
  51. {
  52. struct sigaction act;
  53. struct itimerval interval;
  54. sigfillset(&act.sa_mask);
  55. sigdelset(&act.sa_mask, SIGINT);
  56. sigdelset(&act.sa_mask, SIGTERM);
  57. sigdelset(&act.sa_mask, SIGPIPE);
  58. sigdelset(&act.sa_mask, SIGALRM);
  59. sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
  60. act.sa_flags = SA_SIGINFO;
  61. act.sa_sigaction = signals_handler;
  62. interval.it_interval.tv_sec = 1;
  63. interval.it_interval.tv_usec = 0;
  64. interval.it_value.tv_sec = 1;
  65. interval.it_value.tv_usec = 0;
  66. sigaction(SIGINT, &act, NULL);
  67. sigaction(SIGTERM, &act, NULL);
  68. sigaction(SIGPIPE, &act, NULL);
  69. sigaction(SIGALRM, &act, NULL);
  70. setitimer(ITIMER_REAL, &interval, NULL);
  71. }
  72. static size_t recv_head_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
  73. {
  74. data_t *recv_head = (data_t*)userdata;
  75. unsigned int append = size*nmemb;
  76. recv_head->value = (unsigned char*)realloc(recv_head->value, recv_head->length+append+1);
  77. if(!recv_head->value)
  78. return -1;
  79. memcpy(recv_head->value+recv_head->length, ptr, append);
  80. recv_head->length += append;
  81. recv_head->value[recv_head->length] = 0;
  82. log_debug("recv http response head: %s", recv_head->value);
  83. return size*nmemb;
  84. }
  85. static size_t recv_body_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
  86. {
  87. data_t *recv_body = (data_t*)userdata;
  88. unsigned int append = size*nmemb;
  89. recv_body->value = (unsigned char*)realloc(recv_body->value, recv_body->length+append+1);
  90. if(!recv_body->value)
  91. return -1;
  92. memcpy(recv_body->value+recv_body->length, ptr, append);
  93. recv_body->length += append;
  94. recv_body->value[recv_body->length] = 0;
  95. log_debug("recv http response body: %s", recv_body->value);
  96. return size*nmemb;
  97. }
  98. static int jsonrpc_request_url(char *url)
  99. {
  100. CURL *curl = NULL;
  101. CURLcode rcode;
  102. struct curl_slist *headers = NULL;
  103. json_t *json_req = NULL;
  104. json_t *json_res = NULL;
  105. data_t send_body, recv_head, recv_body;
  106. memset(&send_body, 0, sizeof(data_t));
  107. memset(&recv_head, 0, sizeof(data_t));
  108. memset(&recv_body, 0, sizeof(data_t));
  109. rcode = curl_global_init(CURL_GLOBAL_ALL);
  110. if(rcode != CURLE_OK)
  111. {
  112. log_error("curl global init failed: %s", curl_easy_strerror(rcode));
  113. return -1;
  114. }
  115. curl = curl_easy_init();
  116. if(!curl)
  117. {
  118. log_error("curl easy init failed: %s", curl_easy_strerror(rcode));
  119. goto ErrP;
  120. }
  121. json_req = json_pack("{ s:s, s:s, s:s }", "jsonrpc", "2.0", "method", "jsonrpc", "id", "1");
  122. if(json_req == NULL)
  123. {
  124. log_error("json pack http request body failed");
  125. goto ErrP;
  126. }
  127. send_body.value = (unsigned char *)json_dumps(json_req, 0);
  128. send_body.length = strlen((const char *)send_body.value);
  129. curl_easy_setopt(curl, CURLOPT_URL, url);
  130. curl_easy_setopt(curl, CURLOPT_POST, 1L);
  131. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, send_body.value);
  132. curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, send_body.length);
  133. curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
  134. curl_easy_setopt(curl, CURLOPT_USERPWD, "admin:111111");
  135. curl_easy_setopt(curl, CURLOPT_COOKIE, "tool=curl; fun=yes;");
  136. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  137. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L);
  138. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
  139. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  140. headers = curl_slist_append(headers, "Accept: text/json");
  141. headers = curl_slist_append(headers, "Content-Type: text/json; charset=UTF-8");
  142. headers = curl_slist_append(headers, "Connection: keep-alive");
  143. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  144. curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, recv_head_callback);
  145. curl_easy_setopt(curl, CURLOPT_HEADERDATA, &recv_head);
  146. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, recv_body_callback);
  147. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &recv_body);
  148. rcode = curl_easy_perform(curl);
  149. if(rcode != CURLE_OK)
  150. {
  151. log_error("curl easy perform failed: %s", curl_easy_strerror(rcode));
  152. goto ErrP;
  153. }
  154. unsigned int code = 200;
  155. rcode = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
  156. if(rcode != CURLE_OK || code != 200)
  157. {
  158. log_error("Response-Code: %d", code);
  159. goto ErrP;
  160. }
  161. unsigned char *ct;
  162. rcode = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
  163. if(rcode == CURLE_OK)
  164. {
  165. log_debug("Content-Type: %s", ct);
  166. }
  167. json_res = json_loadb((const char *)(recv_body.value), recv_body.length, 0, NULL);
  168. if(json_res == NULL)
  169. {
  170. log_error("json unpack http response body failed");
  171. goto ErrP;
  172. }
  173. json_t *json_result = json_object_get(json_res, "result");
  174. char *buf_result = (char*)json_string_value(json_result);
  175. if(!json_result || !buf_result || strncasecmp(buf_result, "succeed", 7))
  176. {
  177. log_error("jsonrpc request url result failed");
  178. goto ErrP;
  179. }
  180. log_info("jsonrpc request url result succeed");
  181. if(send_body.value) free(send_body.value);
  182. if(json_req) json_decref(json_req);
  183. if(recv_head.value) free(recv_head.value);
  184. if(recv_body.value) free(recv_body.value);
  185. if(json_res) json_decref(json_res);
  186. if(headers) curl_slist_free_all(headers);
  187. if(curl) curl_easy_cleanup(curl);
  188. curl_global_cleanup();
  189. return 0;
  190. ErrP:
  191. if(send_body.value) free(send_body.value);
  192. if(json_req) json_decref(json_req);
  193. if(recv_head.value) free(recv_head.value);
  194. if(recv_body.value) free(recv_body.value);
  195. if(json_res) json_decref(json_res);
  196. if(headers) curl_slist_free_all(headers);
  197. if(curl) curl_easy_cleanup(curl);
  198. curl_global_cleanup();
  199. return -1;
  200. }
  201. int main(int argc, char *argv[])
  202. {
  203. int ret = 0;
  204. log_open(basename(argv[0]), 1);
  205. #if 0
  206. if(argc != 2)
  207. {
  208. log_error("Usage: %s URL", argv[0]);
  209. return -1;
  210. }
  211. #endif
  212. signals_register();
  213. while(!isterm)
  214. {
  215. if(unlikely(isterm))
  216. {
  217. log_info("term signal: %d", isterm);
  218. isterm = 0;
  219. }
  220. if(likely(isalarm))
  221. {
  222. log_info("alarm signal: %d", isalarm);
  223. isalarm = 0;
  224. ret = jsonrpc_request_url(argv[1] ? argv[1] : "http://127.0.0.1:1990/jsonrpc.php");
  225. if(ret != 0)
  226. {
  227. log_error("jsonrpc request url failed: %d", ret);
  228. break;
  229. }
  230. }
  231. sleep(-1);
  232. }
  233. log_close();
  234. return ret;
  235. }

  1. #include <sys/wait.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <stdint.h>
  9. #include <stdbool.h>
  10. #include <libgen.h>
  11. #include <signal.h>
  12. #include <event.h>
  13. #include <evhttp.h>
  14. #include <event2/event.h>
  15. #include <event2/thread.h>
  16. #include <event2/buffer.h>
  17. #include <event2/bufferevent.h>
  18. #include <event2/util.h>
  19. #include <event2/dns.h>
  20. #include <event2/http.h>
  21. #include <event2/rpc.h>
  22. #include <jansson.h>
  23. #include "log.h"
  24. static void jsonrpc_request_cb(struct evhttp_request *req, void *arg)
  25. {
  26. struct evkeyvalq *headers = NULL;
  27. struct evkeyval *header = NULL;
  28. struct evbuffer *req_evb = NULL;
  29. struct evbuffer *res_evb = NULL;
  30. int ret = 0;
  31. int req_len = 0;
  32. char *req_buf = NULL;
  33. char *res_buf = NULL;
  34. json_t *req_json = NULL;
  35. json_t *res_json = NULL;
  36. if(evhttp_request_get_command(req) != EVHTTP_REQ_POST)
  37. {
  38. log_error("jsonrpc_request_cb EVHTTP_REQ_POST failed");
  39. goto EndP;
  40. }
  41. headers = evhttp_request_get_input_headers(req);
  42. for (header = headers->tqh_first; header; header = header->next.tqe_next)
  43. log_debug("%s: %s", header->key, header->value);
  44. req_evb = evhttp_request_get_input_buffer(req);
  45. req_len = evbuffer_get_length(req_evb);
  46. req_buf = (char*)malloc(req_len+1);
  47. if(!req_buf)
  48. {
  49. log_error("malloc failed");
  50. goto EndP;
  51. }
  52. memset(req_buf, 0, req_len+1);
  53. ret = evbuffer_remove(req_evb, req_buf, req_len);
  54. if(ret != req_len)
  55. {
  56. log_error("evbuffer_copyout failed");
  57. goto EndP;
  58. }
  59. req_buf[req_len] = 0;
  60. log_info("Request: %s", req_buf);
  61. req_json = json_loadb((const char *)req_buf, req_len, 0, NULL);
  62. if(!req_json)
  63. {
  64. log_error("jsonrpc_request_cb json_loadb failed: %s", strerror(errno));
  65. goto EndP;
  66. }
  67. json_t *method_json = json_object_get(req_json, "method");
  68. char *method_buf = (char*)json_string_value(method_json);
  69. if(!method_json || !method_buf || strncasecmp(method_buf, "jsonrpc", 7))
  70. {
  71. log_error("jsonrpc_request_cb method failed");
  72. goto EndP;
  73. }
  74. evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/json; charset=UTF-8");
  75. evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "keep-alive");
  76. res_json = json_pack("{ s:s, s:s, s:s }", "jsonrpc", "2.0", "result", "succeed", "id", "1");
  77. if(!res_json)
  78. {
  79. log_error("jsonrpc_request_cb json_pack failed: %s", strerror(errno));
  80. goto EndP;
  81. }
  82. res_buf = json_dumps(res_json, 0);
  83. if(!res_buf)
  84. {
  85. log_error("jsonrpc_request_cb json_dunmps failed: %s", strerror(errno));
  86. goto EndP;
  87. }
  88. res_evb = evbuffer_new();
  89. if(!res_evb)
  90. {
  91. log_error("jsonrpc_request_cb evbuffer_new failed: %s", strerror(errno));
  92. goto EndP;
  93. }
  94. evbuffer_add_printf(res_evb, "%s", res_buf);
  95. log_info("Response: %s", res_buf);
  96. evhttp_send_reply(req, HTTP_OK, "OK", res_evb);
  97. if(res_evb) evbuffer_free(res_evb);
  98. if(res_buf) free(res_buf);
  99. if(res_json) json_decref(res_json);
  100. if(req_json) json_decref(req_json);
  101. if(req_buf) free(req_buf);
  102. return;
  103. EndP:
  104. evhttp_send_error(req, HTTP_BADMETHOD, "BAD METHOD");
  105. if(res_evb) evbuffer_free(res_evb);
  106. if(res_buf) free(res_buf);
  107. if(res_json) json_decref(res_json);
  108. if(req_json) json_decref(req_json);
  109. if(req_buf) free(req_buf);
  110. return;
  111. }
  112. static void default_request_cb(struct evhttp_request *req, void *arg)
  113. {
  114. evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8");
  115. evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");
  116. evhttp_send_error(req, HTTP_NOTFOUND, "NOT FOUND");
  117. }
  118. static void term_evsignal_cb(evutil_socket_t fd, short event, void *arg)
  119. {
  120. struct event_base *base = arg;
  121. struct timeval tv = { 1, 0 };
  122. log_info("term signal: %d", SIGINT);
  123. event_base_loopexit(base, &tv);
  124. }
  125. static void alrm_evsignal_cb(evutil_socket_t fd, short event, void *arg)
  126. {
  127. //struct event *signal_alrm = arg;
  128. log_info("alrm signal: %d", SIGALRM);
  129. //event_del(signal_alrm);
  130. }
  131. static void cycle_timout_cb(evutil_socket_t fd, short event, void *arg)
  132. {
  133. struct timeval tv = {1, 0};
  134. log_info("cycle timeout callback");
  135. event_add(*(struct event**)arg, &tv);
  136. }
  137. int main(int argc, char *argv[])
  138. {
  139. int ret = 0;
  140. char *server_ip = "0.0.0.0";
  141. unsigned short server_port = 1990;
  142. struct event_base *base = NULL;
  143. struct evhttp *http = NULL;
  144. struct evhttp_bound_socket *handle = NULL;
  145. evutil_socket_t server_fd = -1;
  146. struct event *timeout = NULL;
  147. struct event *signal_int = NULL;
  148. struct event signal_alrm;
  149. log_open(basename(argv[0]), 1);
  150. base = event_base_new();
  151. if(!base)
  152. {
  153. log_error("event_base_new failed: %s", strerror(errno));
  154. goto ErrP;
  155. }
  156. struct timeval tv = {1, 0};
  157. timeout = event_new(base, -1, 0, cycle_timout_cb, (void*)&timeout);
  158. if(!timeout)
  159. {
  160. log_error("evtimer_new failed: %s", strerror(errno));
  161. goto ErrP;
  162. }
  163. event_add(timeout, &tv);
  164. signal_int = event_new(base, SIGINT, EV_SIGNAL|EV_PERSIST, term_evsignal_cb, (void *)base);
  165. if(!signal_int)
  166. {
  167. log_error("evsignal_new failed: %s", strerror(errno));
  168. goto ErrP;
  169. }
  170. event_add(signal_int, NULL);
  171. ret = event_assign(&signal_alrm, base, SIGALRM, EV_SIGNAL|EV_PERSIST, alrm_evsignal_cb, (void *)&signal_alrm);
  172. if(ret != 0)
  173. {
  174. log_error("evsignal_assign failed: %s", strerror(errno));
  175. goto ErrP;
  176. }
  177. event_add(&signal_alrm, NULL);
  178. http = evhttp_new(base);
  179. if(!http)
  180. {
  181. log_error("evhttp_new failed: %s", strerror(errno));
  182. goto ErrP;
  183. }
  184. handle = evhttp_bind_socket_with_handle(http, server_ip, server_port);
  185. if(!handle)
  186. {
  187. log_error("evhttp_bind_socket_with_handle failed: %s", strerror(errno));
  188. goto ErrP;
  189. }
  190. server_fd = evhttp_bound_socket_get_fd(handle);
  191. log_info("evhttp_bind_socket_with_handle succeed: %d", server_fd);
  192. evhttp_set_timeout(http, 120);
  193. evhttp_set_cb(http, "/jsonrpc.php", jsonrpc_request_cb, &base);
  194. evhttp_set_gencb(http, default_request_cb, &base);
  195. event_base_dispatch(base);
  196. if(http) evhttp_free(http);
  197. if(signal_int) event_free(signal_int);
  198. if(timeout) event_free(timeout);
  199. if(base) event_base_free(base);
  200. log_close();
  201. return 0;
  202. ErrP:
  203. if(http) evhttp_free(http);
  204. if(signal_int) event_free(signal_int);
  205. if(timeout) event_free(timeout);
  206. if(base) event_base_free(base);
  207. log_close();
  208. return -1;
  209. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/685460
推荐阅读
相关标签
  

闽ICP备14008679号