Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | merge with trunk |
---|---|
Timelines: | family | ancestors | descendants | both | wtf-8-experiment |
Files: | files | file ages | folders |
SHA1: |
8cacd3399fd184696815d3405daf8f0b |
User & Date: | chw 2019-02-13 18:39:26 |
2019-02-14
| ||
06:12 | merge with trunk check-in: 82d11a9e50 user: chw tags: wtf-8-experiment | |
2019-02-13
| ||
18:39 | merge with trunk check-in: 8cacd3399f user: chw tags: wtf-8-experiment | |
18:33 | use internally built libwebsockets for Wayland and KMSDRM undroidwishes check-in: 22ec538f4d user: chw tags: trunk | |
2019-02-12
| ||
06:16 | merge with trunk check-in: 68a876b70a user: chw tags: wtf-8-experiment | |
Changes to jni/SDL2/configure.
21696 21697 21698 21699 21700 21701 21702 21703 21704 21705 21706 21707 21708 21709 |
if ac_fn_c_try_compile "$LINENO"; then : video_jsmpeg=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_jsmpeg" >&5 $as_echo "$video_jsmpeg" >&6; } if test x$video_jsmpeg = xyes; then |
> > > |
21696 21697 21698 21699 21700 21701 21702 21703 21704 21705 21706 21707 21708 21709 21710 21711 21712 |
if ac_fn_c_try_compile "$LINENO"; then : video_jsmpeg=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" if test x$have_loadso = xyes; then LAV_LIBS="" fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_jsmpeg" >&5 $as_echo "$video_jsmpeg" >&6; } if test x$video_jsmpeg = xyes; then |
Changes to jni/SDL2/configure.in.
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 |
struct lws_context *lwc; struct lws_context_creation_info lwi; lwc = lws_create_context(&lwi); ],[ video_jsmpeg=yes ]) CFLAGS="$save_CFLAGS" fi fi AC_MSG_RESULT($video_jsmpeg) if test x$video_jsmpeg = xyes; then AC_DEFINE(SDL_VIDEO_DRIVER_JSMPEG, 1, [ ]) JSMPEG_SOURCES="$srcdir/src/video/jsmpeg/*.c" |
> > > |
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 |
struct lws_context *lwc; struct lws_context_creation_info lwi; lwc = lws_create_context(&lwi); ],[ video_jsmpeg=yes ]) CFLAGS="$save_CFLAGS" if test x$have_loadso = xyes; then LAV_LIBS="" fi fi fi AC_MSG_RESULT($video_jsmpeg) if test x$video_jsmpeg = xyes; then AC_DEFINE(SDL_VIDEO_DRIVER_JSMPEG, 1, [ ]) JSMPEG_SOURCES="$srcdir/src/video/jsmpeg/*.c" |
Changes to jni/SDL2/src/video/jsmpeg/SDL_jsmpeg.c.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 ... 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 ... 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 ... 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 ... 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 ... 752 753 754 755 756 757 758 759 760 761 762 763 764 765 ... 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 |
#include <libavutil/avutil.h> #include <libavutil/imgutils.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> #include <libwebsockets.h> #include "SDL_jsmpeg_files.h" #if SDL_THREADS_DISABLED #undef USE_ENCODER_THREAD #else #define USE_ENCODER_THREAD ................................................................................ p[0] = v >> 24; p[1] = v >> 16; p[2] = v >> 8; p[3] = v; } /* .keyCode to scancode https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode */ static const SDL_Scancode scancode_table[] = { /* 0 */ SDL_SCANCODE_UNKNOWN, /* 1 */ SDL_SCANCODE_UNKNOWN, /* 2 */ SDL_SCANCODE_UNKNOWN, /* 3 */ SDL_SCANCODE_CANCEL, /* 4 */ SDL_SCANCODE_UNKNOWN, ................................................................................ } static void silentium(void *avcl, int level, const char *fmt, va_list vl) { /* No log messages from ffmpeg libs */ } /* JSMPEG driver bootstrap functions */ static int JSMPEG_Available(void) { av_log_set_callback(silentium); avcodec_register_all(); lws_set_log_level(0, NULL); return 1; } static void JSMPEG_DeleteDevice(SDL_VideoDevice *device) { SDL_free(device); // unload?? } static SDL_VideoDevice * JSMPEG_CreateDevice(int devindex) { SDL_VideoDevice *device; SDL_VideoData *data; ................................................................................ } return SDL_Unsupported(); } static Frame * JSMPEG_EncodeFrame(SDL_WindowData *data) { AVPacket packet; Frame *frame = NULL; unsigned char *p; int ok = 0; memset(&packet, 0, sizeof(packet)); av_init_packet(&packet); avcodec_encode_video2(data->context, &packet, data->frame, &ok); if (ok) { frame = (Frame *) SDL_malloc(sizeof(Frame) + LWS_PRE + 8 + packet.size); if (frame != NULL) { frame->ref_count = 1; frame->size = packet.size + 8; frame->type = LWS_WRITE_BINARY; frame->data = frame + 1; p = (unsigned char *) frame->data; p += LWS_PRE; puti32(p + 0, FRAME_TYPE_VIDEO); puti32(p + 4, frame->size); memcpy(p + 8, packet.data, packet.size); } } av_free_packet(&packet); return frame; } static void JSMPEG_TransmitFrame(Frame *frame, Client *client) { while (frame != NULL && client != NULL) { ................................................................................ /* Transmission */ JSMPEG_TransmitFrame(frame, client); #endif ticks = SDL_GetTicks(); /* About 15 frames per second */ if (ticks - data->ticks >= 62) { uint8_t *pixels[1]; int linesizes[1]; data->ticks = ticks; if (client == NULL) { /* No client connected, do nothing */ ................................................................................ { SDL_WindowData *data; const Uint32 surface_format = SDL_PIXELFORMAT_BGR888; int w, h, bpp, frame_size; Uint32 Rmask, Gmask, Bmask, Amask; const char *env; struct lws_context_creation_info info; /* Free the old framebuffer surface and related data */ data = (SDL_WindowData *) window->driverdata; JSMPEG_CleanupWindowData(data); /* Create a new one */ SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); ................................................................................ data->context = avcodec_alloc_context3(data->codec); if (data->context == NULL) { JSMPEG_CleanupWindowData(data); return -1; } data->context->dct_algo = FF_DCT_FASTINT; data->context->bit_rate = 10000 * w; data->context->bit_rate_tolerance = data->context->bit_rate << 2; data->context->width = w; data->context->height = h; data->context->time_base.num = 1; data->context->time_base.den = 30; data->context->gop_size = 30; data->context->max_b_frames = 0; data->context->pix_fmt = AV_PIX_FMT_YUV420P; avcodec_open2(data->context, data->codec, NULL); data->frame = av_frame_alloc(); if (data->frame == NULL) { JSMPEG_CleanupWindowData(data); return -1; } data->frame->format = AV_PIX_FMT_YUV420P; data->frame->width = w; data->frame->height = h; data->frame->pts = 0; frame_size = avpicture_get_size(AV_PIX_FMT_YUV420P, w, h); data->frame_buffer = SDL_calloc(1, frame_size); if (data->frame_buffer == NULL) { JSMPEG_CleanupWindowData(data); return -1; } avpicture_fill((AVPicture *) data->frame, (uint8_t *) data->frame_buffer, AV_PIX_FMT_YUV420P, w, h); data->sws = sws_getContext(w, h, AV_PIX_FMT_RGB32, w, h, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0); if (data->sws == NULL) { JSMPEG_CleanupWindowData(data); return -1; } data->clients = NULL; memset(&info, 0, sizeof(struct lws_context_creation_info)); |
> > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | > > > > > > > > > > > > > | | < | | | | | | > > > > > | > | > | < > | > | > | > | > | > | > | | | | < > | < < |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 ... 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 ... 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 ... 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 ... 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 ... 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 ... 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 |
#include <libavutil/avutil.h> #include <libavutil/imgutils.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> #include <libwebsockets.h> #if !defined(SDL_LOADSO_DUMMY) && !defined(SDL_LOADSO_DISABLED) #define USE_LOADSO 1 #include "SDL_loadso.h" #endif #include "SDL_jsmpeg_files.h" #if SDL_THREADS_DISABLED #undef USE_ENCODER_THREAD #else #define USE_ENCODER_THREAD ................................................................................ p[0] = v >> 24; p[1] = v >> 16; p[2] = v >> 8; p[3] = v; } /* * .keyCode to scancode * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode */ static const SDL_Scancode scancode_table[] = { /* 0 */ SDL_SCANCODE_UNKNOWN, /* 1 */ SDL_SCANCODE_UNKNOWN, /* 2 */ SDL_SCANCODE_UNKNOWN, /* 3 */ SDL_SCANCODE_CANCEL, /* 4 */ SDL_SCANCODE_UNKNOWN, ................................................................................ } static void silentium(void *avcl, int level, const char *fmt, va_list vl) { /* No log messages from ffmpeg libs */ } /* Runtime linking if supported */ #ifdef USE_LOADSO static void *libavutil = NULL; static void *libavcodec = NULL; static void *libswscale = NULL; #if defined(__WIN32__) #define LIB_AVUTIL_55 "avutil-55.dll" #define LIB_AVUTIL_56 "avutil-56.dll" #define LIB_AVCODEC_57 "avcodec-57.dll" #define LIB_AVCODEC_58 "avcodec-58.dll" #define LIB_SWSCALE_4 "swscale-4.dll" #define LIB_SWSCALE_5 "swscale-5.dll" #elif defined(__MACOSX__) #error fix library names for MACOSX #else #define LIB_AVUTIL_55 "libavutil.so.55" #define LIB_AVUTIL_56 "libavutil.so.56" #define LIB_AVCODEC_57 "libavcodec.so.57" #define LIB_AVCODEC_58 "libavcodec.so.58" #define LIB_SWSCALE_4 "libswscale.so.4" #define LIB_SWSCALE_5 "libswscale.so.5" #endif static struct { /* avutil */ AVFrame *(*av_frame_alloc)(void); void (*av_free)(void *); enum AVPixelFormat (*av_get_pix_fmt)(const char *); void (*av_log_set_callback)(void (*)(void *, int, const char *, va_list)); int (*av_opt_set_image_size)(void *, const char *, int, int, int); int (*av_opt_set_int)(void *, const char *, int64_t, int); int (*av_opt_set_q)(void *, const char *, AVRational, int); int (*av_opt_set_pixel_fmt)(void *, const char *, enum AVPixelFormat, int); /* avcodec */ int (*av_image_fill_arrays)(uint8_t **, int *, uint8_t *, enum AVPixelFormat, int, int, int); AVPacket *(*av_packet_alloc)(void); void (*av_packet_free)(AVPacket **); AVCodecContext *(*avcodec_alloc_context3)(const AVCodec *codec); int (*avcodec_close)(AVCodecContext *); int (*avcodec_encode_video2)(AVCodecContext *, AVPacket *, const AVFrame *, int *); AVCodec *(*avcodec_find_encoder)(enum AVCodecID); int (*avcodec_open2)(AVCodecContext *, const AVCodec *, AVDictionary **); void (*avcodec_register_all)(void); int (*avpicture_get_size)(enum AVPixelFormat, int, int); /* swscale */ void (*sws_freeContext)(struct SwsContext *); struct SwsContext *(*sws_getContext)(int, int, enum AVPixelFormat, int, int, enum AVPixelFormat, int, SwsFilter *, SwsFilter *, const double *); int (*sws_scale)(struct SwsContext *, uint8_t **, int *, int, int, uint8_t **, int *); } syms; static int load_objects_and_syms() { if (libavutil != NULL && libavcodec != NULL && libswscale != NULL) { return 0; } libavutil = SDL_LoadObject(LIB_AVUTIL_55); if (libavutil == NULL) { libavutil = SDL_LoadObject(LIB_AVUTIL_56); } if (libavutil == NULL) { goto error; } libavcodec = SDL_LoadObject(LIB_AVCODEC_57); if (libavcodec == NULL) { libavcodec = SDL_LoadObject(LIB_AVCODEC_58); } if (libavcodec == NULL) { goto error; } libswscale = SDL_LoadObject(LIB_SWSCALE_4); if (libswscale == NULL) { libswscale = SDL_LoadObject(LIB_SWSCALE_5); } if (libswscale == NULL) { goto error; } #undef GET_SYM #define GET_SYM(x) \ if ((syms.x = SDL_LoadFunction(libavutil, #x)) == NULL) \ goto error; GET_SYM(av_frame_alloc); GET_SYM(av_free); GET_SYM(av_get_pix_fmt); GET_SYM(av_log_set_callback); GET_SYM(av_opt_set_image_size); GET_SYM(av_opt_set_int); GET_SYM(av_opt_set_q); GET_SYM(av_opt_set_pixel_fmt); #undef GET_SYM #define GET_SYM(x) \ if ((syms.x = SDL_LoadFunction(libavcodec, #x)) == NULL) \ goto error; GET_SYM(av_image_fill_arrays); GET_SYM(av_packet_alloc); GET_SYM(av_packet_free); GET_SYM(avcodec_alloc_context3); GET_SYM(avcodec_close); GET_SYM(avcodec_encode_video2); GET_SYM(avcodec_find_encoder); GET_SYM(avcodec_open2); GET_SYM(avcodec_register_all); GET_SYM(avpicture_get_size); #undef GET_SYM #define GET_SYM(x) \ if ((syms.x = SDL_LoadFunction(libswscale, #x)) == NULL) \ goto error; GET_SYM(sws_freeContext); GET_SYM(sws_getContext); GET_SYM(sws_scale); #undef GET_SYM return 0; error: if (libswscale != NULL) { SDL_UnloadObject(libswscale); libswscale = NULL; } if (libavcodec != NULL) { SDL_UnloadObject(libavcodec); libavcodec = NULL; } if (libavutil != NULL) { SDL_UnloadObject(libavutil); libavutil = NULL; } return -1; } /* avutil */ #define av_frame_alloc syms.av_frame_alloc #define av_free syms.av_free #define av_get_pix_fmt syms.av_get_pix_fmt #define av_log_set_callback syms.av_log_set_callback #define av_opt_set_image_size syms.av_opt_set_image_size #define av_opt_set_int syms.av_opt_set_int #define av_opt_set_q syms.av_opt_set_q #define av_opt_set_pixel_fmt syms.av_opt_set_pixel_fmt /* avcodec */ #define av_image_fill_arrays syms.av_image_fill_arrays #define av_packet_alloc syms.av_packet_alloc #define av_packet_free syms.av_packet_free #define avcodec_alloc_context3 syms.avcodec_alloc_context3 #define avcodec_close syms.avcodec_close #define avcodec_encode_video2 syms.avcodec_encode_video2 #define avcodec_find_encoder syms.avcodec_find_encoder #define avcodec_open2 syms.avcodec_open2 #define avcodec_register_all syms.avcodec_register_all #define avpicture_get_size syms.avpicture_get_size /* swscale */ #define sws_freeContext syms.sws_freeContext #define sws_getContext syms.sws_getContext #define sws_scale syms.sws_scale #endif /* JSMPEG driver bootstrap functions */ static int JSMPEG_Available(void) { lws_set_log_level(0, NULL); #ifdef USE_LOADSO if (load_objects_and_syms() < 0) { return 0; } #endif av_log_set_callback(silentium); avcodec_register_all(); return 1; } static void JSMPEG_DeleteDevice(SDL_VideoDevice *device) { SDL_free(device); #ifdef USE_LOADSO if (libswscale != NULL) { SDL_UnloadObject(libswscale); libswscale = NULL; } if (libavcodec != NULL) { SDL_UnloadObject(libavcodec); libavcodec = NULL; } if (libavutil != NULL) { SDL_UnloadObject(libavutil); libavutil = NULL; } #endif } static SDL_VideoDevice * JSMPEG_CreateDevice(int devindex) { SDL_VideoDevice *device; SDL_VideoData *data; ................................................................................ } return SDL_Unsupported(); } static Frame * JSMPEG_EncodeFrame(SDL_WindowData *data) { AVPacket *packet; Frame *frame = NULL; unsigned char *p; int ok = 0; packet = av_packet_alloc(); avcodec_encode_video2(data->context, packet, data->frame, &ok); if (ok) { frame = (Frame *) SDL_malloc(sizeof(Frame) + LWS_PRE + 8 + packet->size); if (frame != NULL) { frame->ref_count = 1; frame->size = packet->size + 8; frame->type = LWS_WRITE_BINARY; frame->data = frame + 1; p = (unsigned char *) frame->data; p += LWS_PRE; puti32(p + 0, FRAME_TYPE_VIDEO); puti32(p + 4, frame->size); memcpy(p + 8, packet->data, packet->size); } } av_packet_free(&packet); return frame; } static void JSMPEG_TransmitFrame(Frame *frame, Client *client) { while (frame != NULL && client != NULL) { ................................................................................ /* Transmission */ JSMPEG_TransmitFrame(frame, client); #endif ticks = SDL_GetTicks(); /* About 15 frames per second */ if (ticks - data->ticks >= 63) { uint8_t *pixels[1]; int linesizes[1]; data->ticks = ticks; if (client == NULL) { /* No client connected, do nothing */ ................................................................................ { SDL_WindowData *data; const Uint32 surface_format = SDL_PIXELFORMAT_BGR888; int w, h, bpp, frame_size; Uint32 Rmask, Gmask, Bmask, Amask; const char *env; struct lws_context_creation_info info; AVRational q; enum AVPixelFormat fmt_yuv, fmt_rgb; /* Free the old framebuffer surface and related data */ data = (SDL_WindowData *) window->driverdata; JSMPEG_CleanupWindowData(data); /* Create a new one */ SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); ................................................................................ data->context = avcodec_alloc_context3(data->codec); if (data->context == NULL) { JSMPEG_CleanupWindowData(data); return -1; } fmt_yuv = av_get_pix_fmt("yuv420p"); fmt_rgb = av_get_pix_fmt("rgb32"); /* dct_algo = FF_DCT_FASTINT */ av_opt_set_int(data->context, "dct", FF_DCT_FASTINT, 0); /* bit_rate = 10000 * w */ av_opt_set_int(data->context, "b", 10000 * w, 0); /* bit_rate_tolerance = (10000 * w) << 2 */ av_opt_set_int(data->context, "bt", (10000 * w) << 2, 0); /* width = w, height = h */ av_opt_set_image_size(data->context, "video_size", w, h, 0); /* time_base.num = 1, time_base.den = 30 */ q.num = 1; q.den = 30; av_opt_set_q(data->context, "time_base", q, 0); /* gop_size = 30 */ av_opt_set_int(data->context, "g", 30, 0); /* max_b_frames = 0 */ av_opt_set_int(data->context, "bf", 0, 0); /* pix_fmt = AV_PIX_FMT_YUV420P */ av_opt_set_pixel_fmt(data->context, "pixel_format", fmt_yuv, 0); avcodec_open2(data->context, data->codec, NULL); data->frame = av_frame_alloc(); if (data->frame == NULL) { JSMPEG_CleanupWindowData(data); return -1; } data->frame->format = fmt_yuv; data->frame->width = w; data->frame->height = h; data->frame->pts = 0; frame_size = avpicture_get_size(fmt_yuv, w, h); data->frame_buffer = SDL_malloc(frame_size); if (data->frame_buffer == NULL) { JSMPEG_CleanupWindowData(data); return -1; } av_image_fill_arrays(data->frame->data, data->frame->linesize, data->frame_buffer, fmt_yuv, w, h, 1); data->sws = sws_getContext(w, h, fmt_rgb, w, h, fmt_yuv, SWS_FAST_BILINEAR, NULL, NULL, NULL); if (data->sws == NULL) { JSMPEG_CleanupWindowData(data); return -1; } data->clients = NULL; memset(&info, 0, sizeof(struct lws_context_creation_info)); |
Changes to jni/sdl2tk/macosx/tkMacOSXWindowEvent.c.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 .. 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 ... 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 |
isEqualToString:NSWindowDidMoveNotification]; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect bounds = [w frame]; NSRect screenRect = [[w screen] frame]; int x, y, width = -1, height = -1, flags = 0; int minY = 1 + [[NSApp mainMenu] menuBarHeight]; x = bounds.origin.x; y = screenRect.size.height - (bounds.origin.y + bounds.size.height); if (winPtr->changes.x != x || winPtr->changes.y != y) { flags |= TK_LOCATION_CHANGED; } else { x = y = -1; } if (!movedOnly && (winPtr->changes.width != bounds.size.width || winPtr->changes.height != bounds.size.height)) { ................................................................................ * Propagate geometry changes immediately. */ flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY; } /* * Mac windows cannot go higher than the bottom of the menu bar. The * Tk window manager can request that a window be drawn so that it * overlaps the menu bar, but it will actually be drawn immediately * below the menu bar. In such a case it saves a lot of trouble and * causes no harm if we let Tk think that the window is located at the * requested point. (Many of the the tests assume that this is the * case, especially for windows with upper left corner at (0,0).) So * we just tell a harmless white lie here. ................................................................................ */ if (Tk_IsTopLevel(winPtr)) { wmPtr = winPtr->wmInfoPtr; if (flags & TK_LOCATION_CHANGED) { wmPtr->x = x; wmPtr->y = y; //wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); } if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) && ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { /* * Don't set external width, since the user didn't change it |
< | | < |
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 .. 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ... 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
isEqualToString:NSWindowDidMoveNotification]; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect bounds = [w frame]; int x, y, width = -1, height = -1, flags = 0; int minY = 1 + [[NSApp mainMenu] menuBarHeight]; x = bounds.origin.x; y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height); if (winPtr->changes.x != x || winPtr->changes.y != y) { flags |= TK_LOCATION_CHANGED; } else { x = y = -1; } if (!movedOnly && (winPtr->changes.width != bounds.size.width || winPtr->changes.height != bounds.size.height)) { ................................................................................ * Propagate geometry changes immediately. */ flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY; } /* * Mac windows are not allowed to overlap the menu bar. The * Tk window manager can request that a window be drawn so that it * overlaps the menu bar, but it will actually be drawn immediately * below the menu bar. In such a case it saves a lot of trouble and * causes no harm if we let Tk think that the window is located at the * requested point. (Many of the the tests assume that this is the * case, especially for windows with upper left corner at (0,0).) So * we just tell a harmless white lie here. ................................................................................ */ if (Tk_IsTopLevel(winPtr)) { wmPtr = winPtr->wmInfoPtr; if (flags & TK_LOCATION_CHANGED) { wmPtr->x = x; wmPtr->y = y; } if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) && ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { /* * Don't set external width, since the user didn't change it |
Changes to jni/sdl2tk/sdl/SdlTkX.c.
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 |
} if (CheckGroups(checkInput) < 0) { SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Permission problem, exiting"); goto fatal; } #endif retryInit: #endif if (SDL_Init(initMask) < 0) { #ifdef ANDROID __android_log_print(ANDROID_LOG_ERROR, "libtk", "Couldn't initialize SDL: %s", SDL_GetError()); #else |
> |
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 |
}
if (CheckGroups(checkInput) < 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
"Permission problem, exiting");
goto fatal;
}
#endif
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
retryInit:
#endif
if (SDL_Init(initMask) < 0) {
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "libtk",
"Couldn't initialize SDL: %s", SDL_GetError());
#else
|
Changes to undroid/build-undroidwish-kmsdrm.sh.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 ... 130 131 132 133 134 135 136 137 138 139 140 141 142 143 ... 248 249 250 251 252 253 254 255 256 257 258 259 260 261 ... 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 |
AR=ar RANLIB=ranlib CC="gcc -DTCL_UTF_MAX=3" CXX="g++ -fno-exceptions -fno-rtti -DTCL_UTF_MAX=3" NM=nm export STRIP AR RANLIB CC CXX RC NM SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls" SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo" SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2" SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint" SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral" SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf libsocketcan tclcan vu" SUBDIRS="${SUBDIRS} rl_json mpexpr" SUBDIRS="${SUBDIRS} tclcsv tkzinc libffi ffidl tcl-lmdb DiffUtilTcl" ................................................................................ ;; mpexpr) rm -f ${i}/unix/build-stamp ;; snap7) rm -f ${i}/build/unix/build-stamp ;; *) rm -f ${i}/build-stamp ;; esac done } ................................................................................ ) || true ;; snap7) ( exec >> build.log 2>&1 make -C snap7/build/unix -f unix.mk clean || true ) || true ;; *) ( exec >> build.log 2>&1 make -C $i ${ACTION} || true ) || true ;; ................................................................................ perl -ni -e 'print unless /t42_driver/' objs/ftmodule.h perl -ni -e 'print unless /winfnt_driver/' objs/ftmodule.h make || exit 1 make install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build SDL2 (static, pic) ... " ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" cd SDL2 test -e build-stamp && echo >&3 "already done" && exit 0 # Enabled video drivers: KMSDRM only ./configure --prefix=${PFX_HERE} \ --disable-shared --disable-arts --disable-esd --disable-nas \ --enable-pulseaudio-shared --enable-alsa --disable-rpath \ --disable-video-wayland --disable-video-wayland-qt-touch \ --disable-video-x11 --enable-video-opengles --enable-video-opengles2 \ --enable-video-opengles1 --enable-video-kmsdrm \ --disable-video-vulkan --disable-video-mir --enable-video-jsmpeg \ |
| > > > > > > > > > > > > > > > > > > > > > > > > > > > |
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ... 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 ... 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 ... 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 |
AR=ar RANLIB=ranlib CC="gcc -DTCL_UTF_MAX=3" CXX="g++ -fno-exceptions -fno-rtti -DTCL_UTF_MAX=3" NM=nm export STRIP AR RANLIB CC CXX RC NM SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload" SUBDIRS="${SUBDIRS} tls libwebsockets" SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo" SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2" SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint" SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral" SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf libsocketcan tclcan vu" SUBDIRS="${SUBDIRS} rl_json mpexpr" SUBDIRS="${SUBDIRS} tclcsv tkzinc libffi ffidl tcl-lmdb DiffUtilTcl" ................................................................................ ;; mpexpr) rm -f ${i}/unix/build-stamp ;; snap7) rm -f ${i}/build/unix/build-stamp ;; libwebsockets) rm -f ${i}/build/build-stamp ;; *) rm -f ${i}/build-stamp ;; esac done } ................................................................................ ) || true ;; snap7) ( exec >> build.log 2>&1 make -C snap7/build/unix -f unix.mk clean || true ) || true ;; libwebsockets) ( exec >> build.log 2>&1 rm -rf libwebsockets/build ) || true ;; *) ( exec >> build.log 2>&1 make -C $i ${ACTION} || true ) || true ;; ................................................................................ perl -ni -e 'print unless /t42_driver/' objs/ftmodule.h perl -ni -e 'print unless /winfnt_driver/' objs/ftmodule.h make || exit 1 make install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build libwebsockets (static, pic) ..." ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" mkdir -p libwebsockets/build cd libwebsockets/build cmake .. -DCMAKE_INSTALL_PREFIX=${PFX_HERE}/extra \ -DLWS_IPV6=ON -DLWS_WITH_SHARED=OFF -DLWS_WITH_SSL=OFF || exit 1 make VERBOSE=1 COLOR=0 || exit 1 make VERBOSE=1 COLOR=0 install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build SDL2 (static, pic) ... " ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" cd SDL2 test -e build-stamp && echo >&3 "already done" && exit 0 # Enabled video drivers: KMSDRM only PKG_CONFIG_PATH="${PFX_HERE}/extra/lib/pkgconfig" \ ./configure --prefix=${PFX_HERE} \ --disable-shared --disable-arts --disable-esd --disable-nas \ --enable-pulseaudio-shared --enable-alsa --disable-rpath \ --disable-video-wayland --disable-video-wayland-qt-touch \ --disable-video-x11 --enable-video-opengles --enable-video-opengles2 \ --enable-video-opengles1 --enable-video-kmsdrm \ --disable-video-vulkan --disable-video-mir --enable-video-jsmpeg \ |
Changes to undroid/build-undroidwish-wayland.sh.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 ... 130 131 132 133 134 135 136 137 138 139 140 141 142 143 ... 248 249 250 251 252 253 254 255 256 257 258 259 260 261 ... 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 |
AR=ar RANLIB=ranlib CC="gcc -DTCL_UTF_MAX=3" CXX="g++ -fno-exceptions -fno-rtti -DTCL_UTF_MAX=3" NM=nm export STRIP AR RANLIB CC CXX RC NM SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls" SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo" SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2" SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint" SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral" SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf libsocketcan tclcan vu" SUBDIRS="${SUBDIRS} rl_json mpexpr" SUBDIRS="${SUBDIRS} tclcsv tkzinc libffi ffidl tcl-lmdb DiffUtilTcl" ................................................................................ ;; mpexpr) rm -f ${i}/unix/build-stamp ;; snap7) rm -f ${i}/build/unix/build-stamp ;; *) rm -f ${i}/build-stamp ;; esac done } ................................................................................ ) || true ;; snap7) ( exec >> build.log 2>&1 make -C snap7/build/unix -f unix.mk clean || true ) || true ;; *) ( exec >> build.log 2>&1 make -C $i ${ACTION} || true ) || true ;; ................................................................................ perl -ni -e 'print unless /t42_driver/' objs/ftmodule.h perl -ni -e 'print unless /winfnt_driver/' objs/ftmodule.h make || exit 1 make install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build SDL2 (static, pic) ... " ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" cd SDL2 test -e build-stamp && echo >&3 "already done" && exit 0 # Enabled video drivers: wayland, X11, KMSDRM ./configure --prefix=${PFX_HERE} \ --disable-shared --disable-arts --disable-esd --disable-nas \ --enable-pulseaudio-shared --enable-alsa --disable-rpath \ --enable-video-wayland --disable-video-wayland-qt-touch \ --enable-video-opengles --enable-video-opengles2 \ --enable-video-opengles1 --enable-wayland-shared \ --enable-video-kmsdrm --disable-video-vulkan --disable-video-mir \ |
| > > > > > > > > > > > > > > > > > > > > > > > > > > > |
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ... 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 ... 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 ... 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 |
AR=ar RANLIB=ranlib CC="gcc -DTCL_UTF_MAX=3" CXX="g++ -fno-exceptions -fno-rtti -DTCL_UTF_MAX=3" NM=nm export STRIP AR RANLIB CC CXX RC NM SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload" SUBDIRS="${SUBDIRS} tls libwebsockets" SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo" SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2" SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint" SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral" SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf libsocketcan tclcan vu" SUBDIRS="${SUBDIRS} rl_json mpexpr" SUBDIRS="${SUBDIRS} tclcsv tkzinc libffi ffidl tcl-lmdb DiffUtilTcl" ................................................................................ ;; mpexpr) rm -f ${i}/unix/build-stamp ;; snap7) rm -f ${i}/build/unix/build-stamp ;; libwebsockets) rm -f ${i}/build/build-stamp ;; *) rm -f ${i}/build-stamp ;; esac done } ................................................................................ ) || true ;; snap7) ( exec >> build.log 2>&1 make -C snap7/build/unix -f unix.mk clean || true ) || true ;; libwebsockets) ( exec >> build.log 2>&1 rm -rf libwebsockets/build ) || true ;; *) ( exec >> build.log 2>&1 make -C $i ${ACTION} || true ) || true ;; ................................................................................ perl -ni -e 'print unless /t42_driver/' objs/ftmodule.h perl -ni -e 'print unless /winfnt_driver/' objs/ftmodule.h make || exit 1 make install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build libwebsockets (static, pic) ..." ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" mkdir -p libwebsockets/build cd libwebsockets/build cmake .. -DCMAKE_INSTALL_PREFIX=${PFX_HERE}/extra \ -DLWS_IPV6=ON -DLWS_WITH_SHARED=OFF -DLWS_WITH_SSL=OFF || exit 1 make VERBOSE=1 COLOR=0 || exit 1 make VERBOSE=1 COLOR=0 install || exit 1 touch build-stamp echo >&3 "done" ) || fail echo -n "build SDL2 (static, pic) ... " ( exec 3>&1 exec >> build.log 2>&1 CC="$CC -fPIC" CXX="$CXX -fPIC" cd SDL2 test -e build-stamp && echo >&3 "already done" && exit 0 # Enabled video drivers: wayland, X11, KMSDRM PKG_CONFIG_PATH="${PFX_HERE}/extra/lib/pkgconfig" \ ./configure --prefix=${PFX_HERE} \ --disable-shared --disable-arts --disable-esd --disable-nas \ --enable-pulseaudio-shared --enable-alsa --disable-rpath \ --enable-video-wayland --disable-video-wayland-qt-touch \ --enable-video-opengles --enable-video-opengles2 \ --enable-video-opengles1 --enable-wayland-shared \ --enable-video-kmsdrm --disable-video-vulkan --disable-video-mir \ |
Added undroid/libwebsockets/Android.mk.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# example Android Native Library makefile # contributed by Gregory Junker <ggjunker@gmail.com> LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libwebsockets LOCAL_CFLAGS := -DLWS_BUILTIN_GETIFADDRS LWS_LIB_PATH := ../../../shared/libwebsockets/lib LOCAL_C_INCLUDES:= $(LOCAL_PATH)/$(LWS_LIB_PATH) LOCAL_SRC_FILES := \ $(LWS_LIB_PATH)/base64-decode.c \ $(LWS_LIB_PATH)/client.c \ $(LWS_LIB_PATH)/client-handshake.c \ $(LWS_LIB_PATH)/client-parser.c \ $(LWS_LIB_PATH)/daemonize.c \ $(LWS_LIB_PATH)/extension.c \ $(LWS_LIB_PATH)/extension-deflate-frame.c \ $(LWS_LIB_PATH)/extension-deflate-stream.c \ $(LWS_LIB_PATH)/getifaddrs.c \ $(LWS_LIB_PATH)/handshake.c \ $(LWS_LIB_PATH)/libwebsockets.c \ $(LWS_LIB_PATH)/md5.c \ $(LWS_LIB_PATH)/output.c \ $(LWS_LIB_PATH)/parsers.c \ $(LWS_LIB_PATH)/sha-1.c include $(BUILD_STATIC_LIBRARY) |
Added undroid/libwebsockets/CMakeLists.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 |
cmake_minimum_required(VERSION 2.8) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") endif() project(libwebsockets C) set(PACKAGE "libwebsockets") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "2") set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "3") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VENDOR "andy@warmcat.com") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}") set(SOVERSION "8.1") set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(VERSION "${CPACK_PACKAGE_VERSION}") set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION}) set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set(LWS_LIBRARY_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) set(LWS_LIBRARY_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") # Try to find the current Git hash. find_package(Git) if(GIT_EXECUTABLE) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMAND "${GIT_EXECUTABLE}" describe OUTPUT_VARIABLE GIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMAND "whoami" OUTPUT_VARIABLE GIT_USER OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMAND "hostname" OUTPUT_VARIABLE GIT_HOST OUTPUT_STRIP_TRAILING_WHITESPACE ) string(REGEX REPLACE "([^\\])[\\]([^\\])" "\\1\\\\\\\\\\2" GIT_USER ${GIT_USER}) set(LWS_BUILD_HASH ${GIT_USER}@${GIT_HOST}-${GIT_HASH}) message("Git commit hash: ${LWS_BUILD_HASH}") endif() set(LWS_USE_BUNDLED_ZLIB_DEFAULT OFF) if(WIN32) set(LWS_USE_BUNDLED_ZLIB_DEFAULT ON) endif() option(LWS_WITH_STATIC "Build the static version of the library" ON) option(LWS_WITH_SHARED "Build the shared version of the library" ON) option(LWS_WITH_SSL "Include SSL support (default OpenSSL, wolfSSL if LWS_USE_WOLFSSL is set)" ON) option(LWS_USE_CYASSL "Use CyaSSL replacement for OpenSSL. When setting this, you also need to specify LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS" OFF) option(LWS_USE_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF) option(LWS_USE_POLARSSL "Use Polarssl (or mbedtls < 2.0) replacement for OpenSSL. When setting this, you also need to specify LWS_POLARSSL_LIBRARIES and LWS_POLARSSL_INCLUDE_DIRS" OFF) option(LWS_USE_MBEDTLS "Use mbedTLS (>=2.0) replacement for OpenSSL. When setting this, you also need to specify LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS" OFF) option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" ON) option(LWS_WITH_LIBEV "Compile with support for libev" OFF) option(LWS_WITH_LIBUV "Compile with support for libuv" OFF) option(LWS_USE_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_USE_BUNDLED_ZLIB_DEFAULT}) option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of the OS-installed CA root certs" ON) option(LWS_WITHOUT_BUILTIN_GETIFADDRS "Don't use the BSD getifaddrs implementation from libwebsockets if it is missing (this will result in a compilation error) ... The default is to assume that your libc provides it. On some systems such as uclibc it doesn't exist." OFF) option(LWS_WITHOUT_BUILTIN_SHA1 "Don't build the lws sha-1 (eg, because openssl will provide it" OFF) option(LWS_WITHOUT_CLIENT "Don't build the client part of the library" OFF) option(LWS_WITHOUT_SERVER "Don't build the server part of the library" OFF) option(LWS_LINK_TESTAPPS_DYNAMIC "Link the test apps to the shared version of the library. Default is to link statically" OFF) option(LWS_WITHOUT_TESTAPPS "Don't build the libwebsocket-test-apps" OFF) option(LWS_WITHOUT_TEST_SERVER "Don't build the test server" OFF) option(LWS_WITHOUT_TEST_SERVER_EXTPOLL "Don't build the test server version that uses external poll" OFF) option(LWS_WITHOUT_TEST_PING "Don't build the ping test application" OFF) option(LWS_WITHOUT_TEST_ECHO "Don't build the echo test application" OFF) option(LWS_WITHOUT_TEST_CLIENT "Don't build the client test application" OFF) option(LWS_WITHOUT_TEST_FRAGGLE "Don't build the ping test application" OFF) option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF) option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF) option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" ON) option(LWS_IPV6 "Compile with support for ipv6" OFF) option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF) option(LWS_WITH_HTTP2 "Compile with support for http2" OFF) option(LWS_MBED3 "Platform is MBED3" OFF) option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF) option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF) option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying" OFF) option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF) option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF) option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF) option(LWS_WITH_SERVER_STATUS "Support json + jscript server monitoring" OFF) if (LWS_WITH_LWSWS) message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV") set(LWS_WITH_PLUGINS 1) set(LWS_WITH_LIBUV 1) set(LWS_WITH_ACCESS_LOG 1) set(LWS_WITH_SERVER_STATUS 1) endif() if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) message(STATUS "LWS_WITH_PLUGINS --> Enabling LWS_WITH_LIBUV") set(LWS_WITH_LIBUV 1) endif() if (DEFINED YOTTA_WEBSOCKETS_VERSION_STRING) set(LWS_WITH_SHARED OFF) set(LWS_WITH_SSL OFF) set(LWS_WITH_ZLIB OFF) set(LWS_WITHOUT_CLIENT ON) set(LWS_WITHOUT_TESTAPPS ON) set(LWS_WITHOUT_EXTENSIONS ON) set(LWS_WITH_PLUGINS OFF) set(LWS_MBED3 ON) # this implies no pthreads in the lib set(LWS_MAX_SMP 1) endif() if (WIN32) # this implies no pthreads in the lib set(LWS_MAX_SMP 1) endif() if (LWS_WITHOUT_SERVER) set(LWS_WITH_LWSWS OFF) endif() if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER)) message(FATAL_ERROR "You have to enable both client and server for http proxy") endif() # Allow the user to override installation directories. set(LWS_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") set(LWS_INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") set(LWS_INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") set(LWS_INSTALL_EXAMPLES_DIR bin CACHE PATH "Installation directory for example files") # Allow the user to use the old CyaSSL options/library in stead of wolfSSL if (LWS_USE_CYASSL AND LWS_USE_WOLFSSL) message(FATAL_ERROR "LWS_USE_CYASSL and LWS_USE_WOLFSSL are mutually exclusive!") endif() if (LWS_USE_CYASSL) # Copy CyaSSL options to the wolfSSL options set(LWS_USE_WOLFSSL ${LWS_USE_CYASSL} CACHE BOOL "Use wolfSSL/CyaSSL instead of OpenSSL" FORCE) set(LWS_WOLFSSL_LIBRARIES ${LWS_CYASSL_LIBRARIES} CACHE PATH "Path to wolfSSL/CyaSSL libraries" FORCE) set(LWS_WOLFSSL_INCLUDE_DIRS ${LWS_CYASSL_INCLUDE_DIRS} CACHE PATH "Path to wolfSSL/CyaSSL header files" FORCE) endif() if (LWS_WITHOUT_CLIENT AND LWS_WITHOUT_SERVER) message(FATAL_ERROR "Makes no sense to compile with neither client nor server.") endif() if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") endif() if (NOT LWS_WITHOUT_EXTENSIONS) if (NOT LWS_WITH_ZLIB) message(FATAL_ERROR "zlib is required for extensions.") endif() endif() set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib library") set(LWS_ZLIB_INCLUDE_DIRS CACHE PATH "Path to the zlib include directory") set(LWS_OPENSSL_LIBRARIES CACHE PATH "Path to the OpenSSL library") set(LWS_OPENSSL_INCLUDE_DIRS CACHE PATH "Path to the OpenSSL include directory") set(LWS_WOLFSSL_LIBRARIES CACHE PATH "Path to the wolfSSL library") set(LWS_WOLFSSL_INCLUDE_DIRS CACHE PATH "Path to the wolfSSL include directory") set(LWS_POLARSSL_LIBRARIES CACHE PATH "Path to the PolarSSL library") set(LWS_POLARSSL_INCLUDE_DIRS CACHE PATH "Path to the PolarSSL include directory") set( CACHE PATH "Path to the libev library") set(LWS_LIBEV_INCLUDE_DIRS CACHE PATH "Path to the libev include directory") set(LWS_LIBUV_LIBRARIES CACHE PATH "Path to the libuv library") set(LWS_LIBUV_INCLUDE_DIRS CACHE PATH "Path to the libuv include directory") if (NOT LWS_WITH_SSL) set(LWS_WITHOUT_BUILTIN_SHA1 OFF) endif() if (LWS_WITH_SSL AND NOT LWS_USE_WOLFSSL AND NOT LWS_USE_POLARSSL AND NOT LWS_USE_MBEDTLS) if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "") else() set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES}) set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS}) set(OPENSSL_FOUND 1) endif() endif() if (LWS_WITH_SSL AND LWS_USE_WOLFSSL) if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") if (NOT WOLFSSL_FOUND) if (LWS_USE_CYASSL) message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_USE_CYASSL is turned on.") else() message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_USE_WOLFSSL is turned on.") endif() endif() else() set(WOLFSSL_LIBRARIES ${LWS_WOLFSSL_LIBRARIES}) set(WOLFSSL_INCLUDE_DIRS ${LWS_WOLFSSL_INCLUDE_DIRS}) set(WOLFSSL_FOUND 1) endif() set(USE_WOLFSSL 1) if (LWS_USE_CYASSL) set(USE_OLD_CYASSL 1) endif() endif() if (LWS_WITH_SSL AND LWS_USE_POLARSSL) if ("${LWS_POLARSSL_LIBRARIES}" STREQUAL "" OR "${LWS_POLARSSL_INCLUDE_DIRS}" STREQUAL "") if (NOT POLARSSL_FOUND) message(FATAL_ERROR "You must set LWS_POLARSSL_LIBRARIES and LWS_POLARSSL_INCLUDE_DIRS when LWS_USE_POLARSSL is turned on.") endif() else() set(POLARSSL_LIBRARIES ${LWS_POLARSSL_LIBRARIES}) set(POLARSSL_INCLUDE_DIRS ${LWS_POLARSSL_INCLUDE_DIRS}) set(POLARSSL_FOUND 1) endif() set(USE_POLARSSL 1) endif() if (LWS_WITH_SSL AND LWS_USE_MBEDTLS) if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") if (NOT MBEDTLS_FOUND) message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_USE_MBEDTLS is turned on.") endif() else() set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) set(MBEDTLS_FOUND 1) endif() set(USE_MBEDTLS 1) endif() if (LWS_WITH_ZLIB AND NOT LWS_USE_BUNDLED_ZLIB) if ("${LWS_ZLIB_LIBRARIES}" STREQUAL "" OR "${LWS_ZLIB_INCLUDE_DIRS}" STREQUAL "") else() set(ZLIB_LIBRARIES ${LWS_ZLIB_LIBRARIES}) set(ZLIB_INCLUDE_DIRS ${LWS_ZLIB_INCLUDE_DIRS}) set(ZLIB_FOUND 1) endif() endif() if (LWS_WITH_LIBEV) if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "") else() set(LIBEV_LIBRARIES ${LWS_LIBEV_LIBRARIES}) set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS}) set(LIBEV_FOUND 1) endif() endif() if (LWS_WITH_LIBUV) if ("${LWS_LIBUV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBUV_INCLUDE_DIRS}" STREQUAL "") else() set(LIBUV_LIBRARIES ${LWS_LIBUV_LIBRARIES}) set(LIBUV_INCLUDE_DIRS ${LWS_LIBUV_INCLUDE_DIRS}) set(LIBUV_FOUND 1) endif() endif() # FIXME: This must be runtime-only option. # The base dir where the test-apps look for the SSL certs. set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") if (WIN32) set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory") if (LWS_IPV6) set(LWS_IPV6 OFF) message(WARNING "IPv6 does not currently work on Windows!") endif() if (LWS_UNIX_SOCK) set(LWS_UNIX_SOCK OFF) message(WARNING "Windows does not support UNIX domain sockets") endif() else() set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") endif() if (LWS_WITHOUT_EXTENSIONS) set(LWS_NO_EXTENSIONS 1) endif() if (LWS_WITH_SSL) set(LWS_OPENSSL_SUPPORT 1) endif() if (LWS_SSL_CLIENT_USE_OS_CA_CERTS) set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1) endif() if (LWS_WITH_LATENCY) set(LWS_LATENCY 1) endif() if (LWS_WITHOUT_DAEMONIZE OR WIN32) set(LWS_NO_DAEMONIZE 1) endif() if (LWS_WITHOUT_SERVER) set(LWS_NO_SERVER 1) endif() if (LWS_WITHOUT_CLIENT) set(LWS_NO_CLIENT 1) endif() if (LWS_WITH_LIBEV) set(LWS_USE_LIBEV 1) endif() if (LWS_WITH_LIBUV) set(LWS_USE_LIBUV 1) endif() if (LWS_IPV6) set(LWS_USE_IPV6 1) endif() if (LWS_UNIX_SOCK) set(LWS_USE_UNIX_SOCK 1) endif() if (LWS_WITH_HTTP2) set(LWS_USE_HTTP2 1) endif() if ("${LWS_MAX_SMP}" STREQUAL "") set(LWS_MAX_SMP 32) endif() #if (LWS_MBED3) # set(CMAKE_C_FLAGS "-D_DEBUG ${CMAKE_C_FLAGS}") #endif() if (MINGW) set(LWS_MINGW_SUPPORT 1) set(CMAKE_C_FLAGS "-D__USE_MINGW_ANSI_STDIO ${CMAKE_C_FLAGS}") endif() if (LWS_SSL_SERVER_WITH_ECDH_CERT) set(LWS_SSL_SERVER_WITH_ECDH_CERT 1) endif() include_directories("${PROJECT_BINARY_DIR}") include(CheckCSourceCompiles) # Check for different inline keyword versions. foreach(KEYWORD "inline" "__inline__" "__inline") set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}") CHECK_C_SOURCE_COMPILES( " #include <stdio.h> static KEYWORD void a() {} int main(int argc, char **argv) { a(); return 0; } " LWS_HAVE_${KEYWORD}) endforeach() if (NOT LWS_HAVE_inline) if (LWS_HAVE___inline__) set(inline __inline__) elseif(LWS_HAVE___inline) set(inline __inline) endif() endif() # Put the libaries and binaries that get built into directories at the # top of the build tree rather than in hard-to-find leaf directories. SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") # Put absolute path of dynamic libraries into the object code. Some # architectures, notably Mac OS X, need this. SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}") include(CheckFunctionExists) include(CheckSymbolExists) include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckLibraryExists) include(CheckTypeSize) if (LWS_WITHOUT_BUILTIN_SHA1) set(LWS_SHA1_USE_OPENSSL_NAME 1) endif() CHECK_FUNCTION_EXISTS(bzero LWS_HAVE_BZERO) CHECK_FUNCTION_EXISTS(fork LWS_HAVE_FORK) CHECK_FUNCTION_EXISTS(getenv LWS_HAVE_GETENV) CHECK_FUNCTION_EXISTS(malloc LWS_HAVE_MALLOC) CHECK_FUNCTION_EXISTS(memset LWS_HAVE_MEMSET) CHECK_FUNCTION_EXISTS(realloc LWS_HAVE_REALLOC) CHECK_FUNCTION_EXISTS(socket LWS_HAVE_SOCKET) CHECK_FUNCTION_EXISTS(strerror LWS_HAVE_STRERROR) CHECK_FUNCTION_EXISTS(vfork LWS_HAVE_VFORK) CHECK_FUNCTION_EXISTS(execvpe LWS_HAVE_EXECVPE) CHECK_FUNCTION_EXISTS(getifaddrs LWS_HAVE_GETIFADDRS) CHECK_FUNCTION_EXISTS(snprintf LWS_HAVE_SNPRINTF) CHECK_FUNCTION_EXISTS(_snprintf LWS_HAVE__SNPRINTF) CHECK_FUNCTION_EXISTS(_vsnprintf LWS_HAVE__VSNPRINTF) CHECK_FUNCTION_EXISTS(getloadavg LWS_HAVE_GETLOADAVG) if (NOT LWS_HAVE_GETIFADDRS) if (LWS_WITHOUT_BUILTIN_GETIFADDRS) message(FATAL_ERROR "No getifaddrs was found on the system. Turn off the LWS_WITHOUT_BUILTIN_GETIFADDRS compile option to use the supplied BSD version.") endif() set(LWS_BUILTIN_GETIFADDRS 1) endif() CHECK_INCLUDE_FILE(dlfcn.h LWS_HAVE_DLFCN_H) CHECK_INCLUDE_FILE(fcntl.h LWS_HAVE_FCNTL_H) CHECK_INCLUDE_FILE(in6addr.h LWS_HAVE_IN6ADDR_H) CHECK_INCLUDE_FILE(inttypes.h LWS_HAVE_INTTYPES_H) CHECK_INCLUDE_FILE(memory.h LWS_HAVE_MEMORY_H) CHECK_INCLUDE_FILE(netinet/in.h LWS_HAVE_NETINET_IN_H) CHECK_INCLUDE_FILE(stdint.h LWS_HAVE_STDINT_H) CHECK_INCLUDE_FILE(stdlib.h LWS_HAVE_STDLIB_H) CHECK_INCLUDE_FILE(strings.h LWS_HAVE_STRINGS_H) CHECK_INCLUDE_FILE(string.h LWS_HAVE_STRING_H) CHECK_INCLUDE_FILE(sys/prctl.h LWS_HAVE_SYS_PRCTL_H) CHECK_INCLUDE_FILE(sys/socket.h LWS_HAVE_SYS_SOCKET_H) CHECK_INCLUDE_FILE(sys/stat.h LWS_HAVE_SYS_STAT_H) CHECK_INCLUDE_FILE(sys/types.h LWS_HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILE(unistd.h LWS_HAVE_UNISTD_H) CHECK_INCLUDE_FILE(vfork.h LWS_HAVE_VFORK_H) if (LWS_WITH_ZLIB AND NOT LWS_USE_BUNDLED_ZLIB) CHECK_INCLUDE_FILE(zlib.h LWS_HAVE_ZLIB_H) endif() # TODO: These can also be tested to see whether they actually work... set(LWS_HAVE_WORKING_FORK LWS_HAVE_FORK) set(LWS_HAVE_WORKING_VFORK LWS_HAVE_VFORK) CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) # These don't work Cross... #CHECK_TYPE_SIZE(pid_t PID_T_SIZE) #CHECK_TYPE_SIZE(size_t SIZE_T_SIZE) #CHECK_TYPE_SIZE("void *" LWS_SIZEOFPTR LANGUAGE C) if (NOT PID_T_SIZE) set(pid_t int) endif() if (NOT SIZE_T_SIZE) set(size_t "unsigned int") endif() if (NOT LWS_HAVE_MALLOC) set(malloc rpl_malloc) endif() if (NOT LWS_HAVE_REALLOC) set(realloc rpl_realloc) endif() if (MSVC) # Turn off stupid microsoft security warnings. add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) endif(MSVC) include_directories("${PROJECT_SOURCE_DIR}/lib") # Group headers and sources. # Some IDEs use this for nicer file structure. set(HDR_PRIVATE lib/private-libwebsockets.h) set(HDR_PUBLIC "${PROJECT_SOURCE_DIR}/lib/libwebsockets.h" "${PROJECT_BINARY_DIR}/lws_config.h") set(SOURCES lib/base64-decode.c lib/handshake.c lib/libwebsockets.c lib/service.c lib/pollfd.c lib/output.c lib/parsers.c lib/context.c lib/alloc.c lib/header.c) if (NOT LWS_WITHOUT_CLIENT) list(APPEND SOURCES lib/client.c lib/client-handshake.c lib/client-parser.c) endif() if (LWS_WITH_SSL) list(APPEND SOURCES lib/ssl.c) if (NOT LWS_WITHOUT_SERVER) list(APPEND SOURCES lib/ssl-server.c) endif() if (NOT LWS_WITHOUT_CLIENT) list(APPEND SOURCES lib/ssl-client.c) endif() endif() if (NOT LWS_WITHOUT_BUILTIN_SHA1) list(APPEND SOURCES lib/sha-1.c) endif() if (LWS_WITH_HTTP2) list(APPEND SOURCES lib/http2.c lib/hpack.c lib/ssl-http2.c) endif() # select the active platform files if (WIN32) list(APPEND SOURCES lib/lws-plat-win.c) else() if (LWS_MBED3) list(APPEND SOURCES lib/lws-plat-mbed3.cpp lib/lws-plat-mbed3.c) else() list(APPEND SOURCES lib/lws-plat-unix.c) endif() endif() if (NOT LWS_WITHOUT_SERVER) list(APPEND SOURCES lib/server.c lib/server-handshake.c) endif() if (NOT LWS_WITHOUT_EXTENSIONS) list(APPEND HDR_PRIVATE lib/extension-permessage-deflate.h) list(APPEND SOURCES lib/extension.c lib/extension-permessage-deflate.c) endif() if (LWS_WITH_HTTP_PROXY) list(APPEND SOURCES lib/rewrite.c) endif() if (LWS_WITH_LIBEV) list(APPEND SOURCES lib/libev.c) endif() if (LWS_WITH_LIBUV) list(APPEND SOURCES lib/libuv.c) endif() # Add helper files for Windows. if (WIN32) set(WIN32_HELPERS_PATH win32port/win32helpers) include_directories(${WIN32_HELPERS_PATH}) else() # Unix. if (NOT LWS_WITHOUT_DAEMONIZE) list(APPEND SOURCES lib/daemonize.c) endif() endif() if (UNIX) if (NOT LWS_HAVE_GETIFADDRS) list(APPEND HDR_PRIVATE lib/getifaddrs.h) list(APPEND SOURCES lib/getifaddrs.c) endif() endif() if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) include (CheckCCompilerFlag) CHECK_C_COMPILER_FLAG(-fvisibility=hidden LWS_HAVE_VISIBILITY) if (LWS_HAVE_VISIBILITY) set(VISIBILITY_FLAG -fvisibility=hidden) endif() if (UNIX) set(CMAKE_C_FLAGS "-Wall -Werror ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" ) else(UNIX) set(CMAKE_C_FLAGS "-Wall ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" ) endif(UNIX) endif () if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS) if (UNIX) # jeez clang understands -pthread but dies if he sees it at link time! # http://stackoverflow.com/questions/2391194/what-is-gs-pthread-equiv-in-clang set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread" ) endif() endif() if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) # otherwise osx blows a bunch of openssl deprecated api errors set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations" ) endif() source_group("Headers Private" FILES ${HDR_PRIVATE}) source_group("Headers Public" FILES ${HDR_PUBLIC}) source_group("Sources" FILES ${SOURCES}) # # Create the lib. # set(LWS_LIBRARIES) if (LWS_WITH_STATIC) add_library(websockets STATIC ${HDR_PRIVATE} ${HDR_PUBLIC} ${SOURCES}) list(APPEND LWS_LIBRARIES websockets) if (WIN32) # Windows uses the same .lib ending for static libraries and shared # library linker files, so rename the static library. set_target_properties(websockets PROPERTIES OUTPUT_NAME websockets_static) endif() endif() if (LWS_WITH_SHARED) add_library(websockets_shared SHARED ${HDR_PRIVATE} ${HDR_PUBLIC} ${SOURCES}) list(APPEND LWS_LIBRARIES websockets_shared) # We want the shared lib to be named "libwebsockets" # not "libwebsocket_shared". set_target_properties(websockets_shared PROPERTIES OUTPUT_NAME websockets) if (WIN32) # Compile as DLL (export function declarations) set_property( TARGET websockets_shared PROPERTY COMPILE_DEFINITIONS LWS_DLL LWS_INTERNAL) endif() if (APPLE) set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) endif() endif() # Set the so version of the lib. # Equivalent to LDFLAGS=-version-info x:x:x if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) foreach(lib ${LWS_LIBRARIES}) set_target_properties(${lib} PROPERTIES SOVERSION ${SOVERSION}) endforeach() endif() set(LIB_LIST) # # Find libraries. # # # ZLIB (Only needed for deflate extensions). # if (LWS_WITH_ZLIB) if (LWS_USE_BUNDLED_ZLIB) if (WIN32) set(WIN32_ZLIB_PATH "win32port/zlib") set(ZLIB_SRCS ${WIN32_ZLIB_PATH}/adler32.c ${WIN32_ZLIB_PATH}/compress.c ${WIN32_ZLIB_PATH}/crc32.c ${WIN32_ZLIB_PATH}/deflate.c ${WIN32_ZLIB_PATH}/gzclose.c ${WIN32_ZLIB_PATH}/gzio.c ${WIN32_ZLIB_PATH}/gzlib.c ${WIN32_ZLIB_PATH}/gzread.c ${WIN32_ZLIB_PATH}/gzwrite.c ${WIN32_ZLIB_PATH}/infback.c ${WIN32_ZLIB_PATH}/inffast.c ${WIN32_ZLIB_PATH}/inflate.c ${WIN32_ZLIB_PATH}/inftrees.c ${WIN32_ZLIB_PATH}/trees.c ${WIN32_ZLIB_PATH}/uncompr.c ${WIN32_ZLIB_PATH}/zutil.c) add_library(zlib_internal STATIC ${ZLIB_SRCS}) set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH}) get_property(ZLIB_LIBRARIES TARGET zlib_internal PROPERTY LOCATION) set(ZLIB_FOUND 1) # Make sure zlib_internal is compiled before the libs. foreach (lib ${LWS_LIBRARIES}) add_dependencies(${lib} zlib_internal) endforeach() else() message(FATAL_ERROR "Don't have bundled zlib for that platform") endif() elseif (NOT ZLIB_FOUND) find_package(ZLIB REQUIRED) endif() message("zlib include dirs: ${ZLIB_INCLUDE_DIRS}") message("zlib libraries: ${ZLIB_LIBRARIES}") include_directories(${ZLIB_INCLUDE_DIRS}) list(APPEND LIB_LIST ${ZLIB_LIBRARIES}) endif() # # OpenSSL # if (LWS_WITH_SSL) message("Compiling with SSL support") set(chose_ssl 0) if (LWS_USE_WOLFSSL) # Use wolfSSL as OpenSSL replacement. # TODO: Add a find_package command for this also. message("wolfSSL include dir: ${WOLFSSL_INCLUDE_DIRS}") message("wolfSSL libraries: ${WOLFSSL_LIBRARIES}") # Additional to the root directory we need to include # the wolfssl/ subdirectory which contains the OpenSSL # compatibility layer headers. if (LWS_USE_CYASSL) foreach(inc ${WOLFSSL_INCLUDE_DIRS}) include_directories("${inc}" "${inc}/cyassl") endforeach() else() foreach(inc ${WOLFSSL_INCLUDE_DIRS}) include_directories("${inc}" "${inc}/wolfssl") endforeach() endif() list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") set(chose_ssl 1) endif() if (LWS_USE_POLARSSL) message("POLARSSL include dir: ${POLARSSL_INCLUDE_DIRS}") message("POLARSSL libraries: ${POLARSSL_LIBRARIES}") foreach(inc ${POLARSSL_INCLUDE_DIRS}) include_directories("${inc}" "${inc}/polarssl") endforeach() list(APPEND LIB_LIST "${POLARSSL_LIBRARIES}") set(chose_ssl 1) endif() if (LWS_USE_MBEDTLS) message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") foreach(inc ${MBEDTLS_INCLUDE_DIRS}) include_directories("${inc}" "${inc}/mbedtls") endforeach() list(APPEND LIB_LIST "${MBEDTLS_LIBRARIES}") set(chose_ssl 1) endif() if (NOT chose_ssl) if (NOT OPENSSL_FOUND) # TODO: Add support for STATIC also. find_package(OpenSSL REQUIRED) set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") endif() message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}") message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") include_directories("${OPENSSL_INCLUDE_DIRS}") list(APPEND LIB_LIST ${OPENSSL_LIBRARIES}) # older (0.98) Openssl lacks this set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") endif() endif() endif(LWS_WITH_SSL) if (LWS_WITH_LIBEV) if (NOT LIBEV_FOUND) find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) find_library(LIBEV_LIBRARIES NAMES ev) if(LIBEV_INCLUDE_DIRS AND LIBEV_LIBRARIES) set(LIBEV_FOUND 1) endif() endif() message("libev include dir: ${LIBEV_INCLUDE_DIRS}") message("libev libraries: ${LIBEV_LIBRARIES}") include_directories("${LIBEV_INCLUDE_DIRS}") list(APPEND LIB_LIST ${LIBEV_LIBRARIES}) endif(LWS_WITH_LIBEV) if (LWS_WITH_LIBUV) if (NOT LIBUV_FOUND) find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) find_library(LIBUV_LIBRARIES NAMES uv) if(LIBUV_INCLUDE_DIRS AND LIBUV_LIBRARIES) set(LIBUV_FOUND 1) endif() endif() message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") message("libuv libraries: ${LIBUV_LIBRARIES}") include_directories("${LIBUV_INCLUDE_DIRS}") list(APPEND LIB_LIST ${LIBUV_LIBRARIES}) endif() if (LWS_WITH_HTTP_PROXY) find_library(LIBHUBBUB_LIBRARIES NAMES libhubbub) list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} ) endif() # # Platform specific libs. # if (WINCE) list(APPEND LIB_LIST ws2.lib) elseif (WIN32) list(APPEND LIB_LIST ws2_32.lib) endif() if (UNIX) list(APPEND LIB_LIST m) endif() # Setup the linking for all libs. foreach (lib ${LWS_LIBRARIES}) target_link_libraries(${lib} ${LIB_LIST}) endforeach() set (temp ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) set(CMAKE_REQUIRED_LIBRARIES ${temp}) # Generate the lws_config.h that includes all the public compilation settings. configure_file( "${PROJECT_SOURCE_DIR}/lws_config.h.in" "${PROJECT_BINARY_DIR}/lws_config.h") # Generate the lws_config.h that includes all the private compilation settings. configure_file( "${PROJECT_SOURCE_DIR}/lws_config_private.h.in" "${PROJECT_BINARY_DIR}/lws_config_private.h") # # Test applications # set(TEST_APP_LIST) if (NOT LWS_WITHOUT_TESTAPPS) # # Helper function for adding a test app. # macro(create_test_app TEST_NAME MAIN_SRC S2 S3 S4 S5 S6) set(TEST_SRCS ${MAIN_SRC}) set(TEST_HDR) if ("${S2}" STREQUAL "") else() list(APPEND TEST_SRCS ${S2}) endif() if ("${S3}" STREQUAL "") else() list(APPEND TEST_SRCS ${S3}) endif() if ("${S4}" STREQUAL "") else() list(APPEND TEST_SRCS ${S4}) endif() if ("${S5}" STREQUAL "") else() list(APPEND TEST_SRCS ${S5}) endif() if ("${S6}" STREQUAL "") else() list(APPEND TEST_SRCS ${S6}) endif() if (WIN32) list(APPEND TEST_SRCS ${WIN32_HELPERS_PATH}/getopt.c ${WIN32_HELPERS_PATH}/getopt_long.c ${WIN32_HELPERS_PATH}/gettimeofday.c ) list(APPEND TEST_HDR ${WIN32_HELPERS_PATH}/getopt.h ${WIN32_HELPERS_PATH}/gettimeofday.h ) endif(WIN32) source_group("Headers Private" FILES ${TEST_HDR}) source_group("Sources" FILES ${TEST_SRCS}) add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR}) if (LWS_LINK_TESTAPPS_DYNAMIC) if (NOT LWS_WITH_SHARED) message(FATAL_ERROR "Build of the shared library is disabled. LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_SHARED.") endif() target_link_libraries(${TEST_NAME} websockets_shared) add_dependencies(${TEST_NAME} websockets_shared) else() if (NOT LWS_WITH_STATIC) message(FATAL_ERROR "Build of the static library is disabled. Disabled LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_STATIC.") endif() target_link_libraries(${TEST_NAME} websockets) add_dependencies(${TEST_NAME} websockets) endif() # Set test app specific defines. set_property(TARGET ${TEST_NAME} PROPERTY COMPILE_DEFINITIONS INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" ) # Prefix the binary names with libwebsockets. set_target_properties(${TEST_NAME} PROPERTIES OUTPUT_NAME libwebsockets-${TEST_NAME}) # Add to the list of tests. list(APPEND TEST_APP_LIST ${TEST_NAME}) endmacro() if (LWS_WITH_SSL AND NOT LWS_USE_WOLFSSL AND NOT LWS_USE_POLARSSL AND NOT LWS_USE_MBEDTLS) message("Searching for OpenSSL executable and dlls") find_package(OpenSSLbins) message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") endif() if (UNIX AND LWS_WITH_PLUGINS) set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") target_link_libraries(websockets dl) endif() if (NOT LWS_WITHOUT_SERVER) # # test-server # if (NOT LWS_WITHOUT_TEST_SERVER) create_test_app(test-server "test-server/test-server.c" "test-server/test-server-http.c" "test-server/test-server-dumb-increment.c" "test-server/test-server-mirror.c" "test-server/test-server-status.c" "test-server/test-server-echogen.c") if (UNIX) create_test_app(test-fuzxy "test-server/fuzxy.c" "" "" "" "" "") endif() if (UNIX AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))) create_test_app(test-server-pthreads "test-server/test-server-pthreads.c" "test-server/test-server-http.c" "test-server/test-server-dumb-increment.c" "test-server/test-server-mirror.c" "test-server/test-server-status.c" "test-server/test-server-echogen.c") endif() if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND LWS_WITH_LIBEV) create_test_app(test-server-libev "test-server/test-server-libev.c" "test-server/test-server-http.c" "test-server/test-server-dumb-increment.c" "test-server/test-server-mirror.c" "test-server/test-server-status.c" "test-server/test-server-echogen.c") endif() if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND LWS_WITH_LIBUV) create_test_app(test-server-libuv "test-server/test-server-libuv.c" "test-server/test-server-http.c" "test-server/test-server-dumb-increment.c" "test-server/test-server-mirror.c" "test-server/test-server-status.c" "test-server/test-server-echogen.c") endif() endif() # # test-server-extpoll # if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL) create_test_app(test-server-extpoll "test-server/test-server.c" "test-server/test-server-http.c" "test-server/test-server-dumb-increment.c" "test-server/test-server-mirror.c" "test-server/test-server-status.c" "test-server/test-server-echogen.c") # Set defines for this executable only. set_property( TARGET test-server-extpoll PROPERTY COMPILE_DEFINITIONS EXTERNAL_POLL INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" ) # We need to link against winsock code. if (WIN32) target_link_libraries(test-server-extpoll ws2_32.lib) endif(WIN32) endif() # # test-server-v2.0 # if (LWS_WITH_PLUGINS) create_test_app( test-server-v2.0 "test-server/test-server-v2.0.c" "" "" "" "" "") endif() # Data files for running the test server. set(TEST_SERVER_DATA "${PROJECT_SOURCE_DIR}/test-server/favicon.ico" "${PROJECT_SOURCE_DIR}/test-server/leaf.jpg" "${PROJECT_SOURCE_DIR}/test-server/libwebsockets.org-logo.png" "${PROJECT_SOURCE_DIR}/test-server/test.html") # Generate self-signed SSL certs for the test-server. if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER) message("Generating SSL Certificates for the test-server...") set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem") set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem") if (WIN32) if (MINGW) message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") execute_process( COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE) else() file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" "GB\n" "Erewhon\n" "All around\n" "libwebsockets-test\n" "localhost\n" "none@invalid.org\n\n" ) # The "type" command is a bit picky with paths. file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") execute_process( COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE OUTPUT_QUIET ERROR_QUIET) message("\n") endif() if (OPENSSL_RETURN_CODE) message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") else() message("SUCCSESFULLY generated SSL certificate") endif() else() # Unix. execute_process( COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE OUTPUT_QUIET ERROR_QUIET) if (OPENSSL_RETURN_CODE) message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") else() message("SUCCESSFULLY generated SSL certificate") endif() endif() list(APPEND TEST_SERVER_DATA "${TEST_SERVER_SSL_KEY}" "${TEST_SERVER_SSL_CERT}") endif() add_custom_command(TARGET test-server POST_BUILD COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:test-server>/../share/libwebsockets-test-server") # Copy the file needed to run the server so that the test apps can # reach them from their default output location foreach (TEST_FILE ${TEST_SERVER_DATA}) if (EXISTS ${TEST_FILE}) add_custom_command(TARGET test-server POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$<TARGET_FILE_DIR:test-server>/../share/libwebsockets-test-server" VERBATIM) endif() endforeach() endif(NOT LWS_WITHOUT_SERVER) if (NOT LWS_WITHOUT_CLIENT) # # test-client # if (NOT LWS_WITHOUT_TEST_CLIENT) create_test_app(test-client "test-server/test-client.c" "" "" "" "" "") endif() # # test-fraggle # if (NOT LWS_WITHOUT_TEST_FRAGGLE) create_test_app(test-fraggle "test-server/test-fraggle.c" "" "" "" "" "") endif() # # test-ping # if (NOT LWS_WITHOUT_TEST_PING) create_test_app(test-ping "test-server/test-ping.c" "" "" "" "" "") endif() # # test-echo # if (NOT LWS_WITHOUT_TEST_ECHO) create_test_app(test-echo "test-server/test-echo.c" "" "" "" "" "") endif() endif(NOT LWS_WITHOUT_CLIENT) if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) macro(create_plugin PLUGIN_NAME MAIN_SRC) set(PLUGIN_SRCS ${MAIN_SRC}) if (WIN32) list(APPEND PLUGIN_SRCS ${WIN32_HELPERS_PATH}/getopt.c ${WIN32_HELPERS_PATH}/getopt_long.c ${WIN32_HELPERS_PATH}/gettimeofday.c ) list(APPEND PLUGIN_HDR ${WIN32_HELPERS_PATH}/getopt.h ${WIN32_HELPERS_PATH}/gettimeofday.h ) endif(WIN32) source_group("Headers Private" FILES ${PLUGIN_HDR}) source_group("Sources" FILES ${PLUGIN_SRCS}) add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) target_link_libraries(${PLUGIN_NAME} websockets_shared) add_dependencies(${PLUGIN_NAME} websockets_shared) # Set test app specific defines. set_property(TARGET ${PLUGIN_NAME} PROPERTY COMPILE_DEFINITIONS INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins" ) # set_target_properties(${PLUGIN_NAME} # PROPERTIES # OUTPUT_NAME ${PLUGIN_NAME}) list(APPEND PLUGINS_LIST ${PLUGIN_NAME}) endmacro() create_plugin(protocol_dumb_increment "plugins/protocol_dumb_increment.c") create_plugin(protocol_lws_mirror "plugins/protocol_lws_mirror.c") create_plugin(protocol_lws_status "plugins/protocol_lws_status.c") if (LWS_WITH_SERVER_STATUS) create_plugin(protocol_lws_server_status "plugins/protocol_lws_server_status.c") endif() endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) # # Copy OpenSSL dlls to the output directory on Windows. # (Otherwise we'll get an error when trying to run) # if (WIN32 AND LWS_WITH_SSL AND NOT LWS_USE_WOLFSSL) if(OPENSSL_BIN_FOUND) message("OpenSSL dlls found:") message(" Libeay: ${LIBEAY_BIN}") message(" SSLeay: ${SSLEAY_BIN}") foreach(TARGET_BIN ${TEST_APP_LIST}) add_custom_command(TARGET ${TARGET_BIN} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM) add_custom_command(TARGET ${TARGET_BIN} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM) endforeach() endif() endif() endif(NOT LWS_WITHOUT_TESTAPPS) if (LWS_WITH_LWSWS) list(APPEND LWSWS_SRCS "lwsws/main.c" "lwsws/lejp.c" "lwsws/conf.c" "lwsws/http.c" ) if (WIN32) list(APPEND LWSWS_SRCS ${WIN32_HELPERS_PATH}/getopt.c ${WIN32_HELPERS_PATH}/getopt_long.c ${WIN32_HELPERS_PATH}/gettimeofday.c ) list(APPEND LWSWS_HDR ${WIN32_HELPERS_PATH}/getopt.h ${WIN32_HELPERS_PATH}/gettimeofday.h ) endif(WIN32) source_group("Headers Private" FILES ${LWSWS_HDR}) source_group("Sources" FILES ${LWSWS_SRCS}) add_executable("lwsws" ${LWSWS_SRCS} ${LWSWS_HDR}) target_link_libraries("lwsws" websockets_shared) add_dependencies("lwsws" websockets_shared) # Set test app specific defines. set_property(TARGET "lwsws" PROPERTY COMPILE_DEFINITIONS INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" ) endif (LWS_WITH_LWSWS) if (UNIX) # Generate documentation. # TODO: Fix this on Windows. message("Generating API documentation") file(GLOB C_FILES "${PROJECT_SOURCE_DIR}/lib/*.c") list(SORT C_FILES) execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/doc/") execute_process( COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -html ${C_FILES} ${HDR_PUBLIC} OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.html" ERROR_QUIET) execute_process( COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -text ${C_FILES} ${HDR_PUBLIC} OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.txt" ERROR_QUIET) # Generate and install pkgconfig. # (This is not indented, because the tabs will be part of the output) file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc" "prefix=\"${CMAKE_INSTALL_PREFIX}\" exec_prefix=\${prefix} libdir=\${exec_prefix}/lib${LIB_SUFFIX} includedir=\${prefix}/include Name: libwebsockets Description: Websockets server and client library Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} Libs: -L\${libdir} -lwebsockets Cflags: -I\${includedir}" ) install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig) endif(UNIX) # # Installation preparations. # if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKE_DIR cmake) else() set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) endif() set(LWS_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") # Export targets (This is used for other CMake projects to easily find the libraries and include files). export(TARGETS ${LWS_LIBRARIES} FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake") export(PACKAGE libwebsockets) # Generate the config file for the build-tree. set(LWS__INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/lib" "${PROJECT_BINARY_DIR}") set(LIBWEBSOCKETS_INCLUDE_DIRS ${LWS__INCLUDE_DIRS} CACHE PATH "Libwebsockets include directories") configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in ${PROJECT_BINARY_DIR}/LibwebsocketsConfig.cmake @ONLY) # Generate the config file for the installation tree. get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE) get_filename_component(LWS_ABSOLUTE_INSTALL_INCLUDE_DIR ${LWS_INSTALL_INCLUDE_DIR} ABSOLUTE) file(RELATIVE_PATH REL_INCLUDE_DIR "${LWS_ABSOLUTE_INSTALL_CMAKE_DIR}" "${LWS_ABSOLUTE_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the cmake dir. # Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in, # we escape it here so it's evaluated when it is included instead # so that the include dirs are given relative to where the # config file is located. set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake @ONLY) # Generate version info for both build-tree and install-tree. configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfigVersion.cmake.in ${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake @ONLY) set_target_properties(${LWS_LIBRARIES} PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}") # # Installation. # # Install libs and headers. install(TARGETS ${LWS_LIBRARIES} EXPORT LibwebsocketsTargets LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev) set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files") # Install test apps. if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_CLIENT) install(TARGETS test-client ${TEST_APP_LIST} RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR} COMPONENT examples) set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files") endif() # lwsws if (LWS_WITH_LWSWS) install(TARGETS lwsws RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT lwsws ) endif() # Programs shared files used by the test-server. if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_SERVER) install(FILES ${TEST_SERVER_DATA} DESTINATION share/libwebsockets-test-server COMPONENT examples) if (LWS_WITH_CGI) set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-server/lws-cgi-test.sh") install(FILES ${CGI_TEST_SCRIPT} PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ DESTINATION share/libwebsockets-test-server COMPONENT examples) endif() endif() # plugins if (LWS_WITH_PLUGINS) install(TARGETS ${PLUGINS_LIST} PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ DESTINATION share/libwebsockets-test-server/plugins COMPONENT plugins) if (LWS_WITH_SERVER_STATUS) install(FILES plugins/server-status.html;plugins/lwsws-logo.png DESTINATION share/libwebsockets-test-server/server-status COMPONENT examples) endif() endif() # Install the LibwebsocketsConfig.cmake and LibwebsocketsConfigVersion.cmake install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake" "${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake" DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev) # Install exports for the install-tree. install(EXPORT LibwebsocketsTargets DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev) # build subdir is not part of sources set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) ".git" "build" "tgz" "tar.gz") # Most people are more used to "make dist" compared to "make package_source" add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source) include(UseRPMTools) if (RPMTools_FOUND) RPMTools_ADD_RPM_TARGETS(libwebsockets libwebsockets.spec) endif() message("---------------------------------------------------------------------") message(" Settings: (For more help do cmake -LH <srcpath>)") message("---------------------------------------------------------------------") message(" LWS_WITH_STATIC = ${LWS_WITH_STATIC}") message(" LWS_WITH_SHARED = ${LWS_WITH_SHARED}") message(" LWS_WITH_SSL = ${LWS_WITH_SSL} (SSL Support)") message(" LWS_SSL_CLIENT_USE_OS_CA_CERTS = ${LWS_SSL_CLIENT_USE_OS_CA_CERTS}") message(" LWS_USE_WOLFSSL = ${LWS_USE_WOLFSSL} (wolfSSL/CyaSSL replacement for OpenSSL)") if (LWS_USE_WOLFSSL) message(" LWS_WOLFSSL_LIBRARIES = ${LWS_WOLFSSL_LIBRARIES}") message(" LWS_WOLFSSL_INCLUDE_DIRS = ${LWS_WOLFSSL_INCLUDE_DIRS}") endif() message(" LWS_USE_POLARSSL = ${LWS_USE_POLARSSL} (PolarSSL replacement for OpenSSL)") message(" LWS_USE_MBEDTLS = ${LWS_USE_MBEDTLS} (mbedtls (nee Polarssl) replacement for OpenSSL)") message(" LWS_WITHOUT_BUILTIN_SHA1 = ${LWS_WITHOUT_BUILTIN_SHA1}") message(" LWS_WITHOUT_BUILTIN_GETIFADDRS = ${LWS_WITHOUT_BUILTIN_GETIFADDRS}") message(" LWS_WITHOUT_CLIENT = ${LWS_WITHOUT_CLIENT}") message(" LWS_WITHOUT_SERVER = ${LWS_WITHOUT_SERVER}") message(" LWS_LINK_TESTAPPS_DYNAMIC = ${LWS_LINK_TESTAPPS_DYNAMIC}") message(" LWS_WITHOUT_TESTAPPS = ${LWS_WITHOUT_TESTAPPS}") message(" LWS_WITHOUT_TEST_SERVER = ${LWS_WITHOUT_TEST_SERVER}") message(" LWS_WITHOUT_TEST_SERVER_EXTPOLL = ${LWS_WITHOUT_TEST_SERVER_EXTPOLL}") message(" LWS_WITHOUT_TEST_PING = ${LWS_WITHOUT_TEST_PING}") message(" LWS_WITHOUT_TEST_ECHO = ${LWS_WITHOUT_TEST_ECHO}") message(" LWS_WITHOUT_TEST_CLIENT = ${LWS_WITHOUT_TEST_CLIENT}") message(" LWS_WITHOUT_TEST_FRAGGLE = ${LWS_WITHOUT_TEST_FRAGGLE}") message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}") message(" LWS_WITH_LATENCY = ${LWS_WITH_LATENCY}") message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}") message(" LWS_USE_LIBEV = ${LWS_USE_LIBEV}") message(" LWS_USE_LIBUV = ${LWS_USE_LIBUV}") message(" LWS_IPV6 = ${LWS_IPV6}") message(" LWS_UNIX_SOCK = ${LWS_UNIX_SOCK}") message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}") message(" LWS_MBED3 = ${LWS_MBED3}") message(" LWS_SSL_SERVER_WITH_ECDH_CERT = ${LWS_SSL_SERVER_WITH_ECDH_CERT}") message(" LWS_MAX_SMP = ${LWS_MAX_SMP}") message(" LWS_WITH_CGI = ${LWS_WITH_CGI}") message(" LWS_HAVE_OPENSSL_ECDH_H = ${LWS_HAVE_OPENSSL_ECDH_H}") message(" LWS_HAVE_SSL_CTX_set1_param = ${LWS_HAVE_SSL_CTX_set1_param}") message(" LWS_WITH_HTTP_PROXY = ${LWS_WITH_HTTP_PROXY}") message(" LIBHUBBUB_LIBRARIES = ${LIBHUBBUB_LIBRARIES}") message(" PLUGINS = ${PLUGINS_LIST}") message(" LWS_WITH_ACCESS_LOG = ${LWS_WITH_ACCESS_LOG}") message(" LWS_WITH_SERVER_STATUS = ${LWS_WITH_SERVER_STATUS}") message("---------------------------------------------------------------------") # These will be available to parent projects including libwebsockets using add_subdirectory() set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") if (LWS_WITH_STATIC) set(LIBWEBSOCKETS_LIBRARIES_STATIC websocket CACHE STRING "Libwebsocket static library") endif() if (LWS_WITH_SHARED) set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library") endif() # This must always be last! include(CPack) |
Added undroid/libwebsockets/FindLibWebSockets.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# This module tries to find libWebsockets library and include files # # LIBWEBSOCKETS_INCLUDE_DIR, path where to find libwebsockets.h # LIBWEBSOCKETS_LIBRARY_DIR, path where to find libwebsockets.so # LIBWEBSOCKETS_LIBRARIES, the library to link against # LIBWEBSOCKETS_FOUND, If false, do not try to use libWebSockets # # This currently works probably only for Linux FIND_PATH ( LIBWEBSOCKETS_INCLUDE_DIR libwebsockets.h /usr/local/include /usr/include ) FIND_LIBRARY ( LIBWEBSOCKETS_LIBRARIES websockets /usr/local/lib /usr/lib ) GET_FILENAME_COMPONENT( LIBWEBSOCKETS_LIBRARY_DIR ${LIBWEBSOCKETS_LIBRARIES} PATH ) SET ( LIBWEBSOCKETS_FOUND "NO" ) IF ( LIBWEBSOCKETS_INCLUDE_DIR ) IF ( LIBWEBSOCKETS_LIBRARIES ) SET ( LIBWEBSOCKETS_FOUND "YES" ) ENDIF ( LIBWEBSOCKETS_LIBRARIES ) ENDIF ( LIBWEBSOCKETS_INCLUDE_DIR ) MARK_AS_ADVANCED( LIBWEBSOCKETS_LIBRARY_DIR LIBWEBSOCKETS_INCLUDE_DIR LIBWEBSOCKETS_LIBRARIES ) |
Added undroid/libwebsockets/LICENSE.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
Libwebsockets and included programs are provided under the terms of the GNU Library General Public License (LGPL) 2.1, with the following exceptions: 1) Static linking of programs with the libwebsockets library does not constitute a derivative work and does not require the author to provide source code for the program, use the shared libwebsockets libraries, or link their program against a user-supplied version of libwebsockets. If you link the program to a modified version of libwebsockets, then the changes to libwebsockets must be provided under the terms of the LGPL in sections 1, 2, and 4. 2) You do not have to provide a copy of the libwebsockets license with programs that are linked to the libwebsockets library, nor do you have to identify the libwebsockets license in your program or documentation as required by section 6 of the LGPL. However, programs must still identify their use of libwebsockets. The following example statement can be included in user documentation to satisfy this requirement: "[program] is based in part on the work of the libwebsockets project (https://libwebsockets.org)" 3) Some sources included have their own, more liberal licenses, or options to get original sources with the liberal terms. Original liberal license retained - lib/sha-1.c - 3-clause BSD license retained, link to original - win32port/zlib - ZLIB license (see zlib.h) Relicensed to libwebsocket license - lib/base64-decode.c - relicensed to LGPL2.1+SLE, link to original - lib/daemonize.c - relicensed from Public Domain to LGPL2.1+SLE, link to original Public Domain version Public Domain (CC-zero) to simplify reuse - test-server/*.c - test-server/*.h 4) lwsws (Libwebsocket web server) is a bundled application that is not part of the libwebsockets library, it's a separate application that uses the library. The related sources are in a separate directory. If you don't distribute lwsws, you do not need to observe its license. - lwsws/lejp.c - LGPL2.1 - lwsws/lejp.h - LGPL2.1 - lwsws/[all else] - GPL2.1 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the library's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. <signature of Ty Coon>, 1 April 1990 Ty Coon, President of Vice That's all there is to it! |
Added undroid/libwebsockets/README.build.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
Introduction to CMake --------------------- CMake is a multi-platform build tool that can generate build files for many different target platforms. See more info at http://www.cmake.org CMake also allows/recommends you to do "out of source"-builds, that is, the build files are separated from your sources, so there is no need to create elaborate clean scripts to get a clean source tree, instead you simply remove your build directory. Libwebsockets has been tested to build successfully on the following platforms with SSL support (both OpenSSL/wolfSSL): - Windows (Visual Studio) - Windows (MinGW) - Linux (x86 and ARM) - OSX - NetBSD Building the library and test apps ---------------------------------- The project settings used by CMake to generate the platform specific build files is called [CMakeLists.txt](CMakeLists.txt). CMake then uses one of its "Generators" to output a Visual Studio project or Make file for instance. To see a list of the available generators for your platform, simply run the "cmake" command. Note that by default OpenSSL will be linked, if you don't want SSL support see below on how to toggle compile options. Building on Unix: ----------------- 1. Install CMake 2.8 or greater: http://cmake.org/cmake/resources/software.html (Most Unix distributions comes with a packaged version also) 2. Install OpenSSL. 3. Generate the build files (default is Make files): ```bash $ cd /path/to/src $ mkdir build $ cd build $ cmake .. ``` (**NOTE**: The `build/`` directory can have any name and be located anywhere on your filesystem, and that the argument `..` given to cmake is simply the source directory of **libwebsockets** containing the [CMakeLists.txt](CMakeLists.txt) project file. All examples in this file assumes you use "..") **NOTE2**: A common option you may want to give is to set the install path, same as --prefix= with autotools. It defaults to /usr/local. You can do this by, eg ```bash $ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. ``` **NOTE3**: On machines that want libraries in lib64, you can also add the following to the cmake line ```bash -DLIB_SUFFIX=64 ``` **NOTE4**: If you are building against a non-distro OpenSSL (eg, in order to get access to ALPN support only in newer OpenSSL versions) the nice way to express that in one cmake command is eg, ```bash $ cmake .. -DOPENSSL_ROOT_DIR=/usr/local/ssl \ -DCMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE=/usr/local/ssl \ -DLWS_WITH_HTTP2=1 ``` When you run the test apps using non-distro SSL, you have to force them to use your libs, not the distro ones ```bash $ LD_LIBRARY_PATH=/usr/local/ssl/lib libwebsockets-test-server --ssl ``` To get it to build on latest openssl (2016-04-10) it needed this approach ```bash cmake .. -DLWS_WITH_HTTP2=1 -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/include/openssl -DLWS_OPENSSL_LIBRARIES="/usr/local/lib64/libssl.so;/usr/local/lib64/libcrypto.so" ``` **NOTE5**: To build with debug info and _DEBUG for lower priority debug messages compiled in, use ```bash $ cmake .. -DCMAKE_BUILD_TYPE=DEBUG ```` 4. Finally you can build using the generated Makefile: ```bash $ make ``` Quirk of cmake -------------- When changing cmake options, for some reason the only way to get it to see the changes sometimes is delete the contents of your build directory and do the cmake from scratch. Building on Windows (Visual Studio) ----------------------------------- 1. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html 2. Install OpenSSL binaries. http://www.openssl.org/related/binaries.html (**NOTE**: Preferably in the default location to make it easier for CMake to find them) **NOTE2**: Be sure that OPENSSL_CONF environment variable is defined and points at <OpenSSL install location>\bin\openssl.cfg 3. Generate the Visual studio project by opening the Visual Studio cmd prompt: ```bash cd <path to src> md build cd build cmake -G "Visual Studio 10" .. ``` (**NOTE**: There is also a cmake-gui available on Windows if you prefer that) **NOTE2**: See this link to find out the version number corresponding to your Visual Studio edition: http://superuser.com/a/194065 4. Now you should have a generated Visual Studio Solution in your `<path to src>/build` directory, which can be used to build. 5. Some additional deps may be needed - iphlpapi.lib - psapi.lib - userenv.lib 6. If you're using libuv, you must make sure to compile libuv with the same multithread-dll / Mtd attributes as libwebsockets itself Building on Windows (MinGW) --------------------------- 1. Install MinGW: http://sourceforge.net/projects/mingw/files (**NOTE**: Preferably in the default location C:\MinGW) 2. Fix up MinGW headers a) Add the following lines to C:\MinGW\include\winsock2.h: ```c #if(_WIN32_WINNT >= 0x0600) typedef struct pollfd { SOCKET fd; SHORT events; SHORT revents; } WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD; WINSOCK_API_LINKAGE int WSAAPI WSAPoll(LPWSAPOLLFD fdArray, ULONG fds, INT timeout); #endif // (_WIN32_WINNT >= 0x0600) ``` b) Create C:\MinGW\include\mstcpip.h and copy and paste the content from following link into it: http://wine-unstable.sourcearchive.com/documentation/1.1.32/mstcpip_8h-source.html 3. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html 4. Install OpenSSL binaries. http://www.openssl.org/related/binaries.html (**NOTE**: Preferably in the default location to make it easier for CMake to find them) **NOTE2**: Be sure that OPENSSL_CONF environment variable is defined and points at <OpenSSL install location>\bin\openssl.cfg 5. Generate the build files (default is Make files) using MSYS shell: ```bash $ cd /drive/path/to/src $ mkdir build $ cd build $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW .. ``` (**NOTE**: The `build/`` directory can have any name and be located anywhere on your filesystem, and that the argument `..` given to cmake is simply the source directory of **libwebsockets** containing the [CMakeLists.txt](CMakeLists.txt) project file. All examples in this file assumes you use "..") **NOTE2**: To generate build files allowing to create libwebsockets binaries with debug information set the CMAKE_BUILD_TYPE flag to DEBUG: ```bash $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW -DCMAKE_BUILD_TYPE=DEBUG .. ``` 6. Finally you can build using the generated Makefile and get the results deployed into your MinGW installation: ```bash $ make $ make install ``` Setting compile options ----------------------- To set compile time flags you can either use one of the CMake gui applications or do it via command line. Command line ------------ To list avaialable options (ommit the H if you don't want the help text): cmake -LH .. Then to set an option and build (for example turn off SSL support): cmake -DLWS_WITH_SSL=0 .. or cmake -DLWS_WITH_SSL:BOOL=OFF .. Building on mbed3 ----------------- MBED3 is a non-posix embedded OS targeted on Cortex M class chips. https://www.mbed.com/ It's quite unlike any other Posixy platform since the OS is linked statically in with lws to form one binary. At the minute server-only is supported and due to bugs in mbed3 network support, the port is of alpha quality. However it can serve the test html, favicon.ico and logo png and may be able to make ws connections. The binary for that including the OS, test app, lws and all the assets is only 117KB. 0) Today mbed3 only properly works on FRDM K64F $35 Freescale Dev Board with 1MB Flash, 256KB SRAM and Ethernet. http://www.freescale.com/products/arm-processors/kinetis-cortex-m/k-series/k6x-ethernet-mcus/freescale-freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F 1) Get a working mbed3 environment with arm-none-eabi-cs toolchain (available in Fedora, Ubuntu and other distros) 2) Confirm you can build things using yotta by following the getting started guide here https://docs.mbed.com/docs/getting-started-mbed-os/en/latest/ 3) git clone https://github.com/warmcat/lws-test-server and cd into it 4) mkdir -p yotta_modules ; cd yotta_modules 5) git clone https://github.com/warmcat/libwebsockets ; mv libwebsockets websockets ; cd .. 6) yotta target frdm-k64f-gcc 7) yotta install 8) yotta build Unix GUI -------- If you have a curses-enabled build you simply type: (not all packages include this, my debian install does not for example). ccmake Windows GUI ----------- On windows CMake comes with a gui application: Start -> Programs -> CMake -> CMake (cmake-gui) wolfSSL/CyaSSL replacement for OpenSSL -------------------------------------- wolfSSL/CyaSSL is a lightweight SSL library targeted at embedded systems: https://www.wolfssl.com/wolfSSL/Products-wolfssl.html It contains a OpenSSL compatibility layer which makes it possible to pretty much link to it instead of OpenSSL, giving a much smaller footprint. **NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for this to work. Compiling libwebsockets with wolfSSL ------------------------------------ ```bash cmake .. -DLWS_USE_WOLFSSL=1 \ -DLWS_WOLFSSL_INCLUDE_DIRS=/path/to/wolfssl \ -DLWS_WOLFSSL_LIBRARIES=/path/to/wolfssl/wolfssl.a .. ``` **NOTE**: On windows use the .lib file extension for `LWS_WOLFSSL_LIBRARIES` instead. Compiling libwebsockets with CyaSSL ----------------------------------- ```bash cmake .. -DLWS_USE_CYASSL=1 \ -DLWS_CYASSL_INCLUDE_DIRS=/path/to/cyassl \ -DLWS_CYASSL_LIBRARIES=/path/to/wolfssl/cyassl.a .. ``` **NOTE**: On windows use the .lib file extension for `LWS_CYASSL_LIBRARIES` instead. Compiling libwebsockets with PolarSSL ------------------------------------- Caution... at some point PolarSSL became MbedTLS. But it did not happen all at once. The name changed first then at mbedTLS 2.0 the apis changed. So eg in Fedora 22, there is an "mbedtls" package which is actually using polarssl for the include dir and polarssl apis... this should be treated as polarssl then. Example config for this case is cmake .. -DLWS_USE_POLARSSL=1 -DLWS_POLARSSL_LIBRARIES=/usr/lib64/libmbedtls.so \ -DLWS_POLARSSL_INCLUDE_DIRS=/usr/include/polarssl/ Building plugins outside of lws itself -------------------------------------- The directory ./plugin-standalone/ shows how easy it is to create plugins outside of lws itself. First build lws itself with -DLWS_WITH_PLUGINS, then use the same flow to build the standalone plugin ``` cd ./plugin-standalone mkdir build cd build cmake .. make && sudo make install ``` if you changed the default plugin directory when you built lws, you must also give the same arguments to cmake here (eg, ` -DCMAKE_INSTALL_PREFIX:PATH=/usr/something/else...` ) Otherwise if you run lwsws or libwebsockets-test-server-v2.0, it will now find the additional plugin "libprotocol_example_standalone.so" ``` lwsts[21257]: Plugins: lwsts[21257]: libprotocol_dumb_increment.so lwsts[21257]: libprotocol_example_standalone.so lwsts[21257]: libprotocol_lws_mirror.so lwsts[21257]: libprotocol_lws_server_status.so lwsts[21257]: libprotocol_lws_status.so ``` If you have multiple vhosts, you must enable plugins at the vhost additionally, discovered plugins are not enabled automatically for security reasons. You do this using info->pvo or for lwsws, in the JSON config. Reproducing HTTP2.0 tests ------------------------- You must have built and be running lws against a version of openssl that has ALPN / NPN. Most distros still have older versions. You'll know it's right by seeing ```bash lwsts[4752]: Compiled with OpenSSL support lwsts[4752]: Using SSL mode lwsts[4752]: HTTP2 / ALPN enabled ``` at lws startup. For non-SSL HTTP2.0 upgrade ```bash $ nghttp -nvasu http://localhost:7681/test.htm ``` For SSL / ALPN HTTP2.0 upgrade ``` $ nghttp -nvas https://localhost:7681/test.html ``` Cross compiling --------------- To enable cross-compiling **libwebsockets** using CMake you need to create a "Toolchain file" that you supply to CMake when generating your build files. CMake will then use the cross compilers and build paths specified in this file to look for dependencies and such. **Libwebsockets** includes an example toolchain file [cross-arm-linux-gnueabihf.cmake](cross-arm-linux-gnueabihf.cmake) you can use as a starting point. The commandline to configure for cross with this would look like ```bash $ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr \ -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake \ -DWITHOUT_EXTENSIONS=1 -DWITH_SSL=0 ``` The example shows how to build with no external cross lib dependencies, you need to provide the cross libraries otherwise. **NOTE**: start from an EMPTY build directory if you had a non-cross build in there before the settings will be cached and your changes ignored. Additional information on cross compilation with CMake: http://www.vtk.org/Wiki/CMake_Cross_Compiling Memory efficiency ----------------- Embedded server-only configuration without extensions (ie, no compression on websocket connections), but with full v13 websocket features and http server, built on ARM Cortex-A9: Update at 8dac94d (2013-02-18) ```bash $ ./configure --without-client --without-extensions --disable-debug --without-daemonize Context Creation, 1024 fd limit[2]: 16720 (includes 12 bytes per fd) Per-connection [3]: 72 bytes, +1328 during headers .text .rodata .data .bss 11512 2784 288 4 ``` This shows the impact of the major configuration with/without options at 13ba5bbc633ea962d46d using Ubuntu ARM on a PandaBoard ES. These are accounting for static allocations from the library elf, there are additional dynamic allocations via malloc. These are a bit old now but give the right idea for relative "expense" of features. Static allocations, ARM9 | | .text | .rodata | .data | .bss | |--------------------------------|---------|---------|-------|------| | All (no without) | 35024 | 9940 | 336 | 4104 | | without client | 25684 | 7144 | 336 | 4104 | | without client, exts | 21652 | 6288 | 288 | 4104 | | without client, exts, debug[1] | 19756 | 3768 | 288 | 4104 | | without server | 30304 | 8160 | 336 | 4104 | | without server, exts | 25382 | 7204 | 288 | 4104 | | without server, exts, debug[1] | 23712 | 4256 | 288 | 4104 | [1] `--disable-debug` only removes messages below `lwsl_notice`. Since that is the default logging level the impact is not noticeable, error, warn and notice logs are all still there. [2] `1024` fd per process is the default limit (set by ulimit) in at least Fedora and Ubuntu. You can make significant savings tailoring this to actual expected peak fds, ie, at a limit of `20`, context creation allocation reduces to `4432 + 240 = 4672`) [3] known header content is freed after connection establishment |
Added undroid/libwebsockets/README.coding.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
Daemonization ------------- There's a helper api `lws_daemonize` built by default that does everything you need to daemonize well, including creating a lock file. If you're making what's basically a daemon, just call this early in your init to fork to a headless background process and exit the starting process. Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your daemon is headless, so you'll need to sort out alternative logging, by, eg, syslog. Maximum number of connections ----------------------------- The maximum number of connections the library can deal with is decided when it starts by querying the OS to find out how many file descriptors it is allowed to open (1024 on Fedora for example). It then allocates arrays that allow up to that many connections, minus whatever other file descriptors are in use by the user code. If you want to restrict that allocation, or increase it, you can use ulimit or similar to change the avaiable number of file descriptors, and when restarted **libwebsockets** will adapt accordingly. Libwebsockets is singlethreaded ------------------------------- Directly performing websocket actions from other threads is not allowed. Aside from the internal data being inconsistent in `forked()` processes, the scope of a `wsi` (`struct websocket`) can end at any time during service with the socket closing and the `wsi` freed. Websocket write activities should only take place in the `LWS_CALLBACK_SERVER_WRITEABLE` callback as described below. Only live connections appear in the user callbacks, so this removes any possibility of trying to used closed and freed wsis. If you need to service other socket or file descriptors as well as the websocket ones, you can combine them together with the websocket ones in one poll loop, see "External Polling Loop support" below, and still do it all in one thread / process context. If you insist on trying to use it from multiple threads, take special care if you might simultaneously create more than one context from different threads. SSL_library_init() is called from the context create api and it also is not reentrant. So at least create the contexts sequentially. Only send data when socket writeable ------------------------------------ You should only send data on a websocket connection from the user callback `LWS_CALLBACK_SERVER_WRITEABLE` (or `LWS_CALLBACK_CLIENT_WRITEABLE` for clients). If you want to send something, do not just send it but request a callback when the socket is writeable using - `lws_callback_on_writable(context, wsi)`` for a specific `wsi`, or - `lws_callback_on_writable_all_protocol(protocol)` for all connections using that protocol to get a callback when next writeable. Usually you will get called back immediately next time around the service loop, but if your peer is slow or temporarily inactive the callback will be delayed accordingly. Generating what to write and sending it should be done in the ...WRITEABLE callback. See the test server code for an example of how to do this. Do not rely on only your own WRITEABLE requests appearing --------------------------------------------------------- Libwebsockets may generate additional `LWS_CALLBACK_CLIENT_WRITEABLE` events if it met network conditions where it had to buffer your send data internally. So your code for `LWS_CALLBACK_CLIENT_WRITEABLE` needs to own the decision about what to send, it can't assume that just because the writeable callback came it really is time to send something. It's quite possible you get an 'extra' writeable callback at any time and just need to `return 0` and wait for the expected callback later. Closing connections from the user side -------------------------------------- When you want to close a connection, you do it by returning `-1` from a callback for that connection. You can provoke a callback by calling `lws_callback_on_writable` on the wsi, then notice in the callback you want to close it and just return -1. But usually, the decision to close is made in a callback already and returning -1 is simple. If the socket knows the connection is dead, because the peer closed or there was an affirmitive network error like a FIN coming, then **libwebsockets** will take care of closing the connection automatically. If you have a silently dead connection, it's possible to enter a state where the send pipe on the connection is choked but no ack will ever come, so the dead connection will never become writeable. To cover that, you can use TCP keepalives (see later in this document) Fragmented messages ------------------- To support fragmented messages you need to check for the final frame of a message with `lws_is_final_fragment`. This check can be combined with `libwebsockets_remaining_packet_payload` to gather the whole contents of a message, eg: ``` case LWS_CALLBACK_RECEIVE: { Client * const client = (Client *)user; const size_t remaining = lws_remaining_packet_payload(wsi); if (!remaining && lws_is_final_fragment(wsi)) { if (client->HasFragments()) { client->AppendMessageFragment(in, len, 0); in = (void *)client->GetMessage(); len = client->GetMessageLength(); } client->ProcessMessage((char *)in, len, wsi); client->ResetMessage(); } else client->AppendMessageFragment(in, len, remaining); } break; ``` The test app libwebsockets-test-fraggle sources also show how to deal with fragmented messages. Debug Logging ------------- Also using `lws_set_log_level` api you may provide a custom callback to actually emit the log string. By default, this points to an internal emit function that sends to stderr. Setting it to `NULL` leaves it as it is instead. A helper function `lwsl_emit_syslog()` is exported from the library to simplify logging to syslog. You still need to use `setlogmask`, `openlog` and `closelog` in your user code. The logging apis are made available for user code. - `lwsl_err(...)` - `lwsl_warn(...)` - `lwsl_notice(...)` - `lwsl_info(...)` - `lwsl_debug(...)` The difference between notice and info is that notice will be logged by default whereas info is ignored by default. External Polling Loop support ----------------------------- **libwebsockets** maintains an internal `poll()` array for all of its sockets, but you can instead integrate the sockets into an external polling array. That's needed if **libwebsockets** will cooperate with an existing poll array maintained by another server. Four callbacks `LWS_CALLBACK_ADD_POLL_FD`, `LWS_CALLBACK_DEL_POLL_FD`, `LWS_CALLBACK_SET_MODE_POLL_FD` and `LWS_CALLBACK_CLEAR_MODE_POLL_FD` appear in the callback for protocol 0 and allow interface code to manage socket descriptors in other poll loops. You can pass all pollfds that need service to `lws_service_fd()`, even if the socket or file does not belong to **libwebsockets** it is safe. If **libwebsocket** handled it, it zeros the pollfd `revents` field before returning. So you can let **libwebsockets** try and if `pollfd->revents` is nonzero on return, you know it needs handling by your code. Using with in c++ apps ---------------------- The library is ready for use by C++ apps. You can get started quickly by copying the test server ```bash $ cp test-server/test-server.c test.cpp ``` and building it in C++ like this ```bash $ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets ``` `INSTALL_DATADIR` is only needed because the test server uses it as shipped, if you remove the references to it in your app you don't need to define it on the g++ line either. Availability of header information ---------------------------------- From v1.2 of the library onwards, the HTTP header content is `free()`d as soon as the websocket connection is established. For websocket servers, you can copy interesting headers by handling `LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION` callback, for clients there's a new callback just for this purpose `LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH`. TCP Keepalive ------------- It is possible for a connection which is not being used to send to die silently somewhere between the peer and the side not sending. In this case by default TCP will just not report anything and you will never get any more incoming data or sign the link is dead until you try to send. To deal with getting a notification of that situation, you can choose to enable TCP keepalives on all **libwebsockets** sockets, when you create the context. To enable keepalive, set the ka_time member of the context creation parameter struct to a nonzero value (in seconds) at context creation time. You should also fill ka_probes and ka_interval in that case. With keepalive enabled, the TCP layer will send control packets that should stimulate a response from the peer without affecting link traffic. If the response is not coming, the socket will announce an error at `poll()` forcing a close. Note that BSDs don't support keepalive time / probes / interval per-socket like Linux does. On those systems you can enable keepalive by a nonzero value in `ka_time`, but the systemwide kernel settings for the time / probes/ interval are used, regardless of what nonzero value is in `ka_time`. Optimizing SSL connections -------------------------- There's a member `ssl_cipher_list` in the `lws_context_creation_info` struct which allows the user code to restrict the possible cipher selection at context-creation time. You might want to look into that to stop the ssl peers selecting a cipher which is too computationally expensive. To use it, point it to a string like `"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"` if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select. Async nature of client connections ---------------------------------- When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not mean your connection is active. It just means it started trying to connect. Your client connection is actually active only when you receive `LWS_CALLBACK_CLIENT_ESTABLISHED` for it. There's a 5 second timeout for the connection, and it may give up or die for other reasons, if any of that happens you'll get a `LWS_CALLBACK_CLIENT_CONNECTION_ERROR` callback on protocol 0 instead for the `wsi`. After attempting the connection and getting back a non-`NULL` `wsi` you should loop calling `lws_service()` until one of the above callbacks occurs. As usual, see [test-client.c](test-server/test-client.c) for example code. Lws platform-independent file access apis ----------------------------------------- lws now exposes his internal platform file abstraction in a way that can be both used by user code to make it platform-agnostic, and be overridden or subclassed by user code. This allows things like handling the URI "directory space" as a virtual filesystem that may or may not be backed by a regular filesystem. One example use is serving files from inside large compressed archive storage without having to unpack anything except the file being requested. The test server shows how to use it, basically the platform-specific part of lws prepares a file operations structure that lives in the lws context. The user code can get a pointer to the file operations struct LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * `lws_get_fops`(struct lws_context *context); and then can use helpers to also leverage these platform-independent file handling apis static inline lws_filefd_type `lws_plat_file_open`(struct lws *wsi, const char *filename, unsigned long *filelen, int flags) static inline int `lws_plat_file_close`(struct lws *wsi, lws_filefd_type fd) static inline unsigned long `lws_plat_file_seek_cur`(struct lws *wsi, lws_filefd_type fd, long offset_from_cur_pos) static inline int `lws_plat_file_read`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len) static inline int `lws_plat_file_write`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len) The user code can also override or subclass the file operations, to either wrap or replace them. An example is shown in test server. ECDH Support ------------ ECDH Certs are now supported. Enable the CMake option cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 **and** the info->options flag LWS_SERVER_OPTION_SSL_ECDH to build in support and select it at runtime. SMP / Multithreaded service --------------------------- SMP support is integrated into LWS without any internal threading. It's very simple to use, libwebsockets-test-server-pthread shows how to do it, use -j <n> argument there to control the number of service threads up to 32. Two new members are added to the info struct unsigned int count_threads; unsigned int fd_limit_per_thread; leave them at the default 0 to get the normal singlethreaded service loop. Set count_threads to n to tell lws you will have n simultaneous service threads operating on the context. There is still a single listen socket on one port, no matter how many service threads. When a connection is made, it is accepted by the service thread with the least connections active to perform load balancing. The user code is responsible for spawning n threads running the service loop associated to a specific tsi (Thread Service Index, 0 .. n - 1). See the libwebsockets-test-server-pthread for how to do. If you leave fd_limit_per_thread at 0, then the process limit of fds is shared between the service threads; if you process was allowed 1024 fds overall then each thread is limited to 1024 / n. You can set fd_limit_per_thread to a nonzero number to control this manually, eg the overall supported fd limit is less than the process allowance. You can control the context basic data allocation for multithreading from Cmake using -DLWS_MAX_SMP=, if not given it's set to 32. The serv_buf allocation for the threads (currently 4096) is made at runtime only for active threads. Because lws will limit the requested number of actual threads supported according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to discover how many threads were actually allowed when the context was created. It's required to implement locking in the user code in the same way that libwebsockets-test-server-pthread does it, for the FD locking callbacks. There is no knowledge or dependency in lws itself about pthreads. How the locking is implemented is entirely up to the user code. Libev / Libuv support --------------------- You can select either or both -DLWS_WITH_LIBEV=1 -DLWS_WITH_LIBUV=1 at cmake configure-time. The user application may use one of the context init options flags LWS_SERVER_OPTION_LIBEV LWS_SERVER_OPTION_LIBUV to indicate it will use either of the event libraries. Extension option control from user code --------------------------------------- User code may set per-connection extension options now, using a new api "lws_set_extension_option()". This should be called from the ESTABLISHED callback like this lws_set_extension_option(wsi, "permessage-deflate", "rx_buf_size", "12"); /* 1 << 12 */ If the extension is not active (missing or not negotiated for the connection, or extensions are disabled on the library) the call is just returns -1. Otherwise the connection's extension has its named option changed. The extension may decide to alter or disallow the change, in the example above permessage-deflate restricts the size of his rx output buffer also considering the protocol's rx_buf_size member. Client connections as HTTP[S] rather than WS[S] ----------------------------------------------- You may open a generic http client connection using the same struct lws_client_connect_info used to create client ws[s] connections. To stay in http[s], set the optional info member "method" to point to the string "GET" instead of the default NULL. After the server headers are processed, when payload from the server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP will be made. You can choose whether to process the data immediately, or queue a callback when an outgoing socket is writeable to provide flow control, and process the data in the writable callback. Either way you use the api `lws_http_client_read()` to access the data, eg case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: { char buffer[1024 + LWS_PRE]; char *px = buffer + LWS_PRE; int lenx = sizeof(buffer) - LWS_PRE; lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n"); /* * Often you need to flow control this by something * else being writable. In that case call the api * to get a callback when writable here, and do the * pending client read in the writeable callback of * the output. */ if (lws_http_client_read(wsi, &px, &lenx) < 0) return -1; while (lenx--) putchar(*px++); } break; Using lws v2 vhosts ------------------- If you set LWS_SERVER_OPTION_EXPLICIT_VHOSTS options flag when you create your context, it won't create a default vhost using the info struct members for compatibility. Instead you can call lws_create_vhost() afterwards to attach one or more vhosts manually. ``` LWS_VISIBLE struct lws_vhost * lws_create_vhost(struct lws_context *context, struct lws_context_creation_info *info, struct lws_http_mount *mounts); ``` lws_create_vhost() uses the same info struct as lws_create_context(), it ignores members related to context and uses the ones meaningful for vhost (marked with VH in libwebsockets.h). ``` struct lws_context_creation_info { int port; /* VH */ const char *iface; /* VH */ const struct lws_protocols *protocols; /* VH */ const struct lws_extension *extensions; /* VH */ ... ``` When you attach the vhost, if the vhost's port already has a listen socket then both vhosts share it and use SNI (is SSL in use) or the Host: header from the client to select the right one. Or if no other vhost already listening the a new listen socket is created. There are some new members but mainly it's stuff you used to set at context creation time. How lws matches hostname or SNI to a vhost ------------------------------------------ LWS first strips any trailing :port number. Then it tries to find an exact name match for a vhost listening on the correct port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a vhost named abc.com that is listening on port 1234. If there is no exact match, lws will consider wildcard matches, for example if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will accept a vhost "abc.com" listening on port 1234. If there was a better, exact, match, it will have been chosen in preference to this. Connections with SSL will still have the client go on to check the certificate allows wildcards and error out if not. Using lws v2 mounts on a vhost ------------------------------ The last argument to lws_create_vhost() lets you associate a linked list of lws_http_mount structures with that vhost's URL 'namespace', in a similar way that unix lets you mount filesystems into areas of your / filesystem how you like and deal with the contents transparently. ``` struct lws_http_mount { struct lws_http_mount *mount_next; const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */ const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */ const char *def; /* default target, eg, "index.html" */ struct lws_protocol_vhost_options *cgienv; int cgi_timeout; int cache_max_age; unsigned int cache_reusable:1; unsigned int cache_revalidate:1; unsigned int cache_intermediaries:1; unsigned char origin_protocol; unsigned char mountpoint_len; }; ``` The last mount structure should have a NULL mount_next, otherwise it should point to the 'next' mount structure in your list. Both the mount structures and the strings must persist until the context is destroyed, since they are not copied but used in place. `.origin_protocol` should be one of ``` enum { LWSMPRO_HTTP, LWSMPRO_HTTPS, LWSMPRO_FILE, LWSMPRO_CGI, LWSMPRO_REDIR_HTTP, LWSMPRO_REDIR_HTTPS, }; ``` LWSMPRO_FILE is used for mapping url namespace to a filesystem directory and serve it automatically. |
Added undroid/libwebsockets/README.lwsws.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
Libwebsockets Web Server ------------------------ lwsws is an implementation of a very lightweight, ws-capable generic web server, which uses libwebsockets to implement everything underneath. Build ----- Just enable -DLWS_WITH_LWSWS=1 at cmake-time. It enables libuv and plugin support automatically. Configuration ------------- lwsws uses JSON config files, they're pure JSON but # may be used to turn the rest of the line into a comment. There is a single file intended for global settings /etc/lwsws/conf ``` # these are the server global settings # stuff related to vhosts should go in one # file per vhost in ../conf.d/ { "global": { "uid": "48", # apache user "gid": "48", # apache user "count-threads": "1", "server-string": "myserver v1", # returned in http headers "init-ssl": "yes" } } ``` and a config directory intended to take one file per vhost /etc/lwsws/conf.d/warmcat.com ``` { "vhosts": [{ "name": "warmcat.com", "port": "443", "interface": "eth0", # optional "host-ssl-key": "/etc/pki/tls/private/warmcat.com.key", # if given enable ssl "host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt", "host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer", "mounts": [{ # autoserve "mountpoint": "/", "origin": "file:///var/www/warmcat.com", "default": "index.html" }] }] } ``` Vhosts ------ One server can run many vhosts, where SSL is in use SNI is used to match the connection to a vhost and its vhost-specific SSL keys during SSL negotiation. Listing multiple vhosts looks something like this ``` { "vhosts": [ { "name": "localhost", "port": "443", "host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key", "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt", "host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer", "mounts": [{ "mountpoint": "/", "origin": "file:///var/www/libwebsockets.org", "default": "index.html" }, { "mountpoint": "/testserver", "origin": "file:///usr/local/share/libwebsockets-test-server", "default": "test.html" }], # which protocols are enabled for this vhost, and optional # vhost-specific config options for the protocol # "ws-protocols": [{ "warmcat,timezoom": { "status": "ok" } }] }, { "name": "localhost", "port": "7681", "host-ssl-key": "/etc/pki/tls/private/libwebsockets.org.key", "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt", "host-ssl-ca": "/etc/pki/tls/certs/libwebsockets.org.cer", "mounts": [{ "mountpoint": "/", "origin": ">https://localhost" }] }, { "name": "localhost", "port": "80", "mounts": [{ "mountpoint": "/", "origin": ">https://localhost" }] } ] } ``` That sets up three vhosts all called "localhost" on ports 443 and 7681 with SSL, and port 80 without SSL but with a forced redirect to https://localhost Vhost name and port ------------------- The vhost name field is used to match on incoming SNI or Host: header, so it must always be the host name used to reach the vhost externally. - Vhosts may have the same name and different ports, these will each create a listening socket on the appropriate port. - Vhosts may also have the same port and different name: these will be treated as true vhosts on one listening socket and the active vhost decided at SSL negotiation time (via SNI) or if no SSL, then after the Host: header from the client has been parsed. Protocols --------- Vhosts by default have available the union of any initial protocols from context creation time, and any protocols exposed by plugins. Vhosts can select which plugins they want to offer and give them per-vhost settings using this syntax ``` "ws-protocols": [{ "warmcat-timezoom": { "status": "ok" } }] ``` The "x":"y" parameters like "status":"ok" are made available to the protocol during its per-vhost LWS_CALLBACK_PROTOCOL_INIT (@in is a pointer to a linked list of struct lws_protocol_vhost_options containing the name and value pointers). To indicate that a protocol should be used when no Protocol: header is sent by the client, you can use "default": "1" ``` "ws-protocols": [{ "warmcat-timezoom": { "status": "ok", "default": "1" } }] ``` Other vhost options ------------------- - If the three options `host-ssl-cert`, `host-ssl-ca` and `host-ssl-key` are given, then the vhost supports SSL. Each vhost may have its own certs, SNI is used during the initial connection negotiation to figure out which certs to use by the server name it's asking for from the request DNS name. - `keeplive-timeout` (in secs) defaults to 60 for lwsws, it may be set as a vhost option - `interface` lets you specify which network interface to listen on, if not given listens on all - "`unix-socket`": "1" causes the unix socket specified in the interface option to be used instead of an INET socket - "`sts`": "1" causes lwsws to send a Strict Transport Security header with responses that informs the client he should never accept to connect to this address using http. This is needed to get the A+ security rating from SSL Labs for your server. - "`access-log`": "filepath" sets where apache-compatible access logs will be written - "`ciphers`": "<cipher list>" sets the allowed list of ciphers and key exchange protocols for the vhost. The default list is restricted to only those providing PFS (Perfect Forward Secrecy) on the author's Fedora system. If you need to allow weaker ciphers,you can provide an alternative list here per-vhost. - "`ecdh-curve`": "<curve name>" The default ecdh curve is "prime256v1", but you can override it here, per-vhost Mounts ------ Where mounts are given in the vhost definition, then directory contents may be auto-served if it matches the mountpoint. Mount protocols are used to control what kind of translation happens - file:// serve the uri using the remainder of the url past the mountpoint based on the origin directory. Eg, with this mountpoint ``` { "mountpoint": "/", "origin": "file:///var/www/mysite.com", "default": "/" } ``` The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched. - ^http:// or ^https:// these cause any url matching the mountpoint to issue a redirect to the origin url - cgi:// this causes any matching url to be given to the named cgi, eg ``` { "mountpoint": "/git", "origin": "cgi:///var/www/cgi-bin/cgit", "default": "/" }, { "mountpoint": "/cgit-data", "origin": "file:///usr/share/cgit", "default": "/" }, ``` would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client. Note: currently only a fixed set of mimetypes are supported. Other mount options ------------------- 1) When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this ``` { "mountpoint": "/git", "origin": "cgi:///var/www/cgi-bin/cgit", "default": "/", "cgi-env": [{ "CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org" }] } ``` This allows you to customize one cgi depending on the mountpoint (and / or vhost). 2) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this ``` "cgi-timeout": "30" ``` 3) Cache policy of the files in the mount can also be set. If no options are given, the content is marked uncacheable. { "mountpoint": "/", "origin": "file:///var/www/mysite.com", "cache-max-age": "60", # seconds "cache-reuse": "1", # allow reuse at client at all "cache-revalidate": "1", # check it with server each time "cache-intermediaries": "1" # allow intermediary caches to hold } 4) You can also define a list of additional mimetypes per-mount "extra-mimetypes": { ".zip": "application/zip", ".doc": "text/evil" } Plugins ------- Protcols and extensions may also be provided from "plugins", these are lightweight dynamic libraries. They are scanned for at init time, and any protocols and extensions found are added to the list given at context creation time. Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction (LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements they can make per-vhost allocations and get hold of the correct pointer from the wsi at the callback. This allows a protocol to choose to strictly segregate data on a per-vhost basis, and also allows the plugin to handle its own initialization and context storage. To help that happen conveniently, there are some new apis - lws_vhost_get(wsi) - lws_protocol_get(wsi) - lws_callback_on_writable_all_protocol_vhost(vhost, protocol) - lws_protocol_vh_priv_zalloc(vhost, protocol, size) - lws_protocol_vh_priv_get(vhost, protocol) dumb increment, mirror and status protocol plugins are provided as examples. Additional plugin search paths ------------------------------ Packages that have their own lws plugins can install them in their own preferred dir and ask lwsws to scan there by using a config fragment like this, in its own conf.d/ file managed by the other package { "global": { "plugin-dir": "/usr/local/share/coherent-timeline/plugins" } } lws-server-status plugin ------------------------ One provided protocol can be used to monitor the server status. Enable the protocol like this on a vhost's ws-protocols section "lws-server-status": { "status": "ok", "update-ms": "5000" } "update-ms" is used to control how often updated JSON is sent on a ws link. And map the provided HTML into the vhost in the mounts section { "mountpoint": "/server-status", "origin": "file:///usr/local/share/libwebsockets-test-server/server-status", "default": "server-status.html" } You might choose to put it on its own vhost which has "interface": "lo", so it's not externally visible. Integration with Systemd ------------------------ lwsws needs a service file like this as `/usr/lib/systemd/system/lwsws.service` ``` [Unit] Description=Libwebsockets Web Server After=syslog.target [Service] ExecStart=/usr/local/bin/lwsws StandardError=null [Install] WantedBy=multi-user.target ``` You can find this prepared in `./lwsws/usr-lib-systemd-system-lwsws.service` Integration with logrotate -------------------------- For correct operation with logrotate, `/etc/logrotate.d/lwsws` (if that's where we're putting the logs) should contain ``` /var/log/lwsws/*log { copytruncate missingok notifempty delaycompress } ``` You can find this prepared in `/lwsws/etc-logrotate.d-lwsws` Prepare the log directory like this ``` sudo mkdir /var/log/lwsws sudo chmod 700 /var/log/lwsws ``` |
Added undroid/libwebsockets/README.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
libwebsockets ------------- This is the libwebsockets C library for lightweight websocket clients and servers. For support, visit https://libwebsockets.org https://github.com/warmcat/libwebsockets and consider joining the project mailing list at https://libwebsockets.org/mailman/listinfo/libwebsockets | News | ------ | We have updated https://libwebsockets.org, if you would like your project using lws featured in the image carousel, send an image, project URL and brief summary to andy@warmcat.com | You can get the latest version of the library from git: - https://github.com/warmcat/libwebsockets - https://libwebsockets.org/git for more information: - [README.build.md](README.build.md) - information on building the library - [README.coding.md](README.coding.md) - information for writing code using the library - [README.test-apps.md](README.test-apps.md) - information about the test apps built with the library After libwebsockets 1.3, tags will be signed using a key corresponding to this public key ``` -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQINBFRe35QBEADZA7snW7MoEXkT2deDYZeggVD3694dg1o5G4q36NWjC8Pn/b2V d+L9Nmw8ydKIv8PLJW762rnveQpPYRqCRD8X4bVTYzYz3qsOl5BrYf6cuVn0ZrPB 13TVRg+NZwUaVxc7O+tdOvvEBdA9OCIygctPNK9Nyh53xs5gPHhghZrKVrt0xM1A 2LYsgoHmMBCCY25SHb1nuapvhA3LvuJb4cNNVRCukCoA6yx0uhSEz2AUPJSLqnZ9 XnNBMKq+1a9C+y7jo4O78upTTmuOmRmNEVAu7pxCSUXDrNa87T8n6vFkV/MiW8nv VmhppKJrKPJ0KxJF9b7uG6eKosfoK2PKyE7pAoDN1fuNyBTB0dkFAwyTCN8hmhOg z71QrCltotq/AxSCsKzgFkDBL7D3KUM10QR5kmznjcm8tFWHoSttPR334z/1Yepf ATqH/tfYydW42qeeHgKjfeegnlI65nTDtwYW6lSqZsXg+/ABg0ki9m5HA6l713ig gRbVHSNkiz56O+UOqBtfcJZBc8QZqqixq8rbP2Is0HBBEtD+aFMuKx/sQ3ULkQs2 8dZ5qsGTBT/xHmqpHJsIFX/jwjY5zeEiFbnO5bMH7YLmkjynVsn5zxTyXKQJe29C Uq0Yd9+JpDhHnZoiz/1hIIBsr89Z4Yy6c59YNJ3yJEOast0ODERcKSaUAQARAQAB tC9BbmR5IEdyZWVuIChMaW5hcm8ga2V5KSA8YW5keS5ncmVlbkBsaW5hcm8ub3Jn PokCPQQTAQoAJwUCVF7flAIbAwUJBaOagAULCQgHAwUVCgkICwUWAwIBAAIeAQIX gAAKCRA8ZxoDS3lTexApD/9WT7JWy3tK33OIACYV40XwLEhRam4Xku4rhtsoIeJK P0k/wa7J2PpceX6gKV+QBsOx3UbUfpqZ/Mu7ff3M0J6W87XpKRROAmP43zyiBkmM A6v0pJXozknmCU28p3DuLC8spVDFg9N52xV7Qb+9TDHcTYiVi4swKYuDEuHBC/qa M69+ANgsGbrMFRypxtU7OEhls3AEo3Cq03xD8QvLjFyPpYp1f0vNRFm2Jjgm2CRe YLVsCGxG35Dz7DpJHekHNxje6xsZ2w9Q38M0rLQ0ICOVQ+E1Dir3hwmZQWASzMMi +R0P+MVYpVt5y7KtiLywJ4BzNogS7gY3wQxksJOFA1uuk5h/hO54a361mcdA0Ta5 HHhGKRw87lVjEQSaRjFZmHFClB+Sb8MuWR51JTzVS5HtJlcNqcWhF63vZ8bZ7b6y Aj8cXNjH6ULXyX3QnTUWXX/QU3an3yh8iPONWOGP5d5Hi/qejHGIhP2L5H+h05CP aZQYFLjjebYgEHijuA28eKWsBsoBPFSLpLloHTDkiycgFdV2AkQcxZN9ZElAqURP xUkEIscQg3YhExGiVEtaxBp1/p/WctMxs5HNoi0Oc97ZUcKvSCz9FDGXX9wYBpRf gzjNn055Xn4QyxBDnp5DrYT0ft/8BEnRK0JP6z3gNfnhOxZo4XA+M6w4Hjh3tI2A 3rkCDQRUXt+UARAA0yHmONtW3L1HpvWFR+VgVNHa1HBWWk7lMsI6ajeiUK/lN3F/ +vNbux46bPj/sNT9twbWmYhv6c0yVzCpmv5M5ztefS7mW/zPNLJmCmH32kAvVFr1 Z90R/X+Z1Uh8wCCU72S2pSIXQFza3LF53pbpKi5m1F2icYcx+35egAvvZVZtcrMu TjHUa+N9mFKxa7tb5PI8Lv93nRLwB7aKkp5PKy9Yvse0jACrAAGeIpI73H467/wO ujermKlyPOOv+Lpjd7kedWKdaweitva7FVI20K/afn4AwCI8HJUIqVbil0Yrg9Le M1TRsRydzMQQejsb/cWi3fQ3U3HxvSJijKltckPMqjJaXbqmrLz3FOA5Km0ciIOB WW0Qq0WREcS3rc5FHU29duS9OAieAWFYyLDieug4nQ29KQE6I0lMqLnz8vWYtbmw 6AHk9i2GsXOZiPnztuADgt9o9Os8fm7ZiacA1LISl86P7wpFk+Gf4LRvv8Fk08NV b2K1BY4YC9KP+AynyYQmxmyB1YQCh/dZHiD4ikGKttHAy4ZsMW6IRL5bRP0Z97pA lyBtXP0cGTJtuPt2feh0zaiA7blZ/IDXkB1UqH6jnTa71d1FeNKtVFi8FhPIREN6 Rc5imyRxubZEgsxhdjqGgdT5k6Qr42SewAN391ygutpgGizGQtTwzvmKa0UAEQEA AYkCJQQYAQoADwUCVF7flAIbDAUJBaOagAAKCRA8ZxoDS3lTewuBD/9/rakAMCRC +WmbUVpCbJSWP5ViH87Xko4ku437gq56whcGjQpxfCYt8oeVgS8fZetUOHs2gspJ CEc8TYLUFntfyt2AzKU29oQoizPm33W9S1u7aRGWsVVutd2sqUaQUDsl9z35+Ka9 YcWoATJSWBgnhSAmNcM60OG0P5qrZloTlbRSlDZTSZT3RvY4JWtWCubGsjEpXO4h ZqbKCu3KgV/6NOuTLciriSOZ/iyva3WsCP2S8mRRvma7x04oMTEWX80zozTCK8gG XqqS9eDhCkRbdmMyUQbHIhc/ChYchO5+fQ1o0zMS5cv6xgkhWI3NJRUkNdXolH9a 5F9q4CmCTcdEZkqpnjsLNiQLIENfHbgC0A5IjR6YgN6qAP8ZJ5hBgyTfyKkwB7bW DcCnuoC9R79hkI8nWkoRVou9tdzKxo0bGR6O4CfLj+4d3hpWkv9Rw7Xxygo5JOqN 4cNZGtHkmIFFk9fSXul5rkjfF/XmThIwoI8aHSBZ7j3IMtmkKVkBjNjiTfbgW8RT XIIR+QQdVLOyJqq+NZC/SrKVQITg0ToYJutRTUJViqyz5b3psJo5o2SW6jcexQpE cX6tdPyGz3o0aywfJ9dcN6izleSV1gYmXmIoS0cQyezVqTUkT8C12zeRB7mtWsDa +AWJGq/WfB7N6pPh8S/XMW4e6ptuUodjiA== =HV8t -----END PGP PUBLIC KEY BLOCK----- ``` |
Added undroid/libwebsockets/README.test-apps.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
Testing server with a browser ----------------------------- If you run [libwebsockets-test-server](test-server/test-server.c) and point your browser (eg, Chrome) to http://127.0.0.1:7681 It will fetch a script in the form of `test.html`, and then run the script in there on the browser to open a websocket connection. Incrementing numbers should appear in the browser display. By default the test server logs to both stderr and syslog, you can control what is logged using `-d <log level>`, see later. Running test server as a Daemon ------------------------------- You can use the -D option on the test server to have it fork into the background and return immediately. In this daemonized mode all stderr is disabled and logging goes only to syslog, eg, `/var/log/messages` or similar. The server maintains a lockfile at `/tmp/.lwsts-lock` that contains the pid of the master process, and deletes this file when the master process terminates. To stop the daemon, do ```bash $ kill `cat /tmp/.lwsts-lock` ``` If it finds a stale lock (the pid mentioned in the file does not exist any more) it will delete the lock and create a new one during startup. If the lock is valid, the daemon will exit with a note on stderr that it was already running. Using SSL on the server side ---------------------------- To test it using SSL/WSS, just run the test server with ```bash $ libwebsockets-test-server --ssl ``` and use the URL https://127.0.0.1:7681 The connection will be entirely encrypted using some generated certificates that your browser will not accept, since they are not signed by any real Certificate Authority. Just accept the certificates in the browser and the connection will proceed in first https and then websocket wss, acting exactly the same. [test-server.c](test-server/test-server.c) is all that is needed to use libwebsockets for serving both the script html over http and websockets. Testing websocket client support -------------------------------- If you run the test server as described above, you can also connect to it using the test client as well as a browser. ```bash $ libwebsockets-test-client localhost ``` will by default connect to the test server on localhost:7681 and print the dumb increment number from the server at the same time as drawing random circles in the mirror protocol; if you connect to the test server using a browser at the same time you will be able to see the circles being drawn. The test client supports SSL too, use ```bash $ libwebsockets-test-client localhost --ssl -s ``` the -s tells it to accept the default selfsigned cert from the server, otherwise it will strictly fail the connection if there is no CA cert to validate the server's certificate. Choosing between test server variations --------------------------------------- If you will be doing standalone serving with lws, ideally you should avoid making your own server at all, and use lwsws with your own protocol plugins. The second best option is follow test-server-v2.0.c, which uses a mount to autoserve a directory, and lws protocol plugins for ws, without needing any user callback code (other than what's needed in the protocol plugin). For those two options libuv is needed to support the protocol plugins, if that's not possible then the other variations with their own protocol code should be considered. Testing simple echo ------------------- You can test against `echo.websockets.org` as a sanity test like this (the client connects to port `80` by default): ```bash $ libwebsockets-test-echo --client echo.websocket.org ``` This echo test is of limited use though because it doesn't negotiate any protocol. You can run the same test app as a local server, by default on localhost:7681 ```bash $ libwebsockets-test-echo ``` and do the echo test against the local echo server ```bash $ libwebsockets-test-echo --client localhost --port 7681 ``` If you add the `--ssl` switch to both the client and server, you can also test with an encrypted link. Testing SSL on the client side ------------------------------ To test SSL/WSS client action, just run the client test with ```bash $ libwebsockets-test-client localhost --ssl ``` By default the client test applet is set to accept selfsigned certificates used by the test server, this is indicated by the `use_ssl` var being set to `2`. Set it to `1` to reject any server certificate that it doesn't have a trusted CA cert for. Using the websocket ping utility -------------------------------- libwebsockets-test-ping connects as a client to a remote websocket server using 04 protocol and pings it like the normal unix ping utility. ```bash $ libwebsockets-test-ping localhost handshake OK for protocol lws-mirror-protocol Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data. 64 bytes from localhost: req=1 time=0.1ms 64 bytes from localhost: req=2 time=0.1ms 64 bytes from localhost: req=3 time=0.1ms 64 bytes from localhost: req=4 time=0.2ms 64 bytes from localhost: req=5 time=0.1ms 64 bytes from localhost: req=6 time=0.2ms 64 bytes from localhost: req=7 time=0.2ms 64 bytes from localhost: req=8 time=0.1ms ^C --- localhost.localdomain websocket ping statistics --- 8 packets transmitted, 8 received, 0% packet loss, time 7458ms rtt min/avg/max = 0.110/0.185/0.218 ms $ ``` By default it sends 64 byte payload packets using the 04 PING packet opcode type. You can change the payload size using the `-s=` flag, up to a maximum of 125 mandated by the 04 standard. Using the lws-mirror protocol that is provided by the test server, libwebsockets-test-ping can also use larger payload sizes up to 4096 is BINARY packets; lws-mirror will copy them back to the client and they appear as a PONG. Use the `-m` flag to select this operation. The default interval between pings is 1s, you can use the -i= flag to set this, including fractions like `-i=0.01` for 10ms interval. Before you can even use the PING opcode that is part of the standard, you must complete a handshake with a specified protocol. By default lws-mirror-protocol is used which is supported by the test server. But if you are using it on another server, you can specify the protcol to handshake with by `--protocol=protocolname` Fraggle test app ---------------- By default it runs in server mode ```bash $ libwebsockets-test-fraggle libwebsockets test fraggle (C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1 Compiled with SSL support, not using it Listening on port 7681 server sees client connect accepted v06 connection Spamming 360 random fragments Spamming session over, len = 371913. sum = 0x2D3C0AE Spamming 895 random fragments Spamming session over, len = 875970. sum = 0x6A74DA1 ... ``` You need to run a second session in client mode, you have to give the `-c` switch and the server address at least: ```bash $ libwebsockets-test-fraggle -c localhost libwebsockets test fraggle (C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1 Client mode Connecting to localhost:7681 denied deflate-stream extension handshake OK for protocol fraggle-protocol client connects to server EOM received 371913 correctly from 360 fragments EOM received 875970 correctly from 895 fragments EOM received 247140 correctly from 258 fragments EOM received 695451 correctly from 692 fragments ... ``` The fraggle test sends a random number up to 1024 fragmented websocket frames each of a random size between 1 and 2001 bytes in a single message, then sends a checksum and starts sending a new randomly sized and fragmented message. The fraggle test client receives the same message fragments and computes the same checksum using websocket framing to see when the message has ended. It then accepts the server checksum message and compares that to its checksum. proxy support ------------- The http_proxy environment variable is respected by the client connection code for both `ws://` and `wss://`. It doesn't support authentication. You use it like this ```bash $ export http_proxy=myproxy.com:3128 $ libwebsockets-test-client someserver.com ``` debug logging ------------- By default logging of severity "notice", "warn" or "err" is enabled to stderr. Again by default other logging is compiled in but disabled from printing. If you want to eliminate the debug logging below notice in severity, use the `--disable-debug` configure option to have it removed from the code by the preprocesser. If you want to see more detailed debug logs, you can control a bitfield to select which logs types may print using the `lws_set_log_level()` api, in the test apps you can use `-d <number>` to control this. The types of logging available are (OR together the numbers to select multiple) - 1 ERR - 2 WARN - 4 NOTICE - 8 INFO - 16 DEBUG - 32 PARSER - 64 HEADER - 128 EXTENSION - 256 CLIENT - 512 LATENCY Websocket version supported --------------------------- The final IETF standard is supported for both client and server, protocol version 13. Latency Tracking ---------------- Since libwebsockets runs using `poll()` and a single threaded approach, any unexpected latency coming from system calls would be bad news. There's now a latency tracking scheme that can be built in with `--with-latency` at configure-time, logging the time taken for system calls to complete and if the whole action did complete that time or was deferred. You can see the detailed data by enabling logging level 512 (eg, `-d 519` on the test server to see that and the usual logs), however even without that the "worst" latency is kept and reported to the logs with NOTICE severity when the context is destroyed. Some care is needed interpreting them, if the action completed the first figure (in us) is the time taken for the whole action, which may have retried through the poll loop many times and will depend on network roundtrip times. High figures here don't indicate a problem. The figure in us reported after "lat" in the logging is the time taken by this particular attempt. High figures here may indicate a problem, or if you system is loaded with another app at that time, such as the browser, it may simply indicate the OS gave preferential treatment to the other app during that call. Autobahn Test Suite ------------------- Lws can be tested against the autobahn websocket fuzzer. 1) pip install autobahntestsuite 2) wstest -m fuzzingserver 3) Run tests like this libwebsockets-test-echo --client localhost --port 9001 -u "/runCase?case=20&agent=libwebsockets" -v -d 65535 -n 1 (this runs test 20) 4) In a browser, go here http://localhost:8080/test_browser.html fill in "libwebsockets" in "User Agent Identifier" and press "Update Reports (Manual)" 5) In a browser go to the directory you ran wstest in (eg, /projects/libwebsockets) file:///projects/libwebsockets/reports/clients/index.html to see the results Autobahn Test Notes ------------------- 1) Autobahn tests the user code + lws implementation. So to get the same results, you need to follow test-echo.c in terms of user implmentation. 2) Some of the tests make no sense for Libwebsockets to support and we fail them. - Tests 2.10 + 2.11: sends multiple pings on one connection. Lws policy is to only allow one active ping in flight on each connection, the rest are dropped. The autobahn test itself admits this is not part of the standard, just someone's random opinion about how they think a ws server should act. So we will fail this by design and it is no problem about RFC6455 compliance. |
Added undroid/libwebsockets/appveyor.yml.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
environment: matrix: - LWS_METHOD: lwsws CMAKE_ARGS: -DLWS_WITH_LWSWS=1 -DLIBUV_INCLUDE_DIRS=C:\assets\libuv\include -DLIBUV_LIBRARIES=C:\assets\libuv\libuv.lib - LWS_METHOD: default - LWS_METHOD: noserver CMAKE_ARGS: -DLWS_WITHOUT_SERVER=ON - LWS_METHOD: noclient CMAKE_ARGS: -DLWS_WITHOUT_CLIENT=ON - LWS_METHOD: noext CMAKE_ARGS: -DLWS_WITHOUT_EXTENSIONS=ON - LWS_METHOD: nossl CMAKE_ARGS: -DLWS_WITH_SSL=OFF install: - appveyor DownloadFile https://libwebsockets.org:444/win-libuv.zip - mkdir c:\assets - mkdir c:\assets\libuv - 7z x -oc:\assets\libuv win-libuv.zip # - appveyor DownloadFile https://slproweb.com/download/Win32OpenSSL-1_0_2h.exe - appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2h.exe - Win32OpenSSL-1_0_2h.exe /silent /verysilent /sp- /suppressmsgboxes - appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe - cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis - SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;c:\nsis;%PATH% build: build_script: - md build - cd build - cmake -DCMAKE_BUILD_TYPE=Release %CMAKE_ARGS% .. - cmake --build . --config Release # TODO: Keeps breaking Windows build, should be rewritten using CPack properly instead... #after_build: # - cd .. # - cd win32port # - makensis -DVERSION=%APPVEYOR_BUILD_VERSION% libwebsockets.nsi artifacts: - name: Installer path: 'win32port/libwebsockets-*-install.exe' cache: - C:\OpenSSL-Win32 matrix: fast_finish: true |
Added undroid/libwebsockets/autobahn-test.sh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#!/bin/sh N=1 for i in '1.1.1' '1.1.2' '1.1.3' '1.1.4' '1.1.5' '1.1.6' '1.1.7' '1.1.8' '1.2.1' '1.2.2' '1.2.3' '1.2.4' '1.2.5' '1.2.6' '1.2.7' '1.2.8' '2.1' '2.2' '2.3' '2.4' '2.5' '2.6' '2.7' '2.8' '2.9' '2.10' '2.11' '3.1' '3.2' '3.3' '3.4' '3.5' '3.6' '3.7' '4.1.1' '4.1.2' '4.1.3' '4.1.4' '4.1.5' '4.2.1' '4.2.2' '4.2.3' '4.2.4' '4.2.5' '5.1' '5.2' '5.3' '5.4' '5.5' '5.6' '5.7' '5.8' '5.9' '5.10' '5.11' '5.12' '5.13' '5.14' '5.15' '5.16' '5.17' '5.18' '5.19' '5.20' '6.1.1' '6.1.2' '6.1.3' '6.2.1' '6.2.2' '6.2.3' '6.2.4' '6.3.1' '6.3.2' '6.4.1' '6.4.2' '6.4.3' '6.4.4' '6.5.1' '6.5.2' '6.5.3' '6.5.4' '6.5.5' '6.6.1' '6.6.2' '6.6.3' '6.6.4' '6.6.5' '6.6.6' '6.6.7' '6.6.8' '6.6.9' '6.6.10' '6.6.11' '6.7.1' '6.7.2' '6.7.3' '6.7.4' '6.8.1' '6.8.2' '6.9.1' '6.9.2' '6.9.3' '6.9.4' '6.10.1' '6.10.2' '6.10.3' '6.11.1' '6.11.2' '6.11.3' '6.11.4' '6.11.5' '6.12.1' '6.12.2' '6.12.3' '6.12.4' '6.12.5' '6.12.6' '6.12.7' '6.12.8' '6.13.1' '6.13.2' '6.13.3' '6.13.4' '6.13.5' '6.14.1' '6.14.2' '6.14.3' '6.14.4' '6.14.5' '6.14.6' '6.14.7' '6.14.8' '6.14.9' '6.14.10' '6.15.1' '6.16.1' '6.16.2' '6.16.3' '6.17.1' '6.17.2' '6.17.3' '6.17.4' '6.17.5' '6.18.1' '6.18.2' '6.18.3' '6.18.4' '6.18.5' '6.19.1' '6.19.2' '6.19.3' '6.19.4' '6.19.5' '6.20.1' '6.20.2' '6.20.3' '6.20.4' '6.20.5' '6.20.6' '6.20.7' '6.21.1' '6.21.2' '6.21.3' '6.21.4' '6.21.5' '6.21.6' '6.21.7' '6.21.8' '6.22.1' '6.22.2' '6.22.3' '6.22.4' '6.22.5' '6.22.6' '6.22.7' '6.22.8' '6.22.9' '6.22.10' '6.22.11' '6.22.12' '6.22.13' '6.22.14' '6.22.15' '6.22.16' '6.22.17' '6.22.18' '6.22.19' '6.22.20' '6.22.21' '6.22.22' '6.22.23' '6.22.24' '6.22.25' '6.22.26' '6.22.27' '6.22.28' '6.22.29' '6.22.30' '6.22.31' '6.22.32' '6.22.33' '6.22.34' '6.23.1' '6.23.2' '6.23.3' '6.23.4' '6.23.5' '6.23.6' '6.23.7' '7.1.1' '7.1.2' '7.1.3' '7.1.4' '7.1.5' '7.1.6' '7.3.1' '7.3.2' '7.3.3' '7.3.4' '7.3.5' '7.3.6' '7.5.1' '7.7.1' '7.7.2' '7.7.3' '7.7.4' '7.7.5' '7.7.6' '7.7.7' '7.7.8' '7.7.9' '7.7.10' '7.7.11' '7.7.12' '7.7.13' '7.9.1' '7.9.2' '7.9.3' '7.9.4' '7.9.5' '7.9.6' '7.9.7' '7.9.8' '7.9.9' '7.9.10' '7.9.11' '7.9.12' '7.9.13' '7.13.1' '7.13.2' '9.1.1' '9.1.2' '9.1.3' '9.1.4' '9.1.5' '9.1.6' '9.2.1' '9.2.2' '9.2.3' '9.2.4' '9.2.5' '9.2.6' '9.3.1' '9.3.2' '9.3.3' '9.3.4' '9.3.5' '9.3.6' '9.3.7' '9.3.8' '9.3.9' '9.4.1' '9.4.2' '9.4.3' '9.4.4' '9.4.5' '9.4.6' '9.4.7' '9.4.8' '9.4.9' '9.5.1' '9.5.2' '9.5.3' '9.5.4' '9.5.5' '9.5.6' '9.6.1' '9.6.2' '9.6.3' '9.6.4' '9.6.5' '9.6.6' '9.7.1' '9.7.2' '9.7.3' '9.7.4' '9.7.5' '9.7.6' '9.8.1' '9.8.2' '9.8.3' '9.8.4' '9.8.5' '9.8.6' '10.1.1' '12.1.1' '12.1.2' '12.1.3' '12.1.4' '12.1.5' '12.1.6' '12.1.7' '12.1.8' '12.1.9' '12.1.10' '12.1.11' '12.1.12' '12.1.13' '12.1.14' '12.1.15' '12.1.16' '12.1.17' '12.1.18' '12.2.1' '12.2.2' '12.2.3' '12.2.4' '12.2.5' '12.2.6' '12.2.7' '12.2.8' '12.2.9' '12.2.10' '12.2.11' '12.2.12' '12.2.13' '12.2.14' '12.2.15' '12.2.16' '12.2.17' '12.2.18' '12.3.1' '12.3.2' '12.3.3' '12.3.4' '12.3.5' '12.3.6' '12.3.7' '12.3.8' '12.3.9' '12.3.10' '12.3.11' '12.3.12' '12.3.13' '12.3.14' '12.3.15' '12.3.16' '12.3.17' '12.3.18' '12.4.1' '12.4.2' '12.4.3' '12.4.4' '12.4.5' '12.4.6' '12.4.7' '12.4.8' '12.4.9' '12.4.10' '12.4.11' '12.4.12' '12.4.13' '12.4.14' '12.4.15' '12.4.16' '12.4.17' '12.4.18' '12.5.1' '12.5.2' '12.5.3' '12.5.4' '12.5.5' '12.5.6' '12.5.7' '12.5.8' '12.5.9' '12.5.10' '12.5.11' '12.5.12' '12.5.13' '12.5.14' '12.5.15' '12.5.16' '12.5.17' '12.5.18' '13.1.1' '13.1.2' '13.1.3' '13.1.4' '13.1.5' '13.1.6' '13.1.7' '13.1.8' '13.1.9' '13.1.10' '13.1.11' '13.1.12' '13.1.13' '13.1.14' '13.1.15' '13.1.16' '13.1.17' '13.1.18' '13.2.1' '13.2.2' '13.2.3' '13.2.4' '13.2.5' '13.2.6' '13.2.7' '13.2.8' '13.2.9' '13.2.10' '13.2.11' '13.2.12' '13.2.13' '13.2.14' '13.2.15' '13.2.16' '13.2.17' '13.2.18' '13.3.1' '13.3.2' '13.3.3' '13.3.4' '13.3.5' '13.3.6' '13.3.7' '13.3.8' '13.3.9' '13.3.10' '13.3.11' '13.3.12' '13.3.13' '13.3.14' '13.3.15' '13.3.16' '13.3.17' '13.3.18' '13.4.1' '13.4.2' '13.4.3' '13.4.4' '13.4.5' '13.4.6' '13.4.7' '13.4.8' '13.4.9' '13.4.10' '13.4.11' '13.4.12' '13.4.13' '13.4.14' '13.4.15' '13.4.16' '13.4.17' '13.4.18' '13.5.1' '13.5.2' '13.5.3' '13.5.4' '13.5.5' '13.5.6' '13.5.7' '13.5.8' '13.5.9' '13.5.10' '13.5.11' '13.5.12' '13.5.13' '13.5.14' '13.5.15' '13.5.16' '13.5.17' '13.5.18' '13.6.1' '13.6.2' '13.6.3' '13.6.4' '13.6.5' '13.6.6' '13.6.7' '13.6.8' '13.6.9' '13.6.10' '13.6.11' '13.6.12' '13.6.13' '13.6.14' '13.6.15' '13.6.16' '13.6.17' '13.6.18' '13.7.1' '13.7.2' '13.7.3' '13.7.4' '13.7.5' '13.7.6' '13.7.7' '13.7.8' '13.7.9' '13.7.10' '13.7.11' '13.7.12' '13.7.13' '13.7.14' '13.7.15' '13.7.16' '13.7.17' '13.7.18' ; do libwebsockets-test-echo --client localhost --port 9001 -u "/runCase?case=$N&agent=libwebsockets" -v -n 1 & C=99 while [ $C -gt 8 ] ; do C=`ps fax | grep libwebsockets-test-echo | wc -l` if [ $C -gt 8 ] ; then sleep 1s fi done N=$(( $N + 1 )) done echo "waiting for forks to complete..." while [ 1 ] ; do n=`ps fax | grep libwebsocket | grep -v grep | wc -l` echo "$n forks running..." if [ $n -eq 0 ] ; then echo "Completed" exit 0 fi sleep 1s done |
Added undroid/libwebsockets/changelog.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 |
Changelog --------- v2.0.3 ====== NB New api lws_snprintf() -> SONAME bump to 8.1 Fixes ----- 1) Remove duplicate close in one error path 2) Build fix for ecdh and non-openssl 3) Client confirms server cert 4) SNI falls back to match wildcard DNS names (this is later checked against the cert for actual validity at SSL level) 5) Fix one error path on vhost adopt_socket where we are left on timeout list 6) lws_snprintf() - fix critical problem with snprintf not truncating buffer lengths (it truncated the buffer write) as (wrongly) expected v2.0.2 ====== Fixes ----- 1) Fix possible pthread mutex leak 2) Make sure ACCESS_LOG can't touch freed area 3) extra options in lwsws conf for cipher list and ecdh curve 4) extra options in lwsws conf for extra mimetypes 5) fix default rxbuf trimming for output 6) lwsl_timestamp month number was off-by-one 7) fix daemonize.c v2.0.1 ====== Fixes ----- 1) OpenSSL version tests not needed on LibreSSL and BoringSSL 2) Fix IPV6 build breakage 3) Some fixes for WinCE build 4) Additional canned mimetypes for mounts, the full list is .ico image/x-icon .gif image/gif .js text/javascript .png image/png .jpg image/jpeg .gz application/gzip .JPG image/jpeg .html text/html .css text/css .txt text/plain .ttf application/x-font-ttf .woff application/font-woff .xml application/xml 5) Allow per-vhost setting of which protocol should get used when the protocol: header is not sent by the client 6) MINOR: user_space arg was mistakenly NULL on LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER 7) MINOR: treating recv() returning 0 as peer close destroyed throughput on ab tests, reverted 8) MINOR: %3d on URL part was always turned to _... this should only happen in ?na%3dme=x part of the URL 9) MINOR: some malloc escaped check for NULL / OOM 10) MINOR: libuv cleanups and client connections can operate correctly with libuv 11) MINOR: POST used to hang up the connection when the body had all arrived. Change it so you can reply with a 200 directly rather than requiring a redirect 12) MINOR: API docs were a little behind the docs in the code v2.0.0 ====== Summary ------- - There are only api additions, the api is compatible with v1.7.x. But there is necessarily an soname bump to 8. - If you are using lws client, you mainly need to be aware the option LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT is needed at context-creation time if you will use SSL. - If you are using lws for serving, the above is also true but there are many new features to simplify your code (and life). There is a summany online here https://libwebsockets.org/lws-2.0-new-features.html but basically the keywords are vhosts, mounts and plugins. You can now do the web serving part from lws without any user callback code at all. See ./test-server/test-server-v2.0.c for an example, it has no user code for ws either since it uses the protocol plugins... that one C file is all that is needed to do the whole test server function. You now have the option to use a small generic ws-capable webserver "lwsws" and write your ws part as a plugin. That eliminates even cut-and-pasting the test server code and offers more configurable features like control over http cacheability in JSON. Fixes ----- These are already in 1.7.x series 1) MAJOR (Windows-only) fix assert firing 2) MAJOR http:/1.1 connections handled by lws_return_http_status() did not get sent a content-length resulting in the link hanging until the peer closed it. attack.sh updated to add a test for this. 3) MINOR An error about hdr struct in _lws_ws_related is corrected, it's not known to affect anything until after it was fixed 4) MINOR During the close shutdown wait state introduced at v1.7, if something requests callback on writeable for the socket it will busywait until the socket closes 5) MAJOR Although the test server has done it for a few versions already, it is now required for the user code to explicitly call if (lws_http_transaction_completed(wsi)) return -1; when it finishes replying to a transaction in http. Previously the library did it for you, but that disallowed large, long transfers with multiple trips around the event loop (and cgi...). 6) MAJOR connections on ah waiting list that closed did not get removed from the waiting list... 7) MAJOR since we added the ability to hold an ah across http keepalive transactions where more headers had already arrived, we broke the ability to tell if more headers had arrived. Result was if the browser didn't close the keepalive, we retained ah for the lifetime of the keepalive, using up the pool. 8) MAJOR windows-only-POLLHUP was not coming 9) Client should not send ext hdr if no exts Changes ------- 1) MINOR test-server gained some new switches -C <file> use external SSL cert file -K <file> use external SSL key file -A <file> use external SSL CA cert file -u <uid> set effective uid -g <gid> set effective gid together you can use them like this to have the test-server work with the usual purchased SSL certs from an official CA. --ssl -C your.crt -K your.key -A your.cer -u 99 -g 99 2) MINOR the OpenSSL magic to setup ECDH cipher usage is implemented in the library, and the ciphers restricted to use ECDH only. Using this, the lws test server can score an A at SSLLABS test 3) MINOR STS (SSL always) header is added to the test server if you use --ssl. With that, we score A+ at SSLLABS test 4) MINOR daemonize function (disabled at cmake by default) is updated to work with systemd 5) MINOR example systemd .service file now provided for test server (not installed by default) 6) test server html is updated with tabs and a new live server monitoring feature. Input sanitization added to the js. 7) client connections attempted when no ah is free no longer fail, they are just deferred until an ah becomes available. 8) The test client pays attention to if you give it an http:/ or https:// protocol string to its argument in URL format. If so, it stays in http[s] client mode and doesn't upgrade to ws[s], allowing you to do generic http client operations. Receiving transfer-encoding: chunked is supported. 9) If you enable -DLWS_WITH_HTTP_PROXY=1 at cmake, the test server has a new URI path http://localhost:7681/proxytest If you visit here, a client connection to http://example.com:80 is spawned, and the results piped on to your original connection. 10) Also with LWS_WITH_HTTP_PROXY enabled at cmake, lws wants to link to an additional library, "libhubbub". This allows lws to do html rewriting on the fly, adjusting proxied urls in a lightweight and fast way. 11) There's a new context creation flag LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT, this is included automatically if you give any other SSL-related option flag. If you give no SSL-related option flag, nor this one directly, then even though SSL support may be compiled in, it is never initialized nor used for the whole lifetime of the lws context. Conversely in order to prepare the context to use SSL, even though, eg, you are not listening on SSL but will use SSL client connections later, you must give this flag explicitly to make sure SSL is initialized. User API additions ------------------ 1) MINOR APIBREAK There's a new member in struct lws_context_creation_info, ecdh_curve, which lets you set the name of the ECDH curve OpenSSL should use. By default (if you leave ecdh_curve NULL) it will use "prime256v1" 2) MINOR NEWAPI It was already possible to adopt a foreign socket that had not been read from using lws_adopt_socket() since v1.7. Now you can adopt a partially-used socket if you don't need SSL, by passing it what you read so it can drain that before reading from the socket. LWS_VISIBLE LWS_EXTERN struct lws * lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, const char *readbuf, size_t len); 3) MINOR NEWAPI CGI type "network io" subprocess execution is now possible from a simple api. LWS_VISIBLE LWS_EXTERN int lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, int timeout_secs); LWS_VISIBLE LWS_EXTERN int lws_cgi_kill(struct lws *wsi); To use it, you must first set the cmake option $ cmake .. -DLWS_WITH_CGI=1 See test-server-http.c and test server path http://localhost:7681/cgitest stdin gets http body, you can test it with wget $ echo hello > hello.txt $ wget http://localhost:7681/cgitest --post-file=hello.txt -O- --quiet lwstest script read="hello" The test script returns text/html table showing /proc/meminfo. But the cgi support is complete enough to run cgit cgi. 4) There is a helper api for forming logging timestamps LWS_VISIBLE int lwsl_timestamp(int level, char *p, int len) this generates this kind of timestamp for use as logging preamble lwsts[13116]: [2016/01/25 14:52:52:8386] NOTICE: Initial logging level 7 5) struct lws_client_connect_info has a new member const char *method If it's NULL, then everything happens as before, lws_client_connect_via_info() makes a ws or wss connection to the address given. If you set method to a valid http method like "GET", though, then this method is used and the connection remains in http[s], it's not upgraded to ws[s]. So with this, you can perform http[s] client operations as well as ws[s] ones. There are 4 new related callbacks LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP = 44, LWS_CALLBACK_CLOSED_CLIENT_HTTP = 45, LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46, LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47, 6) struct lws_client_connect_info has a new member const char *parent_wsi if non-NULL, the client wsi is set to be a child of parent_wsi. This ensures if parent_wsi closes, then the client child is closed just before. 7) If you're using SSL, there's a new context creation-time option flag LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS. If you give this, non-ssl connections to the server listen port are accepted and receive a 301 redirect to / on the same host and port using https:// 8) User code may set per-connection extension options now, using a new api "lws_set_extension_option()". This should be called from the ESTABLISHED callback like this lws_set_extension_option(wsi, "permessage-deflate", "rx_buf_size", "12"); /* 1 << 12 */ If the extension is not active (missing or not negotiated for the connection, or extensions are disabled on the library) the call is just returns -1. Otherwise the connection's extension has its named option changed. The extension may decide to alter or disallow the change, in the example above permessage-deflate restricts the size of his rx output buffer also considering the protocol's rx_buf_size member. New application lwsws --------------------- A libwebsockets-based general webserver is built by default now, lwsws. It's configured by JSON, by default in /etc/lwsws/conf which contains global lws context settings like this { "global": { "uid": "99", "gid": "99", "interface": "eth0", "count-threads": "1" } } /etc/lwsws/conf.d/* which contains zero or more files describing vhosts, like this { "vhosts": [ { "name": "warmcat.com", "port": "443", "host-ssl-key": "/etc/pki/tls/private/warmcat.com.key", "host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt", "host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer", "mounts": [ { "/": [ { "home": "file:///var/www/warmcat.com" }, { "default": "index.html" } ] } ] } ] } v1.7.0 ====== Extension Changes ----------------- 1) There is now a "permessage-deflate" / RFC7692 implementation. It's very similar to "deflate-frame" we have offered for a long while; deflate-frame is now provided as an alias of permessage-deflate. The main differences are that the new permessage-deflate implementation: - properly performs streaming respecting input and output buffer limits. The old deflate-frame implementation could only work on complete deflate input and produce complete inflate output for each frame. The new implementation only mallocs buffers at initialization. - goes around the event loop after each input package is processed allowing interleaved output processing. The RX flow control api can be used to force compressed input processing to match the rate of compressed output processing (test--echo shows an example of how to do this). - when being "deflate-frame" for compatibility he uses the same default zlib settings as the old "deflate-frame", but instead of exponentially increasing malloc allocations until the whole output will fit, he observes the default input and output chunking buffer sizes of "permessage-deflate", that's 1024 in and 1024 out at a time. 2) deflate-stream has been disabled for many versions (for over a year) and is now removed. Browsers are now standardizing on "permessage-deflate" / RFC7692 3) struct lws_extension is simplified, and lws extensions now have a public api (their callback) for use in user code to compose extensions and options the user code wants. lws_get_internal_exts() is deprecated but kept around as a NOP. The changes allow one extension implementation to go by different names and allows the user client code to control option offers per-ext. The test client and server are updated to use the new way. If you use the old way it should still work, but extensions will be disabled until you update your code. Extensions are now responsible for allocating and per-instance private struct at instance construction time and freeing it when the instance is destroyed. Not needing to know the size means the extension's struct can be opaque to user code. User api additions ------------------ 1) The info struct gained three new members - max_http_header_data: 0 for default (1024) or set the maximum amount of known http header payload that lws can deal with. Payload in unknown http headers is dropped silently. If for some reason you need to send huge cookies or other HTTP-level headers, you can now increase this at context- creation time. - max_http_header_pool: 0 for default (16) or set the maximum amount of http headers that can be tracked by lws in this context. For the server, if the header pool is completely in use then accepts on the listen socket are disabled until one becomes free. For the client, if you simultaneously have pending connects for more than this number of client connections, additional connects will fail until some of the pending connections timeout or complete. - timeout_secs: 0 for default (currently 20s), or set the library's network activity timeout to the given number of seconds HTTP header processing in lws only exists until just after the first main callback after the HTTP handshake... for ws connections that is ESTABLISHED and for HTTP connections the HTTP callback. So these settings are not related to the maximum number of simultaneous connections, but the number of HTTP handshakes that may be expected or ongoing, or have just completed, at one time. The reason it's useful is it changes the memory allocation for header processing to be one-time at context creation instead of every time there is a new connection, and gives you control over the peak allocation. Setting max_http_header_pool to 1 is fine it will just queue incoming connections before the accept as necessary, you can still have as many simultaneous post-header connections as you like. Since the http header processing is completed and the allocation released after ESTABLISHED or the HTTP callback, even with a pool of 1 many connections can be handled rapidly. 2) There is a new callback that allows the user code to get acccess to the optional close code + aux data that may have been sent by the peer. LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: The peer has sent an unsolicited Close WS packet. @in and @len are the optional close code (first 2 bytes, network order) and the optional additional information which is not defined in the standard, and may be a string or non-human- readble data. If you return 0 lws will echo the close and then close the connection. If you return nonzero lws will just close the connection. As usual not handling it does the right thing, if you're not interested in it just ignore it. The test server has "open and close" testing buttons at the bottom, if you open and close that connection, on close it will send a close code 3000 decimal and the string "Bye!" as the aux data. The test server dumb-increment callback handles this callback reason and prints lwsts[15714]: LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: len 6 lwsts[15714]: 0: 0x0B lwsts[15714]: 1: 0xB8 lwsts[15714]: 2: 0x42 lwsts[15714]: 3: 0x79 lwsts[15714]: 4: 0x65 lwsts[15714]: 5: 0x21 3) There is a new API to allow the user code to control the content of the close frame sent when about to return nonzero from the user callback to indicate the connection should close. /** * lws_close_reason - Set reason and aux data to send with Close packet * If you are going to return nonzero from the callback * requesting the connection to close, you can optionally * call this to set the reason the peer will be told if * possible. * * @wsi: The websocket connection to set the close reason on * @status: A valid close status from websocket standard * @buf: NULL or buffer containing up to 124 bytes of auxiliary data * @len: Length of data in @buf to send */ LWS_VISIBLE LWS_EXTERN void lws_close_reason(struct lws *wsi, enum lws_close_status status, unsigned char *buf, size_t len); An extra button is added to the "open and close" test server page that requests that the test server close the connection from his end. The test server code will do so by lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *)"seeya", 5); return -1; The browser shows the close code and reason he received websocket connection CLOSED, code: 1001, reason: seeya 4) There's a new context creation time option flag LWS_SERVER_OPTION_VALIDATE_UTF8 if you set it in info->options, then TEXT and CLOSE frames will get checked to confirm that they contain valid UTF-8. If they don't, the connection will get closed by lws. 5) ECDH Certs are now supported. Enable the CMake option cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 **and** the info->options flag LWS_SERVER_OPTION_SSL_ECDH to build in support and select it at runtime. 6) There's a new api lws_parse_uri() that simplifies chopping up https://xxx:yyy/zzz uris into parts nicely. The test client now uses this to allow proper uris as well as the old address style. 7) SMP support is integrated into LWS without any internal threading. It's very simple to use, libwebsockets-test-server-pthread shows how to do it, use -j <n> argument there to control the number of service threads up to 32. Two new members are added to the info struct unsigned int count_threads; unsigned int fd_limit_per_thread; leave them at the default 0 to get the normal singlethreaded service loop. Set count_threads to n to tell lws you will have n simultaneous service threads operating on the context. There is still a single listen socket on one port, no matter how many service threads. When a connection is made, it is accepted by the service thread with the least connections active to perform load balancing. The user code is responsible for spawning n threads running the service loop associated to a specific tsi (Thread Service Index, 0 .. n - 1). See the libwebsockets-test-server-pthread for how to do. If you leave fd_limit_per_thread at 0, then the process limit of fds is shared between the service threads; if you process was allowed 1024 fds overall then each thread is limited to 1024 / n. You can set fd_limit_per_thread to a nonzero number to control this manually, eg the overall supported fd limit is less than the process allowance. You can control the context basic data allocation for multithreading from Cmake using -DLWS_MAX_SMP=, if not given it's set to 32. The serv_buf allocation for the threads (currently 4096) is made at runtime only for active threads. Because lws will limit the requested number of actual threads supported according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to discover how many threads were actually allowed when the context was created. It's required to implement locking in the user code in the same way that libwebsockets-test-server-pthread does it, for the FD locking callbacks. If LWS_MAX_SMP=1, then there is no code related to pthreads compiled in the library. If more than 1, a small amount of pthread mutex code is built into the library. 8) New API LWS_VISIBLE struct lws * lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd) allows foreign sockets accepted by non-lws code to be adopted by lws as if they had just been accepted by lws' own listen socket. 9) X-Real-IP: header has been added as WSI_TOKEN_HTTP_X_REAL_IP 10) Libuv support is added, there are new related user apis typedef void (lws_uv_signal_cb_t)(uv_loop_t *l, uv_signal_t *w, int revents); LWS_VISIBLE LWS_EXTERN int lws_uv_sigint_cfg(struct lws_context *context, int use_uv_sigint, lws_uv_signal_cb_t *cb); LWS_VISIBLE LWS_EXTERN int lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi); LWS_VISIBLE void lws_uv_sigint_cb(uv_loop_t *loop, uv_signal_t *watcher, int revents); and CMAKE option LWS_WITH_LIBUV User api changes ---------------- 1) LWS_SEND_BUFFER_POST_PADDING is now 0 and deprecated. You can remove it; if you still use it, obviously it does nothing. Old binary code with nonzero LWS_SEND_BUFFER_POST_PADDING is perfectly compatible, the old code just allocated a buffer bigger than the library is going to use. The example apps no longer use LWS_SEND_BUFFER_POST_PADDING. The only path who made use of it was sending with LWS_WRITE_CLOSE ---> 2) Because of lws_close_reason() formalizing handling close frames, LWS_WRITE_CLOSE is removed from libwebsockets.h. It was only of use to send close frames...close frame content should be managed using lws_close_reason() now. 3) We check for invalid CLOSE codes and complain about protocol violation in our close code. But it changes little since we were in the middle of closing anyway. 4) zero-length RX frames and zero length TX frames are now allowed. 5) Pings and close used to be limited to 124 bytes, the correct limit is 125 so that is now also allowed. 6) LWS_PRE is provided as a synonym for LWS_SEND_BUFFER_PRE_PADDING, either is valid to use now. 7) There's generic support for RFC7462 style extension options built into the library now. As a consequence, a field "options" is added to lws_extension. It can be NULL if there are no options on the extension. Extension internal info is part of the public abi because extensions may be implemented outside the library. 8) WSI_TOKEN_PROXY enum was accidentally defined to collide with another token of value 73. That's now corrected and WSI_TOKEN_PROXY moved to his own place at 77. 9) With the addition of libuv support, libev is not the only event loop library in town and his api names must be elaborated with _ev_ Callback typedef: lws_signal_cb ---> lws_ev_signal_cb_t lws_sigint_cfg --> lws_ev_sigint_cfg lws_initloop --> lws_ev_initloop lws_sigint_cb --> lws_ev_sigint_cb 10) Libev support is made compatible with multithreaded service, lws_ev_initloop (was lws_initloop) gets an extra argument for the thread service index (use 0 if you will just have 1 service thread). LWS_VISIBLE LWS_EXTERN int lws_ev_initloop(struct lws_context *context, ev_loop_t *loop, int tsi); v1.6.0-chrome48-firefox42 ======================= Major API improvements ---------------------- v1.6.0 has many cleanups and improvements in the API. Although at first it looks pretty drastic, user code will only need four actions to update it. - Do the three search/replaces in your user code, /libwebsocket_/lws_/, /libwebsockets_/lws_/, and /struct\ libwebsocket/struct\ lws/ - Remove the context parameter from your user callbacks - Remove context as the first parameter from the "Eleven APIS" listed in the User Api Changes section - Add lws_get_context(wsi) as the first parameter on the "Three APIS" listed in the User Api Changes section, and anywhere else you still need context That's it... generally only a handful of the 14 affected APIs are actually in use in your user code and you can find them quickest by compiling and visiting the errors each in turn. And the end results are much cleaner, more predictable and maintainable. User api additions ------------------ 1) lws now exposes his internal platform file abstraction in a way that can be both used by user code to make it platform-agnostic, and be overridden or subclassed by user code. This allows things like handling the URI "directory space" as a virtual filesystem that may or may not be backed by a regular filesystem. One example use is serving files from inside large compressed archive storage without having to unpack anything except the file being requested. The test server shows how to use it, basically the platform-specific part of lws prepares a file operations structure that lives in the lws context. Helpers are provided to also leverage these platform-independent file handling apis static inline lws_filefd_type lws_plat_file_open(struct lws *wsi, const char *filename, unsigned long *filelen, int flags) static inline int lws_plat_file_close(struct lws *wsi, lws_filefd_type fd) static inline unsigned long lws_plat_file_seek_cur(struct lws *wsi, lws_filefd_type fd, long offset) static inline int lws_plat_file_read(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len) static inline int lws_plat_file_write(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len) The user code can also override or subclass the file operations, to either wrap or replace them. An example is shown in test server. A wsi can be associated with the file activity, allowing per-connection authentication and state to be used when interpreting the file request. 2) A new API void * lws_wsi_user(struct lws *wsi) lets you get the pointer to the user data associated with the wsi, just from the wsi. 3) URI argument handling. Libwebsockets parses and protects URI arguments like test.html?arg1=1&arg2=2, it decodes %xx uriencoding format and reduces path attacks like ../.../../etc/passwd so they cannot go behind the web server's /. There is a list of confirmed attacks we're proof against in ./test-server/attack.sh. There is a new API lws_hdr_copy_fragment that should be used now to access the URI arguments (it returns the fragments length) while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_URI_ARGS, n) > 0) { lwsl_info("URI Arg %d: %s\n", ++n, buf); } For the example above, calling with n=0 will return "arg1=1" and n=1 "arg2=2". All legal uriencodings will have been reduced in those strings. lws_hdr_copy_fragment() returns the length of the x=y fragment, so it's also possible to deal with arguments containing %00. If you don't care about that, the returned string has '\0' appended to simplify processing. User api changes ---------------- 1) Three APIS - lws_callback_on_writable_all_protocol(const struct lws_protocols *protocol) - lws_callback_all_protocol(const struct lws_protocols *protocol) - lws_rx_flow_allow_all_protocol(lws_rx_flow_allow_all_protocol) Now take an additional pointer to the lws_context in their first argument. The reason for this change is struct lws_protocols has been changed to remove members that lws used for private storage: so the protocols struct in now truly const and may be reused serially or simultaneously by different contexts. 2) Eleven APIs LWS_VISIBLE LWS_EXTERN int lws_add_http_header_by_name(struct lws_context *context, struct lws *wsi, const unsigned char *name, const unsigned char *value, int length, unsigned char **p, unsigned char *end); LWS_VISIBLE LWS_EXTERN int lws_finalize_http_header(struct lws_context *context, struct lws *wsi, unsigned char **p, unsigned char *end); LWS_VISIBLE LWS_EXTERN int lws_add_http_header_by_token(struct lws_context *context, struct lws *wsi, enum lws_token_indexes token, const unsigned char *value, int length, unsigned char **p, unsigned char *end); LWS_VISIBLE LWS_EXTERN int lws_add_http_header_content_length(struct lws_context *context, struct lws *wsi, unsigned long content_length, unsigned char **p, unsigned char *end); LWS_VISIBLE LWS_EXTERN int lws_add_http_header_status(struct lws_context *context, struct lws *wsi, unsigned int code, unsigned char **p, unsigned char *end); LWS_VISIBLE LWS_EXTERN int lws_serve_http_file(struct lws_context *context, struct lws *wsi, const char *file, const char *content_type, const char *other_headers, int other_headers_len); LWS_VISIBLE LWS_EXTERN int lws_serve_http_file_fragment(struct lws_context *context, struct lws *wsi); LWS_VISIBLE LWS_EXTERN int lws_return_http_status(struct lws_context *context, struct lws *wsi, unsigned int code, const char *html_body); LWS_VISIBLE LWS_EXTERN int lws_callback_on_writable(const struct lws_context *context, struct lws *wsi); LWS_VISIBLE LWS_EXTERN void lws_get_peer_addresses(struct lws_context *context, struct lws *wsi, lws_sockfd_type fd, char *name, int name_len, char *rip, int rip_len); LWS_VISIBLE LWS_EXTERN int lws_read(struct lws_context *context, struct lws *wsi, unsigned char *buf, size_t len); no longer require their initial struct lws_context * parameter. 3) Several older apis start with libwebsocket_ or libwebsockets_ while newer ones all begin lws_. These apis have been changed to all begin with lws_. To convert, search-replace - libwebsockets_/lws_ - libwebsocket_/lws_ - struct\ libwebsocket/struct\ lws 4) context parameter removed from user callback. Since almost all apis no longer need the context as a parameter, it's no longer provided at the user callback directly. However if you need it, for ALL callbacks wsi is valid and has a valid context pointer you can recover using lws_get_context(wsi). v1.5-chrome47-firefox41 ======================= User api changes ---------------- LWS_CALLBACK_CLIENT_CONNECTION_ERROR may provide an error string if in is non-NULL. If so, the string has length len. LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED is available to relax the requirement for peer certs if you are using the option to require client certs. LWS_WITHOUT_BUILTIN_SHA1 cmake option forces lws to use SHA1() defined externally, eg, byOpenSSL, and disables build of libwebsockets_SHA1() v1.4-chrome43-firefox36 ======================= User api additions ------------------ There's a new member in the info struct used to control context creation, ssl_private_key_password, which allows passing into lws the passphrase on an SSL cetificate There's a new member in struct protocols, id, which is ignored by lws but can be used by the user code to mark the selected protocol by user-defined version or capabliity flag information, for the case multiple versions of a protocol are supported. int lws_is_ssl(wsi) added to allow user code to know if the connection was made over ssl or not. If LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT is used, both ssl and non-ssl connections are possible and may need to be treated differently in the user code. int lws_partial_buffered(wsi) added... should be checked after any libwebsocket_write that will be followed by another libwebsocket_write inside the same writeable callback. If set, you can't do any more writes until the writeable callback is called again. If you only do one write per writeable callback, you can ignore this. HTTP2-related: HTTP2 changes how headers are handled, lws now has new version- agnositic header creation APIs. These do the right thing depending on each connection's HTTP version without the user code having to know or care, except to make sure to use the new APIs for headers (test-server is updated to use them already, so look there for examples) The APIs "render" the headers into a user-provided buffer and bump *p as it is used. If *p reaches end, then the APIs return nonzero for error. LWS_VISIBLE LWS_EXTERN int lws_add_http_header_status(struct libwebsocket_context *context, struct libwebsocket *wsi, unsigned int code, unsigned char **p, unsigned char *end); Start a response header reporting status like 200, 500, etc LWS_VISIBLE LWS_EXTERN int lws_add_http_header_by_name(struct libwebsocket_context *context, struct libwebsocket *wsi, const unsigned char *name, const unsigned char *value, int length, unsigned char **p, unsigned char *end); Add a header like name: value in HTTP1.x LWS_VISIBLE LWS_EXTERN int lws_finalize_http_header(struct libwebsocket_context *context, struct libwebsocket *wsi, unsigned char **p, unsigned char *end); Finish off the headers, like add the extra \r\n in HTTP1.x LWS_VISIBLE LWS_EXTERN int lws_add_http_header_by_token(struct libwebsocket_context *context, struct libwebsocket *wsi, enum lws_token_indexes token, const unsigned char *value, int length, unsigned char **p, unsigned char *end); Add a header by using a lws token as the name part. In HTTP2, this can be compressed to one or two bytes. User api removal ---------------- protocols struct member no_buffer_all_partial_tx is removed. Under some conditions like rewriting extension such as compression in use, the built-in partial send buffering is the only way to deal with the problem, so turning it off is deprecated. User api changes ---------------- HTTP2-related: API libwebsockets_serve_http_file() takes an extra parameter at the end now int other_headers_len) If you are providing other headers, they must be generated using the new HTTP-version-agnostic APIs, and you must provide the length of them using this additional parameter. struct lws_context_creation_info now has an additional member SSL_CTX *provided_client_ssl_ctx you may set to an externally-initialized SSL_CTX managed outside lws. Defaulting to zero keeps the existing behaviour of lws managing the context, if you memset the struct to 0 or have as a filescope initialized struct in bss, no need to change anything. v1.3-chrome37-firefox30 ======================= .gitignore | 1 - CMakeLists.txt | 447 +++-- README.build | 35 +- README.coding | 14 + changelog | 66 + cmake/LibwebsocketsConfig.cmake.in | 17 + cmake/LibwebsocketsConfigVersion.cmake.in | 11 + config.h.cmake | 18 + cross-ming.cmake | 31 + cross-openwrt-makefile | 91 + lib/client-handshake.c | 205 ++- lib/client-parser.c | 58 +- lib/client.c | 158 +- lib/context.c | 341 ++++ lib/extension-deflate-frame.c | 2 +- lib/extension.c | 178 ++ lib/handshake.c | 287 +--- lib/lextable.h | 338 ++++ lib/libev.c | 175 ++ lib/libwebsockets.c | 2089 +++-------------------- lib/libwebsockets.h | 253 ++- lib/lws-plat-unix.c | 404 +++++ lib/lws-plat-win.c | 358 ++++ lib/minilex.c | 530 +++--- lib/output.c | 445 ++--- lib/parsers.c | 682 ++++---- lib/pollfd.c | 239 +++ lib/private-libwebsockets.h | 501 +++++- lib/server-handshake.c | 274 +-- lib/server.c | 858 ++++++++-- lib/service.c | 517 ++++++ lib/sha-1.c | 38 +- lib/ssl-http2.c | 78 + lib/ssl.c | 571 +++++++ test-server/attack.sh | 101 +- test-server/test-client.c | 9 +- test-server/test-echo.c | 17 +- test-server/test-fraggle.c | 7 - test-server/test-ping.c | 12 +- test-server/test-server.c | 330 ++-- test-server/test.html | 4 +- win32port/client/client.vcxproj | 259 --- win32port/client/client.vcxproj.filters | 39 - .../libwebsocketswin32.vcxproj.filters | 93 - win32port/server/server.vcxproj | 276 --- win32port/server/server.vcxproj.filters | 51 - win32port/win32helpers/gettimeofday.h | 59 +- win32port/win32helpers/netdb.h | 1 - win32port/win32helpers/strings.h | 0 win32port/win32helpers/sys/time.h | 1 - win32port/win32helpers/unistd.h | 0 win32port/win32helpers/websock-w32.c | 104 -- win32port/win32helpers/websock-w32.h | 62 - win32port/win32port.sln | 100 -- win32port/zlib/gzio.c | 3 +- 55 files changed, 6779 insertions(+), 5059 deletions(-) User api additions ------------------ POST method is supported The protocol 0 / HTTP callback can now get two new kinds of callback, LWS_CALLBACK_HTTP_BODY (in and len are a chunk of the body of the HTTP request) and LWS_CALLBACK_HTTP_BODY_COMPLETION (the expected amount of body has arrived and been passed to the user code already). These callbacks are used with the post method (see the test server for details). The period between the HTTP header completion and the completion of the body processing is protected by a 5s timeout. The chunks are stored in a malloc'd buffer of size protocols[0].rx_buffer_size. New server option you can enable from user code LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT allows non-SSL connections to also be accepted on an SSL listening port. It's disabled unless you enable it explicitly. Two new callbacks are added in protocols[0] that are optional for allowing limited thread access to libwebsockets, LWS_CALLBACK_LOCK_POLL and LWS_CALLBACK_UNLOCK_POLL. If you use them, they protect internal and external poll list changes, but if you want to use external thread access to libwebsocket_callback_on_writable() you have to implement your locking here even if you don't use external poll support. If you will use another thread for this, take a lot of care about managing your list of live wsi by doing it from ESTABLISHED and CLOSED callbacks (with your own locking). If you configure cmake with -DLWS_WITH_LIBEV=1 then the code allowing the libev eventloop instead of the default poll() one will also be compiled in. But to use it, you must also set the LWS_SERVER_OPTION_LIBEV flag on the context creation info struct options member. IPV6 is supported and enabled by default except for Windows, you can disable the support at build-time by giving -DLWS_IPV6=, and disable use of it even if compiled in by making sure the flag LWS_SERVER_OPTION_DISABLE_IPV6 is set on the context creation info struct options member. You can give LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS option flag to guarantee the OS CAs will not be used, even if that support was selected at build-time. Optional "token limits" may be enforced by setting the member "token_limits" in struct lws_context_creation_info to point to a struct lws_token_limits. NULL means no token limits used for compatibility. User api changes ---------------- Extra optional argument to libwebsockets_serve_http_file() allows injecion of HTTP headers into the canned response. Eg, cookies may be added like that without getting involved in having to send the header by hand. A new info member http_proxy_address may be used at context creation time to set the http proxy. If non-NULL, it overrides http_proxy environment var. Cmake supports LWS_SSL_CLIENT_USE_OS_CA_CERTS defaulting to on, which gets the client to use the OS CA Roots. If you're worried somebody with the ability to forge for force creation of a client cert from the root CA in your OS, you should disable this since your selfsigned $0 cert is a lot safer then... v1.23-chrome32-firefox24 ======================== Android.mk | 29 + CMakeLists.txt | 573 ++++++++---- COPYING | 503 ----------- INSTALL | 365 -------- Makefile.am | 13 - README.build | 371 ++------ README.coding | 63 ++ autogen.sh | 1578 --------------------------------- changelog | 69 ++ cmake/FindGit.cmake | 163 ++++ cmake/FindOpenSSLbins.cmake | 15 +- cmake/UseRPMTools.cmake | 176 ++++ config.h.cmake | 25 +- configure.ac | 226 ----- cross-arm-linux-gnueabihf.cmake | 28 + lib/Makefile.am | 89 -- lib/base64-decode.c | 98 +- lib/client-handshake.c | 123 ++- lib/client-parser.c | 19 +- lib/client.c | 145 ++- lib/daemonize.c | 4 +- lib/extension.c | 2 +- lib/getifaddrs.h | 4 +- lib/handshake.c | 76 +- lib/libwebsockets.c | 491 ++++++---- lib/libwebsockets.h | 164 ++-- lib/output.c | 214 ++++- lib/parsers.c | 102 +-- lib/private-libwebsockets.h | 66 +- lib/server-handshake.c | 5 +- lib/server.c | 29 +- lib/sha-1.c | 2 +- libwebsockets-api-doc.html | 249 +++--- libwebsockets.pc.in | 11 - libwebsockets.spec | 14 +- m4/ignore-me | 2 - scripts/FindLibWebSockets.cmake | 33 + scripts/kernel-doc | 1 + test-server/Makefile.am | 131 --- test-server/leaf.jpg | Bin 0 -> 2477518 bytes test-server/test-client.c | 78 +- test-server/test-echo.c | 33 +- test-server/test-fraggle.c | 26 +- test-server/test-ping.c | 15 +- test-server/test-server.c | 197 +++- test-server/test.html | 5 +- win32port/win32helpers/gettimeofday.c | 74 +- win32port/win32helpers/websock-w32.h | 6 +- 48 files changed, 2493 insertions(+), 4212 deletions(-) User api additions ------------------ - You can now call libwebsocket_callback_on_writable() on http connectons, and get a LWS_CALLBACK_HTTP_WRITEABLE callback, the same way you can regulate writes with a websocket protocol connection. - A new member in the context creation parameter struct "ssl_cipher_list" is added, replacing CIPHERS_LIST_STRING. NULL means use the ssl library default list of ciphers. - Not really an api addition, but libwebsocket_service_fd() will now zero the revents field of the pollfd it was called with if it handled the descriptor. So you can tell if it is a non-lws fd by checking revents after the service call... if it's still nonzero, the descriptor belongs to you and you need to take care of it. - libwebsocket_rx_flow_allow_all_protocol(protocol) will unthrottle all connections with the established protocol. It's designed to be called from user server code when it sees it can accept more input and may have throttled connections using the server rx flow apis while it was unable to accept any other input The user server code then does not have to try to track while connections it choked, this will free up all of them in one call. - there's a new, optional callback LWS_CALLBACK_CLOSED_HTTP which gets called when an HTTP protocol socket closes - for LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION callback, the user_space alloc has already been done before the callback happens. That means we can use the user parameter to the callback to contain the user pointer, and move the protocol name to the "in" parameter. The docs for this callback are also updated to reflect how to check headers in there. - libwebsocket_client_connect() is now properly nonblocking and async. See README.coding and test-client.c for information on the callbacks you can rely on controlling the async connection period with. - if your OS does not support the http_proxy environment variable convention (eg, reportedly OSX), you can use a new api libwebsocket_set_proxy() to set the proxy details in between context creation and the connection action. For OSes that support http_proxy, that's used automatically. User api changes ---------------- - the external poll callbacks now get the socket descriptor coming from the "in" parameter. The user parameter provides the user_space for the wsi as it normally does on the other callbacks. LWS_CALLBACK_FILTER_NETWORK_CONNECTION also has the socket descriptor delivered by @in now instead of @user. - libwebsocket_write() now returns -1 for error, or the amount of data actually accepted for send. Under load, the OS may signal it is ready to send new data on the socket, but have only a restricted amount of memory to buffer the packet compared to usual. User api removal ---------------- - libwebsocket_ensure_user_space() is removed from the public api, if you were using it to get user_space, you need to adapt your code to only use user_space inside the user callback. - CIPHERS_LIST_STRING is removed - autotools build has been removed. See README.build for info on how to use CMake for your platform v1.21-chrome26-firefox18 ======================== - Fixes buffer overflow bug in max frame size handling if you used the default protocol buffer size. If you declared rx_buffer_size in your protocol, which is recommended anyway, your code was unaffected. v1.2-chrome26-firefox18 ======================= Diffstat -------- .gitignore | 16 +++ CMakeLists.txt | 544 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 526 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile.am | 1 + README | 20 +++ README.build | 258 ++++++++++++++++++++++++++++++++----- README.coding | 52 ++++++++ changelog | 136 ++++++++++++++++++++ cmake/FindOpenSSLbins.cmake | 33 +++++ config.h.cmake | 173 +++++++++++++++++++++++++ configure.ac | 22 +++- lib/Makefile.am | 20 ++- lib/base64-decode.c | 2 +- lib/client-handshake.c | 190 +++++++++++----------------- lib/client-parser.c | 88 +++++++------ lib/client.c | 384 ++++++++++++++++++++++++++++++------------------------- lib/daemonize.c | 32 +++-- lib/extension-deflate-frame.c | 58 +++++---- lib/extension-deflate-stream.c | 19 ++- lib/extension-deflate-stream.h | 4 +- lib/extension.c | 11 +- lib/getifaddrs.c | 315 +++++++++++++++++++++++----------------------- lib/getifaddrs.h | 30 ++--- lib/handshake.c | 124 +++++++++++------- lib/libwebsockets.c | 736 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------- lib/libwebsockets.h | 237 ++++++++++++++++++++++------------ lib/output.c | 192 +++++++++++----------------- lib/parsers.c | 966 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------- lib/private-libwebsockets.h | 225 +++++++++++++++++++++------------ lib/server-handshake.c | 82 ++++++------ lib/server.c | 96 +++++++------- libwebsockets-api-doc.html | 189 ++++++++++++++++++---------- libwebsockets.spec | 17 +-- test-server/attack.sh | 148 ++++++++++++++++++++++ test-server/test-client.c | 125 +++++++++--------- test-server/test-echo.c | 31 +++-- test-server/test-fraggle.c | 32 ++--- test-server/test-ping.c | 52 ++++---- test-server/test-server.c | 129 ++++++++++++------- win32port/libwebsocketswin32/libwebsocketswin32.vcxproj | 279 ---------------------------------------- win32port/libwebsocketswin32/libwebsocketswin32.vcxproj.filters | 23 +++- 41 files changed, 4398 insertions(+), 2219 deletions(-) User api additions ------------------ - lws_get_library_version() returns a const char * with a string like "1.1 9e7f737", representing the library version from configure.ac and the git HEAD hash the library was built from - TCP Keepalive can now optionally be applied to all lws sockets, on Linux also with controllable timeout, number of probes and probe interval. (On BSD type OS, you can only use system default settings for the timing and retries, although enabling it is supported by setting ka_time to nonzero, the exact value has no meaning.) This enables detection of idle connections which are logically okay, but are in fact dead, due to network connectivity issues at the server, client, or any intermediary. By default it's not enabled, but you can enable it by setting a non-zero timeout (in seconds) at the new ka_time member at context creation time. - Two new optional user callbacks added, LWS_CALLBACK_PROTOCOL_DESTROY which is called one-time per protocol as the context is being destroyed, and LWS_CALLBACK_PROTOCOL_INIT which is called when the context is created and the protocols are added, again it's a one-time affair. This lets you manage per-protocol allocations properly including cleaning up after yourself when the server goes down. User api changes ---------------- - libwebsocket_create_context() has changed from taking a ton of parameters to just taking a pointer to a struct containing the parameters. The struct lws_context_creation_info is in libwebsockets.h, the members are in the same order as when they were parameters to the call previously. The test apps are all updated accordingly so you can see example code there. - Header tokens are now deleted after the websocket connection is established. Not just the header data is saved, but the pointer and length array is also removed from (union) scope saving several hundred bytes per connection once it is established - struct libwebsocket_protocols has a new member rx_buffer_size, this controls rx buffer size per connection of that protocol now. Sources for apps built against older versions of the library won't declare this in their protocols, defaulting it to 0. Zero buffer is legal, it causes a default buffer to be allocated (currently 4096) If you want to receive only atomic frames in your user callback, you should set this to greater than your largest frame size. If a frame comes that exceeds that, no error occurs but the callback happens as soon as the buffer limit is reached, and again if it is reached again or the frame completes. You can detect that has happened by seeing there is still frame content pending using libwebsockets_remaining_packet_payload() By correctly setting this, you can save a lot of memory when your protocol has small frames (see the test server and client sources). - LWS_MAX_HEADER_LEN now defaults to 1024 and is the total amount of known header payload lws can cope with, that includes the GET URL, origin etc. Headers not understood by lws are ignored and their payload not included in this. User api removals ----------------- - The configuration-time option MAX_USER_RX_BUFFER has been replaced by a buffer size chosen per-protocol. For compatibility, there's a default of 4096 rx buffer, but user code should set the appropriate size for the protocol frames. - LWS_INITIAL_HDR_ALLOC and LWS_ADDITIONAL_HDR_ALLOC are no longer needed and have been removed. There's a new header management scheme that handles them in a much more compact way. - libwebsockets_hangup_on_client() is removed. If you want to close the connection you must do so from the user callback and by returning -1 from there. - libwebsocket_close_and_free_session() is now private to the library code only and not exposed for user code. If you want to close the connection, you must do so from the user callback by returning -1 from there. New features ------------ - Cmake project file added, aimed initially at Windows support: this replaces the visual studio project files that were in the tree until now. - CyaSSL now supported in place of OpenSSL (--use-cyassl on configure) - PATH_MAX or MAX_PATH no longer needed - cutomizable frame rx buffer size by protocol - optional TCP keepalive so dead peers can be detected, can be enabled at context-creation time - valgrind-clean: no SSL or CyaSSL: completely clean. With OpenSSL, 88 bytes lost at OpenSSL library init and symptomless reports of uninitialized memory usage... seems to be a known and ignored problem at OpenSSL - By default debug is enabled and the library is built for -O0 -g to faclitate that. Use --disable-debug configure option to build instead with -O4 and no -g (debug info), obviously providing best performance and reduced binary size. - 1.0 introduced some code to try to not deflate small frames, however this seems to break when confronted with a mixture of frames above and below the threshold, so it's removed. Veto the compression extension in your user callback if you will typically have very small frames. - There are many memory usage improvements, both a reduction in malloc/ realloc and architectural changes. A websocket connection now consumes only 296 bytes with SSL or 272 bytes without on x86_64, during header processing an additional 1262 bytes is allocated in a single malloc, but is freed when the websocket connection starts. The RX frame buffer defined by the protocol in user code is also allocated per connection, this represents the largest frame you can receive atomically in that protocol. - On ARM9 build, just http+ws server no extensions or ssl, <12Kbytes .text and 112 bytes per connection (+1328 only during header processing) v1.1-chrome26-firefox18 ======================= Diffstat -------- Makefile.am | 4 + README-test-server | 291 --- README.build | 239 ++ README.coding | 138 ++ README.rst | 72 - README.test-apps | 272 +++ configure.ac | 116 +- lib/Makefile.am | 55 +- lib/base64-decode.c | 5 +- lib/client-handshake.c | 121 +- lib/client-parser.c | 394 ++++ lib/client.c | 807 +++++++ lib/daemonize.c | 212 ++ lib/extension-deflate-frame.c | 132 +- lib/extension-deflate-stream.c | 12 +- lib/extension-x-google-mux.c | 1223 ---------- lib/extension-x-google-mux.h | 96 - lib/extension.c | 8 - lib/getifaddrs.c | 271 +++ lib/getifaddrs.h | 76 + lib/handshake.c | 582 +---- lib/libwebsockets.c | 2493 ++++++--------------- lib/libwebsockets.h | 115 +- lib/md5.c | 217 -- lib/minilex.c | 440 ++++ lib/output.c | 628 ++++++ lib/parsers.c | 2016 +++++------------ lib/private-libwebsockets.h | 284 +-- lib/server-handshake.c | 275 +++ lib/server.c | 377 ++++ libwebsockets-api-doc.html | 300 +-- m4/ignore-me | 2 + test-server/Makefile.am | 111 +- test-server/libwebsockets.org-logo.png | Bin 0 -> 7029 bytes test-server/test-client.c | 45 +- test-server/test-echo.c | 330 +++ test-server/test-fraggle.c | 20 +- test-server/test-ping.c | 22 +- test-server/test-server-extpoll.c | 554 ----- test-server/test-server.c | 349 ++- test-server/test.html | 3 +- win32port/zlib/ZLib.vcxproj | 749 ++++--- win32port/zlib/ZLib.vcxproj.filters | 188 +- win32port/zlib/adler32.c | 348 ++- win32port/zlib/compress.c | 160 +- win32port/zlib/crc32.c | 867 ++++---- win32port/zlib/crc32.h | 882 ++++---- win32port/zlib/deflate.c | 3799 +++++++++++++++----------------- win32port/zlib/deflate.h | 688 +++--- win32port/zlib/gzclose.c | 50 +- win32port/zlib/gzguts.h | 325 ++- win32port/zlib/gzlib.c | 1157 +++++----- win32port/zlib/gzread.c | 1242 ++++++----- win32port/zlib/gzwrite.c | 1096 +++++---- win32port/zlib/infback.c | 1272 ++++++----- win32port/zlib/inffast.c | 680 +++--- win32port/zlib/inffast.h | 22 +- win32port/zlib/inffixed.h | 188 +- win32port/zlib/inflate.c | 2976 +++++++++++++------------ win32port/zlib/inflate.h | 244 +- win32port/zlib/inftrees.c | 636 +++--- win32port/zlib/inftrees.h | 124 +- win32port/zlib/trees.c | 2468 +++++++++++---------- win32port/zlib/trees.h | 256 +-- win32port/zlib/uncompr.c | 118 +- win32port/zlib/zconf.h | 934 ++++---- win32port/zlib/zlib.h | 3357 ++++++++++++++-------------- win32port/zlib/zutil.c | 642 +++--- win32port/zlib/zutil.h | 526 ++--- 69 files changed, 19556 insertions(+), 20145 deletions(-) user api changes ---------------- - libwebsockets_serve_http_file() now takes a context as first argument - libwebsockets_get_peer_addresses() now takes a context and wsi as first two arguments user api additions ------------------ - lwsl_...() logging apis, default to stderr but retargetable by user code; may be used also by user code - lws_set_log_level() set which logging apis are able to emit (defaults to notice, warn, err severities), optionally set the emit callback - lwsl_emit_syslog() helper callback emits to syslog - lws_daemonize() helper code that forks the app into a headless daemon properly, maintains a lock file with pid in suitable for sysvinit etc to control lifecycle - LWS_CALLBACK_HTTP_FILE_COMPLETION callback added since http file transfer is now asynchronous (see test server code) - lws_frame_is_binary() from a wsi pointer, let you know if the received data was sent in BINARY mode user api removals ----------------- - libwebsockets_fork_service_loop() - no longer supported (had intractable problems) arrange your code to act from the user callback instead from same process context as the service loop - libwebsockets_broadcast() - use libwebsocket_callback_on_writable[_all_protocol]() instead from same process context as the service loop. See the test apps for examples. - x-google-mux() removed until someone wants it - pre -v13 (ancient) protocol support removed New features ------------ - echo test server and client compatible with echo.websocket.org added - many new configure options (see README.build) to reduce footprint of the library to what you actually need, eg, --without-client and --without-server - http + websocket server can build to as little as 12K .text for ARM - no more MAX_CLIENTS limitation; adapts to support the max number of fds allowed to the process by ulimit, defaults to 1024 on Fedora and Ubuntu. Use ulimit to control this without needing to configure the library. Code here is smaller and faster. - adaptive ratio of listen socket to connection socket service allows good behaviour under Apache ab test load. Tested with thousands of simultaneous connections - reduction in per-connection memory footprint by moving to a union to hold mutually-exclusive state for the connection - robustness: Out of Memory taken care of for all allocation code now - internal getifaddrs option if your toolchain lacks it (some uclibc) - configurable memory limit for deflate operations - improvements in SSL code nonblocking operation, possible hang solved, some SSL operations broken down into pollable states so there is no library blocking, timeout coverage for SSL_connect - extpoll test server merged into single test server source - robustness: library should deal with all recoverable socket conditions - rx flowcontrol for backpressure notification fixed and implmeneted correctly in the test server - optimal lexical parser added for header processing; all headers in a single 276-byte state table - latency tracking api added (configure --with-latency) - Improved in-tree documentation, REAME.build, README.coding, README.test-apps, changelog - Many small fixes v1.0-chrome25-firefox17 (6cd1ea9b005933f) |
Added undroid/libwebsockets/cmake/FindGit.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
################################################################################ # # Program: 3D Slicer # # Copyright (c) Kitware Inc. # # See COPYRIGHT.txt # or http://www.slicer.org/copyright/copyright.txt for details. # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc. # and was partially funded by NIH grant 3P41RR013218-12S1 # # AG 2013-02-18: I got it from here # https://github.com/Slicer/Slicer/blob/master/CMake/FindGit.cmake # license is BSD # ################################################################################ # # The module defines the following variables: # GIT_EXECUTABLE - path to git command line client # GIT_FOUND - true if the command line client was found # # If the command line client executable is found the macro # GIT_WC_INFO(<dir> <var-prefix>) # is defined to extract information of a git working copy at # a given location. # # The macro defines the following variables: # <var-prefix>_WC_REVISION_HASH - Current SHA1 hash # <var-prefix>_WC_REVISION - Current SHA1 hash # <var-prefix>_WC_REVISION_NAME - Name associated with <var-prefix>_WC_REVISION_HASH # <var-prefix>_WC_URL - output of command `git config --get remote.origin.url' # <var-prefix>_WC_ROOT - Same value as working copy URL # <var-prefix>_WC_GITSVN - Set to false # # ... and also the following ones if it's a git-svn repository: # <var-prefix>_WC_GITSVN - Set to True if it is a # <var-prefix>_WC_INFO - output of command `git svn info' # <var-prefix>_WC_URL - url of the associated SVN repository # <var-prefix>_WC_ROOT - root url of the associated SVN repository # <var-prefix>_WC_REVISION - current SVN revision number # <var-prefix>_WC_LAST_CHANGED_AUTHOR - author of last commit # <var-prefix>_WC_LAST_CHANGED_DATE - date of last commit # <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit # <var-prefix>_WC_LAST_CHANGED_LOG - last log of base revision # # Example usage: # find_package(Git) # if(GIT_FOUND) # GIT_WC_INFO(${PROJECT_SOURCE_DIR} Project) # message("Current revision is ${Project_WC_REVISION_HASH}") # message("git found: ${GIT_EXECUTABLE}") # endif() # # Look for 'git' or 'eg' (easy git) # set(git_names git eg) # Prefer .cmd variants on Windows unless running in a Makefile # in the MSYS shell. # if(WIN32) if(NOT CMAKE_GENERATOR MATCHES "MSYS") # Note: Due to a bug in 'git.cmd' preventing it from returning the exit code of 'git', # we excluded it from the list of executables to search. # See http://code.google.com/p/msysgit/issues/detail?id=428 # TODO Check if 'git' exists, get the associated version, if the corresponding version # is known to have a working version of 'git.cmd', use it. set(git_names git eg.cmd eg) endif() endif() find_program(GIT_EXECUTABLE ${git_names} PATHS "C:/Program Files/Git/bin" "C:/Program Files (x86)/Git/bin" DOC "git command line client") mark_as_advanced(GIT_EXECUTABLE) if(GIT_EXECUTABLE) macro(GIT_WC_INFO dir prefix) execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=7 HEAD WORKING_DIRECTORY ${dir} ERROR_VARIABLE GIT_error OUTPUT_VARIABLE ${prefix}_WC_REVISION_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) set(${prefix}_WC_REVISION ${${prefix}_WC_REVISION_HASH}) if(NOT ${GIT_error} EQUAL 0) message(SEND_ERROR "Command \"${GIT_EXECUTBALE} rev-parse --verify -q --short=7 HEAD\" in directory ${dir} failed with output:\n${GIT_error}") else(NOT ${GIT_error} EQUAL 0) execute_process(COMMAND ${GIT_EXECUTABLE} name-rev ${${prefix}_WC_REVISION_HASH} WORKING_DIRECTORY ${dir} OUTPUT_VARIABLE ${prefix}_WC_REVISION_NAME OUTPUT_STRIP_TRAILING_WHITESPACE) endif(NOT ${GIT_error} EQUAL 0) execute_process(COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url WORKING_DIRECTORY ${dir} OUTPUT_VARIABLE ${prefix}_WC_URL OUTPUT_STRIP_TRAILING_WHITESPACE) set(${prefix}_WC_GITSVN False) # Check if this git is likely to be a git-svn repository execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp "^svn-remote" WORKING_DIRECTORY ${dir} OUTPUT_VARIABLE git_config_output OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT "${git_config_output}" STREQUAL "") # In case git-svn is used, attempt to extract svn info execute_process(COMMAND ${GIT_EXECUTABLE} svn info WORKING_DIRECTORY ${dir} TIMEOUT 3 ERROR_VARIABLE git_svn_info_error OUTPUT_VARIABLE ${prefix}_WC_INFO RESULT_VARIABLE git_svn_info_result OUTPUT_STRIP_TRAILING_WHITESPACE) if(${git_svn_info_result} EQUAL 0) set(${prefix}_WC_GITSVN True) string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*" "\\2" ${prefix}_WC_URL "${${prefix}_WC_INFO}") string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*" "\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}") string(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*" "\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}") string(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*" "\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}") string(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*" "\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}") string(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*" "\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}") endif(${git_svn_info_result} EQUAL 0) endif(NOT "${git_config_output}" STREQUAL "") # If there is no 'remote.origin', default to "NA" value and print a warning message. if(NOT ${prefix}_WC_URL) message(WARNING "No remote origin set for git repository: ${dir}" ) set( ${prefix}_WC_URL "NA" ) else() set(${prefix}_WC_ROOT ${${prefix}_WC_URL}) endif() endmacro(GIT_WC_INFO) endif(GIT_EXECUTABLE) # Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE) |
Added undroid/libwebsockets/cmake/FindOpenSSLbins.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
if(OPENSSL_FOUND) find_program(OPENSSL_EXECUTABLE openssl openssl.exe bin/openssl.exe HINTS ${_OPENSSL_ROOT_HINTS} PATH /usr/bin/ bin/ DOC "Openssl executable") mark_as_advanced(OPENSSL_EXECUTABLE) # On Windows, we need to copy the OpenSSL dlls # to the output directory. if(WIN32) set(OPENSSL_BIN_FOUND 0) find_file(LIBEAY_BIN NAMES libeay32.dll HINTS ${_OPENSSL_ROOT_HINTS} PATH_SUFFIXES bin) find_file(SSLEAY_BIN NAMES ssleay32.dll HINTS ${_OPENSSL_ROOT_HINTS} PATH_SUFFIXES bin) if(LIBEAY_BIN) if(SSLEAY_BIN) set(OPENSSL_BIN_FOUND 1) endif(SSLEAY_BIN) endif(LIBEAY_BIN) endif(WIN32) endif(OPENSSL_FOUND) |
Added undroid/libwebsockets/cmake/LibwebsocketsConfig.cmake.in.
> > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# - Config file for the Libevent package # It defines the following variables # LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar # LIBWEBSOCKETS_LIBRARIES - libraries to link against # Get the path of the current file. get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) # Set the include directories. set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@") # Include the project Targets file, this contains definitions for IMPORTED targets. include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) # IMPORTED targets from LibwebsocketsTargets.cmake set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) |
Added undroid/libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in.
> > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 |
set(PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif() |
Added undroid/libwebsockets/cmake/UseRPMTools.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# # - Find tools needed for building RPM Packages # on Linux systems and defines macro that helps to # build source or binary RPM, the MACRO assumes # CMake 2.4.x which includes CPack support. # CPack is used to build tar.gz source tarball # which may be used by a custom user-made spec file. # # - Define RPMTools_ADD_RPM_TARGETS which defines # two (top-level) CUSTOM targets for building # source and binary RPMs # # Those CMake macros are provided by the TSP Developer Team # https://savannah.nongnu.org/projects/tsp # IF (WIN32) MESSAGE(STATUS "RPM tools not available on Win32 systems") ENDIF(WIN32) IF (UNIX) # Look for RPM builder executable FIND_PROGRAM(RPMTools_RPMBUILD_EXECUTABLE NAMES rpmbuild PATHS "/usr/bin;/usr/lib/rpm" PATH_SUFFIXES bin DOC "The RPM builder tool") IF (RPMTools_RPMBUILD_EXECUTABLE) MESSAGE(STATUS "Looking for RPMTools... - found rpmuild is ${RPMTools_RPMBUILD_EXECUTABLE}") SET(RPMTools_RPMBUILD_FOUND "YES") GET_FILENAME_COMPONENT(RPMTools_BINARY_DIRS ${RPMTools_RPMBUILD_EXECUTABLE} PATH) ELSE (RPMTools_RPMBUILD_EXECUTABLE) SET(RPMTools_RPMBUILD_FOUND "NO") MESSAGE(STATUS "Looking for RPMTools... - rpmbuild NOT FOUND") ENDIF (RPMTools_RPMBUILD_EXECUTABLE) # Detect if CPack was included or not IF (NOT DEFINED "CPACK_PACKAGE_NAME") MESSAGE(FATAL_ERROR "CPack was not included, you should include CPack before Using RPMTools") ENDIF (NOT DEFINED "CPACK_PACKAGE_NAME") IF (RPMTools_RPMBUILD_FOUND) SET(RPMTools_FOUND TRUE) # # - first arg (ARGV0) is RPM name # - second arg (ARGV1) is the RPM spec file path [optional] # - third arg (ARGV2) is the RPM ROOT DIRECTORY used to build RPMs [optional] # MACRO(RPMTools_ADD_RPM_TARGETS RPMNAME) # # If no spec file is provided create a minimal one # IF ("${ARGV1}" STREQUAL "") SET(SPECFILE_PATH "${CMAKE_BINARY_DIR}/${RPMNAME}.spec") ELSE ("${ARGV1}" STREQUAL "") SET(SPECFILE_PATH "${ARGV1}") ENDIF("${ARGV1}" STREQUAL "") # Verify whether if RPM_ROOTDIR was provided or not IF("${ARGV2}" STREQUAL "") SET(RPM_ROOTDIR ${CMAKE_BINARY_DIR}/RPM) ELSE ("${ARGV2}" STREQUAL "") SET(RPM_ROOTDIR "${ARGV2}") ENDIF("${ARGV2}" STREQUAL "") MESSAGE(STATUS "RPMTools:: Using RPM_ROOTDIR=${RPM_ROOTDIR}") # Prepare RPM build tree FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/tmp) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/BUILD) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/RPMS) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SOURCES) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SPECS) FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SRPMS) # # We check whether if the provided spec file is # to be configure or not. # IF ("${ARGV1}" STREQUAL "") SET(SPECFILE_PATH "${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec") SET(SPECFILE_NAME "${RPMNAME}.spec") MESSAGE(STATUS "No Spec file given generate a minimal one --> ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec") FILE(WRITE ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec "# -*- rpm-spec -*- Summary: ${RPMNAME} Name: ${RPMNAME} Version: ${CPACK_PACKAGE_VERSION} Release: 1 License: Unknown Group: Unknown Source: ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{CPACK_PACKAGE_VERSION}-1-root BuildRequires: cmake %define prefix /opt/${RPMNAME}-%{version} %define rpmprefix $RPM_BUILD_ROOT%{prefix} %define srcdirname %{name}-%{version} %description ${RPMNAME} : No description for now %prep %setup -q -n %{srcdirname} %build cd .. rm -rf build_tree mkdir build_tree cd build_tree cmake -DCMAKE_INSTALL_PREFIX=%{rpmprefix} ../%{srcdirname} make %install cd ../build_tree make install %clean rm -rf %{srcdirname} rm -rf build_tree %files %defattr(-,root,root,-) %dir %{prefix} %{prefix}/* %changelog * Wed Feb 28 2007 Erk <eric.noulard@gmail.com> Generated by CMake UseRPMTools macros" ) ELSE ("${ARGV1}" STREQUAL "") SET(SPECFILE_PATH "${ARGV1}") GET_FILENAME_COMPONENT(SPECFILE_EXT ${SPECFILE_PATH} EXT) IF ("${SPECFILE_EXT}" STREQUAL ".spec") # This is a 'ready-to-use' spec file which does not need to be CONFIGURED GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME) MESSAGE(STATUS "Simple copy spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>") CONFIGURE_FILE( ${SPECFILE_PATH} ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME} COPYONLY) ELSE ("${SPECFILE_EXT}" STREQUAL ".spec") # This is a to-be-configured spec file GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME_WE) SET(SPECFILE_NAME "${SPECFILE_NAME}.spec") MESSAGE(STATUS "Configuring spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>") CONFIGURE_FILE( ${SPECFILE_PATH} ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME} @ONLY) ENDIF ("${SPECFILE_EXT}" STREQUAL ".spec") ENDIF("${ARGV1}" STREQUAL "") ADD_CUSTOM_TARGET(${RPMNAME}_srpm COMMAND cpack -G TGZ --config CPackSourceConfig.cmake COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bs --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME} ) ADD_CUSTOM_TARGET(${RPMNAME}_rpm COMMAND cpack -G TGZ --config CPackSourceConfig.cmake COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bb --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME} ) ENDMACRO(RPMTools_ADD_RPM_TARGETS) ELSE (RPMTools_RPMBUILD_FOUND) SET(RPMTools FALSE) ENDIF (RPMTools_RPMBUILD_FOUND) ENDIF (UNIX) |
Added undroid/libwebsockets/contrib/abi/README.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
ABI Compatility Tracking ======================== This directory contains files that can be used to generate an ABI compatibility timeline for libwebsockets. This gives users an idea of where the library has changed and can be used by the developers to see when incompatible changes have been introduced and either increase the library SO version or fix the changes. The tools used are the abi-\* family available at https://github.com/lvc/ and some example output is here: http://abi-laboratory.pro/tracker/timeline/libuv/ The tools download existing source tarballs and git repository to generate this data, so past versions are compared and in-development code can be compared as well. Although the application is not being included here, FYI the license is dual LGPL2 / GPL2 at your choice. Installation ------------ The author provides an easy way to install the various tools he provides: git clone https://github.com/lvc/installer cd installer make prefix=/usr/local target=abi-tracker It will also list any dependencies that you need to install through normal means. (Although in the case of needing "elfutils-libelf-devel", it may crash during install of vtable-dumper without giving a nice list) Generating the output --------------------- Use the `lws-abi-update.sh` script to download the source files, build them and generate the output html. The output can be deployed to a directory on a web server for example. Modify the commented line in lws-abi-update.sh to do this. As it is configured, lws-abi-update.sh will only download new source - ones that it hasn't built before - so is suitable for use with a cron job. Viewing the output ------------------ The best place to start looking at the data is the `timeline/libwebsockets` directory. If your path is on a web server, navigate there, otherwise you could try: lynx timeline/libwebsockets/ |
Added undroid/libwebsockets/contrib/abi/libwebsockets.json.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
{ "Name": "libwebsockets", "SourceUrl": "https://github.com/warmcat/libwebsockets/releases", "Git": "https://github.com/warmcat/libwebsockets", "Versions": [ { "Number": "current", "Installed": "installed/libwebsockets/current", "Source": "src/libwebsockets/current", "Changelog": "On", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.7.4", "Installed": "installed/libwebsockets/1.7.4", "Source": "src/libwebsockets/1.7.4/libwebsockets-1.7.4.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.7.3", "Installed": "installed/libwebsockets/1.7.3", "Source": "src/libwebsockets/1.7.3/libwebsockets-1.7.3.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.7.2", "Installed": "installed/libwebsockets/1.7.2", "Source": "src/libwebsockets/1.7.2/libwebsockets-1.7.2.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.7.1", "Installed": "installed/libwebsockets/1.7.1", "Source": "src/libwebsockets/1.7.1/libwebsockets-1.7.1.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.7.0", "Installed": "installed/libwebsockets/1.7.0", "Source": "src/libwebsockets/1.7.0/libwebsockets-1.7.0.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.6.3", "Installed": "installed/libwebsockets/1.6.3", "Source": "src/libwebsockets/1.6.3/libwebsockets-1.6.3.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.6.2", "Installed": "installed/libwebsockets/1.6.2", "Source": "src/libwebsockets/1.6.2/libwebsockets-1.6.2.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.6.1", "Installed": "installed/libwebsockets/1.6.1", "Source": "src/libwebsockets/1.6.1/libwebsockets-1.6.1.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }, { "Number": "1.5.1", "Installed": "installed/libwebsockets/1.5.1", "Source": "src/libwebsockets/1.5.1/libwebsockets-1.5.1.tar.gz", "Changelog": "Off", "HeadersDiff": "On", "PkgDiff": "Off", "ABIView": "Off", "ABIDiff": "Off" }] } |
Added undroid/libwebsockets/contrib/abi/lws-abi-update.sh.
> > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/bin/sh if [ ! -z "$1" ] ; then OUT=$1 else OUT="/tmp/lws-abi-track-htdocs" fi D=`dirname $0` if [ ! -z "$D" ] ; then D=$D/ fi J=$D"libwebsockets.json" abi-monitor -get -build-new $J abi-tracker -build $J abi-tracker -deploy $OUT $J |
Added undroid/libwebsockets/contrib/android-make-script.sh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
#!/bin/bash # # Build libwebsockets static library for Android # # requires debian package xutils-dev for makedepend (openssl make depend) # # This is based on http://stackoverflow.com/questions/11929773/compiling-the-latest-openssl-for-android/ # via https://github.com/warmcat/libwebsockets/pull/502 # path to NDK export NDK=/opt/Android/SDK/ndk-bundle set -e # Download packages libz, openssl and libwebsockets [ ! -f zlib-1.2.8.tar.gz ] && { wget http://prdownloads.sourceforge.net/libpng/zlib-1.2.8.tar.gz } [ ! -f openssl-1.0.2g.tar.gz ] && { wget https://openssl.org/source/openssl-1.0.2g.tar.gz } [ ! -f libwebsockets.tar.gz ] && { git clone https://github.com/warmcat/libwebsockets.git tar caf libwebsockets.tar.gz libwebsockets } # Clean then Unzip [ -d zlib-1.2.8 ] && rm -fr zlib-1.2.8 [ -d openssl-1.0.2g ] && rm -fr openssl-1.0.2g [ -d libwebsockets ] && rm -fr libwebsockets [ -d android-toolchain-arm ] && rm -fr android-toolchain-arm tar xf zlib-1.2.8.tar.gz tar xf openssl-1.0.2g.tar.gz tar xf libwebsockets.tar.gz # create a local android toolchain $NDK/build/tools/make-standalone-toolchain.sh \ --platform=android-9 \ --toolchain=arm-linux-androideabi-4.9 \ --install-dir=`pwd`/android-toolchain-arm # setup environment to use the gcc/ld from the android toolchain export TOOLCHAIN_PATH=`pwd`/android-toolchain-arm/bin export TOOL=arm-linux-androideabi export NDK_TOOLCHAIN_BASENAME=${TOOLCHAIN_PATH}/${TOOL} export CC=$NDK_TOOLCHAIN_BASENAME-gcc export CXX=$NDK_TOOLCHAIN_BASENAME-g++ export LINK=${CXX} export LD=$NDK_TOOLCHAIN_BASENAME-ld export AR=$NDK_TOOLCHAIN_BASENAME-ar export RANLIB=$NDK_TOOLCHAIN_BASENAME-ranlib export STRIP=$NDK_TOOLCHAIN_BASENAME-strip # setup buildflags export ARCH_FLAGS="-mthumb" export ARCH_LINK= export CPPFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 " export CXXFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 -frtti -fexceptions " export CFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 " export LDFLAGS=" ${ARCH_LINK} " # configure and build zlib [ ! -f ./android-toolchain-arm/lib/libz.a ] && { cd zlib-1.2.8 PATH=$TOOLCHAIN_PATH:$PATH ./configure --static --prefix=$TOOLCHAIN_PATH/.. PATH=$TOOLCHAIN_PATH:$PATH make PATH=$TOOLCHAIN_PATH:$PATH make install cd .. } # configure and build openssl [ ! -f ./android-toolchain-arm/lib/libssl.a ] && { PREFIX=$TOOLCHAIN_PATH/.. cd openssl-1.0.2g ./Configure android --prefix=${PREFIX} no-shared no-idea no-mdc2 no-rc5 no-zlib no-zlib-dynamic enable-tlsext no-ssl2 no-ssl3 enable-ec enable-ecdh enable-ecp PATH=$TOOLCHAIN_PATH:$PATH make depend PATH=$TOOLCHAIN_PATH:$PATH make PATH=$TOOLCHAIN_PATH:$PATH make install_sw cd .. } # configure and build libwebsockets [ ! -f ./android-toolchain-arm/lib/libwebsockets.a ] && { cd libwebsockets [ ! -d build ] && mkdir build cd build PATH=$TOOLCHAIN_PATH:$PATH cmake \ -DCMAKE_C_COMPILER=$CC \ -DCMAKE_AR=$AR \ -DCMAKE_RANLIB=$RANLIB \ -DCMAKE_C_FLAGS="$CFLAGS" \ -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN_PATH/.. \ -DLWS_WITH_SHARED=OFF \ -DLWS_WITH_STATIC=ON \ -DLWS_WITHOUT_DAEMONIZE=ON \ -DLWS_WITHOUT_TESTAPPS=ON \ -DLWS_IPV6=OFF \ -DLWS_USE_BUNDLED_ZLIB=OFF \ -DLWS_WITH_SSL=ON \ -DLWS_WITH_HTTP2=ON \ -DLWS_OPENSSL_LIBRARIES="$TOOLCHAIN_PATH/../lib/libssl.a;$TOOLCHAIN_PATH/../lib/libcrypto.a" \ -DLWS_OPENSSL_INCLUDE_DIRS=$TOOLCHAIN_PATH/../include \ -DCMAKE_BUILD_TYPE=Debug \ .. PATH=$TOOLCHAIN_PATH:$PATH make PATH=$TOOLCHAIN_PATH:$PATH make install cd ../.. } |
Added undroid/libwebsockets/cross-arm-linux-gnueabihf.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# # CMake Toolchain file for crosscompiling on ARM. # # This can be used when running cmake in the following way: # cd build/ # cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake # set(CROSS_PATH /opt/gcc-linaro-arm-linux-gnueabihf-4.7-2013.02-01-20130221_linux) # Target operating system name. set(CMAKE_SYSTEM_NAME Linux) # Name of C compiler. set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-gcc") set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-g++") # Where to look for the target environment. (More paths can be added here) set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Search headers and libraries in the target environment only. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
Added undroid/libwebsockets/cross-ming.cmake.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# # CMake Toolchain file for crosscompiling on MingW. # # This can be used when running cmake in the following way: # cd build/ # cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-ming.cmake # set(CROSS_PATH /usr/bin) # Target operating system name. set(CMAKE_SYSTEM_NAME Windows) set(BUILD_SHARED_LIBS OFF) # Name of C compiler. set(CMAKE_C_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-gcc") #set(CMAKE_CXX_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-g++") set(CMAKE_RC_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-windres") set(CMAKE_C_FLAGS "-Wno-error") # Where to look for the target environment. (More paths can be added here) set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Search headers and libraries in the target environment only. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
Added undroid/libwebsockets/cross-openwrt-makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# # libwebsockets makefile for openwrt # include $(TOPDIR)/rules.mk PKG_NAME:=libwebsockets PKG_VERSION:=2014-03-01 PKG_RELEASE=$(PKG_SOURCE_VERSION) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/warmcat/libwebsockets.git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_VERSION:=388dc7d201d8d123841869fb49ec4d94d6dd7f54 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz CMAKE_INSTALL:=1 include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/cmake.mk CMAKE_OPTIONS += -DLWS_OPENSSL_CLIENT_CERTS=/etc/ssl/certs CMAKE_OPTIONS += -DLWS_OPENSSL_SUPPORT=ON CMAKE_OPTIONS += -DLWS_WITH_SSL=ON CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON") # for wolfssl, define these in addition to LWS_OPENSSL_SUPPORT and # edit package/libs/wolfssl/Makefile to include --enable-opensslextra # CMAKE_OPTIONS += -DLWS_USE_WOLFSSL=ON # CMAKE_OPTIONS += -DLWS_WOLFSSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libwolfssl.so # CMAKE_OPTIONS += -DLWS_WOLFSSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include # for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and # edit package/libs/wolfssl/Makefile to include --enable-opensslextra # CMAKE_OPTIONS += -DLWS_USE_CYASSL=ON # CMAKE_OPTIONS += -DLWS_CYASSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libcyassl.so # CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include # other options worth noting # CMAKE_OPTIONS += -DLWS_WITHOUT_EXTENSIONS=ON # CMAKE_OPTIONS += -DLWS_WITHOUT_DAEMONIZE=ON # CMAKE_OPTIONS += -DLWS_WITHOUT_SERVER=ON # CMAKE_OPTIONS += -DLWS_WITHOUT_DEBUG=ON define Package/libwebsockets/Default SECTION:=libs CATEGORY:=Libraries TITLE:=libwebsockets DEPENDS:=+zlib +libopenssl endef define Package/libwebsockets $(call Package/libwebsockets/Default) TITLE+= (libraries) endef define Package/libwebsockets/description libwebsockets This package contains libwebsocket libraries endef define Package/libwebsockets-examples $(call Package/libwebsockets/Default) DEPENDS:=libwebsockets TITLE+= (examples) endef define Package/libwebsockets-examples/description libwebsockets examples This package contains libwebsockets examples endef define Package/libwebsockets/install $(INSTALL_DIR) $(1)/usr/lib $(CP) $(PKG_INSTALL_DIR)/usr/lib/libwebsockets.so* $(1)/usr/lib/ endef define Package/libwebsockets-examples/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-client $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-echo $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-fraggle $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-ping $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server-extpoll $(1)/usr/bin/ $(INSTALL_DIR) $(1)/usr/share/libwebsockets-test-server $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/favicon.ico $(1)/usr/share/libwebsockets-test-server/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/leaf.jpg $(1)/usr/share/libwebsockets-test-server/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets.org-logo.png $(1)/usr/share/libwebsockets-test-server/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.key.pem $(1)/usr/share/libwebsockets-test-server/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.pem $(1)/usr/share/libwebsockets-test-server/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/test.html $(1)/usr/share/libwebsockets-test-server/ endef $(eval $(call BuildPackage,libwebsockets)) $(eval $(call BuildPackage,libwebsockets-examples)) |
Added undroid/libwebsockets/lib/alloc.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include "private-libwebsockets.h" static void *_realloc(void *ptr, size_t size) { if (size) return realloc(ptr, size); else if (ptr) free(ptr); return NULL; } void *(*_lws_realloc)(void *ptr, size_t size) = _realloc; void *lws_realloc(void *ptr, size_t size) { return _lws_realloc(ptr, size); } void *lws_zalloc(size_t size) { void *ptr = _lws_realloc(NULL, size); if (ptr) memset(ptr, 0, size); return ptr; } void lws_set_allocator(void *(*cb)(void *ptr, size_t size)) { _lws_realloc = cb; } |
Added undroid/libwebsockets/lib/base64-decode.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
/* * This code originally came from here * * http://base64.sourceforge.net/b64.c * * with the following license: * * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the * Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall * be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * VERSION HISTORY: * Bob Trower 08/04/01 -- Create Version 0.00.00B * * I cleaned it up quite a bit to match the (linux kernel) style of the rest * of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws * since he explicitly allows sublicensing, but I give the URL above so you can * get the original with Bob's super-liberal terms directly if you prefer. */ #include <stdio.h> #include <string.h> #include "private-libwebsockets.h" static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz0123456789+/"; static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW" "$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; LWS_VISIBLE int lws_b64_encode_string(const char *in, int in_len, char *out, int out_size) { unsigned char triple[3]; int i; int len; int line = 0; int done = 0; while (in_len) { len = 0; for (i = 0; i < 3; i++) { if (in_len) { triple[i] = *in++; len++; in_len--; } else triple[i] = 0; } if (done + 4 >= out_size) return -1; *out++ = encode[triple[0] >> 2]; *out++ = encode[((triple[0] & 0x03) << 4) | ((triple[1] & 0xf0) >> 4)]; *out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) | ((triple[2] & 0xc0) >> 6)] : '='); *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '='); done += 4; line += 4; } if (done + 1 >= out_size) return -1; *out++ = '\0'; return done; } /* * returns length of decoded string in out, or -1 if out was too small * according to out_size */ LWS_VISIBLE int lws_b64_decode_string(const char *in, char *out, int out_size) { int len; int i, c; int done = 0; unsigned char v; unsigned char quad[4]; while (*in) { len = 0; for (i = 0; i < 4 && *in; i++) { v = 0; c = 0; while (*in && !v) { c = v = *in++; v = (v < 43 || v > 122) ? 0 : decode[v - 43]; if (v) v = (v == '$') ? 0 : v - 61; } if (c) { len++; if (v) quad[i] = v - 1; } else quad[i] = 0; } if (out_size < (done + len - 1)) /* out buffer is too small */ return -1; if (len >= 2) *out++ = quad[0] << 2 | quad[1] >> 4; if (len >= 3) *out++ = quad[1] << 4 | quad[2] >> 2; if (len >= 4) *out++ = ((quad[2] << 6) & 0xc0) | quad[3]; done += len - 1; } if (done + 1 >= out_size) return -1; *out++ = '\0'; return done; } #if 0 int lws_b64_selftest(void) { char buf[64]; unsigned int n; unsigned int test; static const char * const plaintext[] = { "sanity check base 64" }; static const char * const coded[] = { "c2FuaXR5IGNoZWNrIGJhc2UgNjQ=" }; for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) { buf[sizeof(buf) - 1] = '\0'; n = lws_b64_encode_string(plaintext[test], strlen(plaintext[test]), buf, sizeof buf); if (n != strlen(coded[test]) || strcmp(buf, coded[test])) { lwsl_err("Failed lws_b64 encode selftest " "%d result '%s' %d\n", test, buf, n); return -1; } buf[sizeof(buf) - 1] = '\0'; n = lws_b64_decode_string(coded[test], buf, sizeof buf); if (n != strlen(plaintext[test]) || strcmp(buf, plaintext[test])) { lwsl_err("Failed lws_b64 decode selftest " "%d result '%s' %d\n", test, buf, n); return -1; } } return 0; } #endif |
Added undroid/libwebsockets/lib/client-handshake.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
#include "private-libwebsockets.h" struct lws * lws_client_connect_2(struct lws *wsi) { #ifdef LWS_USE_IPV6 struct sockaddr_in6 server_addr6; struct addrinfo hints, *result; #endif struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct sockaddr_in server_addr4; struct lws_pollfd pfd; struct sockaddr *v; int n, plen = 0; const char *ads; lwsl_client("%s\n", __func__); /* proxy? */ if (wsi->vhost->http_proxy_port) { plen = sprintf((char *)pt->serv_buf, "CONNECT %s:%u HTTP/1.0\x0d\x0a" "User-agent: libwebsockets\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS), wsi->u.hdr.c_port); if (wsi->vhost->proxy_basic_auth_token[0]) plen += sprintf((char *)pt->serv_buf + plen, "Proxy-authorization: basic %s\x0d\x0a", wsi->vhost->proxy_basic_auth_token); plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a"); ads = wsi->vhost->http_proxy_address; #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { memset(&server_addr6, 0, sizeof(struct sockaddr_in6)); server_addr6.sin6_port = htons(wsi->vhost->http_proxy_port); } else #endif server_addr4.sin_port = htons(wsi->vhost->http_proxy_port); } else { ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { memset(&server_addr6, 0, sizeof(struct sockaddr_in6)); server_addr6.sin6_port = htons(wsi->u.hdr.c_port); } else #endif server_addr4.sin_port = htons(wsi->u.hdr.c_port); } /* * prepare the actual connection (to the proxy, if any) */ lwsl_client("%s: address %s\n", __func__, ads); #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { memset(&hints, 0, sizeof(struct addrinfo)); #if !defined(__ANDROID__) hints.ai_family = AF_INET6; hints.ai_flags = AI_V4MAPPED; #endif n = getaddrinfo(ads, NULL, &hints, &result); if (n) { #ifdef _WIN32 lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n)); #else lwsl_err("getaddrinfo: %s\n", gai_strerror(n)); #endif goto oom4; } server_addr6.sin6_family = AF_INET6; switch (result->ai_family) { #if defined(__ANDROID__) case AF_INET: /* map IPv4 to IPv6 */ bzero((char *)&server_addr6.sin6_addr, sizeof(struct in6_addr)); server_addr6.sin6_addr.s6_addr[10] = 0xff; server_addr6.sin6_addr.s6_addr[11] = 0xff; memcpy(&server_addr6.sin6_addr.s6_addr[12], &((struct sockaddr_in *)result->ai_addr)->sin_addr, sizeof(struct in_addr)); break; #endif case AF_INET6: memcpy(&server_addr6.sin6_addr, &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); break; default: lwsl_err("Unknown address family\n"); freeaddrinfo(result); goto oom4; } freeaddrinfo(result); } else #endif { struct addrinfo ai, *res, *result; void *p = NULL; memset (&ai, 0, sizeof ai); ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; ai.ai_flags = AI_CANONNAME; if (getaddrinfo(ads, NULL, &ai, &result)) { lwsl_err("getaddrinfo failed\n"); goto oom4; } res = result; while (!p && res) { switch (res->ai_family) { case AF_INET: p = &((struct sockaddr_in *)res->ai_addr)->sin_addr; break; } res = res->ai_next; } if (!p) { lwsl_err("Couldn't identify address\n"); freeaddrinfo(result); goto oom4; } server_addr4.sin_family = AF_INET; server_addr4.sin_addr = *((struct in_addr *)p); bzero(&server_addr4.sin_zero, 8); freeaddrinfo(result); } if (!lws_socket_is_valid(wsi->sock)) { #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) wsi->sock = socket(AF_INET6, SOCK_STREAM, 0); else #endif wsi->sock = socket(AF_INET, SOCK_STREAM, 0); if (!lws_socket_is_valid(wsi->sock)) { lwsl_warn("Unable to open socket\n"); goto oom4; } if (lws_plat_set_socket_options(wsi->vhost, wsi->sock)) { lwsl_err("Failed to set wsi socket options\n"); compatible_close(wsi->sock); goto oom4; } wsi->mode = LWSCM_WSCL_WAITING_CONNECT; lws_libev_accept(wsi, wsi->sock); lws_libuv_accept(wsi, wsi->sock); if (insert_wsi_socket_into_fds(context, wsi)) { compatible_close(wsi->sock); goto oom4; } /* * past here, we can't simply free the structs as error * handling as oom4 does. We have to run the whole close flow. */ if (!wsi->protocol) wsi->protocol = &wsi->vhost->protocols[0]; wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, wsi->user_space, NULL, 0); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE, AWAITING_TIMEOUT); n = lws_socket_bind(wsi->vhost, wsi->sock, 0, wsi->vhost->iface); if (n < 0) goto failed; } #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { v = (struct sockaddr *)&server_addr6; n = sizeof(struct sockaddr_in6); } else #endif { v = (struct sockaddr *)&server_addr4; n = sizeof(struct sockaddr); } if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) { if (LWS_ERRNO == LWS_EALREADY || LWS_ERRNO == LWS_EINPROGRESS || LWS_ERRNO == LWS_EWOULDBLOCK #ifdef _WIN32 || LWS_ERRNO == WSAEINVAL #endif ) { lwsl_client("nonblocking connect retry\n"); /* * must do specifically a POLLOUT poll to hear * about the connect completion */ if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) goto failed; return wsi; } if (LWS_ERRNO != LWS_EISCONN) { lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO); goto failed; } } lwsl_client("connected\n"); /* we are connected to server, or proxy */ if (wsi->vhost->http_proxy_port) { /* * OK from now on we talk via the proxy, so connect to that * * (will overwrite existing pointer, * leaving old string/frag there but unreferenced) */ if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, wsi->vhost->http_proxy_address)) goto failed; wsi->u.hdr.c_port = wsi->vhost->http_proxy_port; n = send(wsi->sock, (char *)pt->serv_buf, plen, MSG_NOSIGNAL); if (n < 0) { lwsl_debug("ERROR writing to proxy socket\n"); goto failed; } lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, AWAITING_TIMEOUT); wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY; return wsi; } /* * provoke service to issue the handshake directly * we need to do it this way because in the proxy case, this is the * next state and executed only if and when we get a good proxy * response inside the state machine... but notice in SSL case this * may not have sent anything yet with 0 return, and won't until some * many retries from main loop. To stop that becoming endless, * cover with a timeout. */ lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT); wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE; pfd.fd = wsi->sock; pfd.events = LWS_POLLIN; pfd.revents = LWS_POLLIN; n = lws_service_fd(context, &pfd); if (n < 0) goto failed; if (n) /* returns 1 on failure after closing wsi */ return NULL; return wsi; oom4: /* we're closing, losing some rx is OK */ wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; //lwsl_err("%d\n", wsi->mode); if (wsi->mode == LWSCM_HTTP_CLIENT) wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, NULL, 0); /* take care that we might be inserted in fds already */ if (wsi->position_in_fds_table != -1) goto failed; lws_header_table_detach(wsi, 0); lws_free(wsi); return NULL; failed: lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return NULL; } /** * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect) * this only works if still in HTTP, ie, not upgraded yet * wsi: connection to reset * address: network address of the new server * port: port to connect to * path: uri path to connect to on the new server * host: host header to send to the new server */ LWS_VISIBLE struct lws * lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host) { if (wsi->u.hdr.redirects == 3) { lwsl_err("%s: Too many redirects\n", __func__); return NULL; } wsi->u.hdr.redirects++; #ifdef LWS_OPENSSL_SUPPORT wsi->use_ssl = ssl; #else if (ssl) { lwsl_err("%s: not configured for ssl\n", __func__); return NULL; } #endif lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address)) return NULL; if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path)) return NULL; if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host)) return NULL; compatible_close(wsi->sock); remove_wsi_socket_from_fds(wsi); wsi->sock = LWS_SOCK_INVALID; wsi->state = LWSS_CLIENT_UNCONNECTED; wsi->protocol = NULL; wsi->pending_timeout = NO_PENDING_TIMEOUT; wsi->u.hdr.c_port = port; return lws_client_connect_2(wsi); } #ifdef LWS_WITH_HTTP_PROXY static hubbub_error html_parser_cb(const hubbub_token *token, void *pw) { struct lws_rewrite *r = (struct lws_rewrite *)pw; char buf[1024], *start = buf + LWS_PRE, *p = start, *end = &buf[sizeof(buf) - 1]; size_t i; switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ", (int) token->data.doctype.name.len, token->data.doctype.name.ptr, token->data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) printf("\tpublic: missing\n"); else p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n", (int) token->data.doctype.public_id.len, token->data.doctype.public_id.ptr); if (token->data.doctype.system_missing) printf("\tsystem: missing\n"); else p += lws_snprintf(p, end - p, " \"%.*s\">\n", (int) token->data.doctype.system_id.len, token->data.doctype.system_id.ptr); break; case HUBBUB_TOKEN_START_TAG: p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len, token->data.tag.name.ptr); /* (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); */ for (i = 0; i < token->data.tag.n_attributes; i++) { if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) || !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) || !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) { const char *pp = (const char *)token->data.tag.attributes[i].value.ptr; int plen = (int) token->data.tag.attributes[i].value.len; if (!hstrcmp(&token->data.tag.attributes[i].value, r->from, r->from_len)) { pp += r->from_len; plen -= r->from_len; } p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, r->to, plen, pp); } else p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } p += lws_snprintf(p, end - p, ">\n"); break; case HUBBUB_TOKEN_END_TAG: p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len, token->data.tag.name.ptr); /* (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); */ for (i = 0; i < token->data.tag.n_attributes; i++) { p += lws_snprintf(p, end - p, " %.*s='%.*s'\n", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } p += lws_snprintf(p, end - p, ">\n"); break; case HUBBUB_TOKEN_COMMENT: p += lws_snprintf(p, end - p, "<!-- %.*s -->\n", (int) token->data.comment.len, token->data.comment.ptr); break; case HUBBUB_TOKEN_CHARACTER: p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len, token->data.character.ptr); break; case HUBBUB_TOKEN_EOF: p += lws_snprintf(p, end - p, "\n"); break; } if (user_callback_handle_rxflow(r->wsi->protocol->callback, r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ, r->wsi->user_space, start, p - start)) return -1; return HUBBUB_OK; } #endif /** * lws_client_connect_via_info() - Connect to another websocket server * @i:pointer to lws_client_connect_info struct * * This function creates a connection to a remote server */ LWS_VISIBLE struct lws * lws_client_connect_via_info(struct lws_client_connect_info *i) { struct lws *wsi; int v = SPEC_LATEST_SUPPORTED; if (i->context->requested_kill) return NULL; wsi = lws_zalloc(sizeof(struct lws)); if (wsi == NULL) goto bail; wsi->context = i->context; /* assert the mode and union status (hdr) clearly */ lws_union_transition(wsi, LWSCM_HTTP_CLIENT); wsi->sock = LWS_SOCK_INVALID; /* 1) fill up the wsi with stuff from the connect_info as far as it * can go. It's because not only is our connection async, we might * not even be able to get ahold of an ah at this point. */ /* -1 means just use latest supported */ if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one) v = i->ietf_version_or_minus_one; wsi->ietf_spec_revision = v; wsi->user_space = NULL; wsi->state = LWSS_CLIENT_UNCONNECTED; wsi->protocol = NULL; wsi->pending_timeout = NO_PENDING_TIMEOUT; wsi->position_in_fds_table = -1; wsi->u.hdr.c_port = i->port; wsi->vhost = i->vhost; if (!wsi->vhost) wsi->vhost = i->context->vhost_list; wsi->protocol = &wsi->vhost->protocols[0]; if (wsi && !wsi->user_space && i->userdata) { wsi->user_space_externally_allocated = 1; wsi->user_space = i->userdata; } else /* if we stay in http, we can assign the user space now, * otherwise do it after the protocol negotiated */ if (i->method) if (lws_ensure_user_space(wsi)) goto bail; #ifdef LWS_OPENSSL_SUPPORT wsi->use_ssl = i->ssl_connection; #else if (i->ssl_connection) { lwsl_err("libwebsockets not configured for ssl\n"); goto bail; } #endif /* 2) stash the things from connect_info that we can't process without * an ah. Because if no ah, we will go on the ah waiting list and * process those things later (after the connect_info and maybe the * things pointed to have gone out of scope. */ wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash)); if (!wsi->u.hdr.stash) { lwsl_err("%s: OOM\n", __func__); goto bail; } wsi->u.hdr.stash->origin[0] = '\0'; wsi->u.hdr.stash->protocol[0] = '\0'; wsi->u.hdr.stash->method[0] = '\0'; strncpy(wsi->u.hdr.stash->address, i->address, sizeof(wsi->u.hdr.stash->address) - 1); strncpy(wsi->u.hdr.stash->path, i->path, sizeof(wsi->u.hdr.stash->path) - 1); strncpy(wsi->u.hdr.stash->host, i->host, sizeof(wsi->u.hdr.stash->host) - 1); if (i->origin) strncpy(wsi->u.hdr.stash->origin, i->origin, sizeof(wsi->u.hdr.stash->origin) - 1); if (i->protocol) strncpy(wsi->u.hdr.stash->protocol, i->protocol, sizeof(wsi->u.hdr.stash->protocol) - 1); if (i->method) strncpy(wsi->u.hdr.stash->method, i->method, sizeof(wsi->u.hdr.stash->method) - 1); wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0'; wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0'; wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0'; wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0'; wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0'; wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0'; /* if we went on the waiting list, no probs just return the wsi * when we get the ah, now or later, he will call * lws_client_connect_via_info2() below. */ if (lws_header_table_attach(wsi, 0) < 0) return NULL; if (i->parent_wsi) { lwsl_info("%s: created child %p of parent %p\n", __func__, wsi, i->parent_wsi); wsi->parent = i->parent_wsi; wsi->sibling_list = i->parent_wsi->child_list; i->parent_wsi->child_list = wsi; } #ifdef LWS_WITH_HTTP_PROXY if (i->uri_replace_to) wsi->rw = lws_rewrite_create(wsi, html_parser_cb, i->uri_replace_from, i->uri_replace_to); #endif return wsi; bail: lws_free(wsi); return NULL; } struct lws * lws_client_connect_via_info2(struct lws *wsi) { struct client_info_stash *stash = wsi->u.hdr.stash; if (!stash) return wsi; /* * we're not necessarily in a position to action these right away, * stash them... we only need during connect phase so u.hdr is fine */ if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, stash->address)) goto bail1; /* these only need u.hdr lifetime as well */ if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path)) goto bail1; if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host)) goto bail1; if (stash->origin[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, stash->origin)) goto bail1; /* * this is a list of protocols we tell the server we're okay with * stash it for later when we compare server response with it */ if (stash->protocol[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, stash->protocol)) goto bail1; if (stash->method[0]) if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD, stash->method)) goto bail1; lws_free_set_NULL(wsi->u.hdr.stash); /* * Check with each extension if it is able to route and proxy this * connection for us. For example, an extension like x-google-mux * can handle this and then we don't need an actual socket for this * connection. */ if (lws_ext_cb_all_exts(wsi->context, wsi, LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION, (void *)stash->address, wsi->u.hdr.c_port) > 0) { lwsl_client("lws_client_connect: ext handling conn\n"); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE, AWAITING_TIMEOUT); wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT; return wsi; } lwsl_client("lws_client_connect: direct conn\n"); wsi->context->count_wsi_allocated++; return lws_client_connect_2(wsi); bail1: lws_free_set_NULL(wsi->u.hdr.stash); return NULL; } /** * lws_client_connect_extended() - Connect to another websocket server * DEPRECATED use lws_client_connect_via_info * @context: Websocket context * @address: Remote server address, eg, "myserver.com" * @port: Port to connect to on the remote server, eg, 80 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self * signed certs * @path: Websocket path on server * @host: Hostname on server * @origin: Socket origin name * @protocol: Comma-separated list of protocols being asked for from * the server, or just one. The server will pick the one it * likes best. * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest * protocol supported, or the specific protocol ordinal * @userdata: Pre-allocated user data * * This function creates a connection to a remote server */ LWS_VISIBLE struct lws * lws_client_connect_extended(struct lws_context *context, const char *address, int port, int ssl_connection, const char *path, const char *host, const char *origin, const char *protocol, int ietf_version_or_minus_one, void *userdata) { struct lws_client_connect_info i; memset(&i, 0, sizeof(i)); i.context = context; i.address = address; i.port = port; i.ssl_connection = ssl_connection; i.path = path; i.host = host; i.origin = origin; i.protocol = protocol; i.ietf_version_or_minus_one = ietf_version_or_minus_one; i.userdata = userdata; return lws_client_connect_via_info(&i); } /** * lws_client_connect_info() - Connect to another websocket server * DEPRECATED use lws_client_connect_via_info * @context: Websocket context * @address: Remote server address, eg, "myserver.com" * @port: Port to connect to on the remote server, eg, 80 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self * signed certs * @path: Websocket path on server * @host: Hostname on server * @origin: Socket origin name * @protocol: Comma-separated list of protocols being asked for from * the server, or just one. The server will pick the one it * likes best. If you don't want to specify a protocol, which is * legal, use NULL here. * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest * protocol supported, or the specific protocol ordinal * * This function creates a connection to a remote server */ LWS_VISIBLE struct lws * lws_client_connect(struct lws_context *context, const char *address, int port, int ssl_connection, const char *path, const char *host, const char *origin, const char *protocol, int ietf_version_or_minus_one) { struct lws_client_connect_info i; memset(&i, 0, sizeof(i)); i.context = context; i.address = address; i.port = port; i.ssl_connection = ssl_connection; i.path = path; i.host = host; i.origin = origin; i.protocol = protocol; i.ietf_version_or_minus_one = ietf_version_or_minus_one; i.userdata = NULL; return lws_client_connect_via_info(&i); } |
Added undroid/libwebsockets/lib/client-parser.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" int lws_client_rx_sm(struct lws *wsi, unsigned char c) { struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; int callback_action = LWS_CALLBACK_CLIENT_RECEIVE; int handled, n, m, rx_draining_ext = 0; unsigned short close_code; struct lws_tokens eff_buf; unsigned char *pp; if (wsi->u.ws.rx_draining_ext) { struct lws **w = &pt->rx_draining_ext_list; lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__, c); assert(!c); eff_buf.token = NULL; eff_buf.token_len = 0; wsi->u.ws.rx_draining_ext = 0; /* remove us from context draining ext list */ while (*w) { if (*w == wsi) { *w = wsi->u.ws.rx_draining_ext_list; break; } w = &((*w)->u.ws.rx_draining_ext_list); } wsi->u.ws.rx_draining_ext_list = NULL; rx_draining_ext = 1; goto drain_extension; } switch (wsi->lws_rx_parse_state) { case LWS_RXPS_NEW: /* control frames (PING) may interrupt checkable sequences */ wsi->u.ws.defeat_check_utf8 = 0; switch (wsi->ietf_spec_revision) { case 13: wsi->u.ws.opcode = c & 0xf; /* revisit if an extension wants them... */ switch (wsi->u.ws.opcode) { case LWSWSOPC_TEXT_FRAME: wsi->u.ws.rsv_first_msg = (c & 0x70); wsi->u.ws.continuation_possible = 1; wsi->u.ws.check_utf8 = lws_check_opt( wsi->context->options, LWS_SERVER_OPTION_VALIDATE_UTF8); wsi->u.ws.utf8 = 0; break; case LWSWSOPC_BINARY_FRAME: wsi->u.ws.rsv_first_msg = (c & 0x70); wsi->u.ws.check_utf8 = 0; wsi->u.ws.continuation_possible = 1; break; case LWSWSOPC_CONTINUATION: if (!wsi->u.ws.continuation_possible) { lwsl_info("disordered continuation\n"); return -1; } break; case LWSWSOPC_CLOSE: wsi->u.ws.check_utf8 = 0; wsi->u.ws.utf8 = 0; break; case 3: case 4: case 5: case 6: case 7: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf: lwsl_info("illegal opcode\n"); return -1; default: wsi->u.ws.defeat_check_utf8 = 1; break; } wsi->u.ws.rsv = (c & 0x70); /* revisit if an extension wants them... */ if ( #ifndef LWS_NO_EXTENSIONS !wsi->count_act_ext && #endif wsi->u.ws.rsv) { lwsl_info("illegal rsv bits set\n"); return -1; } wsi->u.ws.final = !!((c >> 7) & 1); lwsl_ext("%s: This RX frame Final %d\n", __func__, wsi->u.ws.final); if (wsi->u.ws.owed_a_fin && (wsi->u.ws.opcode == LWSWSOPC_TEXT_FRAME || wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME)) { lwsl_info("hey you owed us a FIN\n"); return -1; } if ((!(wsi->u.ws.opcode & 8)) && wsi->u.ws.final) { wsi->u.ws.continuation_possible = 0; wsi->u.ws.owed_a_fin = 0; } if ((wsi->u.ws.opcode & 8) && !wsi->u.ws.final) { lwsl_info("control message cannot be fragmented\n"); return -1; } if (!wsi->u.ws.final) wsi->u.ws.owed_a_fin = 1; switch (wsi->u.ws.opcode) { case LWSWSOPC_TEXT_FRAME: case LWSWSOPC_BINARY_FRAME: wsi->u.ws.frame_is_binary = wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME; break; } wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN; break; default: lwsl_err("unknown spec version %02d\n", wsi->ietf_spec_revision); break; } break; case LWS_RXPS_04_FRAME_HDR_LEN: wsi->u.ws.this_frame_masked = !!(c & 0x80); switch (c & 0x7f) { case 126: /* control frames are not allowed to have big lengths */ if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2; break; case 127: /* control frames are not allowed to have big lengths */ if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8; break; default: wsi->u.ws.rx_packet_length = c; if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { if (c) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } } break; } break; case LWS_RXPS_04_FRAME_HDR_LEN16_2: wsi->u.ws.rx_packet_length = c << 8; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1; break; case LWS_RXPS_04_FRAME_HDR_LEN16_1: wsi->u.ws.rx_packet_length |= c; if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } } break; case LWS_RXPS_04_FRAME_HDR_LEN64_8: if (c & 0x80) { lwsl_warn("b63 of length must be zero\n"); /* kill the connection */ return -1; } #if defined __LP64__ wsi->u.ws.rx_packet_length = ((size_t)c) << 56; #else wsi->u.ws.rx_packet_length = 0; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7; break; case LWS_RXPS_04_FRAME_HDR_LEN64_7: #if defined __LP64__ wsi->u.ws.rx_packet_length |= ((size_t)c) << 48; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6; break; case LWS_RXPS_04_FRAME_HDR_LEN64_6: #if defined __LP64__ wsi->u.ws.rx_packet_length |= ((size_t)c) << 40; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5; break; case LWS_RXPS_04_FRAME_HDR_LEN64_5: #if defined __LP64__ wsi->u.ws.rx_packet_length |= ((size_t)c) << 32; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4; break; case LWS_RXPS_04_FRAME_HDR_LEN64_4: wsi->u.ws.rx_packet_length |= ((size_t)c) << 24; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3; break; case LWS_RXPS_04_FRAME_HDR_LEN64_3: wsi->u.ws.rx_packet_length |= ((size_t)c) << 16; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2; break; case LWS_RXPS_04_FRAME_HDR_LEN64_2: wsi->u.ws.rx_packet_length |= ((size_t)c) << 8; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1; break; case LWS_RXPS_04_FRAME_HDR_LEN64_1: wsi->u.ws.rx_packet_length |= (size_t)c; if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } } break; case LWS_RXPS_07_COLLECT_FRAME_KEY_1: wsi->u.ws.mask[0] = c; if (c) wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_2: wsi->u.ws.mask[1] = c; if (c) wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_3: wsi->u.ws.mask[2] = c; if (c) wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_4: wsi->u.ws.mask[3] = c; if (c) wsi->u.ws.all_zero_nonce = 0; if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } break; case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED: assert(wsi->u.ws.rx_ubuf); if (wsi->u.ws.this_frame_masked && !wsi->u.ws.all_zero_nonce) c ^= wsi->u.ws.mask[(wsi->u.ws.mask_idx++) & 3]; wsi->u.ws.rx_ubuf[LWS_PRE + (wsi->u.ws.rx_ubuf_head++)] = c; if (--wsi->u.ws.rx_packet_length == 0) { /* spill because we have the whole frame */ wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } /* * if there's no protocol max frame size given, we are * supposed to default to LWS_MAX_SOCKET_IO_BUF */ if (!wsi->protocol->rx_buffer_size && wsi->u.ws.rx_ubuf_head != LWS_MAX_SOCKET_IO_BUF) break; if (wsi->protocol->rx_buffer_size && wsi->u.ws.rx_ubuf_head != wsi->protocol->rx_buffer_size) break; /* spill because we filled our rx buffer */ spill: handled = 0; /* * is this frame a control packet we should take care of at this * layer? If so service it and hide it from the user callback */ switch (wsi->u.ws.opcode) { case LWSWSOPC_CLOSE: pp = (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE]; if (lws_check_opt(wsi->context->options, LWS_SERVER_OPTION_VALIDATE_UTF8) && wsi->u.ws.rx_ubuf_head > 2 && lws_check_utf8(&wsi->u.ws.utf8, pp + 2, wsi->u.ws.rx_ubuf_head - 2)) goto utf8_fail; /* is this an acknowledgement of our close? */ if (wsi->state == LWSS_AWAITING_CLOSE_ACK) { /* * fine he has told us he is closing too, let's * finish our close */ lwsl_parser("seen server's close ack\n"); return -1; } lwsl_parser("client sees server close len = %d\n", wsi->u.ws.rx_ubuf_head); if (wsi->u.ws.rx_ubuf_head >= 2) { close_code = (pp[0] << 8) | pp[1]; if (close_code < 1000 || close_code == 1004 || close_code == 1005 || close_code == 1006 || close_code == 1012 || close_code == 1013 || close_code == 1014 || close_code == 1015 || (close_code >= 1016 && close_code < 3000) ) { pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff; pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff; } } if (user_callback_handle_rxflow( wsi->protocol->callback, wsi, LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, wsi->user_space, pp, wsi->u.ws.rx_ubuf_head)) return -1; /* * parrot the close packet payload back * we do not care about how it went, we are closing * immediately afterwards */ lws_write(wsi, (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE], wsi->u.ws.rx_ubuf_head, LWS_WRITE_CLOSE); wsi->state = LWSS_RETURNED_CLOSE_ALREADY; /* close the connection */ return -1; case LWSWSOPC_PING: lwsl_info("received %d byte ping, sending pong\n", wsi->u.ws.rx_ubuf_head); /* he set a close reason on this guy, ignore PING */ if (wsi->u.ws.close_in_ping_buffer_len) goto ping_drop; if (wsi->u.ws.ping_pending_flag) { /* * there is already a pending ping payload * we should just log and drop */ lwsl_parser("DROP PING since one pending\n"); goto ping_drop; } /* control packets can only be < 128 bytes long */ if (wsi->u.ws.rx_ubuf_head > 128 - 3) { lwsl_parser("DROP PING payload too large\n"); goto ping_drop; } /* stash the pong payload */ memcpy(wsi->u.ws.ping_payload_buf + LWS_PRE, &wsi->u.ws.rx_ubuf[LWS_PRE], wsi->u.ws.rx_ubuf_head); wsi->u.ws.ping_payload_len = wsi->u.ws.rx_ubuf_head; wsi->u.ws.ping_pending_flag = 1; /* get it sent as soon as possible */ lws_callback_on_writable(wsi); ping_drop: wsi->u.ws.rx_ubuf_head = 0; handled = 1; break; case LWSWSOPC_PONG: lwsl_info("client receied pong\n"); lwsl_hexdump(&wsi->u.ws.rx_ubuf[LWS_PRE], wsi->u.ws.rx_ubuf_head); /* issue it */ callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG; break; case LWSWSOPC_CONTINUATION: case LWSWSOPC_TEXT_FRAME: case LWSWSOPC_BINARY_FRAME: break; default: lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode); /* * It's something special we can't understand here. * Pass the payload up to the extension's parsing * state machine. */ eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE]; eff_buf.token_len = wsi->u.ws.rx_ubuf_head; if (lws_ext_cb_active(wsi, LWS_EXT_CB_EXTENDED_PAYLOAD_RX, &eff_buf, 0) <= 0) { /* not handle or fail */ lwsl_ext("Unhandled ext opc 0x%x\n", wsi->u.ws.opcode); wsi->u.ws.rx_ubuf_head = 0; return 0; } handled = 1; break; } /* * No it's real payload, pass it up to the user callback. * It's nicely buffered with the pre-padding taken care of * so it can be sent straight out again using lws_write */ if (handled) goto already_done; eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE]; eff_buf.token_len = wsi->u.ws.rx_ubuf_head; drain_extension: n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0); lwsl_ext("Ext RX returned %d\n", n); if (n < 0) /* fail */ return -1; lwsl_ext("post inflate eff_buf len %d\n", eff_buf.token_len); if (rx_draining_ext && !eff_buf.token_len) { lwsl_err(" --- ignoring zero drain result, ending drain\n"); goto already_done; } if (wsi->u.ws.check_utf8 && !wsi->u.ws.defeat_check_utf8) { if (lws_check_utf8(&wsi->u.ws.utf8, (unsigned char *)eff_buf.token, eff_buf.token_len)) goto utf8_fail; /* we are ending partway through utf-8 character? */ if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final && wsi->u.ws.utf8 && !n) { lwsl_info("FINAL utf8 error\n"); utf8_fail: lwsl_info("utf8 error\n"); return -1; } } if (eff_buf.token_len < 0 && callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG) goto already_done; if (!eff_buf.token) goto already_done; eff_buf.token[eff_buf.token_len] = '\0'; if (!wsi->protocol->callback) goto already_done; if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG) lwsl_info("Client doing pong callback\n"); if (n && eff_buf.token_len) { /* extension had more... main loop will come back * we want callback to be done with this set, if so, * because lws_is_final() hides it was final until the * last chunk */ wsi->u.ws.rx_draining_ext = 1; wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list; pt->rx_draining_ext_list = wsi; lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__); } if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY || wsi->state == LWSS_AWAITING_CLOSE_ACK) goto already_done; m = wsi->protocol->callback(wsi, (enum lws_callback_reasons)callback_action, wsi->user_space, eff_buf.token, eff_buf.token_len); /* if user code wants to close, let caller know */ if (m) return 1; already_done: wsi->u.ws.rx_ubuf_head = 0; break; default: lwsl_err("client rx illegal state\n"); return 1; } return 0; illegal_ctl_length: lwsl_warn("Control frame asking for extended length is illegal\n"); /* kill the connection */ return -1; } |
Added undroid/libwebsockets/lib/client.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" int lws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) { int m; switch (wsi->mode) { case LWSCM_WSCL_WAITING_PROXY_REPLY: case LWSCM_WSCL_ISSUE_HANDSHAKE: case LWSCM_WSCL_WAITING_SERVER_REPLY: case LWSCM_WSCL_WAITING_EXTENSION_CONNECT: case LWSCM_WS_CLIENT: while (len) { /* * we were accepting input but now we stopped doing so */ if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) { lwsl_debug("%s: caching %d\n", __func__, len); lws_rxflow_cache(wsi, *buf, 0, len); return 0; } if (wsi->u.ws.rx_draining_ext) { m = lws_rx_sm(wsi, 0); if (m < 0) return -1; continue; } /* account for what we're using in rxflow buffer */ if (wsi->rxflow_buffer) wsi->rxflow_pos++; if (lws_client_rx_sm(wsi, *(*buf)++)) { lwsl_debug("client_rx_sm exited\n"); return -1; } len--; } lwsl_debug("%s: finished with %d\n", __func__, len); return 0; default: break; } return 0; } int lws_client_socket_service(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pollfd) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char *p = (char *)&pt->serv_buf[0]; char *sb = p; unsigned char c; int n, len; switch (wsi->mode) { case LWSCM_WSCL_WAITING_CONNECT: /* * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE * timeout protection set in client-handshake.c */ if (!lws_client_connect_2(wsi)) { /* closed */ lwsl_client("closed\n"); return -1; } /* either still pending connection, or changed mode */ return 0; case LWSCM_WSCL_WAITING_PROXY_REPLY: /* handle proxy hung up on us */ if (pollfd->revents & LWS_POLLHUP) { lwsl_warn("Proxy connection %p (fd=%d) dead\n", (void *)wsi, pollfd->fd); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } n = recv(wsi->sock, sb, LWS_MAX_SOCKET_IO_BUF, 0); if (n < 0) { if (LWS_ERRNO == LWS_EAGAIN) { lwsl_debug("Proxy read returned EAGAIN... retrying\n"); return 0; } lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); lwsl_err("ERROR reading from proxy socket\n"); return 0; } pt->serv_buf[13] = '\0'; if (strcmp(sb, "HTTP/1.0 200 ") && strcmp(sb, "HTTP/1.1 200 ")) { lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); lwsl_err("ERROR proxy: %s\n", sb); return 0; } /* clear his proxy connection timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); /* fallthru */ case LWSCM_WSCL_ISSUE_HANDSHAKE: /* * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE * timeout protection set in client-handshake.c * * take care of our lws_callback_on_writable * happening at a time when there's no real connection yet */ if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) return -1; #ifdef LWS_OPENSSL_SUPPORT /* we can retry this... just cook the SSL BIO the first time */ if (wsi->use_ssl && !wsi->ssl) { if (lws_ssl_client_bio_create(wsi)) return -1; } if (wsi->use_ssl) { n = lws_ssl_client_connect1(wsi); if (!n) return 0; if (n < 0) goto bail3; } else wsi->ssl = NULL; /* fallthru */ case LWSCM_WSCL_WAITING_SSL: if (wsi->use_ssl) { n = lws_ssl_client_connect2(wsi); if (!n) return 0; if (n < 0) goto bail3; } else wsi->ssl = NULL; #endif wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, context->timeout_secs); /* fallthru */ case LWSCM_WSCL_ISSUE_HANDSHAKE2: p = lws_generate_client_handshake(wsi, p); if (p == NULL) { lwsl_err("Failed to generate handshake for client\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } /* send our request to the server */ lws_latency_pre(context, wsi); n = lws_ssl_capable_write(wsi, (unsigned char *)sb, p - sb); lws_latency(context, wsi, "send lws_issue_raw", n, n == p - sb); switch (n) { case LWS_SSL_CAPABLE_ERROR: lwsl_debug("ERROR writing to client socket\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; case LWS_SSL_CAPABLE_MORE_SERVICE: lws_callback_on_writable(wsi); break; } wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; wsi->u.hdr.lextable_pos = 0; wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, context->timeout_secs); break; case LWSCM_WSCL_WAITING_SERVER_REPLY: /* handle server hung up on us */ if (pollfd->revents & LWS_POLLHUP) { lwsl_debug("Server connection %p (fd=%d) dead\n", (void *)wsi, pollfd->fd); goto bail3; } if (!(pollfd->revents & LWS_POLLIN)) break; /* interpret the server response */ /* * HTTP/1.1 101 Switching Protocols * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo= * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC== * Sec-WebSocket-Protocol: chat */ /* * we have to take some care here to only take from the * socket bytewise. The browser may (and has been seen to * in the case that onopen() performs websocket traffic) * coalesce both handshake response and websocket traffic * in one packet, since at that point the connection is * definitively ready from browser pov. */ len = 1; while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && len > 0) { n = lws_ssl_capable_read(wsi, &c, 1); lws_latency(context, wsi, "send lws_issue_raw", n, n == 1); switch (n) { case 0: case LWS_SSL_CAPABLE_ERROR: goto bail3; case LWS_SSL_CAPABLE_MORE_SERVICE: return 0; } if (lws_parse(wsi, c)) { lwsl_warn("problems parsing header\n"); goto bail3; } } /* * hs may also be coming in multiple packets, there is a 5-sec * libwebsocket timeout still active here too, so if parsing did * not complete just wait for next packet coming in this state */ if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) break; /* * otherwise deal with the handshake. If there's any * packet traffic already arrived we'll trigger poll() again * right away and deal with it that way */ return lws_client_interpret_server_handshake(wsi); bail3: lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n"); wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, NULL, 0); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return -1; case LWSCM_WSCL_WAITING_EXTENSION_CONNECT: lwsl_ext("LWSCM_WSCL_WAITING_EXTENSION_CONNECT\n"); break; case LWSCM_WSCL_PENDING_CANDIDATE_CHILD: lwsl_ext("LWSCM_WSCL_PENDING_CANDIDATE_CHILD\n"); break; default: break; } return 0; } /* * In-place str to lower case */ static void strtolower(char *s) { while (*s) { *s = tolower((int)*s); s++; } } /** * lws_http_transaction_completed() - wait for new http transaction or close * @wsi: websocket connection * * Returns 1 if the HTTP connection must close now * Returns 0 and resets connection to wait for new HTTP header / * transaction if possible */ int LWS_WARN_UNUSED_RESULT lws_http_transaction_completed_client(struct lws *wsi) { lwsl_debug("%s: wsi %p\n", __func__, wsi); /* if we can't go back to accept new headers, drop the connection */ if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) { lwsl_info("%s: %p: close connection\n", __func__, wsi); return 1; } /* otherwise set ourselves up ready to go again */ wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED; wsi->mode = LWSCM_HTTP_CLIENT_ACCEPTED; wsi->u.http.content_length = 0; wsi->hdr_parsing_completed = 0; /* He asked for it to stay alive indefinitely */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); /* * As client, nothing new is going to come until we ask for it * we can drop the ah, if any */ if (wsi->u.hdr.ah) { wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; lws_header_table_detach(wsi, 0); } /* If we're (re)starting on headers, need other implied init */ wsi->u.hdr.ues = URIES_IDLE; lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi); return 0; } int lws_client_interpret_server_handshake(struct lws *wsi) { int n, len, okay = 0, isErrorCodeReceived = 0, port = 0, ssl = 0; int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR; const char *pc, *prot, *ads = NULL, *path; struct allocated_headers *ah; char *p; #ifndef LWS_NO_EXTENSIONS struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char *sb = (char *)&pt->serv_buf[0]; const struct lws_ext_options *opts; const struct lws_extension *ext; char ext_name[128]; const char *c, *a; char ignore; int more = 1; void *v; #endif if (!wsi->do_ws) { /* we are being an http client... */ ah = wsi->u.hdr.ah; lws_union_transition(wsi, LWSCM_HTTP_CLIENT_ACCEPTED); wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED; wsi->u.http.ah = ah; } /* * well, what the server sent looked reasonable for syntax. * Now let's confirm it sent all the necessary headers * * http (non-ws) client will expect something like this * * HTTP/1.0.200 * server:.libwebsockets * content-type:.text/html * content-length:.17703 * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000 * * * */ wsi->u.http.connection_type = HTTP_CONNECTION_KEEP_ALIVE; p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP); if (wsi->do_ws && !p) { lwsl_info("no URI\n"); goto bail3; } if (!p) { p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0); wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE; } if (!p) { lwsl_info("no URI\n"); goto bail3; } n = atoi(p); if (n == 301 || n == 302 || n == 303 || n == 307 || n == 308) { p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION); if (!p) goto bail3; if (lws_parse_uri(p, &prot, &ads, &port, &path)) goto bail3; if (!strcmp(prot, "wss://") || !strcmp(prot, "https://")) ssl = 1; if (lws_client_reset(wsi, ssl, ads, port, path, ads)) { lwsl_err("Redirect failed\n"); goto bail3; } return 0; } if (!wsi->do_ws) { if (n != 200) { lwsl_notice("Connection failed with code %d", n); goto bail2; } #ifdef LWS_WITH_HTTP_PROXY wsi->perform_rewrite = 0; if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { if (!strncmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE), "text/html", 9)) wsi->perform_rewrite = 1; } #endif /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { lwsl_err("Problem allocating wsi user mem\n"); goto bail2; } /* he may choose to send us stuff in chunked transfer-coding */ wsi->chunked = 0; wsi->chunk_remaining = 0; /* ie, next thing is chunk size */ if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING)) { wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING), "chunked"); /* first thing is hex, after payload there is crlf */ wsi->chunk_parser = ELCP_HEX; } if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { wsi->u.http.content_length = atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)); lwsl_notice("%s: incoming content length %d\n", __func__, wsi->u.http.content_length); wsi->u.http.content_remain = wsi->u.http.content_length; } else /* can't do 1.1 without a content length or chunked */ if (!wsi->chunked) wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE; /* * we seem to be good to go, give client last chance to check * headers and OK it */ if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, wsi->user_space, NULL, 0)) goto bail2; /* clear his proxy connection timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; /* call him back to inform him he is up */ if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, wsi->user_space, NULL, 0)) goto bail3; /* free up his parsing allocations */ lws_header_table_detach(wsi, 0); lwsl_notice("%s: client connection up\n", __func__); return 0; } if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) { lwsl_info("no ACCEPT\n"); isErrorCodeReceived = 1; goto bail3; } if (p && strncmp(p, "101", 3)) { lwsl_warn( "lws_client_handshake: got bad HTTP response '%s'\n", p); goto bail3; } p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE); if (!p) { lwsl_info("no UPGRADE\n"); goto bail3; } strtolower(p); if (strcmp(p, "websocket")) { lwsl_warn( "lws_client_handshake: got bad Upgrade header '%s'\n", p); goto bail3; } p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION); if (!p) { lwsl_info("no Connection hdr\n"); goto bail3; } strtolower(p); if (strcmp(p, "upgrade")) { lwsl_warn("lws_client_int_s_hs: bad header %s\n", p); goto bail3; } pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); if (!pc) { lwsl_parser("lws_client_int_s_hs: no protocol list\n"); } else lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc); /* * confirm the protocol the server wants to talk was in the list * of protocols we offered */ len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL); if (!len) { lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n"); /* * no protocol name to work from, * default to first protocol */ wsi->protocol = &wsi->vhost->protocols[0]; goto check_extensions; } p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL); len = strlen(p); while (pc && *pc && !okay) { if (!strncmp(pc, p, len) && (pc[len] == ',' || pc[len] == '\0')) { okay = 1; continue; } while (*pc && *pc++ != ',') ; while (*pc && *pc == ' ') pc++; } if (!okay) { lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p); goto bail2; } /* * identify the selected protocol struct and set it */ n = 0; wsi->protocol = NULL; while (wsi->vhost->protocols[n].callback && !wsi->protocol) { if (strcmp(p, wsi->vhost->protocols[n].name) == 0) { wsi->protocol = &wsi->vhost->protocols[n]; break; } n++; } if (wsi->protocol == NULL) { lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p); goto bail2; } check_extensions: #ifndef LWS_NO_EXTENSIONS /* instantiate the accepted extensions */ if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) { lwsl_ext("no client extensions allowed by server\n"); goto check_accept; } /* * break down the list of server accepted extensions * and go through matching them or identifying bogons */ if (lws_hdr_copy(wsi, sb, LWS_MAX_SOCKET_IO_BUF, WSI_TOKEN_EXTENSIONS) < 0) { lwsl_warn("ext list from server failed to copy\n"); goto bail2; } c = sb; n = 0; ignore = 0; a = NULL; while (more) { if (*c && (*c != ',' && *c != '\t')) { if (*c == ';') { ignore = 1; if (!a) a = c + 1; } if (ignore || *c == ' ') { c++; continue; } ext_name[n] = *c++; if (n < sizeof(ext_name) - 1) n++; continue; } ext_name[n] = '\0'; ignore = 0; if (!*c) more = 0; else { c++; if (!n) continue; } /* check we actually support it */ lwsl_notice("checking client ext %s\n", ext_name); n = 0; ext = wsi->vhost->extensions; while (ext && ext->callback) { if (strcmp(ext_name, ext->name)) { ext++; continue; } n = 1; lwsl_notice("instantiating client ext %s\n", ext_name); /* instantiate the extension on this conn */ wsi->active_extensions[wsi->count_act_ext] = ext; /* allow him to construct his ext instance */ if (ext->callback(lws_get_context(wsi), ext, wsi, LWS_EXT_CB_CLIENT_CONSTRUCT, (void *)&wsi->act_ext_user[wsi->count_act_ext], (void *)&opts, 0)) { lwsl_notice(" ext %s failed construction\n", ext_name); ext++; continue; } /* * allow the user code to override ext defaults if it * wants to */ ext_name[0] = '\0'; if (user_callback_handle_rxflow(wsi->protocol->callback, wsi, LWS_CALLBACK_WS_EXT_DEFAULTS, (char *)ext->name, ext_name, sizeof(ext_name))) goto bail2; if (ext_name[0] && lws_ext_parse_options(ext, wsi, wsi->act_ext_user[ wsi->count_act_ext], opts, ext_name, strlen(ext_name))) { lwsl_err("%s: unable to parse user defaults '%s'", __func__, ext_name); goto bail2; } /* * give the extension the server options */ if (a && lws_ext_parse_options(ext, wsi, wsi->act_ext_user[wsi->count_act_ext], opts, a, c - a)) { lwsl_err("%s: unable to parse remote def '%s'", __func__, a); goto bail2; } if (ext->callback(lws_get_context(wsi), ext, wsi, LWS_EXT_CB_OPTION_CONFIRM, wsi->act_ext_user[wsi->count_act_ext], NULL, 0)) { lwsl_err("%s: ext %s rejects server options %s", ext->name, a); goto bail2; } wsi->count_act_ext++; ext++; } if (n == 0) { lwsl_warn("Unknown ext '%s'!\n", ext_name); goto bail2; } a = NULL; n = 0; } check_accept: #endif /* * Confirm his accept token is the one we precomputed */ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT); if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) { lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p, wsi->u.hdr.ah->initial_handshake_hash_base64); goto bail2; } /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { lwsl_err("Problem allocating wsi user mem\n"); goto bail2; } /* * we seem to be good to go, give client last chance to check * headers and OK it */ if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, wsi->user_space, NULL, 0)) goto bail2; /* clear his proxy connection timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); /* free up his parsing allocations */ lws_header_table_detach(wsi, 0); lws_union_transition(wsi, LWSCM_WS_CLIENT); wsi->state = LWSS_ESTABLISHED; wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; /* * create the frame buffer for this connection according to the * size mentioned in the protocol definition. If 0 there, then * use a big default for compatibility */ n = wsi->protocol->rx_buffer_size; if (!n) n = LWS_MAX_SOCKET_IO_BUF; n += LWS_PRE; wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */); if (!wsi->u.ws.rx_ubuf) { lwsl_err("Out of Mem allocating rx buffer %d\n", n); goto bail2; } wsi->u.ws.rx_ubuf_alloc = n; lwsl_info("Allocating client RX buffer %d\n", n); if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) { lwsl_warn("Failed to set SNDBUF to %d", n); goto bail3; } lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name); /* call him back to inform him he is up */ if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED, wsi->user_space, NULL, 0)) goto bail3; #ifndef LWS_NO_EXTENSIONS /* * inform all extensions, not just active ones since they * already know */ ext = wsi->vhost->extensions; while (ext && ext->callback) { v = NULL; for (n = 0; n < wsi->count_act_ext; n++) if (wsi->active_extensions[n] == ext) v = wsi->act_ext_user[n]; ext->callback(context, ext, wsi, LWS_EXT_CB_ANY_WSI_ESTABLISHED, v, NULL, 0); ext++; } #endif return 0; bail3: close_reason = LWS_CLOSE_STATUS_NOSTATUS; bail2: if (wsi->protocol && wsi->state == LWSS_ESTABLISHED) { if (isErrorCodeReceived && p) { wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, p, (unsigned int)strlen(p)); } else { wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, NULL, 0); } } lwsl_info("closing connection due to bail2 connection error\n"); /* closing will free up his parsing allocations */ lws_close_free_wsi(wsi, close_reason); return 1; } char * lws_generate_client_handshake(struct lws *wsi, char *pkt) { char buf[128], hash[20], key_b64[40], *p = pkt; struct lws_context *context = wsi->context; const char *meth; int n; #ifndef LWS_NO_EXTENSIONS const struct lws_extension *ext; int ext_count = 0; #endif meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD); if (!meth) { meth = "GET"; wsi->do_ws = 1; } else wsi->do_ws = 0; if (wsi->do_ws) { /* * create the random key */ n = lws_get_random(context, hash, 16); if (n != 16) { lwsl_err("Unable to read from random dev %s\n", SYSTEM_RANDOM_FILEPATH); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return NULL; } lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64)); } /* * 04 example client handshake * * GET /chat HTTP/1.1 * Host: server.example.com * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 4 */ p += sprintf(p, "%s %s HTTP/1.1\x0d\x0a", meth, lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI)); p += sprintf(p, "Pragma: no-cache\x0d\x0a" "Cache-Control: no-cache\x0d\x0a"); p += sprintf(p, "Host: %s\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST)); if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) p += sprintf(p, "Origin: http://%s\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)); if (wsi->do_ws) { p += sprintf(p, "Upgrade: websocket\x0d\x0a" "Connection: Upgrade\x0d\x0a" "Sec-WebSocket-Key: "); strcpy(p, key_b64); p += strlen(key_b64); p += sprintf(p, "\x0d\x0a"); if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS)) p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS)); /* tell the server what extensions we could support */ #ifndef LWS_NO_EXTENSIONS ext = wsi->vhost->extensions; while (ext && ext->callback) { n = lws_ext_cb_all_exts(context, wsi, LWS_EXT_CB_CHECK_OK_TO_PROPOSE_EXTENSION, (char *)ext->name, 0); if (n) { /* an extension vetos us */ lwsl_ext("ext %s vetoed\n", (char *)ext->name); ext++; continue; } n = wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED, wsi->user_space, (char *)ext->name, 0); /* * zero return from callback means * go ahead and allow the extension, * it's what we get if the callback is * unhandled */ if (n) { ext++; continue; } /* apply it */ if (ext_count) *p++ = ','; else p += sprintf(p, "Sec-WebSocket-Extensions: "); p += sprintf(p, "%s", ext->client_offer); ext_count++; ext++; } if (ext_count) p += sprintf(p, "\x0d\x0a"); #endif if (wsi->ietf_spec_revision) p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a", wsi->ietf_spec_revision); /* prepare the expected server accept response */ key_b64[39] = '\0'; /* enforce composed length below buf sizeof */ n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64); lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash); lws_b64_encode_string(hash, 20, wsi->u.hdr.ah->initial_handshake_hash_base64, sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64)); } /* give userland a chance to append, eg, cookies */ wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, wsi->user_space, &p, (pkt + LWS_MAX_SOCKET_IO_BUF) - p - 12); p += sprintf(p, "\x0d\x0a"); return p; } |
Added undroid/libwebsockets/lib/context.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" #ifndef LWS_BUILD_HASH #define LWS_BUILD_HASH "unknown-build-hash" #endif static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH; /** * lws_get_library_version: get version and git hash library built from * * returns a const char * to a string like "1.1 178d78c" * representing the library version followed by the git head hash it * was built from */ LWS_VISIBLE const char * lws_get_library_version(void) { return library_version; } static const char * const mount_protocols[] = { "http://", "https://", "file://", "cgi://", ">http://", ">https://", }; LWS_VISIBLE void * lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot, int size) { int n = 0; /* allocate the vh priv array only on demand */ if (!vhost->protocol_vh_privs) { vhost->protocol_vh_privs = (void **)lws_zalloc( vhost->count_protocols * sizeof(void *)); if (!vhost->protocol_vh_privs) return NULL; } while (n < vhost->count_protocols && &vhost->protocols[n] != prot) n++; if (n == vhost->count_protocols) return NULL; vhost->protocol_vh_privs[n] = lws_zalloc(size); return vhost->protocol_vh_privs[n]; } LWS_VISIBLE void * lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *prot) { int n = 0; if (!vhost->protocol_vh_privs) return NULL; while (n < vhost->count_protocols && &vhost->protocols[n] != prot) n++; if (n == vhost->count_protocols) { lwsl_err("%s: unknown protocol %p\n", __func__, prot); return NULL; } return vhost->protocol_vh_privs[n]; } static const struct lws_protocol_vhost_options * lws_vhost_protocol_options(struct lws_vhost *vh, const char *name) { const struct lws_protocol_vhost_options *pvo = vh->pvo; while (pvo) { // lwsl_notice("%s: '%s' '%s'\n", __func__, pvo->name, name); if (!strcmp(pvo->name, name)) return pvo; pvo = pvo->next; } return NULL; } int lws_protocol_init(struct lws_context *context) { struct lws_vhost *vh = context->vhost_list; const struct lws_protocol_vhost_options *pvo, *pvo1; struct lws wsi; int n; memset(&wsi, 0, sizeof(wsi)); wsi.context = context; lwsl_notice("%s\n", __func__); while (vh) { wsi.vhost = vh; /* initialize supported protocols on this vhost */ for (n = 0; n < vh->count_protocols; n++) { wsi.protocol = &vh->protocols[n]; pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name); if (pvo) { /* * linked list of options specific to * vh + protocol */ pvo1 = pvo; pvo = pvo1->options; while (pvo) { lwsl_notice(" vh %s prot %s opt %s\n", vh->name, vh->protocols[n].name, pvo->name); if (!strcmp(pvo->name, "default")) { lwsl_notice("Setting default " "protocol for vh %s to %s\n", vh->name, vh->protocols[n].name); vh->default_protocol_index = n; } pvo = pvo->next; } pvo = pvo1->options; } /* * inform all the protocols that they are doing their one-time * initialization if they want to. * * NOTE the wsi is all zeros except for the context, vh and * protocol ptrs so lws_get_context(wsi) etc can work */ vh->protocols[n].callback(&wsi, LWS_CALLBACK_PROTOCOL_INIT, NULL, (void *)pvo, 0); } vh = vh->vhost_next; } context->protocol_init_done = 1; return 0; } static int callback_http_dummy( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { return 0; } /* list of supported protocols and callbacks */ static const struct lws_protocols protocols_dummy[] = { /* first protocol must always be HTTP handler */ { "http-only", /* name */ callback_http_dummy, /* callback */ 0, /* per_session_data_size */ 0, /* max frame size / rx buffer */ }, /* * the other protocols are provided by lws plugins */ { NULL, NULL, 0, 0 } /* terminator */ }; LWS_VISIBLE struct lws_vhost * lws_create_vhost(struct lws_context *context, struct lws_context_creation_info *info) { struct lws_vhost *vh = lws_zalloc(sizeof(*vh)), **vh1 = &context->vhost_list; const struct lws_http_mount *mounts; #ifdef LWS_WITH_PLUGINS struct lws_plugin *plugin = context->plugin_list; struct lws_protocols *lwsp; int m, n, f = !info->pvo; #endif char *p; if (!vh) return NULL; if (!info->protocols) info->protocols = &protocols_dummy[0]; vh->context = context; if (!info->vhost_name) vh->name = "default"; else vh->name = info->vhost_name; vh->iface = info->iface; for (vh->count_protocols = 0; info->protocols[vh->count_protocols].callback; vh->count_protocols++) ; vh->options = info->options; vh->pvo = info->pvo; vh->keepalive_timeout = info->keepalive_timeout; #ifdef LWS_WITH_PLUGINS if (plugin) { /* * give the vhost a unified list of protocols including the * ones that came from plugins */ lwsp = lws_zalloc(sizeof(struct lws_protocols) * (vh->count_protocols + context->plugin_protocol_count + 1)); if (!lwsp) return NULL; m = vh->count_protocols; memcpy(lwsp, info->protocols, sizeof(struct lws_protocols) * m); /* for compatibility, all protocols enabled on vhost if only * the default vhost exists. Otherwise only vhosts who ask * for a protocol get it enabled. */ if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS) f = 0; while (plugin) { for (n = 0; n < plugin->caps.count_protocols; n++) { /* * for compatibility's sake, no pvo implies * allow all protocols */ if (f || lws_vhost_protocol_options(vh, plugin->caps.protocols[n].name)) { memcpy(&lwsp[m], &plugin->caps.protocols[n], sizeof(struct lws_protocols)); m++; vh->count_protocols++; } } plugin = plugin->list; } vh->protocols = lwsp; } else #endif vh->protocols = info->protocols; vh->same_vh_protocol_list = (struct lws **) lws_zalloc(sizeof(struct lws *) * vh->count_protocols); vh->mount_list = info->mounts; #ifdef LWS_USE_UNIX_SOCK if (LWS_UNIX_SOCK_ENABLED(context)) { lwsl_notice("Creating Vhost '%s' path \"%s\", %d protocols\n", vh->name, info->iface, vh->count_protocols); } else #endif lwsl_notice("Creating Vhost '%s' port %d, %d protocols\n", vh->name, info->port, vh->count_protocols); mounts = info->mounts; while (mounts) { lwsl_notice(" mounting %s%s to %s\n", mount_protocols[mounts->origin_protocol], mounts->origin, mounts->mountpoint); mounts = mounts->mount_next; } #ifndef LWS_NO_EXTENSIONS #ifdef LWS_WITH_PLUGINS if (context->plugin_extension_count) { m = 0; while (info->extensions && info->extensions[m].callback) m++; /* * give the vhost a unified list of extensions including the * ones that came from plugins */ vh->extensions = lws_zalloc(sizeof(struct lws_extension) * (m + context->plugin_extension_count + 1)); if (!vh->extensions) return NULL; memcpy((struct lws_extension *)vh->extensions, info->extensions, sizeof(struct lws_extension) * m); plugin = context->plugin_list; while (plugin) { memcpy((struct lws_extension *)&vh->extensions[m], plugin->caps.extensions, sizeof(struct lws_extension) * plugin->caps.count_extensions); m += plugin->caps.count_extensions; plugin = plugin->list; } } else #endif vh->extensions = info->extensions; #endif vh->listen_port = info->port; vh->http_proxy_port = 0; vh->http_proxy_address[0] = '\0'; /* either use proxy from info, or try get it from env var */ if (info->http_proxy_address) { /* override for backwards compatibility */ if (info->http_proxy_port) vh->http_proxy_port = info->http_proxy_port; lws_set_proxy(vh, info->http_proxy_address); } else { #ifdef LWS_HAVE_GETENV p = getenv("http_proxy"); if (p) lws_set_proxy(vh, p); #endif } vh->ka_time = info->ka_time; vh->ka_interval = info->ka_interval; vh->ka_probes = info->ka_probes; if (vh->options & LWS_SERVER_OPTION_STS) lwsl_notice(" STS enabled\n"); #ifdef LWS_WITH_ACCESS_LOG if (info->log_filepath) { vh->log_fd = open(info->log_filepath, O_CREAT | O_APPEND | O_RDWR, 0600); if (vh->log_fd == LWS_INVALID_FILE) { lwsl_err("unable to open log filepath %s\n", info->log_filepath); goto bail; } #ifndef WIN32 if (context->uid != -1) if (chown(info->log_filepath, context->uid, context->gid) == -1) lwsl_err("unable to chown log file %s\n", info->log_filepath); #endif } else vh->log_fd = LWS_INVALID_FILE; #endif if (lws_context_init_server_ssl(info, vh)) goto bail; if (lws_context_init_client_ssl(info, vh)) goto bail; if (lws_context_init_server(info, vh)) goto bail; while (1) { if (!(*vh1)) { *vh1 = vh; break; } vh1 = &(*vh1)->vhost_next; }; return vh; bail: lws_free(vh); return NULL; } /** * lws_create_context() - Create the websocket handler * @info: pointer to struct with parameters * * This function creates the listening socket (if serving) and takes care * of all initialization in one step. * * After initialization, it returns a struct lws_context * that * represents this server. After calling, user code needs to take care * of calling lws_service() with the context pointer to get the * server's sockets serviced. This must be done in the same process * context as the initialization call. * * The protocol callback functions are called for a handful of events * including http requests coming in, websocket connections becoming * established, and data arriving; it's also called periodically to allow * async transmission. * * HTTP requests are sent always to the FIRST protocol in @protocol, since * at that time websocket protocol has not been negotiated. Other * protocols after the first one never see any HTTP callack activity. * * The server created is a simple http server by default; part of the * websocket standard is upgrading this http connection to a websocket one. * * This allows the same server to provide files like scripts and favicon / * images or whatever over http and dynamic data over websockets all in * one place; they're all handled in the user callback. */ LWS_VISIBLE struct lws_context * lws_create_context(struct lws_context_creation_info *info) { struct lws_context *context = NULL; struct lws wsi; #ifndef LWS_NO_DAEMONIZE int pid_daemon = get_daemonize_pid(); #endif int n, m; #if defined(__ANDROID__) struct rlimit rt; #endif lwsl_notice("Initial logging level %d\n", log_level); lwsl_notice("Libwebsockets version: %s\n", library_version); #if LWS_POSIX #ifdef LWS_USE_IPV6 if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6)) lwsl_notice("IPV6 compiled in and enabled\n"); else lwsl_notice("IPV6 compiled in but disabled\n"); #else lwsl_notice("IPV6 not compiled in\n"); #endif lws_feature_status_libev(info); lws_feature_status_libuv(info); #endif lwsl_info(" LWS_DEF_HEADER_LEN : %u\n", LWS_DEF_HEADER_LEN); lwsl_info(" LWS_MAX_PROTOCOLS : %u\n", LWS_MAX_PROTOCOLS); lwsl_info(" LWS_MAX_SMP : %u\n", LWS_MAX_SMP); lwsl_info(" SPEC_LATEST_SUPPORTED : %u\n", SPEC_LATEST_SUPPORTED); lwsl_info(" sizeof (*info) : %u\n", sizeof(*info)); #if LWS_POSIX lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); #endif if (lws_plat_context_early_init()) return NULL; context = lws_zalloc(sizeof(struct lws_context)); if (!context) { lwsl_err("No memory for websocket context\n"); return NULL; } context->time_up = time(NULL); #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { context->started_with_parent = pid_daemon; lwsl_notice(" Started with daemon pid %d\n", pid_daemon); } #endif #if defined(__ANDROID__) n = getrlimit ( RLIMIT_NOFILE,&rt); if (-1 == n) { lwsl_err("Get RLIMIT_NOFILE failed!\n"); return NULL; } context->max_fds = rt.rlim_cur; #else context->max_fds = getdtablesize(); #endif if (info->count_threads) context->count_threads = info->count_threads; else context->count_threads = 1; if (context->count_threads > LWS_MAX_SMP) context->count_threads = LWS_MAX_SMP; context->token_limits = info->token_limits; context->options = info->options; if (info->timeout_secs) context->timeout_secs = info->timeout_secs; else context->timeout_secs = AWAITING_TIMEOUT; lwsl_info(" default timeout (secs): %u\n", context->timeout_secs); if (info->max_http_header_data) context->max_http_header_data = info->max_http_header_data; else context->max_http_header_data = LWS_DEF_HEADER_LEN; if (info->max_http_header_pool) context->max_http_header_pool = info->max_http_header_pool; else context->max_http_header_pool = LWS_DEF_HEADER_POOL; /* * Allocate the per-thread storage for scratchpad buffers, * and header data pool */ for (n = 0; n < context->count_threads; n++) { context->pt[n].serv_buf = lws_zalloc(LWS_MAX_SOCKET_IO_BUF); if (!context->pt[n].serv_buf) { lwsl_err("OOM\n"); return NULL; } context->pt[n].context = context; context->pt[n].tid = n; context->pt[n].http_header_data = lws_malloc(context->max_http_header_data * context->max_http_header_pool); if (!context->pt[n].http_header_data) goto bail; context->pt[n].ah_pool = lws_zalloc(sizeof(struct allocated_headers) * context->max_http_header_pool); for (m = 0; m < context->max_http_header_pool; m++) context->pt[n].ah_pool[m].data = (char *)context->pt[n].http_header_data + (m * context->max_http_header_data); if (!context->pt[n].ah_pool) goto bail; lws_pt_mutex_init(&context->pt[n]); } if (info->fd_limit_per_thread) context->fd_limit_per_thread = info->fd_limit_per_thread; else context->fd_limit_per_thread = context->max_fds / context->count_threads; lwsl_notice(" Threads: %d each %d fds\n", context->count_threads, context->fd_limit_per_thread); memset(&wsi, 0, sizeof(wsi)); wsi.context = context; if (!info->ka_interval && info->ka_time > 0) { lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); return NULL; } #ifdef LWS_USE_LIBEV /* (Issue #264) In order to *avoid breaking backwards compatibility*, we * enable libev mediated SIGINT handling with a default handler of * lws_sigint_cb. The handler can be overridden or disabled * by invoking lws_sigint_cfg after creating the context, but * before invoking lws_initloop: */ context->use_ev_sigint = 1; context->lws_ev_sigint_cb = &lws_ev_sigint_cb; #endif /* LWS_USE_LIBEV */ #ifdef LWS_USE_LIBUV /* (Issue #264) In order to *avoid breaking backwards compatibility*, we * enable libev mediated SIGINT handling with a default handler of * lws_sigint_cb. The handler can be overridden or disabled * by invoking lws_sigint_cfg after creating the context, but * before invoking lws_initloop: */ context->use_ev_sigint = 1; context->lws_uv_sigint_cb = &lws_uv_sigint_cb; #endif lwsl_info(" mem: context: %5u bytes (%d ctx + (%d thr x %d))\n", sizeof(struct lws_context) + (context->count_threads * LWS_MAX_SOCKET_IO_BUF), sizeof(struct lws_context), context->count_threads, LWS_MAX_SOCKET_IO_BUF); lwsl_info(" mem: http hdr rsvd: %5u bytes (%u thr x (%u + %u) x %u))\n", (context->max_http_header_data + sizeof(struct allocated_headers)) * context->max_http_header_pool * context->count_threads, context->count_threads, context->max_http_header_data, sizeof(struct allocated_headers), context->max_http_header_pool); n = sizeof(struct lws_pollfd) * context->count_threads * context->fd_limit_per_thread; context->pt[0].fds = lws_zalloc(n); if (context->pt[0].fds == NULL) { lwsl_err("OOM allocating %d fds\n", context->max_fds); goto bail; } lwsl_info(" mem: pollfd map: %5u\n", n); if (info->server_string) { context->server_string = info->server_string; context->server_string_len = (short) strlen(context->server_string); } else { context->server_string = "libwebsockets"; context->server_string_len = 13; } #if LWS_MAX_SMP > 1 /* each thread serves his own chunk of fds */ for (n = 1; n < (int)info->count_threads; n++) context->pt[n].fds = context->pt[n - 1].fds + context->fd_limit_per_thread; #endif if (lws_plat_init(context, info)) goto bail; lws_context_init_ssl_library(info); context->user_space = info->user; /* * if he's not saying he'll make his own vhosts later then act * compatibly and make a default vhost using the data in the info */ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) if (!lws_create_vhost(context, info)) { lwsl_err("Failed to create default vhost\n"); return NULL; } lws_context_init_extensions(info, context); lwsl_notice(" mem: per-conn: %5u bytes + protocol rx buf\n", sizeof(struct lws)); strcpy(context->canonical_hostname, "unknown"); lws_server_get_canonical_hostname(context, info); context->uid = info->uid; context->gid = info->gid; /* * drop any root privs for this process * to listen on port < 1023 we would have needed root, but now we are * listening, we don't want the power for anything else */ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) lws_plat_drop_app_privileges(info); /* * give all extensions a chance to create any per-context * allocations they need */ if (info->port != CONTEXT_PORT_NO_LISTEN) { if (lws_ext_cb_all_exts(context, NULL, LWS_EXT_CB_SERVER_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; } else if (lws_ext_cb_all_exts(context, NULL, LWS_EXT_CB_CLIENT_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; return context; bail: lws_context_destroy(context); return NULL; } /** * lws_context_destroy() - Destroy the websocket context * @context: Websocket context * * This function closes any active connections and then frees the * context. After calling this, any further use of the context is * undefined. */ LWS_VISIBLE void lws_context_destroy(struct lws_context *context) { const struct lws_protocols *protocol = NULL; struct lws_context_per_thread *pt; struct lws_vhost *vh = NULL, *vh1; struct lws wsi; int n, m; lwsl_notice("%s\n", __func__); if (!context) return; m = context->count_threads; context->being_destroyed = 1; memset(&wsi, 0, sizeof(wsi)); wsi.context = context; #ifdef LWS_LATENCY if (context->worst_latency_info[0]) lwsl_notice("Worst latency: %s\n", context->worst_latency_info); #endif while (m--) { pt = &context->pt[m]; for (n = 0; (unsigned int)n < context->pt[m].fds_count; n++) { struct lws *wsi = wsi_from_fd(context, pt->fds[n].fd); if (!wsi) continue; lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY /* no protocol close */); n--; } lws_pt_mutex_destroy(pt); } /* * give all extensions a chance to clean up any per-context * allocations they might have made */ n = lws_ext_cb_all_exts(context, NULL, LWS_EXT_CB_SERVER_CONTEXT_DESTRUCT, NULL, 0); n = lws_ext_cb_all_exts(context, NULL, LWS_EXT_CB_CLIENT_CONTEXT_DESTRUCT, NULL, 0); /* * inform all the protocols that they are done and will have no more * callbacks. * * We can't free things until after the event loop shuts down. */ if (context->protocol_init_done) vh = context->vhost_list; while (vh) { wsi.vhost = vh; protocol = vh->protocols; if (protocol) { n = 0; while (n < vh->count_protocols) { wsi.protocol = protocol; protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY, NULL, NULL, 0); protocol++; n++; } } vh = vh->vhost_next; } for (n = 0; n < context->count_threads; n++) { pt = &context->pt[n]; lws_libev_destroyloop(context, n); lws_libuv_destroyloop(context, n); lws_free_set_NULL(context->pt[n].serv_buf); if (pt->ah_pool) lws_free(pt->ah_pool); if (pt->http_header_data) lws_free(pt->http_header_data); } lws_plat_context_early_destroy(context); lws_ssl_context_destroy(context); if (context->pt[0].fds) lws_free_set_NULL(context->pt[0].fds); /* free all the vhost allocations */ vh = context->vhost_list; while (vh) { protocol = vh->protocols; if (protocol) { n = 0; while (n < vh->count_protocols) { if (vh->protocol_vh_privs && vh->protocol_vh_privs[n]) { lws_free(vh->protocol_vh_privs[n]); vh->protocol_vh_privs[n] = NULL; } protocol++; n++; } } if (vh->protocol_vh_privs) lws_free(vh->protocol_vh_privs); lws_ssl_SSL_CTX_destroy(vh); lws_free(vh->same_vh_protocol_list); #ifdef LWS_WITH_PLUGINS if (context->plugin_list) lws_free((void *)vh->protocols); #ifndef LWS_NO_EXTENSIONS if (context->plugin_extension_count) lws_free((void *)vh->extensions); #endif #endif #ifdef LWS_WITH_ACCESS_LOG if (vh->log_fd != LWS_INVALID_FILE) close(vh->log_fd); #endif vh1 = vh->vhost_next; lws_free(vh); vh = vh1; } lws_plat_context_late_destroy(context); lws_free(context); } |
Added undroid/libwebsockets/lib/daemonize.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
/* * This code is mainly taken from Doug Potter's page * * http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize * * I contacted him 2007-04-16 about the license for the original code, * he replied it is Public Domain. Use the URL above to get the original * Public Domain version if you want it. * * This version is LGPL2.1+SLE like the rest of libwebsockets and is * Copyright (c)2006 - 2013 Andy Green <andy@warmcat.com> */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <limits.h> #include <unistd.h> #include <errno.h> #include "private-libwebsockets.h" int pid_daemon; static char *lock_path; int get_daemonize_pid() { return pid_daemon; } static void child_handler(int signum) { int fd, len, sent; char sz[20]; switch (signum) { case SIGALRM: /* timed out daemonizing */ exit(0); break; case SIGUSR1: /* positive confirmation we daemonized well */ /* Create the lock file as the current user */ fd = open(lock_path, O_TRUNC | O_RDWR | O_CREAT, 0640); if (fd < 0) { fprintf(stderr, "unable to create lock file %s, code=%d (%s)\n", lock_path, errno, strerror(errno)); exit(5); } len = sprintf(sz, "%u", pid_daemon); sent = write(fd, sz, len); if (sent != len) fprintf(stderr, "unable to write pid to lock file %s, code=%d (%s)\n", lock_path, errno, strerror(errno)); close(fd); exit(0); //!!(sent == len)); case SIGCHLD: /* daemonization failed */ exit(6); break; } } static void lws_daemon_closing(int sigact) { if (getpid() == pid_daemon) if (lock_path) { unlink(lock_path); lws_free_set_NULL(lock_path); } kill(getpid(), SIGKILL); } /* * You just need to call this from your main(), when it * returns you are all set "in the background" decoupled * from the console you were started from. * * The process context you called from has been terminated then. */ LWS_VISIBLE int lws_daemonize(const char *_lock_path) { struct sigaction act; pid_t sid, parent; int n, fd, ret; char buf[10]; /* already a daemon */ // if (getppid() == 1) // return 1; fd = open(_lock_path, O_RDONLY); if (fd >= 0) { n = read(fd, buf, sizeof(buf)); close(fd); if (n) { n = atoi(buf); ret = kill(n, 0); if (ret >= 0) { fprintf(stderr, "Daemon already running from pid %d\n", n); exit(1); } fprintf(stderr, "Removing stale lock file %s from dead pid %d\n", _lock_path, n); unlink(lock_path); } } n = strlen(_lock_path) + 1; lock_path = lws_malloc(n); if (!lock_path) { fprintf(stderr, "Out of mem in lws_daemonize\n"); return 1; } strcpy(lock_path, _lock_path); /* Trap signals that we expect to receive */ signal(SIGCHLD, child_handler); /* died */ signal(SIGUSR1, child_handler); /* was happy */ signal(SIGALRM, child_handler); /* timeout daemonizing */ /* Fork off the parent process */ pid_daemon = fork(); if (pid_daemon < 0) { fprintf(stderr, "unable to fork daemon, code=%d (%s)", errno, strerror(errno)); exit(9); } /* If we got a good PID, then we can exit the parent process. */ if (pid_daemon > 0) { /* * Wait for confirmation signal from the child via * SIGCHILD / USR1, or for two seconds to elapse * (SIGALRM). pause() should not return. */ alarm(2); pause(); /* should not be reachable */ exit(1); } /* At this point we are executing as the child process */ parent = getppid(); pid_daemon = getpid(); /* Cancel certain signals */ signal(SIGCHLD, SIG_DFL); /* A child process dies */ signal(SIGTSTP, SIG_IGN); /* Various TTY signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */ /* Change the file mode mask */ umask(0); /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { fprintf(stderr, "unable to create a new session, code %d (%s)", errno, strerror(errno)); exit(2); } /* * Change the current working directory. This prevents the current * directory from being locked; hence not being able to remove it. */ if (chdir("/tmp") < 0) { fprintf(stderr, "unable to change directory to %s, code %d (%s)", "/", errno, strerror(errno)); exit(3); } /* Redirect standard files to /dev/null */ if (!freopen("/dev/null", "r", stdin)) fprintf(stderr, "unable to freopen() stdin, code %d (%s)", errno, strerror(errno)); if (!freopen("/dev/null", "w", stdout)) fprintf(stderr, "unable to freopen() stdout, code %d (%s)", errno, strerror(errno)); if (!freopen("/dev/null", "w", stderr)) fprintf(stderr, "unable to freopen() stderr, code %d (%s)", errno, strerror(errno)); /* Tell the parent process that we are A-okay */ kill(parent, SIGUSR1); act.sa_handler = lws_daemon_closing; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGTERM, &act, NULL); /* return to continue what is now "the daemon" */ return 0; } |
Added undroid/libwebsockets/lib/extension-permessage-deflate.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
/* * ./lib/extension-permessage-deflate.c * * Copyright (C) 2016 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" #include "extension-permessage-deflate.h" #include <stdio.h> #include <string.h> #include <assert.h> #define LWS_ZLIB_MEMLEVEL 8 const struct lws_ext_options lws_ext_pm_deflate_options[] = { /* public RFC7692 settings */ { "server_no_context_takeover", EXTARG_NONE }, { "client_no_context_takeover", EXTARG_NONE }, { "server_max_window_bits", EXTARG_OPT_DEC }, { "client_max_window_bits", EXTARG_OPT_DEC }, /* ones only user code can set */ { "rx_buf_size", EXTARG_DEC }, { "tx_buf_size", EXTARG_DEC }, { "compression_level", EXTARG_DEC }, { "mem_level", EXTARG_DEC }, { NULL, 0 }, /* sentinel */ }; static void lws_extension_pmdeflate_restrict_args(struct lws *wsi, struct lws_ext_pm_deflate_priv *priv) { int n, extra; /* cap the RX buf at the nearest power of 2 to protocol rx buf */ n = LWS_MAX_SOCKET_IO_BUF; if (wsi->protocol->rx_buffer_size) n = wsi->protocol->rx_buffer_size; extra = 7; while (n >= 1 << (extra + 1)) extra++; if (extra < priv->args[PMD_RX_BUF_PWR2]) { priv->args[PMD_RX_BUF_PWR2] = extra; lwsl_err(" Capping pmd rx to %d\n", 1 << extra); } } LWS_VISIBLE int lws_extension_callback_pm_deflate(struct lws_context *context, const struct lws_extension *ext, struct lws *wsi, enum lws_extension_callback_reasons reason, void *user, void *in, size_t len) { struct lws_ext_pm_deflate_priv *priv = (struct lws_ext_pm_deflate_priv *)user; struct lws_tokens *eff_buf = (struct lws_tokens *)in; static unsigned char trail[] = { 0, 0, 0xff, 0xff }; int n, ret = 0, was_fin = 0, extra; struct lws_ext_option_arg *oa; switch (reason) { case LWS_EXT_CB_NAMED_OPTION_SET: oa = in; if (!oa->option_name) break; for (n = 0; n < ARRAY_SIZE(lws_ext_pm_deflate_options); n++) if (!strcmp(lws_ext_pm_deflate_options[n].name, oa->option_name)) break; if (n == ARRAY_SIZE(lws_ext_pm_deflate_options)) break; oa->option_index = n; /* fallthru */ case LWS_EXT_CB_OPTION_SET: oa = in; lwsl_info("%s: option set: idx %d, %s, len %d\n", __func__, oa->option_index, oa->start, oa->len); if (oa->start) priv->args[oa->option_index] = atoi(oa->start); else priv->args[oa->option_index] = 1; lws_extension_pmdeflate_restrict_args(wsi, priv); break; case LWS_EXT_CB_OPTION_CONFIRM: if (priv->args[PMD_SERVER_MAX_WINDOW_BITS] < 8 || priv->args[PMD_SERVER_MAX_WINDOW_BITS] > 15 || priv->args[PMD_CLIENT_MAX_WINDOW_BITS] < 8 || priv->args[PMD_CLIENT_MAX_WINDOW_BITS] > 15) return -1; break; case LWS_EXT_CB_CLIENT_CONSTRUCT: case LWS_EXT_CB_CONSTRUCT: n = LWS_MAX_SOCKET_IO_BUF; if (wsi->protocol->rx_buffer_size) n = wsi->protocol->rx_buffer_size; if (n < 128) { lwsl_err(" permessage-deflate requires the protocol (%s) to have an RX buffer >= 128\n", wsi->protocol->name); return -1; } /* fill in **user */ priv = lws_zalloc(sizeof(*priv)); *((void **)user) = priv; lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__); memset(priv, 0, sizeof(*priv)); /* fill in pointer to options list */ if (in) *((const struct lws_ext_options **)in) = lws_ext_pm_deflate_options; /* fallthru */ case LWS_EXT_CB_OPTION_DEFAULT: /* set the public, RFC7692 defaults... */ priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER] = 0, priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER] = 0; priv->args[PMD_SERVER_MAX_WINDOW_BITS] = 15; priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 15; /* ...and the ones the user code can override */ priv->args[PMD_RX_BUF_PWR2] = 10; /* ie, 1024 */ priv->args[PMD_TX_BUF_PWR2] = 10; /* ie, 1024 */ priv->args[PMD_COMP_LEVEL] = 1; priv->args[PMD_MEM_LEVEL] = 8; lws_extension_pmdeflate_restrict_args(wsi, priv); break; case LWS_EXT_CB_DESTROY: lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__); lws_free(priv->buf_rx_inflated); lws_free(priv->buf_tx_deflated); if (priv->rx_init) (void)inflateEnd(&priv->rx); if (priv->tx_init) (void)deflateEnd(&priv->tx); lws_free(priv); return ret; case LWS_EXT_CB_PAYLOAD_RX: lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n", __func__, eff_buf->token_len, priv->rx.avail_in); if (!(wsi->u.ws.rsv_first_msg & 0x40)) return 0; #if 0 for (n = 0; n < eff_buf->token_len; n++) { printf("%02X ", (unsigned char)eff_buf->token[n]); if ((n & 15) == 15) printf("\n"); } printf("\n"); #endif if (!priv->rx_init) if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) { lwsl_err("%s: iniflateInit failed\n", __func__); return -1; } priv->rx_init = 1; if (!priv->buf_rx_inflated) priv->buf_rx_inflated = lws_malloc(LWS_PRE + 7 + 5 + (1 << priv->args[PMD_RX_BUF_PWR2])); if (!priv->buf_rx_inflated) { lwsl_err("%s: OOM\n", __func__); return -1; } /* * We have to leave the input stream alone if we didn't * finish with it yet. The input stream is held in the wsi * rx buffer by the caller, so this assumption is safe while * we block new rx while draining the existing rx */ if (eff_buf->token && eff_buf->token_len) { priv->rx.next_in = (unsigned char *)eff_buf->token; priv->rx.avail_in = eff_buf->token_len; } priv->rx.next_out = priv->buf_rx_inflated + LWS_PRE; eff_buf->token = (char *)priv->rx.next_out; priv->rx.avail_out = 1 << priv->args[PMD_RX_BUF_PWR2]; if (priv->rx_held_valid) { lwsl_ext("-- RX piling on held byte --\n"); *(priv->rx.next_out++) = priv->rx_held; priv->rx.avail_out--; priv->rx_held_valid = 0; } /* if... * * - he has no remaining input content for this message, and * - and this is the final fragment, and * - we used everything that could be drained on the input side * * ...then put back the 00 00 FF FF the sender stripped as our * input to zlib */ if (!priv->rx.avail_in && wsi->u.ws.final && !wsi->u.ws.rx_packet_length) { lwsl_ext("RX APPEND_TRAILER-DO\n"); was_fin = 1; priv->rx.next_in = trail; priv->rx.avail_in = sizeof(trail); } n = inflate(&priv->rx, Z_NO_FLUSH); lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n, priv->rx.avail_in, priv->rx.avail_out, wsi->u.ws.final); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: lwsl_info("zlib error inflate %d: %s\n", n, priv->rx.msg); return -1; } /* * If we did not already send in the 00 00 FF FF, and he's * out of input, he did not EXACTLY fill the output buffer * (which is ambiguous and we will force it to go around * again by withholding a byte), and he's otherwise working on * being a FIN fragment, then do the FIN message processing * of faking up the 00 00 FF FF that the sender stripped. */ if (!priv->rx.avail_in && wsi->u.ws.final && !wsi->u.ws.rx_packet_length && !was_fin && priv->rx.avail_out /* ambiguous as to if it is the end */ ) { lwsl_ext("RX APPEND_TRAILER-DO\n"); was_fin = 1; priv->rx.next_in = trail; priv->rx.avail_in = sizeof(trail); n = inflate(&priv->rx, Z_SYNC_FLUSH); lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n", n, priv->rx.avail_in, priv->rx.avail_out); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: lwsl_info("zlib error inflate %d: %s\n", n, priv->rx.msg); return -1; } } /* * we must announce in our returncode now if there is more * output to be expected from inflate, so we can decide to * set the FIN bit on this bufferload or not. However zlib * is ambiguous when we exactly filled the inflate buffer. It * does not give us a clue as to whether we should understand * that to mean he ended on a buffer boundary, or if there is * more in the pipeline. * * So to work around that safely, if it used all output space * exactly, we ALWAYS say there is more coming and we withhold * the last byte of the buffer to guarantee that is true. * * That still leaves us at least one byte to finish with a FIN * on, even if actually nothing more is coming from the next * inflate action itself. */ if (!priv->rx.avail_out) { /* he used all available out buf */ lwsl_ext("-- rx grabbing held --\n"); /* snip the last byte and hold it for next time */ priv->rx_held = *(--priv->rx.next_out); priv->rx_held_valid = 1; } eff_buf->token_len = (char *)priv->rx.next_out - eff_buf->token; priv->count_rx_between_fin += eff_buf->token_len; lwsl_ext(" %s: RX leaving with new effbuff len %d, " "ret %d, rx.avail_in=%d, TOTAL RX since FIN %d\n", __func__, eff_buf->token_len, priv->rx_held_valid, priv->rx.avail_in, priv->count_rx_between_fin); if (was_fin) { priv->count_rx_between_fin = 0; if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) { (void)inflateEnd(&priv->rx); priv->rx_init = 0; } } #if 0 for (n = 0; n < eff_buf->token_len; n++) putchar(eff_buf->token[n]); puts("\n"); #endif return priv->rx_held_valid; case LWS_EXT_CB_PAYLOAD_TX: if (!priv->tx_init) if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL], Z_DEFLATED, -priv->args[PMD_CLIENT_MAX_WINDOW_BITS + !wsi->vhost->listen_port], priv->args[PMD_MEM_LEVEL], Z_DEFAULT_STRATEGY) != Z_OK) { lwsl_ext("inflateInit2 failed\n"); return 1; } priv->tx_init = 1; if (!priv->buf_tx_deflated) priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 + (1 << priv->args[PMD_TX_BUF_PWR2])); if (!priv->buf_tx_deflated) { lwsl_err("%s: OOM\n", __func__); return -1; } if (eff_buf->token) { lwsl_ext("%s: TX: eff_buf length %d\n", __func__, eff_buf->token_len); priv->tx.next_in = (unsigned char *)eff_buf->token; priv->tx.avail_in = eff_buf->token_len; } #if 0 for (n = 0; n < eff_buf->token_len; n++) { printf("%02X ", (unsigned char)eff_buf->token[n]); if ((n & 15) == 15) printf("\n"); } printf("\n"); #endif priv->tx.next_out = priv->buf_tx_deflated + LWS_PRE + 5; eff_buf->token = (char *)priv->tx.next_out; priv->tx.avail_out = 1 << priv->args[PMD_TX_BUF_PWR2]; n = deflate(&priv->tx, Z_SYNC_FLUSH); if (n == Z_STREAM_ERROR) { lwsl_ext("%s: Z_STREAM_ERROR\n", __func__); return -1; } if (priv->tx_held_valid) { priv->tx_held_valid = 0; if (priv->tx.avail_out == 1 << priv->args[PMD_TX_BUF_PWR2]) /* * we can get a situation he took something in * but did not generate anything out, at the end * of a message (eg, next thing he sends is 80 * 00, a zero length FIN, like Authobahn can * send). * If we have come back as a FIN, we must not * place the pending trailer 00 00 FF FF, just * the 1 byte of live data */ *(--eff_buf->token) = priv->tx_held[0]; else { /* he generated data, prepend whole pending */ eff_buf->token -= 5; for (n = 0; n < 5; n++) eff_buf->token[n] = priv->tx_held[n]; } } priv->compressed_out = 1; eff_buf->token_len = (int)(priv->tx.next_out - (unsigned char *)eff_buf->token); /* * we must announce in our returncode now if there is more * output to be expected from inflate, so we can decide to * set the FIN bit on this bufferload or not. However zlib * is ambiguous when we exactly filled the inflate buffer. It * does not give us a clue as to whether we should understand * that to mean he ended on a buffer boundary, or if there is * more in the pipeline. * * Worse, the guy providing the stuff we are sending may not * know until after that this was, actually, the last chunk, * that can happen even if we did not fill the output buf, ie * he may send after this a zero-length FIN fragment. * * This is super difficult because we must snip the last 4 * bytes in the case this is the last compressed output of the * message. The only way to deal with it is defer sending the * last 5 bytes of each frame until the next one, when we will * be in a position to understand if that has a FIN or not. */ extra = !!(len & LWS_WRITE_NO_FIN) || !priv->tx.avail_out; if (eff_buf->token_len >= 4 + extra) { lwsl_ext("tx held %d\n", 4 + extra); priv->tx_held_valid = extra; for (n = 3 + extra; n >= 0; n--) priv->tx_held[n] = *(--priv->tx.next_out); eff_buf->token_len -= 4 + extra; } lwsl_ext(" TX rewritten with new effbuff len %d, ret %d\n", eff_buf->token_len, !priv->tx.avail_out); return !priv->tx.avail_out; /* 1 == have more tx pending */ case LWS_EXT_CB_PACKET_TX_PRESEND: if (!priv->compressed_out) break; priv->compressed_out = 0; if ((*(eff_buf->token) & 0x80) && priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) { (void)deflateEnd(&priv->tx); priv->tx_init = 0; } n = *(eff_buf->token) & 15; /* set RSV1, but not on CONTINUATION */ if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME) *eff_buf->token |= 0x40; #if 0 for (n = 0; n < eff_buf->token_len; n++) { printf("%02X ", (unsigned char)eff_buf->token[n]); if ((n & 15) == 15) puts("\n"); } puts("\n"); #endif lwsl_ext("%s: tx opcode 0x%02X\n", __func__, (unsigned char)*eff_buf->token); break; default: break; } return 0; } |
Added undroid/libwebsockets/lib/extension-permessage-deflate.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <zlib.h> #define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1 #define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION enum arg_indexes { PMD_SERVER_NO_CONTEXT_TAKEOVER, PMD_CLIENT_NO_CONTEXT_TAKEOVER, PMD_SERVER_MAX_WINDOW_BITS, PMD_CLIENT_MAX_WINDOW_BITS, PMD_RX_BUF_PWR2, PMD_TX_BUF_PWR2, PMD_COMP_LEVEL, PMD_MEM_LEVEL, PMD_ARG_COUNT }; struct lws_ext_pm_deflate_priv { z_stream rx; z_stream tx; unsigned char *buf_rx_inflated; /* RX inflated output buffer */ unsigned char *buf_tx_deflated; /* TX deflated output buffer */ size_t count_rx_between_fin; unsigned char args[PMD_ARG_COUNT]; unsigned char tx_held[5]; unsigned char rx_held; unsigned char tx_init:1; unsigned char rx_init:1; unsigned char compressed_out:1; unsigned char rx_held_valid:1; unsigned char tx_held_valid:1; unsigned char rx_append_trailer:1; unsigned char pending_tx_trailer:1; }; |
Added undroid/libwebsockets/lib/extension.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
#include "private-libwebsockets.h" #include "extension-permessage-deflate.h" LWS_VISIBLE void lws_context_init_extensions(struct lws_context_creation_info *info, struct lws_context *context) { lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE); } enum lws_ext_option_parser_states { LEAPS_SEEK_NAME, LEAPS_EAT_NAME, LEAPS_SEEK_VAL, LEAPS_EAT_DEC, LEAPS_SEEK_ARG_TERM }; LWS_VISIBLE int lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, void *ext_user, const struct lws_ext_options *opts, const char *in, int len) { enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME; unsigned int match_map = 0, n, m, w = 0, count_options = 0, pending_close_quote = 0; struct lws_ext_option_arg oa; oa.option_name = NULL; while (opts[count_options].name) count_options++; while (len) { lwsl_ext("'%c' %d", *in, leap); switch (leap) { case LEAPS_SEEK_NAME: if (*in == ' ') break; if (*in == ',') { len = 1; break; } match_map = (1 << count_options) - 1; leap = LEAPS_EAT_NAME; w = 0; /* fallthru */ case LEAPS_EAT_NAME: oa.start = NULL; oa.len = 0; m = match_map; n = 0; pending_close_quote = 0; while (m) { if (m & 1) { lwsl_ext(" m=%d, n=%d, w=%d\n", m, n, w); if (*in == opts[n].name[w]) { if (!opts[n].name[w + 1]) { oa.option_index = n; lwsl_ext("hit %d\n", oa.option_index); leap = LEAPS_SEEK_VAL; if (len ==1) goto set_arg; break; } } else { match_map &= ~(1 << n); if (!match_map) { lwsl_ext("empty match map\n"); return -1; } } } m >>= 1; n++; } w++; break; case LEAPS_SEEK_VAL: if (*in == ' ') break; if (*in == ',') { len = 1; break; } if (*in == ';' || len == 1) { /* ie,nonoptional */ if (opts[oa.option_index].type == EXTARG_DEC) return -1; leap = LEAPS_SEEK_NAME; goto set_arg; } if (*in == '=') { w = 0; pending_close_quote = 0; if (opts[oa.option_index].type == EXTARG_NONE) return -1; leap = LEAPS_EAT_DEC; break; } return -1; case LEAPS_EAT_DEC: if (*in >= '0' && *in <= '9') { if (!w) oa.start = in; w++; if (len != 1) break; } if (!w && *in =='"') { pending_close_quote = 1; break; } if (!w) return -1; if (pending_close_quote && *in != '"' && len != 1) return -1; leap = LEAPS_SEEK_ARG_TERM; if (oa.start) oa.len = in - oa.start; if (len == 1) oa.len++; set_arg: ext->callback(lws_get_context(wsi), ext, wsi, LWS_EXT_CB_OPTION_SET, ext_user, (char *)&oa, 0); if (len == 1) break; if (pending_close_quote && *in == '"') break; /* fallthru */ case LEAPS_SEEK_ARG_TERM: if (*in == ' ') break; if (*in == ';') { leap = LEAPS_SEEK_NAME; break; } if (*in == ',') { len = 1; break; } return -1; } len--; in++; } return 0; } /* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */ int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len) { int n, m, handled = 0; for (n = 0; n < wsi->count_act_ext; n++) { m = wsi->active_extensions[n]->callback(lws_get_context(wsi), wsi->active_extensions[n], wsi, reason, wsi->act_ext_user[n], arg, len); if (m < 0) { lwsl_ext("Ext '%s' failed to handle callback %d!\n", wsi->active_extensions[n]->name, reason); return -1; } /* valgrind... */ if (reason == LWS_EXT_CB_DESTROY) wsi->act_ext_user[n] = NULL; if (m > handled) handled = m; } return handled; } int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, int reason, void *arg, int len) { int n = 0, m, handled = 0; const struct lws_extension *ext; if (!wsi || !wsi->vhost) return 0; ext = wsi->vhost->extensions; while (ext && ext->callback && !handled) { m = ext->callback(context, ext, wsi, reason, (void *)(long)n, arg, len); if (m < 0) { lwsl_ext("Ext '%s' failed to handle callback %d!\n", wsi->active_extensions[n]->name, reason); return -1; } if (m) handled = 1; ext++; n++; } return 0; } int lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) { struct lws_tokens eff_buf; int ret, m, n = 0; eff_buf.token = (char *)buf; eff_buf.token_len = len; /* * while we have original buf to spill ourselves, or extensions report * more in their pipeline */ ret = 1; while (ret == 1) { /* default to nobody has more to spill */ ret = 0; /* show every extension the new incoming data */ m = lws_ext_cb_active(wsi, LWS_EXT_CB_PACKET_TX_PRESEND, &eff_buf, 0); if (m < 0) return -1; if (m) /* handled */ ret = 1; if ((char *)buf != eff_buf.token) /* * extension recreated it: * need to buffer this if not all sent */ wsi->u.ws.clean_buffer = 0; /* assuming they left us something to send, send it */ if (eff_buf.token_len) { n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token, eff_buf.token_len); if (n < 0) { lwsl_info("closing from ext access\n"); return -1; } /* always either sent it all or privately buffered */ if (wsi->u.ws.clean_buffer) len = n; } lwsl_parser("written %d bytes to client\n", n); /* no extension has more to spill? Then we can go */ if (!ret) break; /* we used up what we had */ eff_buf.token = NULL; eff_buf.token_len = 0; /* * Did that leave the pipe choked? * Or we had to hold on to some of it? */ if (!lws_send_pipe_choked(wsi) && !wsi->trunc_len) /* no we could add more, lets's do that */ continue; lwsl_debug("choked\n"); /* * Yes, he's choked. Don't spill the rest now get a callback * when he is ready to send and take care of it there */ lws_callback_on_writable(wsi); wsi->extension_data_pending = 1; ret = 0; } return len; } int lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r, void *v, size_t len) { struct lws_context *context = wsi->context; int n, handled = 0; /* maybe an extension will take care of it for us */ for (n = 0; n < wsi->count_act_ext && !handled; n++) { if (!wsi->active_extensions[n]->callback) continue; handled |= wsi->active_extensions[n]->callback(context, wsi->active_extensions[n], wsi, r, wsi->act_ext_user[n], v, len); } return handled; } /** * lws_set_extension_option(): set extension option if possible * * @wsi: websocket connection * @ext_name: name of ext, like "permessage-deflate" * @opt_name: name of option, like "rx_buf_size" * @opt_val: value to set option to */ int lws_set_extension_option(struct lws *wsi, const char *ext_name, const char *opt_name, const char *opt_val) { struct lws_ext_option_arg oa; int idx = 0; /* first identify if the ext is active on this wsi */ while (idx < wsi->count_act_ext && strcmp(wsi->active_extensions[idx]->name, ext_name)) idx++; if (idx == wsi->count_act_ext) return -1; /* request ext not active on this wsi */ oa.option_name = opt_name; oa.option_index = 0; oa.start = opt_val; oa.len = 0; return wsi->active_extensions[idx]->callback( wsi->context, wsi->active_extensions[idx], wsi, LWS_EXT_CB_NAMED_OPTION_SET, wsi->act_ext_user[idx], &oa, 0); } |
Added undroid/libwebsockets/lib/getifaddrs.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
/* * downloaded from * http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c */ #if !LWS_HAVE_GETIFADDRS /* * Copyright (c) 2000 - 2001 Kungliga Tekniska H�gskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #include "private-libwebsockets.h" #ifdef LWS_HAVE_SYS_SOCKIO_H #include <sys/sockio.h> #endif #ifdef LWS_HAVE_NETINET_IN6_VAR_H #include <netinet/in6_var.h> #endif #ifndef max #define max(a, b) ((a) > (b) ? (a) : (b)) #endif #include "getifaddrs.h" static int getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags, size_t ifreq_sz) { int ret; int fd; size_t buf_size; char *buf; struct ifconf ifconf; char *p; size_t sz; struct sockaddr sa_zero; struct ifreq *ifr; struct ifaddrs *start, **end = &start; buf = NULL; memset(&sa_zero, 0, sizeof(sa_zero)); fd = socket(af, SOCK_DGRAM, 0); if (fd < 0) return -1; buf_size = 8192; for (;;) { buf = lws_zalloc(buf_size); if (buf == NULL) { ret = ENOMEM; goto error_out; } ifconf.ifc_len = buf_size; ifconf.ifc_buf = buf; /* * Solaris returns EINVAL when the buffer is too small. */ if (ioctl(fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) { ret = errno; goto error_out; } /* * Can the difference between a full and a overfull buf * be determined? */ if (ifconf.ifc_len < (int)buf_size) break; lws_free(buf); buf_size *= 2; } for (p = ifconf.ifc_buf; p < ifconf.ifc_buf + ifconf.ifc_len; p += sz) { struct ifreq ifreq; struct sockaddr *sa; size_t salen; ifr = (struct ifreq *)p; sa = &ifr->ifr_addr; sz = ifreq_sz; salen = sizeof(struct sockaddr); #ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN salen = sa->sa_len; sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len); #endif #ifdef SA_LEN salen = SA_LEN(sa); sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa)); #endif memset(&ifreq, 0, sizeof(ifreq)); memcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name)); if (ioctl(fd, siocgifflags, &ifreq) < 0) { ret = errno; goto error_out; } *end = lws_malloc(sizeof(**end)); (*end)->ifa_next = NULL; (*end)->ifa_name = strdup(ifr->ifr_name); (*end)->ifa_flags = ifreq.ifr_flags; (*end)->ifa_addr = lws_malloc(salen); memcpy((*end)->ifa_addr, sa, salen); (*end)->ifa_netmask = NULL; #if 0 /* fix these when we actually need them */ if (ifreq.ifr_flags & IFF_BROADCAST) { (*end)->ifa_broadaddr = lws_malloc(sizeof(ifr->ifr_broadaddr)); memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr, sizeof(ifr->ifr_broadaddr)); } else if (ifreq.ifr_flags & IFF_POINTOPOINT) { (*end)->ifa_dstaddr = lws_malloc(sizeof(ifr->ifr_dstaddr)); memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr, sizeof(ifr->ifr_dstaddr)); } else (*end)->ifa_dstaddr = NULL; #else (*end)->ifa_dstaddr = NULL; #endif (*end)->ifa_data = NULL; end = &(*end)->ifa_next; } *ifap = start; close(fd); lws_free(buf); return 0; error_out: close(fd); lws_free(buf); errno = ret; return -1; } int getifaddrs(struct ifaddrs **ifap) { int ret = -1; errno = ENXIO; #if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS) if (ret) ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS, sizeof(struct in6_ifreq)); #endif #if defined(LWS_HAVE_IPV6) && defined(SIOCGIFCONF) if (ret) ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq)); #endif #if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS) if (ret) ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq)); #endif return ret; } void freeifaddrs(struct ifaddrs *ifp) { struct ifaddrs *p, *q; for (p = ifp; p; ) { lws_free(p->ifa_name); lws_free(p->ifa_addr); lws_free(p->ifa_dstaddr); lws_free(p->ifa_netmask); lws_free(p->ifa_data); q = p; p = p->ifa_next; lws_free(q); } } #ifdef TEST void print_addr(const char *s, struct sockaddr *sa) { int i; printf(" %s=%d/", s, sa->sa_family); #ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN for (i = 0; i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++) printf("%02x", ((unsigned char *)sa->sa_data)[i]); #else for (i = 0; i < sizeof(sa->sa_data); i++) printf("%02x", ((unsigned char *)sa->sa_data)[i]); #endif printf("\n"); } void print_ifaddrs(struct ifaddrs *x) { struct ifaddrs *p; for (p = x; p; p = p->ifa_next) { printf("%s\n", p->ifa_name); printf(" flags=%x\n", p->ifa_flags); if (p->ifa_addr) print_addr("addr", p->ifa_addr); if (p->ifa_dstaddr) print_addr("dstaddr", p->ifa_dstaddr); if (p->ifa_netmask) print_addr("netmask", p->ifa_netmask); printf(" %p\n", p->ifa_data); } } int main() { struct ifaddrs *a = NULL, *b; getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq)); print_ifaddrs(a); printf("---\n"); getifaddrs(&b); print_ifaddrs(b); return 0; } #endif #endif |
Added undroid/libwebsockets/lib/getifaddrs.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
#if LWS_HAVE_GETIFADDRS #include <sys/types.h> #include <ifaddrs.h> #else #ifdef __cplusplus extern "C" { #endif /* * Copyright (c) 2000 Kungliga Tekniska H�gskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ */ #ifndef ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791 #define ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791 /* * the interface is defined in terms of the fields below, and this is * sometimes #define'd, so there seems to be no simple way of solving * this and this seemed the best. */ #undef ifa_dstaddr struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; unsigned int ifa_flags; struct sockaddr *ifa_addr; struct sockaddr *ifa_netmask; struct sockaddr *ifa_dstaddr; void *ifa_data; }; #ifndef ifa_broadaddr #define ifa_broadaddr ifa_dstaddr #endif int getifaddrs(struct ifaddrs **); void freeifaddrs(struct ifaddrs *); #endif /* __ifaddrs_h__ */ #ifdef __cplusplus } #endif #endif |
Added undroid/libwebsockets/lib/handshake.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" /* * -04 of the protocol (actually the 80th version) has a radically different * handshake. The 04 spec gives the following idea * * The handshake from the client looks as follows: * * GET /chat HTTP/1.1 * Host: server.example.com * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 4 * * The handshake from the server looks as follows: * * HTTP/1.1 101 Switching Protocols * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo= * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC== * Sec-WebSocket-Protocol: chat */ #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #endif /* * We have to take care about parsing because the headers may be split * into multiple fragments. They may contain unknown headers with arbitrary * argument lengths. So, we parse using a single-character at a time state * machine that is completely independent of packet size. * * Returns <0 for error or length of chars consumed from buf (up to len) */ LWS_VISIBLE int lws_read(struct lws *wsi, unsigned char *buf, size_t len) { unsigned char *last_char, *oldbuf = buf; int body_chunk_len; size_t n; lwsl_debug("%s: incoming len %d state %d\n", __func__, (int)len, wsi->state); switch (wsi->state) { #ifdef LWS_USE_HTTP2 case LWSS_HTTP2_AWAIT_CLIENT_PREFACE: case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS: case LWSS_HTTP2_ESTABLISHED: n = 0; while (n < len) { /* * we were accepting input but now we stopped doing so */ if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) { lws_rxflow_cache(wsi, buf, n, len); return 1; } /* account for what we're using in rxflow buffer */ if (wsi->rxflow_buffer) wsi->rxflow_pos++; if (lws_http2_parser(wsi, buf[n++])) { lwsl_debug("%s: http2_parser bailed\n", __func__); goto bail; } } break; #endif case LWSS_CLIENT_HTTP_ESTABLISHED: break; case LWSS_HTTP: wsi->hdr_parsing_completed = 0; /* fallthru */ case LWSS_HTTP_ISSUING_FILE: wsi->state = LWSS_HTTP_HEADERS; wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; wsi->u.hdr.lextable_pos = 0; /* fallthru */ case LWSS_HTTP_HEADERS: if (!wsi->u.hdr.ah) { lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__); assert(0); } lwsl_parser("issuing %d bytes to parser\n", (int)len); if (lws_handshake_client(wsi, &buf, len)) goto bail; last_char = buf; if (lws_handshake_server(wsi, &buf, len)) /* Handshake indicates this session is done. */ goto bail; /* * It's possible that we've exhausted our data already, or * rx flow control has stopped us dealing with this early, * but lws_handshake_server doesn't update len for us. * Figure out how much was read, so that we can proceed * appropriately: */ len -= (buf - last_char); lwsl_debug("%s: thinks we have used %d\n", __func__, len); if (!wsi->hdr_parsing_completed) /* More header content on the way */ goto read_ok; switch (wsi->state) { case LWSS_HTTP: case LWSS_HTTP_HEADERS: goto read_ok; case LWSS_HTTP_ISSUING_FILE: goto read_ok; case LWSS_HTTP_BODY: wsi->u.http.content_remain = wsi->u.http.content_length; if (wsi->u.http.content_remain) goto http_postbody; /* there is no POST content */ goto postbody_completion; default: break; } break; case LWSS_HTTP_BODY: http_postbody: while (len && wsi->u.http.content_remain) { /* Copy as much as possible, up to the limit of: * what we have in the read buffer (len) * remaining portion of the POST body (content_remain) */ body_chunk_len = min(wsi->u.http.content_remain,len); wsi->u.http.content_remain -= body_chunk_len; len -= body_chunk_len; #ifdef LWS_WITH_CGI if (wsi->cgi) { struct lws_cgi_args args; args.ch = LWS_STDIN; args.stdwsi = &wsi->cgi->stdwsi[0]; args.data = buf; args.len = body_chunk_len; /* returns how much used */ n = user_callback_handle_rxflow( wsi->protocol->callback, wsi, LWS_CALLBACK_CGI_STDIN_DATA, wsi->user_space, (void *)&args, 0); if ((int)n < 0) goto bail; } else { #endif n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY, wsi->user_space, buf, body_chunk_len); if (n) goto bail; n = body_chunk_len; #ifdef LWS_WITH_CGI } #endif buf += n; if (wsi->u.http.content_remain) { lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, wsi->context->timeout_secs); break; } /* he sent all the content in time */ postbody_completion: lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); #ifdef LWS_WITH_CGI if (!wsi->cgi) #endif { n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION, wsi->user_space, NULL, 0); if (n) goto bail; } break; } break; case LWSS_ESTABLISHED: case LWSS_AWAITING_CLOSE_ACK: case LWSS_SHUTDOWN: if (lws_handshake_client(wsi, &buf, len)) goto bail; switch (wsi->mode) { case LWSCM_WS_SERVING: if (lws_interpret_incoming_packet(wsi, &buf, len) < 0) { lwsl_info("interpret_incoming_packet has bailed\n"); goto bail; } break; } break; default: lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state); break; } read_ok: /* Nothing more to do for now */ lwsl_info("%s: read_ok, used %d\n", __func__, buf - oldbuf); return buf - oldbuf; bail: lwsl_debug("closing connection at lws_read bail:\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return -1; } |
Added undroid/libwebsockets/lib/header.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" #include "lextable-strings.h" const unsigned char *lws_token_to_string(enum lws_token_indexes token) { if ((unsigned int)token >= ARRAY_SIZE(set)) return NULL; return (unsigned char *)set[token]; } int lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, const unsigned char *value, int length, unsigned char **p, unsigned char *end) { #ifdef LWS_USE_HTTP2 if (wsi->mode == LWSCM_HTTP2_SERVING) return lws_add_http2_header_by_name(wsi, name, value, length, p, end); #else (void)wsi; #endif if (name) { while (*p < end && *name) *((*p)++) = *name++; if (*p == end) return 1; *((*p)++) = ' '; } if (*p + length + 3 >= end) return 1; memcpy(*p, value, length); *p += length; *((*p)++) = '\x0d'; *((*p)++) = '\x0a'; return 0; } int lws_finalize_http_header(struct lws *wsi, unsigned char **p, unsigned char *end) { #ifdef LWS_USE_HTTP2 if (wsi->mode == LWSCM_HTTP2_SERVING) return 0; #else (void)wsi; #endif if ((long)(end - *p) < 3) return 1; *((*p)++) = '\x0d'; *((*p)++) = '\x0a'; return 0; } int lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token, const unsigned char *value, int length, unsigned char **p, unsigned char *end) { const unsigned char *name; #ifdef LWS_USE_HTTP2 if (wsi->mode == LWSCM_HTTP2_SERVING) return lws_add_http2_header_by_token(wsi, token, value, length, p, end); #endif name = lws_token_to_string(token); if (!name) return 1; return lws_add_http_header_by_name(wsi, name, value, length, p, end); } int lws_add_http_header_content_length(struct lws *wsi, unsigned long content_length, unsigned char **p, unsigned char *end) { char b[24]; int n; n = sprintf(b, "%lu", content_length); if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b, n, p, end)) return 1; wsi->u.http.content_length = content_length; wsi->u.http.content_remain = content_length; return 0; } static const char *err400[] = { "Bad Request", "Unauthorized", "Payment Required", "Forbidden", "Not Found", "Method Not Allowed", "Not Acceptable", "Proxy Auth Required", "Request Timeout", "Conflict", "Gone", "Length Required", "Precondition Failed", "Request Entity Too Large", "Request URI too Long", "Unsupported Media Type", "Requested Range Not Satisfiable", "Expectation Failed" }; static const char *err500[] = { "Internal Server Error", "Not Implemented", "Bad Gateway", "Service Unavailable", "Gateway Timeout", "HTTP Version Not Supported" }; int lws_add_http_header_status(struct lws *wsi, unsigned int code, unsigned char **p, unsigned char *end) { unsigned char code_and_desc[60]; const char *description = "", *p1; int n; static const char * const hver[] = { "HTTP/1.0", "HTTP/1.1", "HTTP/2" }; #ifdef LWS_WITH_ACCESS_LOG wsi->access_log.response = code; #endif #ifdef LWS_USE_HTTP2 if (wsi->mode == LWSCM_HTTP2_SERVING) return lws_add_http2_header_status(wsi, code, p, end); #endif if (code >= 400 && code < (400 + ARRAY_SIZE(err400))) description = err400[code - 400]; if (code >= 500 && code < (500 + ARRAY_SIZE(err500))) description = err500[code - 500]; if (code == 200) description = "OK"; if (code == 304) description = "Not Modified"; else if (code >= 300 && code < 400) description = "Redirect"; if (wsi->u.http.request_version < ARRAY_SIZE(hver)) p1 = hver[wsi->u.http.request_version]; else p1 = hver[0]; n = sprintf((char *)code_and_desc, "%s %u %s", p1, code, description); if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p, end)) return 1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *) wsi->context->server_string, wsi->context->server_string_len, p, end)) return 1; if (wsi->vhost->options & LWS_SERVER_OPTION_STS) if (lws_add_http_header_by_name(wsi, (unsigned char *) "Strict-Transport-Security:", (unsigned char *)"max-age=15768000 ; " "includeSubDomains", 36, p, end)) return 1; return 0; } /** * lws_return_http_status() - Return simple http status * @wsi: Websocket instance (available from user callback) * @code: Status index, eg, 404 * @html_body: User-readable HTML description < 1KB, or NULL * * Helper to report HTTP errors back to the client cleanly and * consistently */ LWS_VISIBLE int lws_return_http_status(struct lws *wsi, unsigned int code, const char *html_body) { struct lws_context *context = lws_get_context(wsi); struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; unsigned char *p = pt->serv_buf + LWS_PRE; unsigned char *start = p, *body = p + 512; unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE; int n, m, len; char slen[20]; if (!html_body) html_body = ""; len = sprintf((char *)body, "<html><body><h1>%u</h1>%s</body></html>", code, html_body); if (lws_add_http_header_status(wsi, code, &p, end)) return 1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, &p, end)) return 1; n = sprintf(slen, "%d", len); if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)slen, n, &p, end)) return 1; if (lws_finalize_http_header(wsi, &p, end)) return 1; m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); if (m != (int)(p - start)) return 1; m = lws_write(wsi, body, len, LWS_WRITE_HTTP); return m != n; } LWS_VISIBLE int lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, unsigned char **p, unsigned char *end) { unsigned char *start = *p; int n; if (lws_add_http_header_status(wsi, code, p, end)) return -1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, loc, len, p, end)) return -1; /* * if we're going with http/1.1 and keepalive, * we have to give fake content metadata so the * client knows we completed the transaction and * it can do the redirect... */ if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, p, end)) return -1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)"0", 1, p, end)) return -1; if (lws_finalize_http_header(wsi, p, end)) return -1; n = lws_write(wsi, start, *p - start, LWS_WRITE_HTTP_HEADERS); return n; } |
Added undroid/libwebsockets/lib/hpack.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
/* * lib/hpack.c * * Copyright (C) 2014 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" /* * Official static header table for HPACK * +-------+-----------------------------+---------------+ | 1 | :authority | | | 2 | :method | GET | | 3 | :method | POST | | 4 | :path | / | | 5 | :path | /index.html | | 6 | :scheme | http | | 7 | :scheme | https | | 8 | :status | 200 | | 9 | :status | 204 | | 10 | :status | 206 | | 11 | :status | 304 | | 12 | :status | 400 | | 13 | :status | 404 | | 14 | :status | 500 | | 15 | accept-charset | | | 16 | accept-encoding | gzip, deflate | | 17 | accept-language | | | 18 | accept-ranges | | | 19 | accept | | | 20 | access-control-allow-origin | | | 21 | age | | | 22 | allow | | | 23 | authorization | | | 24 | cache-control | | | 25 | content-disposition | | | 26 | content-encoding | | | 27 | content-language | | | 28 | content-length | | | 29 | content-location | | | 30 | content-range | | | 31 | content-type | | | 32 | cookie | | | 33 | date | | | 34 | etag | | | 35 | expect | | | 36 | expires | | | 37 | from | | | 38 | host | | | 39 | if-match | | | 40 | if-modified-since | | | 41 | if-none-match | | | 42 | if-range | | | 43 | if-unmodified-since | | | 44 | last-modified | | | 45 | link | | | 46 | location | | | 47 | max-forwards | | | 48 | proxy-authenticate | | | 49 | proxy-authorization | | | 50 | range | | | 51 | referer | | | 52 | refresh | | | 53 | retry-after | | | 54 | server | | | 55 | set-cookie | | | 56 | strict-transport-security | | | 57 | transfer-encoding | | | 58 | user-agent | | | 59 | vary | | | 60 | via | | | 61 | www-authenticate | | +-------+-----------------------------+---------------+ */ static const unsigned char static_token[] = { 0, WSI_TOKEN_HTTP_COLON_AUTHORITY, WSI_TOKEN_HTTP_COLON_METHOD, WSI_TOKEN_HTTP_COLON_METHOD, WSI_TOKEN_HTTP_COLON_PATH, WSI_TOKEN_HTTP_COLON_PATH, WSI_TOKEN_HTTP_COLON_SCHEME, WSI_TOKEN_HTTP_COLON_SCHEME, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_COLON_STATUS, WSI_TOKEN_HTTP_ACCEPT_CHARSET, WSI_TOKEN_HTTP_ACCEPT_ENCODING, WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, WSI_TOKEN_HTTP_ACCEPT_RANGES, WSI_TOKEN_HTTP_ACCEPT, WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN, WSI_TOKEN_HTTP_AGE, WSI_TOKEN_HTTP_ALLOW, WSI_TOKEN_HTTP_AUTHORIZATION, WSI_TOKEN_HTTP_CACHE_CONTROL, WSI_TOKEN_HTTP_CONTENT_DISPOSITION, WSI_TOKEN_HTTP_CONTENT_ENCODING, WSI_TOKEN_HTTP_CONTENT_LANGUAGE, WSI_TOKEN_HTTP_CONTENT_LENGTH, WSI_TOKEN_HTTP_CONTENT_LOCATION, WSI_TOKEN_HTTP_CONTENT_RANGE, WSI_TOKEN_HTTP_CONTENT_TYPE, WSI_TOKEN_HTTP_COOKIE, WSI_TOKEN_HTTP_DATE, WSI_TOKEN_HTTP_ETAG, WSI_TOKEN_HTTP_EXPECT, WSI_TOKEN_HTTP_EXPIRES, WSI_TOKEN_HTTP_FROM, WSI_TOKEN_HOST, WSI_TOKEN_HTTP_IF_MATCH, WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, WSI_TOKEN_HTTP_IF_NONE_MATCH, WSI_TOKEN_HTTP_IF_RANGE, WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE, WSI_TOKEN_HTTP_LAST_MODIFIED, WSI_TOKEN_HTTP_LINK, WSI_TOKEN_HTTP_LOCATION, WSI_TOKEN_HTTP_MAX_FORWARDS, WSI_TOKEN_HTTP_PROXY_AUTHENTICATE, WSI_TOKEN_HTTP_PROXY_AUTHORIZATION, WSI_TOKEN_HTTP_RANGE, WSI_TOKEN_HTTP_REFERER, WSI_TOKEN_HTTP_REFRESH, WSI_TOKEN_HTTP_RETRY_AFTER, WSI_TOKEN_HTTP_SERVER, WSI_TOKEN_HTTP_SET_COOKIE, WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY, WSI_TOKEN_HTTP_TRANSFER_ENCODING, WSI_TOKEN_HTTP_USER_AGENT, WSI_TOKEN_HTTP_VARY, WSI_TOKEN_HTTP_VIA, WSI_TOKEN_HTTP_WWW_AUTHENTICATE, }; /* some of the entries imply values as well as header names */ static const char * const http2_canned[] = { "", "", "GET", "POST", "/", "/index.html", "http", "https", "200", "204", "206", "304", "400", "404", "500", "", "gzip, deflate" }; /* see minihuf.c */ #include "huftable.h" static int huftable_decode(int pos, char c) { int q = pos + !!c; if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */ return lextable[q] | 0x8000; return pos + (lextable[q] << 1); } static int lws_hpack_update_table_size(struct lws *wsi, int idx) { lwsl_info("hpack set table size %d\n", idx); return 0; } static int lws_frag_start(struct lws *wsi, int hdr_token_idx) { struct allocated_headers * ah = wsi->u.http2.http.ah; if (!hdr_token_idx) { lwsl_err("%s: zero hdr_token_idx\n", __func__); return 1; } if (ah->nfrag >= ARRAY_SIZE(ah->frag_index)) { lwsl_err("%s: frag index %d too big\n", __func__, ah->nfrag); return 1; } ah->frags[ah->nfrag].offset = ah->pos; ah->frags[ah->nfrag].len = 0; ah->frags[ah->nfrag].nfrag = 0; ah->frag_index[hdr_token_idx] = ah->nfrag; return 0; } static int lws_frag_append(struct lws *wsi, unsigned char c) { struct allocated_headers * ah = wsi->u.http2.http.ah; ah->data[ah->pos++] = c; ah->frags[ah->nfrag].len++; return ah->pos >= wsi->context->max_http_header_data; } static int lws_frag_end(struct lws *wsi) { if (lws_frag_append(wsi, 0)) return 1; wsi->u.http2.http.ah->nfrag++; return 0; } static void lws_dump_header(struct lws *wsi, int hdr) { char s[200]; int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr); s[len] = '\0'; lwsl_info(" hdr tok %d (%s) = '%s'\n", hdr, lws_token_to_string(hdr), s); } static int lws_token_from_index(struct lws *wsi, int index, char **arg, int *len) { struct hpack_dynamic_table *dyn; /* dynamic table only belongs to network wsi */ wsi = lws_http2_get_network_wsi(wsi); dyn = wsi->u.http2.hpack_dyn_table; if (index < ARRAY_SIZE(static_token)) return static_token[index]; if (!dyn) return 0; index -= ARRAY_SIZE(static_token); if (index >= dyn->num_entries) return 0; if (arg && len) { *arg = dyn->args + dyn->entries[index].arg_offset; *len = dyn->entries[index].arg_len; } return dyn->entries[index].token; } static int lws_hpack_add_dynamic_header(struct lws *wsi, int token, char *arg, int len) { struct hpack_dynamic_table *dyn; int ret = 1; wsi = lws_http2_get_network_wsi(wsi); dyn = wsi->u.http2.hpack_dyn_table; if (!dyn) { dyn = lws_zalloc(sizeof(*dyn)); if (!dyn) return 1; wsi->u.http2.hpack_dyn_table = dyn; dyn->args = lws_malloc(1024); if (!dyn->args) goto bail1; dyn->args_length = 1024; dyn->entries = lws_malloc(sizeof(dyn->entries[0]) * 20); if (!dyn->entries) goto bail2; dyn->num_entries = 20; } if (dyn->next == dyn->num_entries) return 1; if (dyn->args_length - dyn->pos < len) return 1; dyn->entries[dyn->next].token = token; dyn->entries[dyn->next].arg_offset = dyn->pos; if (len) memcpy(dyn->args + dyn->pos, arg, len); dyn->entries[dyn->next].arg_len = len; lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n", __func__, dyn->next, token, lws_token_to_string(token), len); dyn->pos += len; dyn->next++; return 0; bail2: lws_free(dyn->args); bail1: lws_free(dyn); wsi->u.http2.hpack_dyn_table = NULL; return ret; } static int lws_write_indexed_hdr(struct lws *wsi, int idx) { const char *p; int tok = lws_token_from_index(wsi, idx, NULL, 0); lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok, lws_token_to_string(tok)); if (lws_frag_start(wsi, tok)) return 1; if (idx < ARRAY_SIZE(http2_canned)) { p = http2_canned[idx]; while (*p) if (lws_frag_append(wsi, *p++)) return 1; } if (lws_frag_end(wsi)) return 1; lws_dump_header(wsi, tok); return 0; } int lws_hpack_interpret(struct lws *wsi, unsigned char c) { unsigned int prev; unsigned char c1; int n; lwsl_debug(" state %d\n", wsi->u.http2.hpack); switch (wsi->u.http2.hpack) { case HPKS_OPT_PADDING: wsi->u.http2.padding = c; lwsl_info("padding %d\n", c); if (wsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) { wsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY; wsi->u.http2.hpack_m = 4; } else wsi->u.http2.hpack = HPKS_TYPE; break; case HKPS_OPT_E_DEPENDENCY: wsi->u.http2.hpack_e_dep <<= 8; wsi->u.http2.hpack_e_dep |= c; if (! --wsi->u.http2.hpack_m) { lwsl_info("hpack_e_dep = 0x%x\n", wsi->u.http2.hpack_e_dep); wsi->u.http2.hpack = HKPS_OPT_WEIGHT; } break; case HKPS_OPT_WEIGHT: /* weight */ wsi->u.http2.hpack = HPKS_TYPE; break; case HPKS_TYPE: if (wsi->u.http2.count > (wsi->u.http2.length - wsi->u.http2.padding)) { lwsl_info("padding eat\n"); break; } if (c & 0x80) { /* indexed header field only */ /* just a possibly-extended integer */ wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7; lwsl_debug("HKPS_TYPE setting header_index %d\n", c & 0x7f); wsi->u.http2.header_index = c & 0x7f; if ((c & 0x7f) == 0x7f) { wsi->u.http2.hpack_len = c & 0x7f; wsi->u.http2.hpack_m = 0; wsi->u.http2.hpack = HPKS_IDX_EXT; break; } lwsl_debug("HKPS_TYPE: %d\n", c & 0x7f); if (lws_write_indexed_hdr(wsi, c & 0x7f)) return 1; /* stay at same state */ break; } if (c & 0x40) { /* literal header incr idx */ /* * [possibly-extended hdr idx (6) | new literal hdr name] * H + possibly-extended value length * literal value */ lwsl_debug("HKPS_TYPE 2 setting header_index %d\n", 0); wsi->u.http2.header_index = 0; if (c == 0x40) { /* literal name */ wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE_INCR; wsi->u.http2.value = 0; wsi->u.http2.hpack = HPKS_HLEN; break; } /* indexed name */ wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_6_VALUE_INCR; if ((c & 0x3f) == 0x3f) { wsi->u.http2.hpack_len = c & 0x3f; wsi->u.http2.hpack_m = 0; wsi->u.http2.hpack = HPKS_IDX_EXT; break; } lwsl_debug("HKPS_TYPE 3 setting header_index %d\n", c & 0x3f); wsi->u.http2.header_index = c & 0x3f; wsi->u.http2.value = 1; wsi->u.http2.hpack = HPKS_HLEN; break; } switch(c & 0xf0) { case 0x10: /* literal header never index */ case 0: /* literal header without indexing */ /* * follows 0x40 except 4-bit hdr idx * and don't add to index */ if (c == 0) { /* literal name */ wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE; wsi->u.http2.hpack = HPKS_HLEN; wsi->u.http2.value = 0; break; } //lwsl_debug("indexed\n"); /* indexed name */ wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_4_VALUE; wsi->u.http2.header_index = 0; if ((c & 0xf) == 0xf) { wsi->u.http2.hpack_len = c & 0xf; wsi->u.http2.hpack_m = 0; wsi->u.http2.hpack = HPKS_IDX_EXT; break; } //lwsl_err("HKPS_TYPE 5 setting header_index %d\n", c & 0xf); wsi->u.http2.header_index = c & 0xf; wsi->u.http2.value = 1; wsi->u.http2.hpack = HPKS_HLEN; break; case 0x20: case 0x30: /* header table size update */ /* possibly-extended size value (5) */ wsi->u.http2.hpack_type = HPKT_SIZE_5; if ((c & 0x1f) == 0x1f) { wsi->u.http2.hpack_len = c & 0x1f; wsi->u.http2.hpack_m = 0; wsi->u.http2.hpack = HPKS_IDX_EXT; break; } lws_hpack_update_table_size(wsi, c & 0x1f); /* stay at HPKS_TYPE state */ break; } break; case HPKS_IDX_EXT: wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m; wsi->u.http2.hpack_m += 7; if (!(c & 0x80)) { switch (wsi->u.http2.hpack_type) { case HPKT_INDEXED_HDR_7: //lwsl_err("HKPS_IDX_EXT hdr idx %d\n", wsi->u.http2.hpack_len); if (lws_write_indexed_hdr(wsi, wsi->u.http2.hpack_len)) return 1; wsi->u.http2.hpack = HPKS_TYPE; break; default: // lwsl_err("HKPS_IDX_EXT setting header_index %d\n", // wsi->u.http2.hpack_len); wsi->u.http2.header_index = wsi->u.http2.hpack_len; wsi->u.http2.value = 1; wsi->u.http2.hpack = HPKS_HLEN; break; } } break; case HPKS_HLEN: /* [ H | 7+ ] */ wsi->u.http2.huff = !!(c & 0x80); wsi->u.http2.hpack_pos = 0; wsi->u.http2.hpack_len = c & 0x7f; if (wsi->u.http2.hpack_len < 0x7f) { pre_data: if (wsi->u.http2.value) { if (wsi->u.http2.header_index) if (lws_frag_start(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL))) { // lwsl_notice("%s: hlen failed\n", __func__); return 1; } } else wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; wsi->u.http2.hpack = HPKS_DATA; break; } wsi->u.http2.hpack_m = 0; wsi->u.http2.hpack = HPKS_HLEN_EXT; break; case HPKS_HLEN_EXT: wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m; wsi->u.http2.hpack_m += 7; if (!(c & 0x80)) goto pre_data; break; case HPKS_DATA: for (n = 0; n < 8; n++) { if (wsi->u.http2.huff) { prev = wsi->u.http2.hpack_pos; wsi->u.http2.hpack_pos = huftable_decode( wsi->u.http2.hpack_pos, (c >> 7) & 1); c <<= 1; if (wsi->u.http2.hpack_pos == 0xffff) return 1; if (!(wsi->u.http2.hpack_pos & 0x8000)) continue; c1 = wsi->u.http2.hpack_pos & 0x7fff; wsi->u.http2.hpack_pos = 0; if (!c1 && prev == HUFTABLE_0x100_PREV) ; /* EOT */ } else { n = 8; c1 = c; } if (wsi->u.http2.value) { /* value */ if (wsi->u.http2.header_index) if (lws_frag_append(wsi, c1)) return 1; } else { /* name */ if (lws_parse(wsi, c1)) return 1; } } if (--wsi->u.http2.hpack_len == 0) { switch (wsi->u.http2.hpack_type) { case HPKT_LITERAL_HDR_VALUE_INCR: case HPKT_INDEXED_HDR_6_VALUE_INCR: // !!! if (lws_hpack_add_dynamic_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL), NULL, 0)) return 1; break; default: break; } n = 8; if (wsi->u.http2.value) { if (lws_frag_end(wsi)) return 1; // lwsl_err("data\n"); lws_dump_header(wsi, lws_token_from_index( wsi, wsi->u.http2.header_index, NULL, NULL)); if (wsi->u.http2.count + wsi->u.http2.padding == wsi->u.http2.length) wsi->u.http2.hpack = HKPS_OPT_DISCARD_PADDING; else wsi->u.http2.hpack = HPKS_TYPE; } else { /* name */ //if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT) wsi->u.http2.value = 1; wsi->u.http2.hpack = HPKS_HLEN; } } break; case HKPS_OPT_DISCARD_PADDING: lwsl_info("eating padding %x\n", c); if (! --wsi->u.http2.padding) wsi->u.http2.hpack = HPKS_TYPE; break; } return 0; } static int lws_http2_num(int starting_bits, unsigned long num, unsigned char **p, unsigned char *end) { int mask = (1 << starting_bits) - 1; if (num < mask) { *((*p)++) |= num; return *p >= end; } *((*p)++) |= mask; if (*p >= end) return 1; num -= mask; while (num >= 128) { *((*p)++) = 0x80 | (num & 0x7f); if (*p >= end) return 1; num >>= 7; } return 0; } int lws_add_http2_header_by_name(struct lws *wsi, const unsigned char *name, const unsigned char *value, int length, unsigned char **p, unsigned char *end) { int len; lwsl_info("%s: %p %s:%s\n", __func__, *p, name, value); len = strlen((char *)name); if (len) if (name[len - 1] == ':') len--; if (end - *p < len + length + 8) return 1; *((*p)++) = 0; /* not indexed, literal name */ **p = 0; /* non-HUF */ if (lws_http2_num(7, len, p, end)) return 1; memcpy(*p, name, len); *p += len; *(*p) = 0; /* non-HUF */ if (lws_http2_num(7, length, p, end)) return 1; memcpy(*p, value, length); *p += length; return 0; } int lws_add_http2_header_by_token(struct lws *wsi, enum lws_token_indexes token, const unsigned char *value, int length, unsigned char **p, unsigned char *end) { const unsigned char *name; name = lws_token_to_string(token); if (!name) return 1; return lws_add_http2_header_by_name(wsi, name, value, length, p, end); } int lws_add_http2_header_status(struct lws *wsi, unsigned int code, unsigned char **p, unsigned char *end) { unsigned char status[10]; int n; wsi->u.http2.send_END_STREAM = !!(code >= 400); n = sprintf((char *)status, "%u", code); if (lws_add_http2_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_STATUS, status, n, p, end)) return 1; return 0; } |
Added undroid/libwebsockets/lib/http2.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "private-libwebsockets.h" const struct http2_settings lws_http2_default_settings = { { 0, /* LWS_HTTP2_SETTINGS__HEADER_TABLE_SIZE */ 4096, /* LWS_HTTP2_SETTINGS__ENABLE_PUSH */ 1, /* LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS */ 100, /* LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE */ 65535, /* LWS_HTTP2_SETTINGS__MAX_FRAME_SIZE */ 16384, /* LWS_HTTP2_SETTINGS__MAX_HEADER_LIST_SIZE */ ~0, }}; void lws_http2_init(struct http2_settings *settings) { memcpy(settings, lws_http2_default_settings.setting, sizeof(*settings)); } struct lws * lws_http2_wsi_from_id(struct lws *wsi, unsigned int sid) { do { if (wsi->u.http2.my_stream_id == sid) return wsi; wsi = wsi->u.http2.next_child_wsi; } while (wsi); return NULL; } struct lws * lws_create_server_child_wsi(struct lws_vhost *vhost, struct lws *parent_wsi, unsigned int sid) { struct lws *wsi = lws_create_new_server_wsi(vhost); if (!wsi) return NULL; /* no more children allowed by parent */ if (parent_wsi->u.http2.child_count + 1 == parent_wsi->u.http2.peer_settings.setting[ LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS]) goto bail; lws_http2_init(&wsi->u.http2.peer_settings); lws_http2_init(&wsi->u.http2.my_settings); wsi->u.http2.stream_id = sid; wsi->u.http2.my_stream_id = sid; wsi->u.http2.parent_wsi = parent_wsi; wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi; parent_wsi->u.http2.next_child_wsi = wsi; parent_wsi->u.http2.child_count++; wsi->u.http2.my_priority = 16; wsi->u.http2.tx_credit = 65535; wsi->state = LWSS_HTTP2_ESTABLISHED; wsi->mode = parent_wsi->mode; wsi->protocol = &vhost->protocols[0]; if (lws_ensure_user_space(wsi)) goto bail; lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__, parent_wsi, wsi, sid, wsi->user_space); return wsi; bail: vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); lws_free(wsi); return NULL; } int lws_remove_server_child_wsi(struct lws_context *context, struct lws *wsi) { struct lws **w = &wsi->u.http2.parent_wsi; do { if (*w == wsi) { *w = wsi->u.http2.next_child_wsi; (wsi->u.http2.parent_wsi)->u.http2.child_count--; return 0; } w = &((*w)->u.http2.next_child_wsi); } while (*w); lwsl_err("%s: can't find %p\n", __func__, wsi); return 1; } int lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned char *buf, int len) { unsigned int a, b; if (!len) return 0; if (len < LWS_HTTP2_SETTINGS_LENGTH) return 1; while (len >= LWS_HTTP2_SETTINGS_LENGTH) { a = (buf[0] << 8) | buf[1]; if (a < LWS_HTTP2_SETTINGS__COUNT) { b = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5]; settings->setting[a] = b; lwsl_info("http2 settings %d <- 0x%x\n", a, b); } len -= LWS_HTTP2_SETTINGS_LENGTH; buf += LWS_HTTP2_SETTINGS_LENGTH; } if (len) return 1; return 0; } struct lws *lws_http2_get_network_wsi(struct lws *wsi) { while (wsi->u.http2.parent_wsi) wsi = wsi->u.http2.parent_wsi; return wsi; } int lws_http2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf) { struct lws *wsi_eff = lws_http2_get_network_wsi(wsi); unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH]; int n; *p++ = len >> 16; *p++ = len >> 8; *p++ = len; *p++ = type; *p++ = flags; *p++ = sid >> 24; *p++ = sid >> 16; *p++ = sid >> 8; *p++ = sid; lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n", __func__, wsi, wsi_eff, type, flags, sid, len, wsi->u.http2.tx_credit); if (type == LWS_HTTP2_FRAME_TYPE_DATA) { if (wsi->u.http2.tx_credit < len) lwsl_err("%s: %p: sending payload len %d" " but tx_credit only %d!\n", len, wsi->u.http2.tx_credit); wsi->u.http2.tx_credit -= len; } n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH); if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH) return n - LWS_HTTP2_FRAME_HEADER_LENGTH; return n; } static void lws_http2_settings_write(struct lws *wsi, int n, unsigned char *buf) { *buf++ = n >> 8; *buf++ = n; *buf++ = wsi->u.http2.my_settings.setting[n] >> 24; *buf++ = wsi->u.http2.my_settings.setting[n] >> 16; *buf++ = wsi->u.http2.my_settings.setting[n] >> 8; *buf = wsi->u.http2.my_settings.setting[n]; } static const char * https_client_preface = "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a"; int lws_http2_parser(struct lws *wsi, unsigned char c) { struct lws *swsi; int n; switch (wsi->state) { case LWSS_HTTP2_AWAIT_CLIENT_PREFACE: if (https_client_preface[wsi->u.http2.count++] != c) return 1; if (!https_client_preface[wsi->u.http2.count]) { lwsl_info("http2: %p: established\n", wsi); wsi->state = LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS; wsi->u.http2.count = 0; wsi->u.http2.tx_credit = 65535; /* * we must send a settings frame -- empty one is OK... * that must be the first thing sent by server * and the peer must send a SETTINGS with ACK flag... */ lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_MY_SETTINGS); } break; case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS: case LWSS_HTTP2_ESTABLISHED: if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload wsi->u.http2.count++; wsi->u.http2.stream_wsi->u.http2.count = wsi->u.http2.count; /* applies to wsi->u.http2.stream_wsi which may be wsi*/ switch(wsi->u.http2.type) { case LWS_HTTP2_FRAME_TYPE_SETTINGS: wsi->u.http2.stream_wsi->u.http2.one_setting[wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH] = c; if (wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH == LWS_HTTP2_SETTINGS_LENGTH - 1) if (lws_http2_interpret_settings_payload( &wsi->u.http2.stream_wsi->u.http2.peer_settings, wsi->u.http2.one_setting, LWS_HTTP2_SETTINGS_LENGTH)) return 1; break; case LWS_HTTP2_FRAME_TYPE_CONTINUATION: case LWS_HTTP2_FRAME_TYPE_HEADERS: lwsl_info(" %02X\n", c); if (!wsi->u.http2.stream_wsi->u.hdr.ah) if (lws_header_table_attach(wsi->u.http2.stream_wsi, 0)) { lwsl_err("%s: Failed to get ah\n", __func__); return 1; } if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c)) { lwsl_notice("%s: lws_hpack_interpret failed\n", __func__); return 1; } break; case LWS_HTTP2_FRAME_TYPE_GOAWAY: if (wsi->u.http2.count >= 5 && wsi->u.http2.count <= 8) { wsi->u.http2.hpack_e_dep <<= 8; wsi->u.http2.hpack_e_dep |= c; if (wsi->u.http2.count == 8) { lwsl_info("goaway err 0x%x\n", wsi->u.http2.hpack_e_dep); } } wsi->u.http2.GOING_AWAY = 1; break; case LWS_HTTP2_FRAME_TYPE_DATA: break; case LWS_HTTP2_FRAME_TYPE_PRIORITY: break; case LWS_HTTP2_FRAME_TYPE_RST_STREAM: break; case LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE: break; case LWS_HTTP2_FRAME_TYPE_PING: if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack } else { /* they're sending us a ping request */ if (wsi->u.http2.count > 8) return 1; wsi->u.http2.ping_payload[wsi->u.http2.count - 1] = c; } break; case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE: wsi->u.http2.hpack_e_dep <<= 8; wsi->u.http2.hpack_e_dep |= c; break; } if (wsi->u.http2.count != wsi->u.http2.length) break; /* end of frame */ wsi->u.http2.frame_state = 0; wsi->u.http2.count = 0; swsi = wsi->u.http2.stream_wsi; /* set our initial window size */ if (!wsi->u.http2.initialized) { wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE]; lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit); wsi->u.http2.initialized = 1; } switch (wsi->u.http2.type) { case LWS_HTTP2_FRAME_TYPE_HEADERS: /* service the http request itself */ lwsl_info("servicing initial http request, wsi=%p, stream wsi=%p\n", wsi, wsi->u.http2.stream_wsi); n = lws_http_action(swsi); (void)n; lwsl_info(" action result %d\n", n); break; case LWS_HTTP2_FRAME_TYPE_PING: if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack } else { /* they're sending us a ping request */ lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_PONG); } break; case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE: wsi->u.http2.hpack_e_dep &= ~(1 << 31); if ((long long)swsi->u.http2.tx_credit + (unsigned long long)wsi->u.http2.hpack_e_dep > (~(1 << 31))) return 1; /* actually need to close swsi not the whole show */ swsi->u.http2.tx_credit += wsi->u.http2.hpack_e_dep; if (swsi->u.http2.waiting_tx_credit && swsi->u.http2.tx_credit > 0) { lwsl_info("%s: %p: waiting_tx_credit -> wait on writeable\n", __func__, wsi); swsi->u.http2.waiting_tx_credit = 0; lws_callback_on_writable(swsi); } break; } break; } switch (wsi->u.http2.frame_state++) { case 0: wsi->u.http2.length = c; break; case 1: case 2: wsi->u.http2.length <<= 8; wsi->u.http2.length |= c; break; case 3: wsi->u.http2.type = c; break; case 4: wsi->u.http2.flags = c; break; case 5: case 6: case 7: case 8: wsi->u.http2.stream_id <<= 8; wsi->u.http2.stream_id |= c; break; } if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { /* frame header complete */ lwsl_info("frame: type 0x%x, flags 0x%x, sid 0x%x, len 0x%x\n", wsi->u.http2.type, wsi->u.http2.flags, wsi->u.http2.stream_id, wsi->u.http2.length); wsi->u.http2.count = 0; wsi->u.http2.stream_wsi = wsi; if (wsi->u.http2.stream_id) wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id); switch (wsi->u.http2.type) { case LWS_HTTP2_FRAME_TYPE_SETTINGS: /* nonzero sid on settings is illegal */ if (wsi->u.http2.stream_id) return 1; if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack } else /* non-ACK coming in means we must ACK it */ lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_ACK_SETTINGS); break; case LWS_HTTP2_FRAME_TYPE_PING: if (wsi->u.http2.stream_id) return 1; if (wsi->u.http2.length != 8) return 1; break; case LWS_HTTP2_FRAME_TYPE_CONTINUATION: if (wsi->u.http2.END_HEADERS) return 1; goto update_end_headers; case LWS_HTTP2_FRAME_TYPE_HEADERS: lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id); if (!wsi->u.http2.stream_id) return 1; if (!wsi->u.http2.stream_wsi) { wsi->u.http2.stream_wsi = lws_create_server_child_wsi(wsi->vhost, wsi, wsi->u.http2.stream_id); wsi->u.http2.stream_wsi->http2_substream = 1; } /* END_STREAM means after servicing this, close the stream */ wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM); lwsl_info("%s: headers END_STREAM = %d\n",__func__, wsi->u.http2.END_STREAM); update_end_headers: /* no END_HEADERS means CONTINUATION must come */ wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS); swsi = wsi->u.http2.stream_wsi; if (!swsi) return 1; /* prepare the hpack parser at the right start */ swsi->u.http2.flags = wsi->u.http2.flags; swsi->u.http2.length = wsi->u.http2.length; swsi->u.http2.END_STREAM = wsi->u.http2.END_STREAM; if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PADDED) swsi->u.http2.hpack = HPKS_OPT_PADDING; else if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) { swsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY; swsi->u.http2.hpack_m = 4; } else swsi->u.http2.hpack = HPKS_TYPE; lwsl_info("initial hpack state %d\n", swsi->u.http2.hpack); break; case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE: if (wsi->u.http2.length != 4) return 1; break; } if (wsi->u.http2.length == 0) wsi->u.http2.frame_state = 0; } break; } return 0; } int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi) { unsigned char settings[LWS_PRE + 6 * LWS_HTTP2_SETTINGS__COUNT]; struct lws *swsi; int n, m = 0; lwsl_debug("%s: %p: %d\n", __func__, wsi, wsi->pps); switch (wsi->pps) { case LWS_PPS_HTTP2_MY_SETTINGS: for (n = 1; n < LWS_HTTP2_SETTINGS__COUNT; n++) if (wsi->u.http2.my_settings.setting[n] != lws_http2_default_settings.setting[n]) { lws_http2_settings_write(wsi, n, &settings[LWS_PRE + m]); m += sizeof(wsi->u.http2.one_setting); } n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS, 0, LWS_HTTP2_STREAM_ID_MASTER, m, &settings[LWS_PRE]); if (n != m) { lwsl_info("send %d %d\n", n, m); return 1; } break; case LWS_PPS_HTTP2_ACK_SETTINGS: /* send ack ... always empty */ n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS, 1, LWS_HTTP2_STREAM_ID_MASTER, 0, &settings[LWS_PRE]); if (n) { lwsl_err("ack tells %d\n", n); return 1; } /* this is the end of the preface dance then? */ if (wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS) { wsi->state = LWSS_HTTP2_ESTABLISHED; wsi->u.http.fd = LWS_INVALID_FILE; if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) { lwsl_info("skipping nonexistant ssl upgrade headers\n"); break; } /* * we need to treat the headers from this upgrade * as the first job. These need to get * shifted to stream ID 1 */ lwsl_info("%s: setting up sid 1\n", __func__); swsi = wsi->u.http2.stream_wsi = lws_create_server_child_wsi(wsi->vhost, wsi, 1); /* pass on the initial headers to SID 1 */ swsi->u.http.ah = wsi->u.http.ah; wsi->u.http.ah = NULL; lwsl_info("%s: inherited headers %p\n", __func__, swsi->u.http.ah); swsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE]; lwsl_info("initial tx credit on conn %p: %d\n", swsi, swsi->u.http2.tx_credit); swsi->u.http2.initialized = 1; /* demanded by HTTP2 */ swsi->u.http2.END_STREAM = 1; lwsl_info("servicing initial http request\n"); return lws_http_action(swsi); } break; case LWS_PPS_HTTP2_PONG: memcpy(&settings[LWS_PRE], wsi->u.http2.ping_payload, 8); n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_PING, LWS_HTTP2_FLAG_SETTINGS_ACK, LWS_HTTP2_STREAM_ID_MASTER, 8, &settings[LWS_PRE]); if (n != 8) { lwsl_info("send %d %d\n", n, m); return 1; } break; default: break; } return 0; } struct lws * lws_http2_get_nth_child(struct lws *wsi, int n) { do { wsi = wsi->u.http2.next_child_wsi; if (!wsi) return NULL; } while (n--); return wsi; } |
Added undroid/libwebsockets/lib/huftable.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
static unsigned char lextable[] = { /* pos 0000: 0 */ /* 0 */ 0x42 /* (to 0x0084 state 98) */, /* 1 */ 0x01 /* (to 0x0002 state 1) */, /* pos 0002: 1 */ /* 0 */ 0x5C /* (to 0x00BA state 151) */, /* 1 */ 0x01 /* (to 0x0004 state 2) */, /* pos 0004: 2 */ /* 0 */ 0x66 /* (to 0x00D0 state 173) */, /* 1 */ 0x01 /* (to 0x0006 state 3) */, /* pos 0006: 3 */ /* 0 */ 0x74 /* (to 0x00EE state 204) */, /* 1 */ 0x01 /* (to 0x0008 state 4) */, /* pos 0008: 4 */ /* 0 */ 0x8C /* (to 0x0120 state 263) */, /* 1 */ 0x01 /* (to 0x000A state 5) */, /* pos 000a: 5 */ /* 0 */ 0x46 /* (to 0x0096 state 113) */, /* 1 */ 0x01 /* (to 0x000C state 6) */, /* pos 000c: 6 */ /* 0 */ 0x75 /* (to 0x00F6 state 211) */, /* 1 */ 0x01 /* (to 0x000E state 7) */, /* pos 000e: 7 */ /* 0 */ 0x40 /* (to 0x008E state 104) */, /* 1 */ 0x01 /* (to 0x0010 state 8) */, /* pos 0010: 8 */ /* 0 */ 0x45 /* (to 0x009A state 116) */, /* 1 */ 0x01 /* (to 0x0012 state 9) */, /* pos 0012: 9 */ /* 0 */ 0x40 /* (to 0x0092 state 108) */, /* 1 */ 0x01 /* (to 0x0014 state 10) */, /* pos 0014: 10 */ /* 0 */ 0x01 /* (to 0x0016 state 11) */, /* 1 */ 0x03 /* (to 0x001A state 14) */, /* pos 0016: 11 */ /* 0 */ 0x01 /* (to 0x0018 state 12) */, /* 1 */ 0x5B /* (to 0x00CC state 166) */, /* pos 0018: 12 */ /* terminal 0 */ 0x00, /* terminal 36 */ 0x24, /* pos 001a: 14 */ /* 0 */ 0x72 /* (to 0x00FE state 220) */, /* 1 */ 0x01 /* (to 0x001C state 15) */, /* pos 001c: 15 */ /* 0 */ 0x72 /* (to 0x0100 state 222) */, /* 1 */ 0x01 /* (to 0x001E state 16) */, /* pos 001e: 16 */ /* 0 */ 0x53 /* (to 0x00C4 state 158) */, /* 1 */ 0x01 /* (to 0x0020 state 17) */, /* pos 0020: 17 */ /* terminal 123 */ 0x7B, /* 1 */ 0x01 /* (to 0x0022 state 18) */, /* pos 0022: 18 */ /* 0 */ 0x6B /* (to 0x00F8 state 216) */, /* 1 */ 0x01 /* (to 0x0024 state 19) */, /* pos 0024: 19 */ /* 0 */ 0x84 /* (to 0x012C state 279) */, /* 1 */ 0x01 /* (to 0x0026 state 20) */, /* pos 0026: 20 */ /* 0 */ 0x01 /* (to 0x0028 state 21) */, /* 1 */ 0x06 /* (to 0x0032 state 27) */, /* pos 0028: 21 */ /* 0 */ 0xB3 /* (to 0x018E state 377) */, /* 1 */ 0x01 /* (to 0x002A state 22) */, /* pos 002a: 22 */ /* 0 */ 0xC3 /* (to 0x01B0 state 414) */, /* 1 */ 0x01 /* (to 0x002C state 23) */, /* pos 002c: 23 */ /* 0 */ 0x01 /* (to 0x002E state 24) */, /* 1 */ 0x8C /* (to 0x0144 state 301) */, /* pos 002e: 24 */ /* 0 */ 0x01 /* (to 0x0030 state 25) */, /* 1 */ 0x8A /* (to 0x0142 state 298) */, /* pos 0030: 25 */ /* terminal 1 */ 0x01, /* terminal 135 */ 0x87, /* pos 0032: 27 */ /* 0 */ 0x8E /* (to 0x014E state 314) */, /* 1 */ 0x01 /* (to 0x0034 state 28) */, /* pos 0034: 28 */ /* 0 */ 0x0F /* (to 0x0052 state 50) */, /* 1 */ 0x01 /* (to 0x0036 state 29) */, /* pos 0036: 29 */ /* 0 */ 0xA4 /* (to 0x017E state 362) */, /* 1 */ 0x01 /* (to 0x0038 state 30) */, /* pos 0038: 30 */ /* 0 */ 0xB7 /* (to 0x01A6 state 403) */, /* 1 */ 0x01 /* (to 0x003A state 31) */, /* pos 003a: 31 */ /* 0 */ 0xC8 /* (to 0x01CA state 440) */, /* 1 */ 0x01 /* (to 0x003C state 32) */, /* pos 003c: 32 */ /* 0 */ 0x01 /* (to 0x003E state 33) */, /* 1 */ 0x0F /* (to 0x005A state 55) */, /* pos 003e: 33 */ /* 0 */ 0x01 /* (to 0x0040 state 34) */, /* 1 */ 0x07 /* (to 0x004C state 46) */, /* pos 0040: 34 */ /* 0 */ 0x01 /* (to 0x0042 state 35) */, /* 1 */ 0x03 /* (to 0x0046 state 39) */, /* pos 0042: 35 */ /* terminal 254 */ 0xFE, /* 1 */ 0x01 /* (to 0x0044 state 36) */, /* pos 0044: 36 */ /* terminal 2 */ 0x02, /* terminal 3 */ 0x03, /* pos 0046: 39 */ /* 0 */ 0x01 /* (to 0x0048 state 40) */, /* 1 */ 0x02 /* (to 0x004A state 43) */, /* pos 0048: 40 */ /* terminal 4 */ 0x04, /* terminal 5 */ 0x05, /* pos 004a: 43 */ /* terminal 6 */ 0x06, /* terminal 7 */ 0x07, /* pos 004c: 46 */ /* 0 */ 0x01 /* (to 0x004E state 47) */, /* 1 */ 0x0E /* (to 0x0068 state 67) */, /* pos 004e: 47 */ /* 0 */ 0x01 /* (to 0x0050 state 48) */, /* 1 */ 0x0C /* (to 0x0066 state 63) */, /* pos 0050: 48 */ /* terminal 8 */ 0x08, /* terminal 11 */ 0x0B, /* pos 0052: 50 */ /* 0 */ 0xA7 /* (to 0x01A0 state 396) */, /* 1 */ 0x01 /* (to 0x0054 state 51) */, /* pos 0054: 51 */ /* 0 */ 0x01 /* (to 0x0056 state 52) */, /* 1 */ 0x7B /* (to 0x014A state 309) */, /* pos 0056: 52 */ /* terminal 239 */ 0xEF, /* 1 */ 0x01 /* (to 0x0058 state 53) */, /* pos 0058: 53 */ /* terminal 9 */ 0x09, /* terminal 142 */ 0x8E, /* pos 005a: 55 */ /* 0 */ 0x0A /* (to 0x006E state 74) */, /* 1 */ 0x01 /* (to 0x005C state 56) */, /* pos 005c: 56 */ /* 0 */ 0x11 /* (to 0x007E state 91) */, /* 1 */ 0x01 /* (to 0x005E state 57) */, /* pos 005e: 57 */ /* 0 */ 0x64 /* (to 0x0126 state 274) */, /* 1 */ 0x01 /* (to 0x0060 state 58) */, /* pos 0060: 58 */ /* terminal 249 */ 0xF9, /* 1 */ 0x01 /* (to 0x0062 state 59) */, /* pos 0062: 59 */ /* 0 */ 0x01 /* (to 0x0064 state 60) */, /* 1 */ 0x0A /* (to 0x0076 state 81) */, /* pos 0064: 60 */ /* terminal 10 */ 0x0A, /* terminal 13 */ 0x0D, /* pos 0066: 63 */ /* terminal 12 */ 0x0C, /* terminal 14 */ 0x0E, /* pos 0068: 67 */ /* 0 */ 0x01 /* (to 0x006A state 68) */, /* 1 */ 0x02 /* (to 0x006C state 71) */, /* pos 006a: 68 */ /* terminal 15 */ 0x0F, /* terminal 16 */ 0x10, /* pos 006c: 71 */ /* terminal 17 */ 0x11, /* terminal 18 */ 0x12, /* pos 006e: 74 */ /* 0 */ 0x01 /* (to 0x0070 state 75) */, /* 1 */ 0x05 /* (to 0x0078 state 84) */, /* pos 0070: 75 */ /* 0 */ 0x01 /* (to 0x0072 state 76) */, /* 1 */ 0x02 /* (to 0x0074 state 79) */, /* pos 0072: 76 */ /* terminal 19 */ 0x13, /* terminal 20 */ 0x14, /* pos 0074: 79 */ /* terminal 21 */ 0x15, /* terminal 23 */ 0x17, /* pos 0076: 81 */ /* terminal 22 */ 0x16, /* terminal 256 */ 0x00, /* pos 0078: 84 */ /* 0 */ 0x01 /* (to 0x007A state 85) */, /* 1 */ 0x02 /* (to 0x007C state 88) */, /* pos 007a: 85 */ /* terminal 24 */ 0x18, /* terminal 25 */ 0x19, /* pos 007c: 88 */ /* terminal 26 */ 0x1A, /* terminal 27 */ 0x1B, /* pos 007e: 91 */ /* 0 */ 0x01 /* (to 0x0080 state 92) */, /* 1 */ 0x02 /* (to 0x0082 state 95) */, /* pos 0080: 92 */ /* terminal 28 */ 0x1C, /* terminal 29 */ 0x1D, /* pos 0082: 95 */ /* terminal 30 */ 0x1E, /* terminal 31 */ 0x1F, /* pos 0084: 98 */ /* 0 */ 0x13 /* (to 0x00AA state 133) */, /* 1 */ 0x01 /* (to 0x0086 state 99) */, /* pos 0086: 99 */ /* 0 */ 0x01 /* (to 0x0088 state 100) */, /* 1 */ 0x0F /* (to 0x00A4 state 129) */, /* pos 0088: 100 */ /* 0 */ 0x4B /* (to 0x011E state 258) */, /* 1 */ 0x01 /* (to 0x008A state 101) */, /* pos 008a: 101 */ /* 0 */ 0x01 /* (to 0x008C state 102) */, /* 1 */ 0x0C /* (to 0x00A2 state 126) */, /* pos 008c: 102 */ /* terminal 32 */ 0x20, /* terminal 37 */ 0x25, /* pos 008e: 104 */ /* 0 */ 0x01 /* (to 0x0090 state 105) */, /* 1 */ 0x08 /* (to 0x009E state 119) */, /* pos 0090: 105 */ /* terminal 33 */ 0x21, /* terminal 34 */ 0x22, /* pos 0092: 108 */ /* terminal 124 */ 0x7C, /* 1 */ 0x01 /* (to 0x0094 state 109) */, /* pos 0094: 109 */ /* terminal 35 */ 0x23, /* terminal 62 */ 0x3E, /* pos 0096: 113 */ /* 0 */ 0x01 /* (to 0x0098 state 114) */, /* 1 */ 0x05 /* (to 0x00A0 state 124) */, /* pos 0098: 114 */ /* terminal 38 */ 0x26, /* terminal 42 */ 0x2A, /* pos 009a: 116 */ /* terminal 63 */ 0x3F, /* 1 */ 0x01 /* (to 0x009C state 117) */, /* pos 009c: 117 */ /* terminal 39 */ 0x27, /* terminal 43 */ 0x2B, /* pos 009e: 119 */ /* terminal 40 */ 0x28, /* terminal 41 */ 0x29, /* pos 00a0: 124 */ /* terminal 44 */ 0x2C, /* terminal 59 */ 0x3B, /* pos 00a2: 126 */ /* terminal 45 */ 0x2D, /* terminal 46 */ 0x2E, /* pos 00a4: 129 */ /* 0 */ 0x01 /* (to 0x00A6 state 130) */, /* 1 */ 0x08 /* (to 0x00B4 state 144) */, /* pos 00a6: 130 */ /* 0 */ 0x01 /* (to 0x00A8 state 131) */, /* 1 */ 0x06 /* (to 0x00B2 state 141) */, /* pos 00a8: 131 */ /* terminal 47 */ 0x2F, /* terminal 51 */ 0x33, /* pos 00aa: 133 */ /* 0 */ 0x01 /* (to 0x00AC state 134) */, /* 1 */ 0x2D /* (to 0x0104 state 229) */, /* pos 00ac: 134 */ /* 0 */ 0x01 /* (to 0x00AE state 135) */, /* 1 */ 0x02 /* (to 0x00B0 state 138) */, /* pos 00ae: 135 */ /* terminal 48 */ 0x30, /* terminal 49 */ 0x31, /* pos 00b0: 138 */ /* terminal 50 */ 0x32, /* terminal 97 */ 0x61, /* pos 00b2: 141 */ /* terminal 52 */ 0x34, /* terminal 53 */ 0x35, /* pos 00b4: 144 */ /* 0 */ 0x01 /* (to 0x00B6 state 145) */, /* 1 */ 0x02 /* (to 0x00B8 state 148) */, /* pos 00b6: 145 */ /* terminal 54 */ 0x36, /* terminal 55 */ 0x37, /* pos 00b8: 148 */ /* terminal 56 */ 0x38, /* terminal 57 */ 0x39, /* pos 00ba: 151 */ /* 0 */ 0x06 /* (to 0x00C6 state 160) */, /* 1 */ 0x01 /* (to 0x00BC state 152) */, /* pos 00bc: 152 */ /* 0 */ 0x2C /* (to 0x0114 state 246) */, /* 1 */ 0x01 /* (to 0x00BE state 153) */, /* pos 00be: 153 */ /* 0 */ 0x2F /* (to 0x011C state 256) */, /* 1 */ 0x01 /* (to 0x00C0 state 154) */, /* pos 00c0: 154 */ /* 0 */ 0x01 /* (to 0x00C2 state 155) */, /* 1 */ 0x07 /* (to 0x00CE state 170) */, /* pos 00c2: 155 */ /* terminal 58 */ 0x3A, /* terminal 66 */ 0x42, /* pos 00c4: 158 */ /* terminal 60 */ 0x3C, /* terminal 96 */ 0x60, /* pos 00c6: 160 */ /* 0 */ 0x01 /* (to 0x00C8 state 161) */, /* 1 */ 0x21 /* (to 0x0108 state 232) */, /* pos 00c8: 161 */ /* 0 */ 0x01 /* (to 0x00CA state 162) */, /* 1 */ 0x1D /* (to 0x0102 state 224) */, /* pos 00ca: 162 */ /* terminal 61 */ 0x3D, /* terminal 65 */ 0x41, /* pos 00cc: 166 */ /* terminal 64 */ 0x40, /* terminal 91 */ 0x5B, /* pos 00ce: 170 */ /* terminal 67 */ 0x43, /* terminal 68 */ 0x44, /* pos 00d0: 173 */ /* 0 */ 0x01 /* (to 0x00D2 state 174) */, /* 1 */ 0x08 /* (to 0x00E0 state 189) */, /* pos 00d2: 174 */ /* 0 */ 0x01 /* (to 0x00D4 state 175) */, /* 1 */ 0x04 /* (to 0x00DA state 182) */, /* pos 00d4: 175 */ /* 0 */ 0x01 /* (to 0x00D6 state 176) */, /* 1 */ 0x02 /* (to 0x00D8 state 179) */, /* pos 00d6: 176 */ /* terminal 69 */ 0x45, /* terminal 70 */ 0x46, /* pos 00d8: 179 */ /* terminal 71 */ 0x47, /* terminal 72 */ 0x48, /* pos 00da: 182 */ /* 0 */ 0x01 /* (to 0x00DC state 183) */, /* 1 */ 0x02 /* (to 0x00DE state 186) */, /* pos 00dc: 183 */ /* terminal 73 */ 0x49, /* terminal 74 */ 0x4A, /* pos 00de: 186 */ /* terminal 75 */ 0x4B, /* terminal 76 */ 0x4C, /* pos 00e0: 189 */ /* 0 */ 0x01 /* (to 0x00E2 state 190) */, /* 1 */ 0x04 /* (to 0x00E8 state 197) */, /* pos 00e2: 190 */ /* 0 */ 0x01 /* (to 0x00E4 state 191) */, /* 1 */ 0x02 /* (to 0x00E6 state 194) */, /* pos 00e4: 191 */ /* terminal 77 */ 0x4D, /* terminal 78 */ 0x4E, /* pos 00e6: 194 */ /* terminal 79 */ 0x4F, /* terminal 80 */ 0x50, /* pos 00e8: 197 */ /* 0 */ 0x01 /* (to 0x00EA state 198) */, /* 1 */ 0x02 /* (to 0x00EC state 201) */, /* pos 00ea: 198 */ /* terminal 81 */ 0x51, /* terminal 82 */ 0x52, /* pos 00ec: 201 */ /* terminal 83 */ 0x53, /* terminal 84 */ 0x54, /* pos 00ee: 204 */ /* 0 */ 0x01 /* (to 0x00F0 state 205) */, /* 1 */ 0x11 /* (to 0x0110 state 242) */, /* pos 00f0: 205 */ /* 0 */ 0x01 /* (to 0x00F2 state 206) */, /* 1 */ 0x02 /* (to 0x00F4 state 209) */, /* pos 00f2: 206 */ /* terminal 85 */ 0x55, /* terminal 86 */ 0x56, /* pos 00f4: 209 */ /* terminal 87 */ 0x57, /* terminal 89 */ 0x59, /* pos 00f6: 211 */ /* terminal 88 */ 0x58, /* terminal 90 */ 0x5A, /* pos 00f8: 216 */ /* 0 */ 0x01 /* (to 0x00FA state 217) */, /* 1 */ 0x1F /* (to 0x0136 state 286) */, /* pos 00fa: 217 */ /* 0 */ 0x01 /* (to 0x00FC state 218) */, /* 1 */ 0x17 /* (to 0x0128 state 276) */, /* pos 00fc: 218 */ /* terminal 92 */ 0x5C, /* terminal 195 */ 0xC3, /* pos 00fe: 220 */ /* terminal 93 */ 0x5D, /* terminal 126 */ 0x7E, /* pos 0100: 222 */ /* terminal 94 */ 0x5E, /* terminal 125 */ 0x7D, /* pos 0102: 224 */ /* terminal 95 */ 0x5F, /* terminal 98 */ 0x62, /* pos 0104: 229 */ /* 0 */ 0x01 /* (to 0x0106 state 230) */, /* 1 */ 0x05 /* (to 0x010E state 240) */, /* pos 0106: 230 */ /* terminal 99 */ 0x63, /* terminal 101 */ 0x65, /* pos 0108: 232 */ /* 0 */ 0x01 /* (to 0x010A state 233) */, /* 1 */ 0x02 /* (to 0x010C state 237) */, /* pos 010a: 233 */ /* terminal 100 */ 0x64, /* terminal 102 */ 0x66, /* pos 010c: 237 */ /* terminal 103 */ 0x67, /* terminal 104 */ 0x68, /* pos 010e: 240 */ /* terminal 105 */ 0x69, /* terminal 111 */ 0x6F, /* pos 0110: 242 */ /* 0 */ 0x01 /* (to 0x0112 state 243) */, /* 1 */ 0x05 /* (to 0x011A state 254) */, /* pos 0112: 243 */ /* terminal 106 */ 0x6A, /* terminal 107 */ 0x6B, /* pos 0114: 246 */ /* 0 */ 0x01 /* (to 0x0116 state 247) */, /* 1 */ 0x02 /* (to 0x0118 state 250) */, /* pos 0116: 247 */ /* terminal 108 */ 0x6C, /* terminal 109 */ 0x6D, /* pos 0118: 250 */ /* terminal 110 */ 0x6E, /* terminal 112 */ 0x70, /* pos 011a: 254 */ /* terminal 113 */ 0x71, /* terminal 118 */ 0x76, /* pos 011c: 256 */ /* terminal 114 */ 0x72, /* terminal 117 */ 0x75, /* pos 011e: 258 */ /* terminal 115 */ 0x73, /* terminal 116 */ 0x74, /* pos 0120: 263 */ /* 0 */ 0x01 /* (to 0x0122 state 264) */, /* 1 */ 0x02 /* (to 0x0124 state 267) */, /* pos 0122: 264 */ /* terminal 119 */ 0x77, /* terminal 120 */ 0x78, /* pos 0124: 267 */ /* terminal 121 */ 0x79, /* terminal 122 */ 0x7A, /* pos 0126: 274 */ /* terminal 127 */ 0x7F, /* terminal 220 */ 0xDC, /* pos 0128: 276 */ /* terminal 208 */ 0xD0, /* 1 */ 0x01 /* (to 0x012A state 277) */, /* pos 012a: 277 */ /* terminal 128 */ 0x80, /* terminal 130 */ 0x82, /* pos 012c: 279 */ /* 0 */ 0x2E /* (to 0x0188 state 372) */, /* 1 */ 0x01 /* (to 0x012E state 280) */, /* pos 012e: 280 */ /* 0 */ 0x01 /* (to 0x0130 state 281) */, /* 1 */ 0x1B /* (to 0x0164 state 332) */, /* pos 0130: 281 */ /* 0 */ 0x01 /* (to 0x0132 state 282) */, /* 1 */ 0x06 /* (to 0x013C state 291) */, /* pos 0132: 282 */ /* terminal 230 */ 0xE6, /* 1 */ 0x01 /* (to 0x0134 state 283) */, /* pos 0134: 283 */ /* terminal 129 */ 0x81, /* terminal 132 */ 0x84, /* pos 0136: 286 */ /* 0 */ 0x01 /* (to 0x0138 state 287) */, /* 1 */ 0x14 /* (to 0x015E state 328) */, /* pos 0138: 287 */ /* 0 */ 0x01 /* (to 0x013A state 288) */, /* 1 */ 0x30 /* (to 0x0198 state 388) */, /* pos 013a: 288 */ /* terminal 131 */ 0x83, /* terminal 162 */ 0xA2, /* pos 013c: 291 */ /* 0 */ 0x01 /* (to 0x013E state 292) */, /* 1 */ 0x02 /* (to 0x0140 state 296) */, /* pos 013e: 292 */ /* terminal 133 */ 0x85, /* terminal 134 */ 0x86, /* pos 0140: 296 */ /* terminal 136 */ 0x88, /* terminal 146 */ 0x92, /* pos 0142: 298 */ /* terminal 137 */ 0x89, /* terminal 138 */ 0x8A, /* pos 0144: 301 */ /* 0 */ 0x01 /* (to 0x0146 state 302) */, /* 1 */ 0x02 /* (to 0x0148 state 305) */, /* pos 0146: 302 */ /* terminal 139 */ 0x8B, /* terminal 140 */ 0x8C, /* pos 0148: 305 */ /* terminal 141 */ 0x8D, /* terminal 143 */ 0x8F, /* pos 014a: 309 */ /* 0 */ 0x01 /* (to 0x014C state 310) */, /* 1 */ 0x06 /* (to 0x0156 state 319) */, /* pos 014c: 310 */ /* terminal 144 */ 0x90, /* terminal 145 */ 0x91, /* pos 014e: 314 */ /* 0 */ 0x01 /* (to 0x0150 state 315) */, /* 1 */ 0x12 /* (to 0x0172 state 350) */, /* pos 0150: 315 */ /* 0 */ 0x01 /* (to 0x0152 state 316) */, /* 1 */ 0x05 /* (to 0x015A state 325) */, /* pos 0152: 316 */ /* 0 */ 0x01 /* (to 0x0154 state 317) */, /* 1 */ 0x03 /* (to 0x0158 state 322) */, /* pos 0154: 317 */ /* terminal 147 */ 0x93, /* terminal 149 */ 0x95, /* pos 0156: 319 */ /* terminal 148 */ 0x94, /* terminal 159 */ 0x9F, /* pos 0158: 322 */ /* terminal 150 */ 0x96, /* terminal 151 */ 0x97, /* pos 015a: 325 */ /* 0 */ 0x01 /* (to 0x015C state 326) */, /* 1 */ 0x08 /* (to 0x016A state 338) */, /* pos 015c: 326 */ /* terminal 152 */ 0x98, /* terminal 155 */ 0x9B, /* pos 015e: 328 */ /* 0 */ 0x42 /* (to 0x01E2 state 465) */, /* 1 */ 0x01 /* (to 0x0160 state 329) */, /* pos 0160: 329 */ /* 0 */ 0x01 /* (to 0x0162 state 330) */, /* 1 */ 0x0C /* (to 0x0178 state 355) */, /* pos 0162: 330 */ /* terminal 153 */ 0x99, /* terminal 161 */ 0xA1, /* pos 0164: 332 */ /* 0 */ 0x01 /* (to 0x0166 state 333) */, /* 1 */ 0x05 /* (to 0x016E state 347) */, /* pos 0166: 333 */ /* 0 */ 0x01 /* (to 0x0168 state 334) */, /* 1 */ 0x03 /* (to 0x016C state 342) */, /* pos 0168: 334 */ /* terminal 154 */ 0x9A, /* terminal 156 */ 0x9C, /* pos 016a: 338 */ /* terminal 157 */ 0x9D, /* terminal 158 */ 0x9E, /* pos 016c: 342 */ /* terminal 160 */ 0xA0, /* terminal 163 */ 0xA3, /* pos 016e: 347 */ /* 0 */ 0x01 /* (to 0x0170 state 348) */, /* 1 */ 0x07 /* (to 0x017C state 360) */, /* pos 0170: 348 */ /* terminal 164 */ 0xA4, /* terminal 169 */ 0xA9, /* pos 0172: 350 */ /* 0 */ 0x01 /* (to 0x0174 state 351) */, /* 1 */ 0x09 /* (to 0x0184 state 369) */, /* pos 0174: 351 */ /* 0 */ 0x01 /* (to 0x0176 state 352) */, /* 1 */ 0x03 /* (to 0x017A state 357) */, /* pos 0176: 352 */ /* terminal 165 */ 0xA5, /* terminal 166 */ 0xA6, /* pos 0178: 355 */ /* terminal 167 */ 0xA7, /* terminal 172 */ 0xAC, /* pos 017a: 357 */ /* terminal 168 */ 0xA8, /* terminal 174 */ 0xAE, /* pos 017c: 360 */ /* terminal 170 */ 0xAA, /* terminal 173 */ 0xAD, /* pos 017e: 362 */ /* 0 */ 0x01 /* (to 0x0180 state 363) */, /* 1 */ 0x1B /* (to 0x01B4 state 417) */, /* pos 0180: 363 */ /* 0 */ 0x01 /* (to 0x0182 state 364) */, /* 1 */ 0x2A /* (to 0x01D4 state 449) */, /* pos 0182: 364 */ /* terminal 171 */ 0xAB, /* terminal 206 */ 0xCE, /* pos 0184: 369 */ /* 0 */ 0x01 /* (to 0x0186 state 370) */, /* 1 */ 0x09 /* (to 0x0196 state 385) */, /* pos 0186: 370 */ /* terminal 175 */ 0xAF, /* terminal 180 */ 0xB4, /* pos 0188: 372 */ /* 0 */ 0x01 /* (to 0x018A state 373) */, /* 1 */ 0x27 /* (to 0x01D6 state 451) */, /* pos 018a: 373 */ /* 0 */ 0x01 /* (to 0x018C state 374) */, /* 1 */ 0x05 /* (to 0x0194 state 381) */, /* pos 018c: 374 */ /* terminal 176 */ 0xB0, /* terminal 177 */ 0xB1, /* pos 018e: 377 */ /* 0 */ 0x01 /* (to 0x0190 state 378) */, /* 1 */ 0x07 /* (to 0x019C state 393) */, /* pos 0190: 378 */ /* 0 */ 0x01 /* (to 0x0192 state 379) */, /* 1 */ 0x05 /* (to 0x019A state 390) */, /* pos 0192: 379 */ /* terminal 178 */ 0xB2, /* terminal 181 */ 0xB5, /* pos 0194: 381 */ /* terminal 179 */ 0xB3, /* terminal 209 */ 0xD1, /* pos 0196: 385 */ /* terminal 182 */ 0xB6, /* terminal 183 */ 0xB7, /* pos 0198: 388 */ /* terminal 184 */ 0xB8, /* terminal 194 */ 0xC2, /* pos 019a: 390 */ /* terminal 185 */ 0xB9, /* terminal 186 */ 0xBA, /* pos 019c: 393 */ /* 0 */ 0x01 /* (to 0x019E state 394) */, /* 1 */ 0x04 /* (to 0x01A4 state 400) */, /* pos 019e: 394 */ /* terminal 187 */ 0xBB, /* terminal 189 */ 0xBD, /* pos 01a0: 396 */ /* 0 */ 0x01 /* (to 0x01A2 state 397) */, /* 1 */ 0x07 /* (to 0x01AE state 412) */, /* pos 01a2: 397 */ /* terminal 188 */ 0xBC, /* terminal 191 */ 0xBF, /* pos 01a4: 400 */ /* terminal 190 */ 0xBE, /* terminal 196 */ 0xC4, /* pos 01a6: 403 */ /* 0 */ 0x01 /* (to 0x01A8 state 404) */, /* 1 */ 0x0D /* (to 0x01C0 state 427) */, /* pos 01a8: 404 */ /* 0 */ 0x01 /* (to 0x01AA state 405) */, /* 1 */ 0x0A /* (to 0x01BC state 424) */, /* pos 01aa: 405 */ /* 0 */ 0x01 /* (to 0x01AC state 406) */, /* 1 */ 0x08 /* (to 0x01BA state 421) */, /* pos 01ac: 406 */ /* terminal 192 */ 0xC0, /* terminal 193 */ 0xC1, /* pos 01ae: 412 */ /* terminal 197 */ 0xC5, /* terminal 231 */ 0xE7, /* pos 01b0: 414 */ /* 0 */ 0x01 /* (to 0x01B2 state 415) */, /* 1 */ 0x1B /* (to 0x01E6 state 475) */, /* pos 01b2: 415 */ /* terminal 198 */ 0xC6, /* terminal 228 */ 0xE4, /* pos 01b4: 417 */ /* 0 */ 0x1B /* (to 0x01EA state 481) */, /* 1 */ 0x01 /* (to 0x01B6 state 418) */, /* pos 01b6: 418 */ /* 0 */ 0x01 /* (to 0x01B8 state 419) */, /* 1 */ 0x19 /* (to 0x01E8 state 478) */, /* pos 01b8: 419 */ /* terminal 199 */ 0xC7, /* terminal 207 */ 0xCF, /* pos 01ba: 421 */ /* terminal 200 */ 0xC8, /* terminal 201 */ 0xC9, /* pos 01bc: 424 */ /* 0 */ 0x01 /* (to 0x01BE state 425) */, /* 1 */ 0x06 /* (to 0x01C8 state 438) */, /* pos 01be: 425 */ /* terminal 202 */ 0xCA, /* terminal 205 */ 0xCD, /* pos 01c0: 427 */ /* 0 */ 0x0D /* (to 0x01DA state 455) */, /* 1 */ 0x01 /* (to 0x01C2 state 428) */, /* pos 01c2: 428 */ /* 0 */ 0x17 /* (to 0x01F0 state 490) */, /* 1 */ 0x01 /* (to 0x01C4 state 429) */, /* pos 01c4: 429 */ /* terminal 255 */ 0xFF, /* 1 */ 0x01 /* (to 0x01C6 state 430) */, /* pos 01c6: 430 */ /* terminal 203 */ 0xCB, /* terminal 204 */ 0xCC, /* pos 01c8: 438 */ /* terminal 210 */ 0xD2, /* terminal 213 */ 0xD5, /* pos 01ca: 440 */ /* 0 */ 0x01 /* (to 0x01CC state 441) */, /* 1 */ 0x14 /* (to 0x01F2 state 494) */, /* pos 01cc: 441 */ /* 0 */ 0x01 /* (to 0x01CE state 442) */, /* 1 */ 0x09 /* (to 0x01DE state 461) */, /* pos 01ce: 442 */ /* 0 */ 0x01 /* (to 0x01D0 state 443) */, /* 1 */ 0x02 /* (to 0x01D2 state 447) */, /* pos 01d0: 443 */ /* terminal 211 */ 0xD3, /* terminal 212 */ 0xD4, /* pos 01d2: 447 */ /* terminal 214 */ 0xD6, /* terminal 221 */ 0xDD, /* pos 01d4: 449 */ /* terminal 215 */ 0xD7, /* terminal 225 */ 0xE1, /* pos 01d6: 451 */ /* 0 */ 0x01 /* (to 0x01D8 state 452) */, /* 1 */ 0x07 /* (to 0x01E4 state 469) */, /* pos 01d8: 452 */ /* terminal 216 */ 0xD8, /* terminal 217 */ 0xD9, /* pos 01da: 455 */ /* 0 */ 0x01 /* (to 0x01DC state 456) */, /* 1 */ 0x09 /* (to 0x01EC state 484) */, /* pos 01dc: 456 */ /* terminal 218 */ 0xDA, /* terminal 219 */ 0xDB, /* pos 01de: 461 */ /* 0 */ 0x01 /* (to 0x01E0 state 462) */, /* 1 */ 0x08 /* (to 0x01EE state 488) */, /* pos 01e0: 462 */ /* terminal 222 */ 0xDE, /* terminal 223 */ 0xDF, /* pos 01e2: 465 */ /* terminal 224 */ 0xE0, /* terminal 226 */ 0xE2, /* pos 01e4: 469 */ /* terminal 227 */ 0xE3, /* terminal 229 */ 0xE5, /* pos 01e6: 475 */ /* terminal 232 */ 0xE8, /* terminal 233 */ 0xE9, /* pos 01e8: 478 */ /* terminal 234 */ 0xEA, /* terminal 235 */ 0xEB, /* pos 01ea: 481 */ /* terminal 236 */ 0xEC, /* terminal 237 */ 0xED, /* pos 01ec: 484 */ /* terminal 238 */ 0xEE, /* terminal 240 */ 0xF0, /* pos 01ee: 488 */ /* terminal 241 */ 0xF1, /* terminal 244 */ 0xF4, /* pos 01f0: 490 */ /* terminal 242 */ 0xF2, /* terminal 243 */ 0xF3, /* pos 01f2: 494 */ /* 0 */ 0x01 /* (to 0x01F4 state 495) */, /* 1 */ 0x04 /* (to 0x01FA state 503) */, /* pos 01f4: 495 */ /* 0 */ 0x01 /* (to 0x01F6 state 496) */, /* 1 */ 0x02 /* (to 0x01F8 state 499) */, /* pos 01f6: 496 */ /* terminal 245 */ 0xF5, /* terminal 246 */ 0xF6, /* pos 01f8: 499 */ /* terminal 247 */ 0xF7, /* terminal 248 */ 0xF8, /* pos 01fa: 503 */ /* 0 */ 0x01 /* (to 0x01FC state 504) */, /* 1 */ 0x02 /* (to 0x01FE state 507) */, /* pos 01fc: 504 */ /* terminal 250 */ 0xFA, /* terminal 251 */ 0xFB, /* pos 01fe: 507 */ /* terminal 252 */ 0xFC, /* terminal 253 */ 0xFD, /* total size 512 bytes, biggest jump 200/256, fails=0 */ }; static unsigned char lextable_terms[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x34, 0x0f, 0x43, 0x03, 0xf1, 0x3c, 0xfc, 0x3c, 0x0f, 0x30, 0x37, 0xf7, 0x0f, 0xc3, 0xcf, 0x03, 0x3c, 0xfc, 0xc0, 0xf3, 0xf0, 0x3c, 0xfc, 0xf0, 0xcf, 0xfc, 0xcc, 0xff, 0xfc, 0x0d, 0x34, 0xcc, 0xcf, 0x33, 0xf0, 0x33, 0x0c, 0x3f, 0xc3, 0x3f, 0xcc, 0x30, 0xfc, 0xcf, 0x3c, 0xf0, 0x0c, 0xcf, 0xd0, 0x03, 0x3f, 0x33, 0xff, 0xff, 0xc3, 0xf3, }; /* state that points to 0x100 for disambiguation with 0x0 */ #define HUFTABLE_0x100_PREV 118 |
Added undroid/libwebsockets/lib/lextable-strings.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
/* set of parsable strings -- ALL LOWER CASE */ static const char *set[] = { "get ", "post ", "options ", "host:", "connection:", "upgrade:", "origin:", "sec-websocket-draft:", "\x0d\x0a", "sec-websocket-extensions:", "sec-websocket-key1:", "sec-websocket-key2:", "sec-websocket-protocol:", "sec-websocket-accept:", "sec-websocket-nonce:", "http/1.1 ", "http2-settings:", "accept:", "access-control-request-headers:", "if-modified-since:", "if-none-match:", "accept-encoding:", "accept-language:", "pragma:", "cache-control:", "authorization:", "cookie:", "content-length:", "content-type:", "date:", "range:", "referer:", "sec-websocket-key:", "sec-websocket-version:", "sec-websocket-origin:", ":authority", ":method", ":path", ":scheme", ":status", "accept-charset:", "accept-ranges:", "access-control-allow-origin:", "age:", "allow:", "content-disposition:", "content-encoding:", "content-language:", "content-location:", "content-range:", "etag:", "expect:", "expires:", "from:", "if-match:", "if-range:", "if-unmodified-since:", "last-modified:", "link:", "location:", "max-forwards:", "proxy-authenticate:", "proxy-authorization:", "refresh:", "retry-after:", "server:", "set-cookie:", "strict-transport-security:", "transfer-encoding:", "user-agent:", "vary:", "via:", "www-authenticate:", "patch", "put", "delete", "uri-args", /* fake header used for uri-only storage */ "proxy ", "x-real-ip:", "http/1.0 ", "", /* not matchable */ }; |
Added undroid/libwebsockets/lib/lextable.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 |
/* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, 0x6F /* 'o' */, 0x51, 0x00 /* (to 0x0057 state 10) */, 0x68 /* 'h' */, 0x5D, 0x00 /* (to 0x0066 state 18) */, 0x63 /* 'c' */, 0x66, 0x00 /* (to 0x0072 state 23) */, 0x75 /* 'u' */, 0x81, 0x00 /* (to 0x0090 state 34) */, 0x73 /* 's' */, 0x97, 0x00 /* (to 0x00A9 state 48) */, 0x0D /* '.' */, 0xD0, 0x00 /* (to 0x00E5 state 68) */, 0x61 /* 'a' */, 0x28, 0x01 /* (to 0x0140 state 129) */, 0x69 /* 'i' */, 0x67, 0x01 /* (to 0x0182 state 163) */, 0x64 /* 'd' */, 0x10, 0x02 /* (to 0x022E state 265) */, 0x72 /* 'r' */, 0x19, 0x02 /* (to 0x023A state 270) */, 0x3A /* ':' */, 0x4A, 0x02 /* (to 0x026E state 299) */, 0x65 /* 'e' */, 0xD6, 0x02 /* (to 0x02FD state 409) */, 0x66 /* 'f' */, 0xF2, 0x02 /* (to 0x031C state 425) */, 0x6C /* 'l' */, 0x14, 0x03 /* (to 0x0341 state 458) */, 0x6D /* 'm' */, 0x37, 0x03 /* (to 0x0367 state 484) */, 0x74 /* 't' */, 0xA6, 0x03 /* (to 0x03D9 state 578) */, 0x76 /* 'v' */, 0xC1, 0x03 /* (to 0x03F7 state 606) */, 0x77 /* 'w' */, 0xCE, 0x03 /* (to 0x0407 state 614) */, 0x78 /* 'x' */, 0xF5, 0x03 /* (to 0x0431 state 650) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, /* pos 0042: 3 */ 0xA0 /* ' ' -> */, /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, 0x72 /* 'r' */, 0x8C, 0x01 /* (to 0x01D4 state 211) */, 0x61 /* 'a' */, 0xCE, 0x03 /* (to 0x0419 state 631) */, 0x75 /* 'u' */, 0xD0, 0x03 /* (to 0x041E state 635) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, /* pos 0054: 8 */ 0xA0 /* ' ' -> */, /* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, /* pos 0057: 10 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x005E state 11) */, 0x72 /* 'r' */, 0x48, 0x00 /* (to 0x00A2 state 42) */, 0x08, /* fail */ /* pos 005e: 11 */ 0xF4 /* 't' -> */, /* pos 005f: 12 */ 0xE9 /* 'i' -> */, /* pos 0060: 13 */ 0xEF /* 'o' -> */, /* pos 0061: 14 */ 0xEE /* 'n' -> */, /* pos 0062: 15 */ 0xF3 /* 's' -> */, /* pos 0063: 16 */ 0xA0 /* ' ' -> */, /* pos 0064: 17 */ 0x00, 0x02 /* - terminal marker 2 - */, /* pos 0066: 18 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 19) */, 0x74 /* 't' */, 0xB6, 0x00 /* (to 0x011F state 110) */, 0x08, /* fail */ /* pos 006d: 19 */ 0xF3 /* 's' -> */, /* pos 006e: 20 */ 0xF4 /* 't' -> */, /* pos 006f: 21 */ 0xBA /* ':' -> */, /* pos 0070: 22 */ 0x00, 0x0 |