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

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

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