├── Makefile ├── README.md ├── cJSON.c ├── cJSON.h ├── https-common.c ├── https-common.h ├── https-server.c ├── server-certificate-chain.pem └── server-private-key.pem /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=gcc 3 | CPPFLAGS= -I. -I./include 4 | CFLAGS=-Wall 5 | LIBS=-lpthread -levent -lm -lssl -lcrypto -levent_openssl 6 | 7 | #找到当前目录下所有的.c文件 8 | src = $(wildcard *.c) 9 | 10 | #将当前目录下所有的.c 转换成.o给obj 11 | obj = $(patsubst %.c, %.o, $(src)) 12 | 13 | 14 | server=server 15 | 16 | target=$(server) 17 | 18 | 19 | ALL:$(target) 20 | 21 | 22 | #生成所有的.o文件 23 | $(obj):%.o:%.c 24 | $(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) 25 | 26 | 27 | #test_main程序 28 | $(server): https-server.o https-common.o cJSON.o 29 | $(CC) $^ -o $@ $(LIBS) 30 | 31 | 32 | 33 | 34 | 35 | #clean指令 36 | 37 | clean: 38 | -rm -rf $(obj) $(target) 39 | 40 | distclean: 41 | -rm -rf $(obj) $(target) 42 | 43 | #将clean目标 改成一个虚拟符号 44 | .PHONY: clean ALL distclean 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libevent-https 2 | 用libevent实现https服务器 3 | 4 | 依赖 5 | --- 6 | libevent 2.1以上版本 7 | 8 | 使用 9 | --- 10 | make 11 | 12 | 测试 13 | --- 14 | 命令:curl -H "Content-Type:application/json" -H "sign:10A8630BEA9CEEC895B6C745C24B3605" -H "appCode:0" -H "timestamp:1547723688" -X POST --connect-timeout 2 -m 2 -k -g -d '{"time":1547723688,"sessionID":"BC4063A88B3C46EA","sid":"60AE1B026F0BFDB5"}' https://127.0.0.1:8080/rest/atas/sessionBegin.do 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /cJSON.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr(void) {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item(void) 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | if (*num=='-') sign=-1,num++; /* Has sign? */ 101 | if (*num=='0') num++; /* is zero */ 102 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 103 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 104 | if (*num=='e' || *num=='E') /* Exponent? */ 105 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 106 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 107 | } 108 | 109 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 110 | 111 | item->valuedouble=n; 112 | item->valueint=(int)n; 113 | item->type=cJSON_Number; 114 | return num; 115 | } 116 | 117 | static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 118 | 119 | typedef struct {char *buffer; int length; int offset; } printbuffer; 120 | 121 | static char* ensure(printbuffer *p,int needed) 122 | { 123 | char *newbuffer;int newsize; 124 | if (!p || !p->buffer) return 0; 125 | needed+=p->offset; 126 | if (needed<=p->length) return p->buffer+p->offset; 127 | 128 | newsize=pow2gt(needed); 129 | newbuffer=(char*)cJSON_malloc(newsize); 130 | if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 131 | if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 132 | cJSON_free(p->buffer); 133 | p->length=newsize; 134 | p->buffer=newbuffer; 135 | return newbuffer+p->offset; 136 | } 137 | 138 | static int update(printbuffer *p) 139 | { 140 | char *str; 141 | if (!p || !p->buffer) return 0; 142 | str=p->buffer+p->offset; 143 | return p->offset+strlen(str); 144 | } 145 | 146 | /* Render the number nicely from the given item into a string. */ 147 | static char *print_number(cJSON *item,printbuffer *p) 148 | { 149 | char *str=0; 150 | double d=item->valuedouble; 151 | if (d==0) 152 | { 153 | if (p) str=ensure(p,2); 154 | else str=(char*)cJSON_malloc(2); /* special case for 0. */ 155 | if (str) strcpy(str,"0"); 156 | } 157 | else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 158 | { 159 | if (p) str=ensure(p,21); 160 | else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 161 | if (str) sprintf(str,"%d",item->valueint); 162 | } 163 | else 164 | { 165 | if (p) str=ensure(p,64); 166 | else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 167 | if (str) 168 | { 169 | if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 170 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 171 | else sprintf(str,"%f",d); 172 | } 173 | } 174 | return str; 175 | } 176 | 177 | static unsigned parse_hex4(const char *str) 178 | { 179 | unsigned h=0; 180 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 181 | h=h<<4;str++; 182 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 183 | h=h<<4;str++; 184 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 185 | h=h<<4;str++; 186 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 187 | return h; 188 | } 189 | 190 | /* Parse the input text into an unescaped cstring, and populate item. */ 191 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 192 | static const char *parse_string(cJSON *item,const char *str) 193 | { 194 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 195 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 196 | 197 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 198 | 199 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 200 | if (!out) return 0; 201 | 202 | ptr=str+1;ptr2=out; 203 | while (*ptr!='\"' && *ptr) 204 | { 205 | if (*ptr!='\\') *ptr2++=*ptr++; 206 | else 207 | { 208 | ptr++; 209 | switch (*ptr) 210 | { 211 | case 'b': *ptr2++='\b'; break; 212 | case 'f': *ptr2++='\f'; break; 213 | case 'n': *ptr2++='\n'; break; 214 | case 'r': *ptr2++='\r'; break; 215 | case 't': *ptr2++='\t'; break; 216 | case 'u': /* transcode utf16 to utf8. */ 217 | uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 218 | 219 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 220 | 221 | if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 222 | { 223 | if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 224 | uc2=parse_hex4(ptr+3);ptr+=6; 225 | if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 226 | uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 227 | } 228 | 229 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 230 | 231 | switch (len) { 232 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 233 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 234 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 235 | case 1: *--ptr2 =(uc | firstByteMark[len]); 236 | } 237 | ptr2+=len; 238 | break; 239 | default: *ptr2++=*ptr; break; 240 | } 241 | ptr++; 242 | } 243 | } 244 | *ptr2=0; 245 | if (*ptr=='\"') ptr++; 246 | item->valuestring=out; 247 | item->type=cJSON_String; 248 | return ptr; 249 | } 250 | 251 | /* Render the cstring provided to an escaped version that can be printed. */ 252 | static char *print_string_ptr(const char *str,printbuffer *p) 253 | { 254 | const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 255 | 256 | for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; 257 | if (!flag) 258 | { 259 | len=ptr-str; 260 | if (p) out=ensure(p,len+3); 261 | else out=(char*)cJSON_malloc(len+3); 262 | if (!out) return 0; 263 | ptr2=out;*ptr2++='\"'; 264 | strcpy(ptr2,str); 265 | ptr2[len]='\"'; 266 | ptr2[len+1]=0; 267 | return out; 268 | } 269 | 270 | if (!str) 271 | { 272 | if (p) out=ensure(p,3); 273 | else out=(char*)cJSON_malloc(3); 274 | if (!out) return 0; 275 | strcpy(out,"\"\""); 276 | return out; 277 | } 278 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 279 | 280 | if (p) out=ensure(p,len+3); 281 | else out=(char*)cJSON_malloc(len+3); 282 | if (!out) return 0; 283 | 284 | ptr2=out;ptr=str; 285 | *ptr2++='\"'; 286 | while (*ptr) 287 | { 288 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 289 | else 290 | { 291 | *ptr2++='\\'; 292 | switch (token=*ptr++) 293 | { 294 | case '\\': *ptr2++='\\'; break; 295 | case '\"': *ptr2++='\"'; break; 296 | case '\b': *ptr2++='b'; break; 297 | case '\f': *ptr2++='f'; break; 298 | case '\n': *ptr2++='n'; break; 299 | case '\r': *ptr2++='r'; break; 300 | case '\t': *ptr2++='t'; break; 301 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 302 | } 303 | } 304 | } 305 | *ptr2++='\"';*ptr2++=0; 306 | return out; 307 | } 308 | /* Invote print_string_ptr (which is useful) on an item. */ 309 | static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 310 | 311 | /* Predeclare these prototypes. */ 312 | static const char *parse_value(cJSON *item,const char *value); 313 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 314 | static const char *parse_array(cJSON *item,const char *value); 315 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 316 | static const char *parse_object(cJSON *item,const char *value); 317 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 318 | 319 | /* Utility to jump whitespace and cr/lf */ 320 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 321 | 322 | /* Parse an object - create a new root, and populate. */ 323 | cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 324 | { 325 | const char *end=0; 326 | cJSON *c=cJSON_New_Item(); 327 | ep=0; 328 | if (!c) return 0; /* memory fail */ 329 | 330 | end=parse_value(c,skip(value)); 331 | if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 332 | 333 | /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 334 | if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 335 | if (return_parse_end) *return_parse_end=end; 336 | return c; 337 | } 338 | /* Default options for cJSON_Parse */ 339 | cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 340 | 341 | /* Render a cJSON item/entity/structure to text. */ 342 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 343 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 344 | 345 | char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 346 | { 347 | printbuffer p; 348 | p.buffer=(char*)cJSON_malloc(prebuffer); 349 | p.length=prebuffer; 350 | p.offset=0; 351 | return print_value(item,0,fmt,&p); 352 | return p.buffer; 353 | } 354 | 355 | 356 | /* Parser core - when encountering text, process appropriately. */ 357 | static const char *parse_value(cJSON *item,const char *value) 358 | { 359 | if (!value) return 0; /* Fail on null. */ 360 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 361 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 362 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 363 | if (*value=='\"') { return parse_string(item,value); } 364 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 365 | if (*value=='[') { return parse_array(item,value); } 366 | if (*value=='{') { return parse_object(item,value); } 367 | 368 | ep=value;return 0; /* failure. */ 369 | } 370 | 371 | /* Render a value to text. */ 372 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 373 | { 374 | char *out=0; 375 | if (!item) return 0; 376 | if (p) 377 | { 378 | switch ((item->type)&255) 379 | { 380 | case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 381 | case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 382 | case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 383 | case cJSON_Number: out=print_number(item,p);break; 384 | case cJSON_String: out=print_string(item,p);break; 385 | case cJSON_Array: out=print_array(item,depth,fmt,p);break; 386 | case cJSON_Object: out=print_object(item,depth,fmt,p);break; 387 | } 388 | } 389 | else 390 | { 391 | switch ((item->type)&255) 392 | { 393 | case cJSON_NULL: out=cJSON_strdup("null"); break; 394 | case cJSON_False: out=cJSON_strdup("false");break; 395 | case cJSON_True: out=cJSON_strdup("true"); break; 396 | case cJSON_Number: out=print_number(item,0);break; 397 | case cJSON_String: out=print_string(item,0);break; 398 | case cJSON_Array: out=print_array(item,depth,fmt,0);break; 399 | case cJSON_Object: out=print_object(item,depth,fmt,0);break; 400 | } 401 | } 402 | return out; 403 | } 404 | 405 | /* Build an array from input text. */ 406 | static const char *parse_array(cJSON *item,const char *value) 407 | { 408 | cJSON *child; 409 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 410 | 411 | item->type=cJSON_Array; 412 | value=skip(value+1); 413 | if (*value==']') return value+1; /* empty array. */ 414 | 415 | item->child=child=cJSON_New_Item(); 416 | if (!item->child) return 0; /* memory fail */ 417 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 418 | if (!value) return 0; 419 | 420 | while (*value==',') 421 | { 422 | cJSON *new_item; 423 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 424 | child->next=new_item;new_item->prev=child;child=new_item; 425 | value=skip(parse_value(child,skip(value+1))); 426 | if (!value) return 0; /* memory fail */ 427 | } 428 | 429 | if (*value==']') return value+1; /* end of array */ 430 | ep=value;return 0; /* malformed. */ 431 | } 432 | 433 | /* Render an array to text */ 434 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 435 | { 436 | char **entries; 437 | char *out=0,*ptr,*ret;int len=5; 438 | cJSON *child=item->child; 439 | int numentries=0,i=0,fail=0; 440 | size_t tmplen=0; 441 | 442 | /* How many entries in the array? */ 443 | while (child) numentries++,child=child->next; 444 | /* Explicitly handle numentries==0 */ 445 | if (!numentries) 446 | { 447 | if (p) out=ensure(p,3); 448 | else out=(char*)cJSON_malloc(3); 449 | if (out) strcpy(out,"[]"); 450 | return out; 451 | } 452 | 453 | if (p) 454 | { 455 | /* Compose the output array. */ 456 | i=p->offset; 457 | ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 458 | child=item->child; 459 | while (child && !fail) 460 | { 461 | print_value(child,depth+1,fmt,p); 462 | p->offset=update(p); 463 | if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 464 | child=child->next; 465 | } 466 | ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 467 | out=(p->buffer)+i; 468 | } 469 | else 470 | { 471 | /* Allocate an array to hold the values for each */ 472 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 473 | if (!entries) return 0; 474 | memset(entries,0,numentries*sizeof(char*)); 475 | /* Retrieve all the results: */ 476 | child=item->child; 477 | while (child && !fail) 478 | { 479 | ret=print_value(child,depth+1,fmt,0); 480 | entries[i++]=ret; 481 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 482 | child=child->next; 483 | } 484 | 485 | /* If we didn't fail, try to malloc the output string */ 486 | if (!fail) out=(char*)cJSON_malloc(len); 487 | /* If that fails, we fail. */ 488 | if (!out) fail=1; 489 | 490 | /* Handle failure. */ 491 | if (fail) 492 | { 493 | for (i=0;itype=cJSON_Object; 520 | value=skip(value+1); 521 | if (*value=='}') return value+1; /* empty array. */ 522 | 523 | item->child=child=cJSON_New_Item(); 524 | if (!item->child) return 0; 525 | value=skip(parse_string(child,skip(value))); 526 | if (!value) return 0; 527 | child->string=child->valuestring;child->valuestring=0; 528 | if (*value!=':') {ep=value;return 0;} /* fail! */ 529 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 530 | if (!value) return 0; 531 | 532 | while (*value==',') 533 | { 534 | cJSON *new_item; 535 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 536 | child->next=new_item;new_item->prev=child;child=new_item; 537 | value=skip(parse_string(child,skip(value+1))); 538 | if (!value) return 0; 539 | child->string=child->valuestring;child->valuestring=0; 540 | if (*value!=':') {ep=value;return 0;} /* fail! */ 541 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 542 | if (!value) return 0; 543 | } 544 | 545 | if (*value=='}') return value+1; /* end of array */ 546 | ep=value;return 0; /* malformed. */ 547 | } 548 | 549 | /* Render an object to text. */ 550 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 551 | { 552 | char **entries=0,**names=0; 553 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 554 | cJSON *child=item->child; 555 | int numentries=0,fail=0; 556 | size_t tmplen=0; 557 | /* Count the number of entries. */ 558 | while (child) numentries++,child=child->next; 559 | /* Explicitly handle empty object case */ 560 | if (!numentries) 561 | { 562 | if (p) out=ensure(p,fmt?depth+4:3); 563 | else out=(char*)cJSON_malloc(fmt?depth+4:3); 564 | if (!out) return 0; 565 | ptr=out;*ptr++='{'; 566 | if (fmt) {*ptr++='\n';for (i=0;ioffset; 574 | len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 575 | *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 576 | child=item->child;depth++; 577 | while (child) 578 | { 579 | if (fmt) 580 | { 581 | ptr=ensure(p,depth); if (!ptr) return 0; 582 | for (j=0;joffset+=depth; 584 | } 585 | print_string_ptr(child->string,p); 586 | p->offset=update(p); 587 | 588 | len=fmt?2:1; 589 | ptr=ensure(p,len); if (!ptr) return 0; 590 | *ptr++=':';if (fmt) *ptr++='\t'; 591 | p->offset+=len; 592 | 593 | print_value(child,depth,fmt,p); 594 | p->offset=update(p); 595 | 596 | len=(fmt?1:0)+(child->next?1:0); 597 | ptr=ensure(p,len+1); if (!ptr) return 0; 598 | if (child->next) *ptr++=','; 599 | if (fmt) *ptr++='\n';*ptr=0; 600 | p->offset+=len; 601 | child=child->next; 602 | } 603 | ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 604 | if (fmt) for (i=0;ibuffer)+i; 607 | } 608 | else 609 | { 610 | /* Allocate space for the names and the objects */ 611 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 612 | if (!entries) return 0; 613 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 614 | if (!names) {cJSON_free(entries);return 0;} 615 | memset(entries,0,sizeof(char*)*numentries); 616 | memset(names,0,sizeof(char*)*numentries); 617 | 618 | /* Collect all the results into our arrays: */ 619 | child=item->child;depth++;if (fmt) len+=depth; 620 | while (child) 621 | { 622 | names[i]=str=print_string_ptr(child->string,0); 623 | entries[i++]=ret=print_value(child,depth,fmt,0); 624 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 625 | child=child->next; 626 | } 627 | 628 | /* Try to allocate the output string */ 629 | if (!fail) out=(char*)cJSON_malloc(len); 630 | if (!out) fail=1; 631 | 632 | /* Handle failure */ 633 | if (fail) 634 | { 635 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 662 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 663 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 664 | 665 | /* Utility for array list handling. */ 666 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 667 | /* Utility for handling references. */ 668 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 669 | 670 | /* Add item to array/object. */ 671 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 672 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 673 | void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 674 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 675 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 676 | 677 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 678 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 679 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 680 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 681 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 682 | 683 | /* Replace array/object items with new ones. */ 684 | void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} 685 | newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} 686 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 687 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 688 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 689 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 690 | 691 | /* Create basic types: */ 692 | cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 693 | cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 694 | cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 695 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 696 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 697 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 698 | cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 699 | cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 700 | 701 | /* Create Arrays: */ 702 | cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 703 | cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 704 | cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 705 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 706 | 707 | /* Duplication */ 708 | cJSON *cJSON_Duplicate(cJSON *item,int recurse) 709 | { 710 | cJSON *newitem,*cptr,*nptr=0,*newchild; 711 | /* Bail on bad ptr */ 712 | if (!item) return 0; 713 | /* Create new item */ 714 | newitem=cJSON_New_Item(); 715 | if (!newitem) return 0; 716 | /* Copy over all vars */ 717 | newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 718 | if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 719 | if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 720 | /* If non-recursive, then we're done! */ 721 | if (!recurse) return newitem; 722 | /* Walk the ->next chain for the child. */ 723 | cptr=item->child; 724 | while (cptr) 725 | { 726 | newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 727 | if (!newchild) {cJSON_Delete(newitem);return 0;} 728 | if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 729 | else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 730 | cptr=cptr->next; 731 | } 732 | return newitem; 733 | } 734 | 735 | void cJSON_Minify(char *json) 736 | { 737 | char *into=json; 738 | while (*json) 739 | { 740 | if (*json==' ') json++; 741 | else if (*json=='\t') json++; /* Whitespace characters. */ 742 | else if (*json=='\r') json++; 743 | else if (*json=='\n') json++; 744 | else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ 745 | else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ 746 | else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 747 | else *into++=*json++; /* All other characters. */ 748 | } 749 | *into=0; /* and null-terminate. */ 750 | } 751 | -------------------------------------------------------------------------------- /cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | /* cJSON Types: */ 32 | #define cJSON_False 0 33 | #define cJSON_True 1 34 | #define cJSON_NULL 2 35 | #define cJSON_Number 3 36 | #define cJSON_String 4 37 | #define cJSON_Array 5 38 | #define cJSON_Object 6 39 | 40 | #define cJSON_IsReference 256 41 | #define cJSON_StringIsConst 512 42 | 43 | /* The cJSON structure: */ 44 | typedef struct cJSON { 45 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 46 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 47 | 48 | int type; /* The type of the item, as above. */ 49 | 50 | char *valuestring; /* The item's string, if type==cJSON_String */ 51 | int valueint; /* The item's number, if type==cJSON_Number */ 52 | double valuedouble; /* The item's number, if type==cJSON_Number */ 53 | 54 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 55 | } cJSON; 56 | 57 | typedef struct cJSON_Hooks { 58 | void *(*malloc_fn)(size_t sz); 59 | void (*free_fn)(void *ptr); 60 | } cJSON_Hooks; 61 | 62 | /* Supply malloc, realloc and free functions to cJSON */ 63 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 64 | 65 | 66 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 67 | extern cJSON *cJSON_Parse(const char *value); 68 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 69 | extern char *cJSON_Print(cJSON *item); 70 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 71 | extern char *cJSON_PrintUnformatted(cJSON *item); 72 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 73 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 74 | /* Delete a cJSON entity and all subentities. */ 75 | extern void cJSON_Delete(cJSON *c); 76 | 77 | /* Returns the number of items in an array (or object). */ 78 | extern int cJSON_GetArraySize(cJSON *array); 79 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 80 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 81 | /* Get item "string" from object. Case insensitive. */ 82 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 83 | 84 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 85 | extern const char *cJSON_GetErrorPtr(void); 86 | 87 | /* These calls create a cJSON item of the appropriate type. */ 88 | extern cJSON *cJSON_CreateNull(void); 89 | extern cJSON *cJSON_CreateTrue(void); 90 | extern cJSON *cJSON_CreateFalse(void); 91 | extern cJSON *cJSON_CreateBool(int b); 92 | extern cJSON *cJSON_CreateNumber(double num); 93 | extern cJSON *cJSON_CreateString(const char *string); 94 | extern cJSON *cJSON_CreateArray(void); 95 | extern cJSON *cJSON_CreateObject(void); 96 | 97 | /* These utilities create an Array of count items. */ 98 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 99 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 100 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 101 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 102 | 103 | /* Append item to the specified array/object. */ 104 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 106 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 107 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 108 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 109 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 110 | 111 | /* Remove/Detatch items from Arrays/Objects. */ 112 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 113 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 114 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 115 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 116 | 117 | /* Update array items. */ 118 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 119 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 120 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 121 | 122 | /* Duplicate a cJSON item */ 123 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 124 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 125 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 126 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 127 | 128 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 129 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 130 | 131 | extern void cJSON_Minify(char *json); 132 | 133 | /* Macros for creating things quickly. */ 134 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 135 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 136 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 137 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 138 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 139 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 140 | 141 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 142 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 143 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 144 | 145 | #ifdef __cplusplus 146 | } 147 | #endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /https-common.c: -------------------------------------------------------------------------------- 1 | 2 | /* (c) Oblong Industries */ 3 | 4 | #include 5 | 6 | #include "https-common.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | 14 | /* 这个是调用openSSL提供的打印log接口 */ 15 | void die_most_horribly_from_openssl_error (const char *func) 16 | { 17 | fprintf (stderr, "%s failed:\n", func); 18 | 19 | /* This is the OpenSSL function that prints the contents of the 20 | * error stack to the specified file handle. */ 21 | ERR_print_errors_fp (stderr); 22 | 23 | exit (EXIT_FAILURE); 24 | } 25 | 26 | void error_exit (const char *fmt, ...) 27 | { va_list ap; 28 | 29 | va_start (ap, fmt); 30 | vfprintf (stderr, fmt, ap); 31 | va_end (ap); 32 | 33 | exit (EXIT_FAILURE); 34 | } 35 | 36 | /* OpenSSL has a habit of using uninitialized memory. (They turn up their 37 | * nose at tools like valgrind.) To avoid spurious valgrind errors (as well 38 | * as to allay any concerns that the uninitialized memory is actually 39 | * affecting behavior), let's install a custom malloc function which is 40 | * actually calloc. 41 | */ 42 | static void *my_zeroing_malloc (size_t howmuch) 43 | { 44 | return calloc (1, howmuch); 45 | } 46 | 47 | void common_setup (void) 48 | { 49 | signal (SIGPIPE, SIG_IGN); 50 | 51 | CRYPTO_set_mem_functions (my_zeroing_malloc, realloc, free); 52 | SSL_library_init (); 53 | SSL_load_error_strings (); 54 | OpenSSL_add_all_algorithms (); 55 | 56 | printf ("Using OpenSSL version \"%s\"\nand libevent version \"%s\"\n", 57 | SSLeay_version (SSLEAY_VERSION), 58 | event_get_version ()); 59 | } 60 | -------------------------------------------------------------------------------- /https-common.h: -------------------------------------------------------------------------------- 1 | 2 | /* (c) Oblong Industries */ 3 | 4 | #ifndef COMMON_MAN 5 | #define COMMON_MAN 6 | 7 | /** 8 | * Rather than using the standard https port of 443, use this one. 9 | */ 10 | #define COMMON_HTTPS_PORT 8080 11 | 12 | /** 13 | * This is the string the client tells the server in the POST request. 14 | */ 15 | #define COMMON_PASSCODE "R23" 16 | 17 | /** 18 | * If an OpenSSL function returns a return value indicating failure 19 | * (for non-pointery functions, generally 1 means success, and non-1 20 | * means failure), then usually it ought to have left one or more 21 | * entries in the OpenSSL "error stack", which is a bit of thread-local 22 | * state containing error information. 23 | * 24 | * This function is a simple way to handle OpenSSL errors (something 25 | * better may be needed in a real application), which prints the 26 | * name of the function which failed (which you must supply as an 27 | * argument), prints the OpenSSL error stack (which hopefully says 28 | * something meaningful) and exits. 29 | */ 30 | void die_most_horribly_from_openssl_error (const char *func); 31 | 32 | void error_exit (const char *fmt, ...); 33 | 34 | #define error_report printf 35 | #define info_report printf 36 | 37 | /** 38 | * Calls some OpenSSL setup functions, which both the client and 39 | * server need to do. 40 | */ 41 | void common_setup (void); 42 | 43 | #endif /* COMMON_MAN */ 44 | -------------------------------------------------------------------------------- /https-server.c: -------------------------------------------------------------------------------- 1 | #include "https-common.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #define MYHTTPD_SIGNATURE "MoCarHttpd v0.1" 31 | 32 | 33 | #ifdef EVENT__HAVE_NETINET_IN_H 34 | #include 35 | # ifdef _XOPEN_SOURCE_EXTENDED 36 | # include 37 | # endif 38 | #endif 39 | 40 | unsigned short serverPort = COMMON_HTTPS_PORT; 41 | //unsigned short serverPort = 6666; 42 | 43 | /* Instead of casting between these types, create a union with all of them, 44 | * to avoid -Wstrict-aliasing warnings. */ 45 | typedef union 46 | { 47 | struct sockaddr_storage ss; 48 | struct sockaddr sa; 49 | struct sockaddr_in in; 50 | struct sockaddr_in6 i6; 51 | } sock_hop; 52 | 53 | 54 | /* This callback gets invoked when we get any http request that doesn't match 55 | * any other callback. Like any evhttp server callback, it has a simple job: 56 | * it must eventually call evhttp_send_error() or evhttp_send_reply(). 57 | */ 58 | static void 59 | login_cb (struct evhttp_request *req, void *arg) 60 | { 61 | struct evbuffer *evb = NULL; 62 | const char *uri = evhttp_request_get_uri (req); 63 | struct evhttp_uri *decoded = NULL; 64 | 65 | /* 判断 req 是否是GET 请求 */ 66 | if (evhttp_request_get_command (req) == EVHTTP_REQ_GET) 67 | { 68 | struct evbuffer *buf = evbuffer_new(); 69 | if (buf == NULL) return; 70 | evbuffer_add_printf(buf, "Requested: %s\n", uri); 71 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 72 | return; 73 | } 74 | 75 | /* 这里只处理Post请求, Get请求,就直接return 200 OK */ 76 | if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) 77 | { 78 | evhttp_send_reply (req, 200, "OK", NULL); 79 | return; 80 | } 81 | 82 | printf ("Got a POST request for <%s>\n", uri); 83 | 84 | //判断此URI是否合法 85 | decoded = evhttp_uri_parse (uri); 86 | if (! decoded) 87 | { 88 | printf ("It's not a good URI. Sending BADREQUEST\n"); 89 | evhttp_send_error (req, HTTP_BADREQUEST, 0); 90 | return; 91 | } 92 | 93 | /* Decode the payload */ 94 | struct evbuffer *buf = evhttp_request_get_input_buffer (req); 95 | evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */ 96 | char *payload = (char *) evbuffer_pullup (buf, -1); 97 | int post_data_len = evbuffer_get_length(buf); 98 | char request_data_buf[4096] = {0}; 99 | memcpy(request_data_buf, payload, post_data_len); 100 | 101 | printf("[post_data][%d]=\n %s\n", post_data_len, payload); 102 | 103 | 104 | /* 105 | 具体的:可以根据Post的参数执行相应操作,然后将结果输出 106 | ... 107 | */ 108 | //unpack json 109 | cJSON* root = cJSON_Parse(request_data_buf); 110 | cJSON* username = cJSON_GetObjectItem(root, "username"); 111 | cJSON* password = cJSON_GetObjectItem(root, "password"); 112 | cJSON* driver = cJSON_GetObjectItem(root, "driver"); 113 | 114 | printf("username = %s\n", username->valuestring); 115 | printf("password = %s\n", password->valuestring); 116 | printf("driver = %s\n", driver->valuestring); 117 | 118 | cJSON_Delete(root); 119 | 120 | 121 | 122 | //packet json 123 | root = cJSON_CreateObject(); 124 | 125 | cJSON_AddStringToObject(root, "result", "ok"); 126 | //cJSON_AddStringToObject(root, "sessionid", "xxxxxxxx"); 127 | 128 | char *response_data = cJSON_Print(root); 129 | cJSON_Delete(root); 130 | 131 | 132 | 133 | 134 | /* This holds the content we're sending. */ 135 | 136 | //HTTP header 137 | evhttp_add_header(evhttp_request_get_output_headers(req), "Server", MYHTTPD_SIGNATURE); 138 | evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8"); 139 | evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); 140 | 141 | evb = evbuffer_new (); 142 | evbuffer_add_printf(evb, "%s", response_data); 143 | //将封装好的evbuffer 发送给客户端 144 | evhttp_send_reply(req, HTTP_OK, "OK", evb); 145 | 146 | if (decoded) 147 | evhttp_uri_free (decoded); 148 | if (evb) 149 | evbuffer_free (evb); 150 | 151 | 152 | printf("[response]:\n"); 153 | printf("%s\n", response_data); 154 | 155 | free(response_data); 156 | } 157 | //会话开始 158 | static void 159 | sessionBegin (struct evhttp_request *req, void *arg) 160 | { 161 | struct evbuffer *evb = NULL; 162 | const char *uri = evhttp_request_get_uri (req); 163 | struct evhttp_uri *decoded = NULL; 164 | 165 | /* 判断 req 是否是GET 请求 */ 166 | if (evhttp_request_get_command (req) == EVHTTP_REQ_GET) 167 | { 168 | struct evbuffer *buf = evbuffer_new(); 169 | if (buf == NULL) return; 170 | evbuffer_add_printf(buf, "Requested: %s\n", uri); 171 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 172 | return; 173 | } 174 | 175 | /* 这里只处理Post请求, Get请求,就直接return 200 OK */ 176 | if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) 177 | { 178 | evhttp_send_reply (req, 200, "OK", NULL); 179 | return; 180 | } 181 | 182 | printf ("Got a POST request for <%s>\n", uri); 183 | 184 | //判断此URI是否合法 185 | decoded = evhttp_uri_parse (uri); 186 | if (! decoded) 187 | { 188 | printf ("It's not a good URI. Sending BADREQUEST\n"); 189 | evhttp_send_error (req, HTTP_BADREQUEST, 0); 190 | return; 191 | } 192 | 193 | /* Decode the payload */ 194 | struct evbuffer *buf = evhttp_request_get_input_buffer (req); 195 | evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */ 196 | char *payload = (char *) evbuffer_pullup (buf, -1); 197 | int post_data_len = evbuffer_get_length(buf); 198 | char request_data_buf[4096] = {0}; 199 | memcpy(request_data_buf, payload, post_data_len); 200 | 201 | printf("[post_data][%d]=\n %s\n", post_data_len, payload); 202 | 203 | 204 | /* 205 | 具体的:可以根据Post的参数执行相应操作,然后将结果输出 206 | ... 207 | */ 208 | //unpack json 209 | cJSON* root = cJSON_Parse(request_data_buf); 210 | cJSON* time = cJSON_GetObjectItem(root, "time"); 211 | cJSON* sessionID = cJSON_GetObjectItem(root, "sessionID"); 212 | cJSON* sid = cJSON_GetObjectItem(root, "sid"); 213 | 214 | //printf("time = %s\n", time->valuestring); 215 | //printf("sessionID = %s\n", sessionID->valuestring); 216 | //printf("sid = %s\n", sid->valuestring); 217 | 218 | cJSON_Delete(root); 219 | 220 | 221 | 222 | //packet json 223 | root = cJSON_CreateObject(); 224 | 225 | cJSON_AddStringToObject(root, "result", "ok"); 226 | //cJSON_AddStringToObject(root, "sessionid", "xxxxxxxx"); 227 | 228 | char *response_data = cJSON_Print(root); 229 | cJSON_Delete(root); 230 | 231 | 232 | 233 | 234 | /* This holds the content we're sending. */ 235 | 236 | //HTTP header 237 | evhttp_add_header(evhttp_request_get_output_headers(req), "Server", MYHTTPD_SIGNATURE); 238 | evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8"); 239 | evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); 240 | 241 | evb = evbuffer_new (); 242 | evbuffer_add_printf(evb, "%s", response_data); 243 | //将封装好的evbuffer 发送给客户端 244 | evhttp_send_reply(req, HTTP_OK, "OK", evb); 245 | 246 | if (decoded) 247 | evhttp_uri_free (decoded); 248 | if (evb) 249 | evbuffer_free (evb); 250 | 251 | 252 | //printf("[response]:\n"); 253 | //printf("%s\n", response_data); 254 | 255 | free(response_data); 256 | } 257 | //会话告警 258 | static void 259 | sessionWarn (struct evhttp_request *req, void *arg) 260 | { 261 | struct evbuffer *evb = NULL; 262 | const char *uri = evhttp_request_get_uri (req); 263 | struct evhttp_uri *decoded = NULL; 264 | 265 | /* 判断 req 是否是GET 请求 */ 266 | if (evhttp_request_get_command (req) == EVHTTP_REQ_GET) 267 | { 268 | struct evbuffer *buf = evbuffer_new(); 269 | if (buf == NULL) return; 270 | evbuffer_add_printf(buf, "Requested: %s\n", uri); 271 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 272 | return; 273 | } 274 | 275 | /* 这里只处理Post请求, Get请求,就直接return 200 OK */ 276 | if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) 277 | { 278 | evhttp_send_reply (req, 200, "OK", NULL); 279 | return; 280 | } 281 | 282 | printf ("Got a POST request for <%s>\n", uri); 283 | 284 | //判断此URI是否合法 285 | decoded = evhttp_uri_parse (uri); 286 | if (! decoded) 287 | { 288 | printf ("It's not a good URI. Sending BADREQUEST\n"); 289 | evhttp_send_error (req, HTTP_BADREQUEST, 0); 290 | return; 291 | } 292 | 293 | /* Decode the payload */ 294 | struct evbuffer *buf = evhttp_request_get_input_buffer (req); 295 | evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */ 296 | char *payload = (char *) evbuffer_pullup (buf, -1); 297 | int post_data_len = evbuffer_get_length(buf); 298 | char request_data_buf[4096] = {0}; 299 | memcpy(request_data_buf, payload, post_data_len); 300 | 301 | printf("[post_data][%d]=\n %s\n", post_data_len, payload); 302 | 303 | /* 304 | 具体的:可以根据Post的参数执行相应操作,然后将结果输出 305 | ... 306 | */ 307 | //unpack json 308 | cJSON* root = cJSON_Parse(request_data_buf); 309 | cJSON* cmd = cJSON_GetObjectItem(root, "cmd"); 310 | //cJSON* password = cJSON_GetObjectItem(root, "password"); 311 | //cJSON* driver = cJSON_GetObjectItem(root, "driver"); 312 | 313 | //printf("cmd = %s\n", cmd->valuestring); 314 | //printf("password = %s\n", password->valuestring); 315 | //printf("driver = %s\n", driver->valuestring); 316 | 317 | cJSON_Delete(root); 318 | 319 | 320 | 321 | //packet json 322 | root = cJSON_CreateObject(); 323 | 324 | cJSON_AddStringToObject(root, "result", "ok"); 325 | //cJSON_AddStringToObject(root, "sessionid", "xxxxxxxx"); 326 | 327 | char *response_data = cJSON_Print(root); 328 | cJSON_Delete(root); 329 | 330 | 331 | 332 | 333 | /* This holds the content we're sending. */ 334 | 335 | //HTTP header 336 | evhttp_add_header(evhttp_request_get_output_headers(req), "Server", MYHTTPD_SIGNATURE); 337 | evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8"); 338 | evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); 339 | 340 | evb = evbuffer_new (); 341 | evbuffer_add_printf(evb, "%s", response_data); 342 | //将封装好的evbuffer 发送给客户端 343 | evhttp_send_reply(req, HTTP_OK, "OK", evb); 344 | 345 | if (decoded) 346 | evhttp_uri_free (decoded); 347 | if (evb) 348 | evbuffer_free (evb); 349 | 350 | 351 | //printf("[response]:\n"); 352 | //printf("%s\n", response_data); 353 | 354 | free(response_data); 355 | } 356 | //会话结束 357 | static void 358 | sessionEnd (struct evhttp_request *req, void *arg) 359 | { 360 | struct evbuffer *evb = NULL; 361 | const char *uri = evhttp_request_get_uri (req); 362 | struct evhttp_uri *decoded = NULL; 363 | 364 | /* 判断 req 是否是GET 请求 */ 365 | if (evhttp_request_get_command (req) == EVHTTP_REQ_GET) 366 | { 367 | struct evbuffer *buf = evbuffer_new(); 368 | if (buf == NULL) return; 369 | evbuffer_add_printf(buf, "Requested: %s\n", uri); 370 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 371 | return; 372 | } 373 | 374 | /* 这里只处理Post请求, Get请求,就直接return 200 OK */ 375 | if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) 376 | { 377 | evhttp_send_reply (req, 200, "OK", NULL); 378 | return; 379 | } 380 | 381 | printf ("Got a POST request for <%s>\n", uri); 382 | 383 | //判断此URI是否合法 384 | decoded = evhttp_uri_parse (uri); 385 | if (! decoded) 386 | { 387 | printf ("It's not a good URI. Sending BADREQUEST\n"); 388 | evhttp_send_error (req, HTTP_BADREQUEST, 0); 389 | return; 390 | } 391 | 392 | /* Decode the payload */ 393 | struct evbuffer *buf = evhttp_request_get_input_buffer (req); 394 | evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */ 395 | char *payload = (char *) evbuffer_pullup (buf, -1); 396 | int post_data_len = evbuffer_get_length(buf); 397 | char request_data_buf[4096] = {0}; 398 | memcpy(request_data_buf, payload, post_data_len); 399 | 400 | printf("[post_data][%d]=\n %s\n", post_data_len, payload); 401 | 402 | 403 | /* 404 | 具体的:可以根据Post的参数执行相应操作,然后将结果输出 405 | ... 406 | */ 407 | //unpack json 408 | cJSON* root = cJSON_Parse(request_data_buf); 409 | cJSON* time = cJSON_GetObjectItem(root, "time"); 410 | cJSON* sessionID = cJSON_GetObjectItem(root, "sessionID"); 411 | cJSON* logSize = cJSON_GetObjectItem(root, "logSize"); 412 | cJSON* cmdNum = cJSON_GetObjectItem(root, "cmdNum"); 413 | cJSON* resultNum = cJSON_GetObjectItem(root, "resultNum"); 414 | 415 | //printf("username = %s\n", username->valuestring); 416 | //printf("password = %s\n", password->valuestring); 417 | //printf("driver = %s\n", driver->valuestring); 418 | 419 | cJSON_Delete(root); 420 | 421 | 422 | 423 | //packet json 424 | root = cJSON_CreateObject(); 425 | 426 | cJSON_AddStringToObject(root, "result", "ok"); 427 | //cJSON_AddStringToObject(root, "sessionid", "xxxxxxxx"); 428 | 429 | char *response_data = cJSON_Print(root); 430 | cJSON_Delete(root); 431 | 432 | 433 | 434 | 435 | /* This holds the content we're sending. */ 436 | 437 | //HTTP header 438 | evhttp_add_header(evhttp_request_get_output_headers(req), "Server", MYHTTPD_SIGNATURE); 439 | evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8"); 440 | evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); 441 | 442 | evb = evbuffer_new (); 443 | evbuffer_add_printf(evb, "%s", response_data); 444 | //将封装好的evbuffer 发送给客户端 445 | evhttp_send_reply(req, HTTP_OK, "OK", evb); 446 | 447 | if (decoded) 448 | evhttp_uri_free (decoded); 449 | if (evb) 450 | evbuffer_free (evb); 451 | 452 | 453 | //printf("[response]:\n"); 454 | //printf("%s\n", response_data); 455 | 456 | free(response_data); 457 | } 458 | 459 | /** 460 | * This callback is responsible for creating a new SSL connection 461 | * and wrapping it in an OpenSSL bufferevent. This is the way 462 | * we implement an https server instead of a plain old http server. 463 | */ 464 | static struct bufferevent* bevcb (struct event_base *base, void *arg) 465 | { 466 | struct bufferevent* r; 467 | SSL_CTX *ctx = (SSL_CTX *) arg; 468 | 469 | r = bufferevent_openssl_socket_new (base, 470 | -1, 471 | SSL_new (ctx), 472 | BUFFEREVENT_SSL_ACCEPTING, 473 | BEV_OPT_CLOSE_ON_FREE); 474 | return r; 475 | } 476 | 477 | static void server_setup_certs (SSL_CTX *ctx, 478 | const char *certificate_chain, 479 | const char *private_key) 480 | { 481 | info_report ("Loading certificate chain from '%s'\n" 482 | "and private key from '%s'\n", 483 | certificate_chain, private_key); 484 | 485 | if (1 != SSL_CTX_use_certificate_chain_file (ctx, certificate_chain)) 486 | die_most_horribly_from_openssl_error ("SSL_CTX_use_certificate_chain_file"); 487 | 488 | if (1 != SSL_CTX_use_PrivateKey_file (ctx, private_key, SSL_FILETYPE_PEM)) 489 | die_most_horribly_from_openssl_error ("SSL_CTX_use_PrivateKey_file"); 490 | 491 | if (1 != SSL_CTX_check_private_key (ctx)) 492 | die_most_horribly_from_openssl_error ("SSL_CTX_check_private_key"); 493 | } 494 | 495 | static int serve_some_http (void) 496 | { 497 | struct event_base *base; 498 | struct evhttp *http; 499 | struct evhttp_bound_socket *handle; 500 | 501 | 502 | base = event_base_new (); 503 | if (! base) 504 | { 505 | fprintf (stderr, "Couldn't create an event_base: exiting\n"); 506 | return 1; 507 | } 508 | 509 | /* 创建一个 evhttp 句柄,去处理用户端的requests请求 */ 510 | http = evhttp_new (base); 511 | if (! http) 512 | { fprintf (stderr, "couldn't create evhttp. Exiting.\n"); 513 | return 1; 514 | } 515 | 516 | /* 创建SSL上下文环境 ,可以理解为 SSL句柄 */ 517 | SSL_CTX *ctx = SSL_CTX_new (SSLv23_server_method ()); 518 | SSL_CTX_set_options (ctx, 519 | SSL_OP_SINGLE_DH_USE | 520 | SSL_OP_SINGLE_ECDH_USE | 521 | SSL_OP_NO_SSLv2); 522 | 523 | /* Cheesily pick an elliptic curve to use with elliptic curve ciphersuites. 524 | * We just hardcode a single curve which is reasonably decent. 525 | * See http://www.mail-archive.com/openssl-dev@openssl.org/msg30957.html */ 526 | EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 527 | if (! ecdh) 528 | die_most_horribly_from_openssl_error ("EC_KEY_new_by_curve_name"); 529 | if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) 530 | die_most_horribly_from_openssl_error ("SSL_CTX_set_tmp_ecdh"); 531 | 532 | /* 选择服务器证书 和 服务器私钥. */ 533 | const char *certificate_chain = "server-certificate-chain.pem"; 534 | const char *private_key = "server-private-key.pem"; 535 | /* 设置服务器证书 和 服务器私钥 到 536 | OPENSSL ctx上下文句柄中 */ 537 | server_setup_certs (ctx, certificate_chain, private_key); 538 | 539 | /* 540 | 使我们创建好的evhttp句柄 支持 SSL加密 541 | 实际上,加密的动作和解密的动作都已经帮 542 | 我们自动完成,我们拿到的数据就已经解密之后的 543 | */ 544 | evhttp_set_bevcb (http, bevcb, ctx); 545 | 546 | /* 设置http回调函数 */ 547 | //默认回调 548 | //专属uri路径回调 549 | evhttp_set_cb(http, "/login", login_cb, NULL); 550 | evhttp_set_cb(http, "/rest/atas/sessionBegin.do", Object, NULL); 551 | evhttp_set_cb(http, "/rest/atas/sessionWarn.do", sessionWarn, NULL); 552 | evhttp_set_cb(http, "/rest/atas/sessionBegin.do", sessionBegin, NULL); 553 | evhttp_set_cb(http, "/rest/atas/sessionWarn.do", sessionWarn, NULL); 554 | evhttp_set_cb(http, "/rest/atas/sessionEnd.do", sessionEnd, NULL); 555 | 556 | /* 设置监听IP和端口 */ 557 | handle = evhttp_bind_socket_with_handle (http, "0.0.0.0", serverPort); 558 | if (! handle) 559 | { 560 | fprintf (stderr, "couldn't bind to port %d. Exiting.\n",(int) serverPort); 561 | return 1; 562 | } 563 | 564 | { 565 | /* 打印收到的客户端链接信息 */ 566 | sock_hop ss; 567 | evutil_socket_t fd; 568 | ev_socklen_t socklen = sizeof (ss); 569 | char addrbuf[128]; 570 | void *inaddr; 571 | const char *addr; 572 | int got_port = -1; 573 | 574 | fd = evhttp_bound_socket_get_fd (handle); 575 | memset (&ss, 0, sizeof(ss)); 576 | 577 | if (getsockname (fd, &ss.sa, &socklen)) 578 | { 579 | perror ("getsockname() failed"); 580 | return 1; 581 | } 582 | if (ss.ss.ss_family == AF_INET) 583 | { 584 | got_port = ntohs (ss.in.sin_port); 585 | inaddr = &ss.in.sin_addr; 586 | } 587 | else if (ss.ss.ss_family == AF_INET6) 588 | { 589 | got_port = ntohs (ss.i6.sin6_port); 590 | inaddr = &ss.i6.sin6_addr; 591 | } 592 | else 593 | { 594 | fprintf (stderr, "Weird address family %d\n", ss.ss.ss_family); 595 | return 1; 596 | } 597 | addr = evutil_inet_ntop (ss.ss.ss_family, inaddr, addrbuf, 598 | sizeof (addrbuf)); 599 | if (addr) 600 | printf ("Listening on %s:%d\n", addr, got_port); 601 | else 602 | { 603 | fprintf (stderr, "evutil_inet_ntop failed\n"); 604 | return 1; 605 | } 606 | } 607 | 608 | /* 开始阻塞监听 (永久执行) */ 609 | event_base_dispatch (base); 610 | 611 | 612 | return 0; 613 | } 614 | 615 | int main (int argc, char **argv) 616 | { 617 | /*OpenSSL 初始化 */ 618 | common_setup (); 619 | 620 | if (argc > 1) { 621 | char *end_ptr; 622 | long lp = strtol(argv[1], &end_ptr, 0); 623 | if (*end_ptr) { 624 | fprintf(stderr, "Invalid integer\n"); 625 | return -1; 626 | } 627 | if (lp <= 0) { 628 | fprintf(stderr, "Port must be positive\n"); 629 | return -1; 630 | } 631 | if (lp >= USHRT_MAX) { 632 | fprintf(stderr, "Port must fit 16-bit range\n"); 633 | return -1; 634 | } 635 | 636 | serverPort = (unsigned short)lp; 637 | } 638 | 639 | /* now run http server (never returns) */ 640 | return serve_some_http (); 641 | } 642 | -------------------------------------------------------------------------------- /server-certificate-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDVDCCAj6gAwIBAgIBAzALBgkqhkiG9w0BAQUwgYcxCzAJBgNVBAYTAlVTMRMw 3 | EQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEaMBgGA1UE 4 | ChMRT2Jsb25nIEluZHVzdHJpZXMxDzANBgNVBAsTBlBsYXNtYTEgMB4GA1UEAxMX 5 | Y2hpdmVzLmxhOTIzLm9ibG9uZy5uZXQwHhcNMTIwNjA1MDIzMjE2WhcNMTcwNjA1 6 | MDIzMjE2WjBxMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFDASBgNVBAcTC0xv 7 | cyBBbmdlbGVzMRowGAYDVQQKExFPYmxvbmcgSW5kdXN0cmllczEPMA0GA1UECxMG 8 | UGxhc21hMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZwwCwYJKoZIhvcNAQEBA4GMADCB 9 | iAKBgL68De74WCE0OcoCze9ekkcNsK864Ll2e0HzBDjIade6Zefmn3iesOOPPW3O 10 | t+p6DOfFJqeKJ3VwBQBRAf5gIeOwzNjBvyTOZm+6G7d243GCvozT62GvcQTxCXHq 11 | CkxVjQY5xd7kvwTKiB2ydseVtrciwjyRKPderenPRNIVcpeLAgMBAAGjazBpMB8G 12 | A1UdIwQYMBaAFDcoIJmKB1ym9TvFnuTo3zyVZkTkMAwGA1UdEwEB/wQCMAAwDwYD 13 | VR0PAQH/BAUDAwe4ADAnBgNVHSUEIDAeBggrBgEFBQcDBAYIKwYBBQUHAwIGCCsG 14 | AQUFBwMBMAsGCSqGSIb3DQEBBQOCAQEAZ8f9tHOaq9tIo76rBAVb3I+2lYufjEcx 15 | Vj36+O2Szmx6WBRCpvnGLwVyx7OuFqCGBaoFBRlkSXMOTCQHRE58l7XZ0F4t86hm 16 | Lf06qtyHUDIwNAVXLXkk+5HC2L1nnFQXhpqlZkpqQfIb4o5X3xtxvBquZjXygncO 17 | pCo7O/U5afaxUET2lQ55eLvONt0jWITdoBjuOymahJzPq17elDRPvQg58x7WjH/j 18 | bTrP1MHdKWKPSZ/ByOOnuHEm0RFc/jDqGiju10roIhZ7LwCSg0YP+kQL0lcs9EiY 19 | 13nVCIgoILzFG/rNg7+IQ3zlp6rMtCM8bLZ+r2joN1ABuIOQPS/4Ow== 20 | -----END CERTIFICATE----- 21 | -----BEGIN CERTIFICATE----- 22 | MIID6DCCAtKgAwIBAgIBATALBgkqhkiG9w0BAQUwgYcxCzAJBgNVBAYTAlVTMRMw 23 | EQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEaMBgGA1UE 24 | ChMRT2Jsb25nIEluZHVzdHJpZXMxDzANBgNVBAsTBlBsYXNtYTEgMB4GA1UEAxMX 25 | Y2hpdmVzLmxhOTIzLm9ibG9uZy5uZXQwHhcNMTIwNTI1MDI1NzMzWhcNMzIwNTI1 26 | MDI1NzMzWjCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDAS 27 | BgNVBAcTC0xvcyBBbmdlbGVzMRowGAYDVQQKExFPYmxvbmcgSW5kdXN0cmllczEP 28 | MA0GA1UECxMGUGxhc21hMSAwHgYDVQQDExdjaGl2ZXMubGE5MjMub2Jsb25nLm5l 29 | dDCCAR8wCwYJKoZIhvcNAQEBA4IBDgAwggEJAoIBALfDzI+LZTJ1f/b0hD/q6cvs 30 | JYV1SM2fudV25prref0XoYDCefK7HchyTyb/HleV2+icAvAODfMlKZOo+yOR/839 31 | GenV9aJFx6G+UVuzkymEFOieWV8013vPxE83oEkzhaY/fLYDebThM69F2kMp3xng 32 | ZTyVOVHq8I6Ca3us0LoAS3z8kHQAYnSkvh5BYYqUXS3Ch9/ljSjuAWGaSZ4x7LQB 33 | 2VRj5Q6LySvZxFmgPbs19tE3l2bSvHCJtTI9VTpZxXy182EGhk4spz2UMwaaPs0F 34 | duV+GVFNgRoct6iz76v6YDo+zip/QuJN7iZnzspfn+QkoyDztyeY4zkm7ja4AJMC 35 | AwEAAaNkMGIwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0GA1Ud 36 | DgQWBBQ3KCCZigdcpvU7xZ7k6N88lWZE5DAfBgNVHSMEGDAWgBQ3KCCZigdcpvU7 37 | xZ7k6N88lWZE5DALBgkqhkiG9w0BAQUDggEBABaDKcP7bsRCJk1QKykeDV/poKGZ 38 | gAcObl5379Hazim5Rt9B3OGzA/pqP/yVdgm9Y5GapmiAXgNdWYmLUsx4Ie4gRmgd 39 | HtV4PAyyk5ula0Q17JASIDCRkkSOFJDxMJgyXNW1mGnc7W3ujTKIWa+NeNqy1wc+ 40 | BzWiL3xsPSZ+kqeRLzp9ZQQNKUqevA9J/rqVpvw1+K3wH4YBkDSoc+iE+dMC0M4I 41 | i7iz0f1ylM+xTipTzgz1RWIBUt9OLaIXStvG2NrmRkk4cgFjP2sgE7hLFrT+tnYm 42 | I+HNJhhhspB6uEVHXWrXJ7WQ2UEPHGdhJBBm0zO87cCE/8IGfxB3WP4uHks= 43 | -----END CERTIFICATE----- 44 | -------------------------------------------------------------------------------- /server-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC+vA3u+FghNDnKAs3vXpJHDbCvOuC5dntB8wQ4yGnXumXn5p94 3 | nrDjjz1tzrfqegznxSaniid1cAUAUQH+YCHjsMzYwb8kzmZvuhu3duNxgr6M0+th 4 | r3EE8Qlx6gpMVY0GOcXe5L8EyogdsnbHlba3IsI8kSj3Xq3pz0TSFXKXiwIDAQAB 5 | AoGAXdUEAck5CfS4bVId36Gl0sDAaCROA89u6c3VCN5He7KeiYxibaOcIAcK0Gd/ 6 | ASJUEP1je86yhMq8GyC/G1ZNtO1O6Xo2uYywROzr5MNahA5nnyiXlk7RsNYfkUMu 7 | 8lRAAHynI1eB7iPIWX0APIh61cSSfh3WVIrMP/tT62MKeAkCQQDStkv5bbRpMuSP 8 | kGOBSC2g4YynkDwuaK2gVVJIab5pJ3X9dZ8pcHyIx4s0k7Z96qurNGUZsgopEv7a 9 | 1L3JIpJ3AkEA57qQfVRKnNDhuo6eIoGRQpnu6uIXS7javjAVOUaAITZaY02Gh4Cz 10 | hHAm1/qKrPFepTNBH9EsAeZ0ZSZVPcZ0jQJBAJRRk2rwaMR/+ViAxznyR4PuH+a2 11 | 5VW5gzXPuQqVvF0iVLBjgfRWZKKW6wrISvWZINtzFxMeOn6tC02X4DtbJYMCQHnp 12 | lkDJiuOLpWZPx/RhdDm04JRkVFs7KqHqjA/w/lH61Xzu+XrqhAeGNXllT3YDGocR 13 | Ow7xLhTl2JCqpSf187UCQHY3feozIwgOf25UKbEpZF9cikTyGx4AYQx3zijLgd48 14 | xyLarqimKw8nNeKWQImLsalGiaw2h62H1Ajg6RGIWU0= 15 | -----END RSA PRIVATE KEY----- 16 | --------------------------------------------------------------------------------